Mon Aug 31 12:30:31 2015

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/netsock.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"

Go to the source code of this file.

Data Structures

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

Defines

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116
#define ALARM_MESSAGE   0x0020
#define BT_AUTOANSWER   STIMULUS_AUTOANSWER
#define BT_CALLPARK   STIMULUS_CALLPARK
#define BT_CALLPICKUP   STIMULUS_CALLPICKUP
#define BT_CONFERENCE   STIMULUS_CONFERENCE
#define BT_CUST_LINE   0xB1
#define BT_CUST_LINESPEEDDIAL   0xB0
#define BT_DISPLAY   STIMULUS_DISPLAY
#define BT_DND   STIMULUS_DND
#define BT_FORWARDALL   STIMULUS_FORWARDALL
#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY
#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER
#define BT_HOLD   STIMULUS_HOLD
#define BT_LINE   STIMULUS_LINE
#define BT_NONE   0x00
#define BT_REDIAL   STIMULUS_REDIAL
#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL
#define BT_TRANSFER   STIMULUS_TRANSFER
#define BT_VOICEMAIL   STIMULUS_VOICEMAIL
#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E
#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097
#define CALL_INFO_MESSAGE   0x008F
#define CALL_STATE_MESSAGE   0x0111
#define CAPABILITIES_REQ_MESSAGE   0x009B
#define CAPABILITIES_RES_MESSAGE   0x0010
#define 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)   (x)
#define htoles(x)   (x)
#define IP_PORT_MESSAGE   0x0002
#define KEEP_ALIVE_ACK_MESSAGE   0x0100
#define KEEP_ALIVE_MESSAGE   0x0000
#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7
#define KEYDEF_CONNWITHTRANS   5
#define KEYDEF_DADFD   6
#define KEYDEF_OFFHOOK   4
#define KEYDEF_OFFHOOKWITHFEAT   9
#define KEYDEF_ONHOLD   2
#define KEYDEF_ONHOOK   0
#define KEYDEF_RINGIN   3
#define KEYDEF_RINGOUT   8
#define KEYDEF_UNKNOWN   10
#define KEYPAD_BUTTON_MESSAGE   0x0003
#define letohl(x)   (x)
#define letohs(x)   (x)
#define LINE_STAT_RES_MESSAGE   0x0092
#define LINE_STATE_REQ_MESSAGE   0x000B
#define OFFHOOK_MESSAGE   0x0006
#define ONHOOK_MESSAGE   0x0007
#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022
#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105
#define REGISTER_ACK_MESSAGE   0x0081
#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D
#define REGISTER_MESSAGE   0x0001
#define REGISTER_REJ_MESSAGE   0x009D
#define RESET_MESSAGE   0x009F
#define SELECT_SOFT_KEYS_MESSAGE   0x0110
#define SERVER_REQUEST_MESSAGE   0x0012
#define SERVER_RES_MESSAGE   0x009E
#define SET_LAMP_MESSAGE   0x0086
#define SET_MICROPHONE_MESSAGE   0x0089
#define SET_RINGER_MESSAGE   0x0085
#define SET_SPEAKER_MESSAGE   0x0088
#define SKINNY_ALERT   0x24
#define SKINNY_BUSY   6
#define SKINNY_BUSYTONE   0x23
#define SKINNY_CALLREMOTEMULTILINE   13
#define SKINNY_CALLWAIT   9
#define SKINNY_CALLWAITTONE   0x2D
#define SKINNY_CFWD_ALL   (1 << 0)
#define SKINNY_CFWD_BUSY   (1 << 1)
#define SKINNY_CFWD_NOANSWER   (1 << 2)
#define SKINNY_CONGESTION   7
#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3
#define SKINNY_CX_CONFERENCE   3
#define SKINNY_CX_INACTIVE   4
#define SKINNY_CX_MUTE   4
#define SKINNY_CX_RECVONLY   1
#define SKINNY_CX_SENDONLY   0
#define SKINNY_CX_SENDRECV   2
#define SKINNY_DEVICE_12   4
#define SKINNY_DEVICE_12SP   3
#define SKINNY_DEVICE_12SPPLUS   2
#define SKINNY_DEVICE_30SPPLUS   1
#define SKINNY_DEVICE_30VIP   5
#define SKINNY_DEVICE_7902   30008
#define SKINNY_DEVICE_7905   20000
#define SKINNY_DEVICE_7906   369
#define SKINNY_DEVICE_7910   6
#define SKINNY_DEVICE_7911   307
#define SKINNY_DEVICE_7912   30007
#define SKINNY_DEVICE_7914   124
#define SKINNY_DEVICE_7920   30002
#define SKINNY_DEVICE_7921   365
#define SKINNY_DEVICE_7931   348
#define SKINNY_DEVICE_7935   9
#define SKINNY_DEVICE_7936   30019
#define SKINNY_DEVICE_7937   431
#define SKINNY_DEVICE_7940   8
#define SKINNY_DEVICE_7941   115
#define SKINNY_DEVICE_7941GE   309
#define SKINNY_DEVICE_7942   434
#define SKINNY_DEVICE_7945   435
#define SKINNY_DEVICE_7960   7
#define SKINNY_DEVICE_7961   30018
#define SKINNY_DEVICE_7961GE   308
#define SKINNY_DEVICE_7962   404
#define SKINNY_DEVICE_7965   436
#define SKINNY_DEVICE_7970   30006
#define SKINNY_DEVICE_7971   119
#define SKINNY_DEVICE_7975   437
#define SKINNY_DEVICE_7985   302
#define SKINNY_DEVICE_ATA186   12
#define SKINNY_DEVICE_CIPC   30016
#define SKINNY_DEVICE_NONE   0
#define SKINNY_DEVICE_OPTIONS
#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027
#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028
#define SKINNY_DEVICE_UNKNOWN   -1
#define SKINNY_DEVONLY(code)
#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8
#define SKINNY_INVALID   14
#define SKINNY_LAMP_BLINK   5
#define SKINNY_LAMP_FLASH   4
#define SKINNY_LAMP_OFF   1
#define SKINNY_LAMP_ON   2
#define SKINNY_LAMP_WINK   3
#define SKINNY_LINE_OPTIONS
#define SKINNY_MAX_CAPABILITIES   18
#define SKINNY_MAX_PACKET   1000
#define SKINNY_MICOFF   2
#define SKINNY_MICON   1
#define SKINNY_NOTONE   0x7F
#define SKINNY_OFFHOOK   1
#define SKINNY_ONHOOK   2
#define SKINNY_PARK   11
#define SKINNY_PROGRESS   12
#define SKINNY_REORDER   0x25
#define SKINNY_RING_FEATURE   4
#define SKINNY_RING_INSIDE   2
#define SKINNY_RING_OFF   1
#define SKINNY_RING_OUTSIDE   3
#define SKINNY_RINGIN   4
#define SKINNY_RINGOUT   3
#define SKINNY_SILENCE   0x00
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_TRANSFER   10
#define SOFT_KEY_EVENT_MESSAGE   0x0026
#define SOFT_KEY_SET_REQ_MESSAGE   0x0025
#define SOFT_KEY_SET_RES_MESSAGE   0x0109
#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028
#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108
#define SOFTKEY_ANSWER   0x0B
#define SOFTKEY_BKSPC   0x08
#define SOFTKEY_CFWDALL   0x05
#define SOFTKEY_CFWDBUSY   0x06
#define SOFTKEY_CFWDNOANSWER   0x07
#define SOFTKEY_CONFRN   0x0D
#define SOFTKEY_DND   0x13
#define SOFTKEY_ENDCALL   0x09
#define SOFTKEY_GPICKUP   0x12
#define SOFTKEY_HOLD   0x03
#define SOFTKEY_IDIVERT   0x14
#define SOFTKEY_INFO   0x0C
#define SOFTKEY_JOIN   0x0F
#define SOFTKEY_MEETME   0x10
#define SOFTKEY_NEWCALL   0x02
#define SOFTKEY_NONE   0x00
#define SOFTKEY_PARK   0x0E
#define SOFTKEY_PICKUP   0x11
#define SOFTKEY_REDIAL   0x01
#define SOFTKEY_RESUME   0x0A
#define SOFTKEY_TRNSFER   0x04
#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A
#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091
#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A
#define START_TONE_MESSAGE   0x0082
#define STIMULUS_AUTOANSWER   0x11
#define STIMULUS_CALLPARK   0x7E
#define STIMULUS_CALLPICKUP   0x7F
#define STIMULUS_CONFERENCE   0x7D
#define STIMULUS_DISPLAY   0x08
#define STIMULUS_DND   0x3F
#define STIMULUS_FORWARDALL   0x05
#define STIMULUS_FORWARDBUSY   0x06
#define STIMULUS_FORWARDNOANSWER   0x07
#define STIMULUS_HOLD   0x03
#define STIMULUS_LINE   0x09
#define STIMULUS_MESSAGE   0x0005
#define STIMULUS_NONE   0xFF
#define STIMULUS_REDIAL   0x01
#define STIMULUS_SPEEDDIAL   0x02
#define STIMULUS_TRANSFER   0x04
#define STIMULUS_VOICEMAIL   0x0F
#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B
#define STOP_TONE_MESSAGE   0x0083
#define TIME_DATE_REQ_MESSAGE   0x000D
#define TYPE_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 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 struct ast_variableadd_var (const char *buf, struct ast_variable *list)
static AST_LIST_HEAD_STATIC (sessions, skinnysession)
static AST_LIST_HEAD_STATIC (devices, skinny_device)
static AST_LIST_HEAD_STATIC (lines, skinny_line)
 AST_MODULE_INFO (ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER,"Skinny Client Control Protocol (Skinny)",.load=load_module,.unload=unload_module,.reload=reload,.load_pri=AST_MODPRI_CHANNEL_DRIVER,)
 AST_MUTEX_DEFINE_STATIC (netlock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_THREADSTORAGE (control2str_threadbuf)
 AST_THREADSTORAGE (device2str_threadbuf)
static void cleanup_stale_contexts (char *new, char *old)
static int codec_ast2skinny (format_t astcodec)
static format_t codec_skinny2ast (enum skinny_codecs skinnycodec)
static char * complete_skinny_devices (const char *word, int state)
static char * complete_skinny_reset (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_device (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_line (const char *line, const char *word, int pos, int state)
static 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_session (struct skinnysession *s)
static char * device2str (int type)
static void * do_monitor (void *data)
static struct skinny_linefind_line_by_instance (struct skinny_device *d, int instance)
static struct skinny_linefind_line_by_name (const char *dest)
static struct skinny_speeddialfind_speeddial_by_instance (struct skinny_device *d, int instance, int isHint)
static struct skinny_subchannelfind_subchannel_by_instance_reference (struct skinny_device *d, int instance, int reference)
static struct skinny_subchannelfind_subchannel_by_reference (struct skinny_device *d, int reference)
static void * get_button_template (struct skinnysession *s, struct button_definition_template *btn)
static int get_devicestate (struct skinny_line *l)
static int get_input (struct skinnysession *s)
static int handle_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_keep_alive_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_message (struct skinny_req *req, struct skinnysession *s)
static int handle_message (struct skinny_req *req, struct skinnysession *s)
static int handle_offhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_onhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_open_receive_channel_ack_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_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_set_debug (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 register_exten (struct skinny_line *l)
static int reload (void)
static struct skinny_reqreq_alloc (size_t size, int response_message)
static int restart_monitor (void)
static int set_callforwards (struct skinny_line *l, const char *cfwd, int cfwdtype)
static int skinny_answer (struct ast_channel *ast)
static int skinny_call (struct ast_channel *ast, char *dest, int timeout)
static int skinny_devicestate (void *data)
static int skinny_extensionstate_cb (char *context, char *exten, int state, void *data)
static int skinny_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_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_hold (struct skinny_subchannel *sub)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelskinny_new (struct skinny_line *l, int state, const char *linkedid)
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, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_senddigit_begin (struct ast_channel *ast, char digit)
static int skinny_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void * skinny_session (void *data)
static int skinny_set_rtp_peer (struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
static void * skinny_ss (void *data)
static int skinny_transfer (struct skinny_subchannel *sub)
static int skinny_unhold (struct skinny_subchannel *sub)
static int skinny_unregister (struct skinny_req *req, struct skinnysession *s)
static int skinny_write (struct ast_channel *ast, struct ast_frame *frame)
static void start_rtp (struct skinny_subchannel *sub)
static void transmit_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_callinfo (struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinny_device *d, int buttonInstance, unsigned callid, int state)
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_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static void transmit_linestatres (struct skinny_device *d, struct skinny_line *l)
static int transmit_response (struct skinny_device *d, struct skinny_req *req)
static void transmit_ringer_mode (struct skinny_device *d, int mode)
static void transmit_selectsoftkeys (struct skinny_device *d, int instance, int callid, int softkey)
static void transmit_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 in_addr __ourip
static pthread_t accept_t
static struct ast_hostent ahp
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_cli_entry cli_skinny []
static const char config [] = "skinny.conf"
static char date_format [6] = "D-M-Y"
static format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW
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 int firstdigittimeout = 16000
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
static char global_vmexten [AST_MAX_EXTENSION]
static struct hostent * hp
static struct io_contextio
static int keep_alive = 120
static int matchdigittimeout = 3000
static pthread_t monitor_thread = AST_PTHREADT_NULL
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 sched_contextsched = NULL
static int skinny_header_size = 12
static struct ast_rtp_glue skinny_rtp_glue
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
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_unknown []
static struct
soft_key_template_definition 
soft_key_template_default []
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"

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

Referenced by transmit_activatecallplane().

#define ALARM_MESSAGE   0x0020

Definition at line 331 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 538 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 541 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 542 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 540 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 549 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 548 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 535 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 539 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 532 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 533 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 534 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 530 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 536 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 543 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 528 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 529 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 531 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 537 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 327 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 498 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 436 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 935 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 571 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 299 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6709 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6708 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 569 of file chan_skinny.c.

Referenced by transmit_clear_display_message().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 568 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 952 of file chan_skinny.c.

Referenced by transmit_clearpromptmessage().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6707 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6706 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 607 of file chan_skinny.c.

Referenced by transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 246 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_AUTH_LIMIT   50

Definition at line 164 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_AUTH_TIMEOUT   30

Definition at line 163 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 161 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 160 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 485 of file chan_skinny.c.

Referenced by transmit_definetimedate().

#define DEVICE2STR_BUFSIZE   15

Definition at line 243 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 969 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 958 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 943 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 563 of file chan_skinny.c.

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 275 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 458 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 358 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     (x)
#define htoles (  )     (x)

Definition at line 189 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define IP_PORT_MESSAGE   0x0002

Definition at line 265 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 594 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 252 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7

Definition at line 628 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 626 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 627 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4
#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 630 of file chan_skinny.c.

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 623 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0
#define KEYDEF_RINGIN   3

Definition at line 624 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8
#define KEYDEF_UNKNOWN   10

Definition at line 631 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 267 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     (x)
#define letohs (  )     (x)

Definition at line 187 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 477 of file chan_skinny.c.

Referenced by transmit_linestatres().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 321 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 287 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 293 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 339 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 596 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 361 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 359 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 573 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 589 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 927 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 329 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 578 of file chan_skinny.c.

Referenced by transmit_serverres().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 392 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 405 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 384 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 399 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1116 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1103 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1115 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1110 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1106 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1118 of file chan_skinny.c.

#define SKINNY_CFWD_ALL   (1 << 0)
#define SKINNY_CFWD_BUSY   (1 << 1)
#define SKINNY_CFWD_NOANSWER   (1 << 2)
#define SKINNY_CONGESTION   7

Definition at line 1104 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3

Definition at line 1140 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1141 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1143 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1142 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1138 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1137 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1139 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1058 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1057 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1056 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1055 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1059 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1085 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1081 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1074 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1060 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1069 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1084 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1067 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1082 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1073 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1072 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1063 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1088 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1076 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1062 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1065 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1071 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1077 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1078 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1061 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1087 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1070 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1075 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1079 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1083 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1066 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1080 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1068 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1064 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1086 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1054 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1312 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1089 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1090 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 1053 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVONLY ( code   ) 

Definition at line 138 of file chan_skinny.c.

Referenced by handle_message(), and transmit_response().

#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8

Definition at line 1105 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1111 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1125 of file chan_skinny.c.

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

#define SKINNY_LAMP_FLASH   4

Definition at line 1124 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1
#define SKINNY_LAMP_ON   2
#define SKINNY_LAMP_WINK   3

Definition at line 1123 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1202 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 309 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 162 of file chan_skinny.c.

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

#define SKINNY_MICOFF   2

Definition at line 1096 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1095 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1119 of file chan_skinny.c.

#define SKINNY_OFFHOOK   1
#define SKINNY_ONHOOK   2
#define SKINNY_PARK   11

Definition at line 1108 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1109 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_REORDER   0x25

Definition at line 1117 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1130 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1128 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1
#define SKINNY_RING_OUTSIDE   3

Definition at line 1129 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1101 of file chan_skinny.c.

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

#define SKINNY_RINGOUT   3

Definition at line 1100 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_SILENCE   0x00

Definition at line 1113 of file chan_skinny.c.

#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_TRANSFER   10

Definition at line 1107 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 349 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 347 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 912 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 357 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 614 of file chan_skinny.c.

Referenced by transmit_softkeytemplateres().

#define SOFTKEY_ANSWER   0x0B

Definition at line 644 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 641 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 639 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 640 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 646 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 652 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 642 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 651 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 636 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 653 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 645 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 648 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 649 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 635 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 647 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 650 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 634 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 643 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 637 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 316 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 470 of file chan_skinny.c.

Referenced by transmit_speeddialstatres().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 410 of file chan_skinny.c.

Referenced by transmit_startmediatransmission().

#define START_TONE_MESSAGE   0x0082

Definition at line 370 of file chan_skinny.c.

Referenced by transmit_start_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 520 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 523 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 524 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 522 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 517 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 521 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 514 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 515 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 516 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 512 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09
#define STIMULUS_MESSAGE   0x0005

Definition at line 280 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 525 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 510 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 511 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 513 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 519 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 429 of file chan_skinny.c.

Referenced by transmit_stopmediatransmission().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 378 of file chan_skinny.c.

Referenced by transmit_stop_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 326 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6701 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6702 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6703 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6700 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6704 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 356 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 328 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

00150                    {
00151    SKINNY_CODEC_ALAW = 2,
00152    SKINNY_CODEC_ULAW = 4,
00153    SKINNY_CODEC_G723_1 = 9,
00154    SKINNY_CODEC_G729A = 12,
00155    SKINNY_CODEC_G726_32 = 82, /* XXX Which packing order does this translate to? */
00156    SKINNY_CODEC_H261 = 100,
00157    SKINNY_CODEC_H263 = 101
00158 };


Function Documentation

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

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

Referenced by handle_skinny_show_device(), and manager_skinny_show_device().

03252 {
03253    struct skinny_device *d;
03254    struct skinny_line *l;
03255    struct skinny_speeddial *sd;
03256    struct skinny_addon *sa;
03257    char codec_buf[512];
03258 
03259    if (argc < 4) {
03260       return CLI_SHOWUSAGE;
03261    }
03262 
03263    AST_LIST_LOCK(&devices);
03264    AST_LIST_TRAVERSE(&devices, d, list) {
03265       if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
03266          int numlines = 0, numaddons = 0, numspeeddials = 0;
03267 
03268          AST_LIST_TRAVERSE(&d->lines, l, list){
03269             numlines++;
03270          }
03271 
03272          AST_LIST_TRAVERSE(&d->addons, sa, list) {
03273             numaddons++;
03274          }
03275 
03276          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03277             numspeeddials++;
03278          }
03279 
03280          if (type == 0) { /* CLI */
03281             ast_cli(fd, "Name:        %s\n", d->name);
03282             ast_cli(fd, "Id:          %s\n", d->id);
03283             ast_cli(fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
03284             ast_cli(fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03285             ast_cli(fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03286             ast_cli(fd, "Device Type: %s\n", device2str(d->type));
03287             ast_cli(fd, "Conf Codecs:");
03288             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcapability);
03289             ast_cli(fd, "%s\n", codec_buf);
03290             ast_cli(fd, "Neg Codecs: ");
03291             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->capability);
03292             ast_cli(fd, "%s\n", codec_buf);
03293             ast_cli(fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
03294             ast_cli(fd, "Lines:       %d\n", numlines);
03295             AST_LIST_TRAVERSE(&d->lines, l, list) {
03296                ast_cli(fd, "  %s (%s)\n", l->name, l->label);
03297             }
03298             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03299                numaddons++;
03300             }  
03301             ast_cli(fd, "Addons:      %d\n", numaddons);
03302             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03303                ast_cli(fd, "  %s\n", sa->type);
03304             }
03305             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03306                numspeeddials++;
03307             }
03308             ast_cli(fd, "Speeddials:  %d\n", numspeeddials);
03309             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03310                ast_cli(fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
03311             }
03312          } else { /* manager */
03313             astman_append(s, "Channeltype: SKINNY\r\n");
03314             astman_append(s, "ObjectName: %s\r\n", d->name);
03315             astman_append(s, "ChannelObjectType: device\r\n");
03316             astman_append(s, "Id: %s\r\n", d->id);
03317             astman_append(s, "version: %s\r\n", S_OR(d->version_id, "Unknown"));
03318             astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03319             astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03320             astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
03321             astman_append(s, "Codecs: ");
03322             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcapability);
03323             astman_append(s, "%s\r\n", codec_buf);
03324             astman_append(s, "CodecOrder: ");
03325             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->capability);
03326             astman_append(s, "%s\r\n", codec_buf);
03327             astman_append(s, "Devicestatus: %s\r\n", (d->registered?"registered":"unregistered"));
03328             astman_append(s, "NumberOfLines: %d\r\n", numlines);
03329             AST_LIST_TRAVERSE(&d->lines, l, list) {
03330                astman_append(s, "Line: %s (%s)\r\n", l->name, l->label);
03331             }
03332             astman_append(s, "NumberOfAddons: %d\r\n", numaddons);
03333             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03334                astman_append(s, "Addon: %s\r\n", sa->type);
03335             }
03336             astman_append(s, "NumberOfSpeeddials: %d\r\n", numspeeddials);
03337             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03338                astman_append(s, "Speeddial: %s (%s) ishint: %d\r\n", sd->exten, sd->label, sd->isHint);
03339             }
03340          }
03341       }
03342    }
03343    AST_LIST_UNLOCK(&devices);
03344    return CLI_SUCCESS;
03345 }

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 3140 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(), devices, id, skinny_device::session, and skinnysession::sin.

Referenced by handle_skinny_show_devices(), and manager_skinny_show_devices().

03141 {
03142    struct skinny_device *d;
03143    struct skinny_line *l;
03144    const char *id;
03145    char idtext[256] = "";
03146    int total_devices = 0;
03147 
03148    if (s) { /* Manager - get ActionID */
03149       id = astman_get_header(m, "ActionID");
03150       if (!ast_strlen_zero(id))
03151          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03152    }
03153 
03154    switch (argc) {
03155    case 3:
03156       break;
03157    default:
03158       return CLI_SHOWUSAGE;
03159    }
03160 
03161    if (!s) {
03162       ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
03163       ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
03164    }
03165 
03166    AST_LIST_LOCK(&devices);
03167    AST_LIST_TRAVERSE(&devices, d, list) {
03168       int numlines = 0;
03169       total_devices++;
03170       AST_LIST_TRAVERSE(&d->lines, l, list) {
03171          numlines++;
03172       }
03173       if (!s) {
03174          ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
03175             d->name,
03176             d->id,
03177             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
03178             device2str(d->type),
03179             d->registered?'Y':'N',
03180             numlines);
03181       } else {
03182          astman_append(s,
03183             "Event: DeviceEntry\r\n%s"
03184             "Channeltype: SKINNY\r\n"
03185             "ObjectName: %s\r\n"
03186             "ChannelObjectType: device\r\n"
03187             "DeviceId: %s\r\n"
03188             "IPaddress: %s\r\n"
03189             "Type: %s\r\n"
03190             "Devicestatus: %s\r\n"
03191             "NumberOfLines: %d\r\n",
03192             idtext,
03193             d->name,
03194             d->id,
03195             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"-none-",
03196             device2str(d->type),
03197             d->registered?"registered":"unregistered",
03198             numlines);
03199       }
03200    }
03201    AST_LIST_UNLOCK(&devices);
03202 
03203    if (total)
03204       *total = total_devices;
03205    
03206    return CLI_SUCCESS;
03207 }

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 3508 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_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_print_group(), astman_append(), CLI_SHOWUSAGE, CLI_SUCCESS, devices, print_codec_to_cli(), S_COR, S_OR, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, and SKINNY_CFWD_NOANSWER.

Referenced by handle_skinny_show_line(), and manager_skinny_show_line().

03509 {
03510    struct skinny_device *d;
03511    struct skinny_line *l;
03512    struct ast_codec_pref *pref;
03513    int x = 0, codec = 0;
03514    char codec_buf[512];
03515    char group_buf[256];
03516    char cbuf[256];
03517 
03518    switch (argc) {
03519    case 4:
03520       break;
03521    case 6:
03522       break;
03523    default:
03524       return CLI_SHOWUSAGE;
03525    }
03526 
03527    AST_LIST_LOCK(&devices);
03528 
03529    /* Show all lines matching the one supplied */
03530    AST_LIST_TRAVERSE(&devices, d, list) {
03531       if (argc == 6 && (strcasecmp(argv[5], d->id) && strcasecmp(argv[5], d->name))) {
03532          continue;
03533       }
03534       AST_LIST_TRAVERSE(&d->lines, l, list) {
03535          if (strcasecmp(argv[3], l->name)) {
03536             continue;
03537          }
03538          if (type == 0) { /* CLI */
03539             ast_cli(fd, "Line:             %s\n", l->name);
03540             ast_cli(fd, "On Device:        %s\n", d->name);
03541             ast_cli(fd, "Line Label:       %s\n", l->label);
03542             ast_cli(fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
03543             ast_cli(fd, "Context:          %s\n", l->context);
03544             ast_cli(fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03545             ast_cli(fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03546             ast_cli(fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
03547             ast_cli(fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
03548             ast_cli(fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
03549             ast_cli(fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
03550             ast_cli(fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
03551             ast_cli(fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
03552             ast_cli(fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03553             ast_cli(fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03554             ast_cli(fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03555             ast_cli(fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
03556             ast_cli(fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
03557             ast_cli(fd, "MWIblink:         %d\n", l->mwiblink);
03558             ast_cli(fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
03559             ast_cli(fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
03560             ast_cli(fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
03561             ast_cli(fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
03562             ast_cli(fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03563             ast_cli(fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
03564             ast_cli(fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
03565             ast_cli(fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
03566             ast_cli(fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
03567             ast_cli(fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
03568             ast_cli(fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
03569             ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
03570             ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
03571             ast_cli(fd, "Group:            %d\n", l->group);
03572             ast_cli(fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
03573             ast_cli(fd, "Conf Codecs:      ");
03574             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03575             ast_cli(fd, "%s\n", codec_buf);
03576             ast_cli(fd, "Neg Codecs:       ");
03577             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
03578             ast_cli(fd, "%s\n", codec_buf);
03579             ast_cli(fd, "Codec Order:      (");
03580             print_codec_to_cli(fd, &l->prefs);
03581             ast_cli(fd, ")\n");
03582             ast_cli(fd, "\n");
03583          } else { /* manager */
03584             astman_append(s, "Channeltype: SKINNY\r\n");
03585             astman_append(s, "ObjectName: %s\r\n", l->name);
03586             astman_append(s, "ChannelObjectType: line\r\n");
03587             astman_append(s, "Device: %s\r\n", d->name);
03588             astman_append(s, "LineLabel: %s\r\n", l->label);
03589             astman_append(s, "Extension: %s\r\n", S_OR(l->exten, "<not set>"));
03590             astman_append(s, "Context: %s\r\n", l->context);
03591             astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03592             astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03593             astman_append(s, "Language: %s\r\n", S_OR(l->language, "<not set>"));
03594             astman_append(s, "Accountcode: %s\r\n", S_OR(l->accountcode, "<not set>"));
03595             astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(l->amaflags));
03596             astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), l->cid_name, l->cid_num, ""));
03597             astman_append(s, "HideCallerId: %s\r\n", (l->hidecallerid ? "Yes" : "No"));
03598             astman_append(s, "CFwdAll: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03599             astman_append(s, "CFwdBusy: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03600             astman_append(s, "CFwdNoAnswer: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03601             astman_append(s, "VoicemailBox: %s\r\n", S_OR(l->mailbox, "<not set>"));
03602             astman_append(s, "VoicemailNumber: %s\r\n", S_OR(l->vmexten, "<not set>"));
03603             astman_append(s, "MWIblink: %d\r\n", l->mwiblink);
03604             astman_append(s, "RegExtension: %s\r\n", S_OR(l->regexten, "<not set>"));
03605             astman_append(s, "Regcontext: %s\r\n", S_OR(l->regcontext, "<not set>"));
03606             astman_append(s, "MoHInterpret: %s\r\n", S_OR(l->mohinterpret, "<not set>"));
03607             astman_append(s, "MoHSuggest: %s\r\n", S_OR(l->mohsuggest, "<not set>"));
03608             astman_append(s, "LastDialedNr: %s\r\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03609             astman_append(s, "LastCallerID: %s\r\n", S_OR(l->lastcallerid, "<not set>"));
03610             astman_append(s, "Transfer: %s\r\n", (l->transfer ? "Yes" : "No"));
03611             astman_append(s, "Callwaiting: %s\r\n", (l->callwaiting ? "Yes" : "No"));
03612             astman_append(s, "3WayCalling: %s\r\n", (l->threewaycalling ? "Yes" : "No"));
03613             astman_append(s, "CanForward: %s\r\n", (l->cancallforward ? "Yes" : "No"));
03614             astman_append(s, "DoNotDisturb: %s\r\n", (l->dnd ? "Yes" : "No"));
03615             astman_append(s, "NAT: %s\r\n", (l->nat ? "Yes" : "No"));
03616             astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
03617             astman_append(s, "Group: %d\r\n", l->group);
03618             astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
03619             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03620             astman_append(s, "Codecs: %s\r\n", codec_buf);
03621             astman_append(s, "CodecOrder: ");
03622             pref = &l->prefs;
03623             for(x = 0; x < 32 ; x++) {
03624                codec = ast_codec_pref_index(pref, x);
03625                if (!codec)
03626                   break;
03627                astman_append(s, "%s", ast_getformatname(codec));
03628                if (x < 31 && ast_codec_pref_index(pref, x+1))
03629                   astman_append(s, ",");
03630             }
03631             astman_append(s, "\r\n");
03632          }
03633       }
03634    }
03635    
03636    AST_LIST_UNLOCK(&devices);
03637    return CLI_SUCCESS;
03638 }

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

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

Referenced by handle_skinny_show_lines(), and manager_skinny_show_lines().

03385 {
03386    struct skinny_line *l;
03387    struct skinny_subchannel *sub;
03388    int total_lines = 0;
03389    int verbose = 0;
03390    const char *id;
03391    char idtext[256] = "";
03392 
03393    if (s) { /* Manager - get ActionID */
03394       id = astman_get_header(m, "ActionID");
03395       if (!ast_strlen_zero(id))
03396          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03397    }
03398 
03399    switch (argc) {
03400    case 4:
03401       verbose = 1;
03402       break;
03403    case 3:
03404       verbose = 0;
03405       break;
03406    default:
03407       return CLI_SHOWUSAGE;
03408    }
03409 
03410    if (!s) {
03411       ast_cli(fd, "Name                 Device Name          Instance Label               \n");
03412       ast_cli(fd, "-------------------- -------------------- -------- --------------------\n");
03413    }
03414    AST_LIST_LOCK(&lines);
03415    AST_LIST_TRAVERSE(&lines, l, all) {
03416       total_lines++;
03417       if (!s) {
03418          ast_cli(fd, "%-20s %-20s %8d %-20s\n",
03419             l->name,
03420             (l->device ? l->device->name : "Not connected"),
03421             l->instance,
03422             l->label);
03423          if (verbose) {
03424             AST_LIST_TRAVERSE(&l->sub, sub, list) {
03425                ast_cli(fd, "  %s> %s to %s\n",
03426                   (sub == l->activesub?"Active  ":"Inactive"),
03427                   sub->owner->name,
03428                   (ast_bridged_channel(sub->owner)?ast_bridged_channel(sub->owner)->name:"")
03429                );
03430             }
03431          }
03432       } else {
03433          astman_append(s,
03434             "Event: LineEntry\r\n%s"
03435             "Channeltype: SKINNY\r\n"
03436             "ObjectName: %s\r\n"
03437             "ChannelObjectType: line\r\n"
03438             "Device: %s\r\n"
03439             "Instance: %d\r\n"
03440             "Label: %s\r\n",
03441             idtext,
03442             l->name,
03443             (l->device?l->device->name:"None"),
03444             l->instance,
03445             l->label);
03446       }
03447    }
03448    AST_LIST_UNLOCK(&lines);
03449 
03450    if (total) {
03451       *total = total_lines;
03452    }
03453 
03454    return CLI_SUCCESS;
03455 }

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

Definition at line 6545 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, ast_verb, destroy_session(), errno, skinnysession::fd, skinnysession::lock, LOG_ERROR, LOG_NOTICE, LOG_WARNING, sessions, skinnysession::sin, skinny_session(), skinnysession::start, and skinnysession::t.

Referenced by config_load().

06546 {
06547    int as;
06548    struct sockaddr_in sin;
06549    socklen_t sinlen;
06550    struct skinnysession *s;
06551    struct protoent *p;
06552    int arg = 1;
06553 
06554    for (;;) {
06555       sinlen = sizeof(sin);
06556       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
06557       if (as < 0) {
06558          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
06559          continue;
06560       }
06561 
06562       if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) {
06563          close(as);
06564          ast_atomic_fetchadd_int(&unauth_sessions, -1);
06565          continue;
06566       }
06567 
06568       p = getprotobyname("tcp");
06569       if(p) {
06570          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
06571             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
06572          }
06573       }
06574       if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
06575          close(as);
06576          ast_atomic_fetchadd_int(&unauth_sessions, -1);
06577          continue;
06578       }
06579 
06580       memcpy(&s->sin, &sin, sizeof(sin));
06581       ast_mutex_init(&s->lock);
06582       s->fd = as;
06583 
06584       if(time(&s->start) == -1) {
06585          ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
06586          destroy_session(s);
06587          continue;
06588       }
06589 
06590       AST_LIST_LOCK(&sessions);
06591       AST_LIST_INSERT_HEAD(&sessions, s, list);
06592       AST_LIST_UNLOCK(&sessions);
06593 
06594       if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
06595          destroy_session(s);
06596       }
06597    }
06598    if (skinnydebug)
06599       ast_verb(1, "killing accept thread\n");
06600    close(as);
06601    return 0;
06602 }

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

implement the setvar config line

Definition at line 1637 of file chan_skinny.c.

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

Referenced by config_parse_variables().

01638 {
01639    struct ast_variable *tmpvar = NULL;
01640    char *varname = ast_strdupa(buf), *varval = NULL;
01641 
01642    if ((varval = strchr(varname,'='))) {
01643       *varval++ = '\0';
01644       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
01645          tmpvar->next = list;
01646          list = tmpvar;
01647       }
01648    }
01649    return list;
01650 }

static AST_LIST_HEAD_STATIC ( sessions  ,
skinnysession   
) [static]
static AST_LIST_HEAD_STATIC ( devices  ,
skinny_device   
) [static]
static AST_LIST_HEAD_STATIC ( lines  ,
skinny_line   
) [static]
AST_MODULE_INFO ( ASTERISK_GPL_KEY  ,
AST_MODFLAG_LOAD_ORDER  ,
"Skinny Client Control Protocol (Skinny)"  ,
load = load_module,
unload = unload_module,
reload = reload,
load_pri = AST_MODPRI_CHANNEL_DRIVER 
)
AST_MUTEX_DEFINE_STATIC ( netlock   ) 
AST_MUTEX_DEFINE_STATIC ( monlock   ) 
AST_THREADSTORAGE ( control2str_threadbuf   ) 
AST_THREADSTORAGE ( device2str_threadbuf   ) 
static void cleanup_stale_contexts ( char *  new,
char *  old 
) [static]

Definition at line 1798 of file chan_skinny.c.

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

Referenced by config_parse_variables().

01799 {
01800    char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];
01801 
01802    while ((oldcontext = strsep(&old, "&"))) {
01803       stalecontext = '\0';
01804       ast_copy_string(newlist, new, sizeof(newlist));
01805       stringp = newlist;
01806       while ((newcontext = strsep(&stringp, "&"))) {
01807          if (strcmp(newcontext, oldcontext) == 0) {
01808             /* This is not the context you're looking for */
01809             stalecontext = '\0';
01810             break;
01811          } else if (strcmp(newcontext, oldcontext)) {
01812             stalecontext = oldcontext;
01813          }
01814          
01815       }
01816       if (stalecontext)
01817          ast_context_destroy(ast_context_find(stalecontext), "Skinny");
01818    }
01819 }

static int codec_ast2skinny ( format_t  astcodec  )  [static]

Definition at line 1741 of file chan_skinny.c.

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

Referenced by transmit_connect(), and transmit_startmediatransmission().

01742 {
01743    switch (astcodec) {
01744    case AST_FORMAT_ALAW:
01745       return SKINNY_CODEC_ALAW;
01746    case AST_FORMAT_ULAW:
01747       return SKINNY_CODEC_ULAW;
01748    case AST_FORMAT_G723_1:
01749       return SKINNY_CODEC_G723_1;
01750    case AST_FORMAT_G729A:
01751       return SKINNY_CODEC_G729A;
01752    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01753       return SKINNY_CODEC_G726_32;
01754    case AST_FORMAT_H261:
01755       return SKINNY_CODEC_H261;
01756    case AST_FORMAT_H263:
01757       return SKINNY_CODEC_H263;
01758    default:
01759       return 0;
01760    }
01761 }

static format_t codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

Definition at line 1719 of file chan_skinny.c.

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

Referenced by handle_capabilities_res_message().

01720 {
01721    switch (skinnycodec) {
01722    case SKINNY_CODEC_ALAW:
01723       return AST_FORMAT_ALAW;
01724    case SKINNY_CODEC_ULAW:
01725       return AST_FORMAT_ULAW;
01726    case SKINNY_CODEC_G723_1:
01727       return AST_FORMAT_G723_1;
01728    case SKINNY_CODEC_G729A:
01729       return AST_FORMAT_G729A;
01730    case SKINNY_CODEC_G726_32:
01731       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01732    case SKINNY_CODEC_H261:
01733       return AST_FORMAT_H261;
01734    case SKINNY_CODEC_H263:
01735       return AST_FORMAT_H263;
01736    default:
01737       return 0;
01738    }
01739 }

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

Definition at line 2944 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and devices.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

02945 {
02946    struct skinny_device *d;
02947    char *result = NULL;
02948    int wordlen = strlen(word), which = 0;
02949 
02950    AST_LIST_TRAVERSE(&devices, d, list) {
02951       if (!strncasecmp(word, d->id, wordlen) && ++which > state)
02952          result = ast_strdup(d->id);
02953    }
02954 
02955    return result;
02956 }

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

Definition at line 2963 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

02964 {
02965    return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02966 }

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

Definition at line 2958 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02959 {
02960    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02961 }

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

Definition at line 2968 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and devices.

Referenced by handle_skinny_show_line().

02969 {
02970    struct skinny_device *d;
02971    struct skinny_line *l;
02972    char *result = NULL;
02973    int wordlen = strlen(word), which = 0;
02974 
02975    if (pos != 3)
02976       return NULL;
02977    
02978    AST_LIST_TRAVERSE(&devices, d, list) {
02979       AST_LIST_TRAVERSE(&d->lines, l, list) {
02980          if (!strncasecmp(word, l->name, wordlen) && ++which > state)
02981             result = ast_strdup(l->name);
02982       }
02983    }
02984 
02985    return result;
02986 }

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

Definition at line 7163 of file chan_skinny.c.

References skinny_device::addr, ast_calloc, ast_copy_string(), 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, config_parse_variables(), default_device, DEFAULT_SKINNY_PORT, skinnysession::device, devices, skinny_line::lock, skinny_device::lock, LOG_ERROR, LOG_NOTICE, skinny_device::session, TYPE_DEVICE, and update().

Referenced by config_load().

07164  {
07165    struct skinny_device *d, *temp;
07166    struct skinny_line *l, *ltemp;
07167    struct skinny_subchannel *sub;
07168    int update = 0;
07169  
07170    ast_log(LOG_NOTICE, "Configuring skinny device %s.\n", dname);
07171 
07172    AST_LIST_LOCK(&devices);
07173    AST_LIST_TRAVERSE(&devices, temp, list) {
07174       if (!strcasecmp(dname, temp->name) && temp->prune) {
07175          update = 1;
07176          break;
07177       }
07178    }
07179 
07180    if (!(d = ast_calloc(1, sizeof(*d)))) {
07181       ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
07182       AST_LIST_UNLOCK(&devices);
07183       return NULL;
07184    }
07185    memcpy(d, default_device, sizeof(*default_device));
07186    ast_mutex_init(&d->lock);
07187    ast_copy_string(d->name, dname, sizeof(d->name));
07188    AST_LIST_INSERT_TAIL(&devices, d, list);
07189 
07190    ast_mutex_lock(&d->lock);
07191    AST_LIST_UNLOCK(&devices);
07192  
07193    config_parse_variables(TYPE_DEVICE, d, v);
07194  
07195    if (!AST_LIST_FIRST(&d->lines)) {
07196       ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
07197       ast_mutex_unlock(&d->lock);
07198       return NULL;
07199    }
07200    if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
07201       d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
07202    }
07203  
07204    if (skinnyreload){
07205       AST_LIST_LOCK(&devices);
07206       AST_LIST_TRAVERSE(&devices, temp, list) {
07207          if (strcasecmp(d->id, temp->id) || !temp->prune || !temp->session) {
07208             continue;
07209          }
07210          ast_mutex_lock(&d->lock);
07211          d->session = temp->session;
07212          d->session->device = d;
07213 
07214          AST_LIST_LOCK(&d->lines);
07215          AST_LIST_TRAVERSE(&d->lines, l, list){
07216             l->device = d; 
07217 
07218             AST_LIST_LOCK(&temp->lines);
07219             AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
07220                if (strcasecmp(l->name, ltemp->name)) {
07221                   continue;
07222                }
07223                ast_mutex_lock(&ltemp->lock);
07224                l->instance = ltemp->instance;
07225                l->hookstate = ltemp->hookstate;
07226                if (!AST_LIST_EMPTY(&ltemp->sub)) {
07227                   ast_mutex_lock(&l->lock);
07228                   l->sub = ltemp->sub;
07229                   AST_LIST_TRAVERSE(&l->sub, sub, list) {
07230                      sub->parent = l;
07231                   }
07232                   ast_mutex_unlock(&l->lock);
07233                }
07234                ast_mutex_unlock(&ltemp->lock);
07235             }
07236             AST_LIST_UNLOCK(&temp->lines);
07237          }
07238          AST_LIST_UNLOCK(&d->lines);
07239          ast_mutex_unlock(&d->lock);
07240       }
07241       AST_LIST_UNLOCK(&devices);
07242    }
07243 
07244    ast_mutex_unlock(&d->lock);
07245 
07246    ast_verb(3, "%s config for device '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), d->name);
07247    
07248    return d;
07249 
07250  }

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

Definition at line 7105 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_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_strlen_zero(), ast_verb, config_parse_variables(), default_line, skinny_line::lock, LOG_NOTICE, mwi_event_cb(), skinny_line::mwi_event_sub, TYPE_LINE, and update().

Referenced by config_load().

07106  {
07107    struct skinny_line *l, *temp;
07108    int update = 0;
07109  
07110    ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);
07111 
07112    /* We find the old line and remove it just before the new
07113       line is created */
07114    AST_LIST_LOCK(&lines);
07115    AST_LIST_TRAVERSE(&lines, temp, all) {
07116       if (!strcasecmp(lname, temp->name) && temp->prune) {
07117          update = 1;
07118          break;
07119       }
07120    }
07121 
07122    if (!(l=ast_calloc(1, sizeof(*l)))) {
07123       ast_verb(1, "Unable to allocate memory for line %s.\n", lname);
07124       AST_LIST_UNLOCK(&lines);
07125       return NULL;
07126    }
07127 
07128    memcpy(l, default_line, sizeof(*default_line));
07129    ast_mutex_init(&l->lock);
07130    ast_copy_string(l->name, lname, sizeof(l->name));
07131    AST_LIST_INSERT_TAIL(&lines, l, all);
07132 
07133    ast_mutex_lock(&l->lock);
07134    AST_LIST_UNLOCK(&lines);
07135 
07136    config_parse_variables(TYPE_LINE, l, v);
07137          
07138    if (!ast_strlen_zero(l->mailbox)) {
07139       char *cfg_mailbox, *cfg_context;
07140       cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
07141       ast_verb(3, "Setting mailbox '%s' on line %s\n", cfg_mailbox, l->name);
07142       strsep(&cfg_context, "@");
07143       if (ast_strlen_zero(cfg_context))
07144           cfg_context = "default";
07145       l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "skinny MWI subsciption", l,
07146          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
07147          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
07148          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
07149          AST_EVENT_IE_END);
07150    }
07151  
07152    ast_mutex_unlock(&l->lock);
07153    
07154    /* We do not want to unlink or free the line yet, it needs
07155       to be available to detect a device reconfig when we load the
07156       devices.  Old lines will be pruned after the reload completes */
07157 
07158    ast_verb(3, "%s config for line '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), l->name);
07159 
07160    return l;
07161  }

static int config_load ( void   )  [static]

Definition at line 7252 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_netsock_set_qos(), ast_pthread_create_background, 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, qos, TYPE_DEF_DEVICE, TYPE_DEF_LINE, and TYPE_GENERAL.

Referenced by load_module(), and skinny_reload().

07253  {
07254    int on = 1;
07255    struct ast_config *cfg;
07256    char *cat;
07257    int oldport = ntohs(bindaddr.sin_port);
07258    struct ast_flags config_flags = { 0 };
07259    
07260    ast_log(LOG_NOTICE, "Configuring skinny from %s\n", config);
07261   
07262    if (gethostname(ourhost, sizeof(ourhost))) {
07263       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled.\n");
07264       return 0;
07265    }
07266    cfg = ast_config_load(config, config_flags);
07267   
07268    /* We *must* have a config file otherwise stop immediately */
07269    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
07270       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled.\n", config);
07271       return -1;
07272    }
07273    memset(&bindaddr, 0, sizeof(bindaddr));
07274    memset(&default_prefs, 0, sizeof(default_prefs));
07275 
07276    /* Copy the default jb config over global_jbconf */
07277    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
07278 
07279    /* load the general section */
07280    cat = ast_category_browse(cfg, "general");
07281    config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));
07282 
07283    if (ntohl(bindaddr.sin_addr.s_addr)) {
07284       __ourip = bindaddr.sin_addr;
07285    } else {
07286       hp = ast_gethostbyname(ourhost, &ahp);
07287       if (!hp) {
07288          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
07289          ast_config_destroy(cfg);
07290          return 0;
07291       }
07292       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
07293    }
07294    if (!ntohs(bindaddr.sin_port)) {
07295       bindaddr.sin_port = htons(DEFAULT_SKINNY_PORT);
07296    }
07297    bindaddr.sin_family = AF_INET;
07298 
07299    /* load the lines sections */
07300    default_line->confcapability = default_capability;
07301    default_line->confprefs = default_prefs;
07302    config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
07303    cat = ast_category_browse(cfg, "lines");
07304    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
07305       config_line(cat, ast_variable_browse(cfg, cat));
07306       cat = ast_category_browse(cfg, cat);
07307    }
07308       
07309    /* load the devices sections */
07310    default_device->confcapability = default_capability;
07311    default_device->confprefs = default_prefs;
07312    config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
07313    cat = ast_category_browse(cfg, "devices");
07314    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
07315       config_device(cat, ast_variable_browse(cfg, cat));
07316       cat = ast_category_browse(cfg, cat);
07317    }
07318 
07319    ast_mutex_lock(&netlock);
07320    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
07321       close(skinnysock);
07322       skinnysock = -1;
07323    }
07324    if (skinnysock < 0) {
07325       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
07326       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
07327          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
07328          ast_config_destroy(cfg);
07329          ast_mutex_unlock(&netlock);
07330          return 0;
07331       }
07332       if (skinnysock < 0) {
07333          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
07334       } else {
07335          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
07336             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
07337                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07338                      strerror(errno));
07339             close(skinnysock);
07340             skinnysock = -1;
07341             ast_config_destroy(cfg);
07342             ast_mutex_unlock(&netlock);
07343             return 0;
07344          }
07345          if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
07346                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
07347                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07348                      strerror(errno));
07349                close(skinnysock);
07350                skinnysock = -1;
07351                ast_config_destroy(cfg);
07352                ast_mutex_unlock(&netlock);
07353                return 0;
07354          }
07355          ast_verb(2, "Skinny listening on %s:%d\n",
07356                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
07357          ast_netsock_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
07358          ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
07359       }
07360    }
07361    ast_mutex_unlock(&netlock);
07362    ast_config_destroy(cfg);
07363    return 1;
07364 }

static void config_parse_variables ( int  type,
void *  item,
struct ast_variable vptr 
) [static]

Definition at line 6711 of file chan_skinny.c.

References add_var(), ahp, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_context_find_or_create(), ast_copy_string(), 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_strlen_zero(), ast_true(), bindaddr, CDEV, CDEV_OPTS, cleanup_stale_contexts(), CLINE, CLINE_OPTS, skinny_speeddial::context, context, DEFAULT_AUTH_LIMIT, DEFAULT_AUTH_TIMEOUT, default_prefs, devices, skinny_speeddial::exten, exten, global_jbconf, skinny_speeddial::instance, skinny_speeddial::isHint, skinny_speeddial::label, ast_variable::lineno, skinny_addon::lock, skinny_speeddial::lock, LOG_WARNING, ast_variable::name, ast_variable::next, qos, S_OR, ast_sockaddr::ss, 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().

06712  {
06713    struct ast_variable *v;
06714    int lineInstance = 1;
06715    int speeddialInstance = 1;
06716    
06717    while(vptr) {
06718       v = vptr;
06719       vptr = vptr->next;
06720  
06721       if (type & (TYPE_GENERAL)) {
06722          char newcontexts[AST_MAX_CONTEXT];
06723          char oldcontexts[AST_MAX_CONTEXT];
06724          char *stringp, *context, *oldregcontext;
06725          if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06726             v = v->next;
06727             continue;
06728          }
06729          if (!strcasecmp(v->name, "bindaddr")) {
06730             if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06731                ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06732             } else {
06733                memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
06734             }
06735             continue;
06736          } else if (!strcasecmp(v->name, "keepalive")) {
06737             keep_alive = atoi(v->value);
06738             continue;
06739          } else if (!strcasecmp(v->name, "authtimeout")) {
06740             int timeout = atoi(v->value);
06741 
06742             if (timeout < 1) {
06743                ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value);
06744                auth_timeout = DEFAULT_AUTH_TIMEOUT;
06745             } else {
06746                auth_timeout = timeout;
06747             }
06748             continue;
06749          } else if (!strcasecmp(v->name, "authlimit")) {
06750             int limit = atoi(v->value);
06751 
06752             if (limit < 1) {
06753                ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value);
06754                auth_limit = DEFAULT_AUTH_LIMIT;
06755             } else {
06756                auth_limit = limit;
06757             }
06758             continue;
06759          } else if (!strcasecmp(v->name, "regcontext")) {
06760             ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
06761             stringp = newcontexts;
06762             /* Initialize copy of current global_regcontext for later use in removing stale contexts */
06763             ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
06764             oldregcontext = oldcontexts;
06765             /* Let's remove any contexts that are no longer defined in regcontext */
06766             cleanup_stale_contexts(stringp, oldregcontext);
06767             /* Create contexts if they don't exist already */
06768             while ((context = strsep(&stringp, "&"))) {
06769                ast_copy_string(used_context, context, sizeof(used_context));
06770                ast_context_find_or_create(NULL, NULL, context, "Skinny");
06771             }
06772             ast_copy_string(regcontext, v->value, sizeof(regcontext));
06773             continue;
06774          } else if (!strcasecmp(v->name, "dateformat")) {
06775             memcpy(date_format, v->value, sizeof(date_format));
06776             continue;
06777          } else if (!strcasecmp(v->name, "tos")) {
06778             if (ast_str2tos(v->value, &qos.tos))
06779                ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06780             continue;
06781          } else if (!strcasecmp(v->name, "tos_audio")) {
06782             if (ast_str2tos(v->value, &qos.tos_audio))
06783                ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06784             continue;
06785          } else if (!strcasecmp(v->name, "tos_video")) {
06786             if (ast_str2tos(v->value, &qos.tos_video))
06787                ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
06788             continue;
06789          } else if (!strcasecmp(v->name, "cos")) {
06790             if (ast_str2cos(v->value, &qos.cos))
06791                ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06792             continue;
06793          } else if (!strcasecmp(v->name, "cos_audio")) {
06794             if (ast_str2cos(v->value, &qos.cos_audio))
06795                ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06796             continue;
06797          } else if (!strcasecmp(v->name, "cos_video")) {
06798             if (ast_str2cos(v->value, &qos.cos_video))
06799                ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
06800             continue;
06801          } else if (!strcasecmp(v->name, "bindport")) {
06802             if (sscanf(v->value, "%5d", &ourport) == 1) {
06803                bindaddr.sin_port = htons(ourport);
06804             } else {
06805                ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
06806             }
06807             continue;
06808          } else if (!strcasecmp(v->name, "allow")) {
06809             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
06810             continue;
06811          } else if (!strcasecmp(v->name, "disallow")) {
06812             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
06813             continue;
06814          } 
06815       }
06816  
06817       if (!strcasecmp(v->name, "transfer")) {
06818          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06819             CDEV_OPTS->transfer = ast_true(v->value);
06820             continue;
06821          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06822             CLINE_OPTS->transfer = ast_true(v->value);
06823             continue;
06824          }
06825       } else if (!strcasecmp(v->name, "callwaiting")) {
06826          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06827             CDEV_OPTS->callwaiting = ast_true(v->value);
06828             continue;
06829          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06830             CLINE_OPTS->callwaiting = ast_true(v->value);
06831             continue;
06832          }
06833       } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
06834          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06835             CLINE_OPTS->directmedia = ast_true(v->value);
06836             continue;
06837          }
06838       } else if (!strcasecmp(v->name, "nat")) {
06839          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06840             CLINE_OPTS->nat = ast_true(v->value);
06841             continue;
06842          }
06843       } else if (!strcasecmp(v->name, "context")) {
06844          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06845             ast_copy_string(CLINE_OPTS->context, v->value, sizeof(CLINE_OPTS->context));
06846             continue;
06847          }
06848       }else if (!strcasecmp(v->name, "vmexten")) {
06849          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06850             ast_copy_string(CDEV_OPTS->vmexten, v->value, sizeof(CDEV_OPTS->vmexten));
06851             continue;
06852          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06853             ast_copy_string(CLINE_OPTS->vmexten, v->value, sizeof(CLINE_OPTS->vmexten));
06854             continue;
06855          }
06856       } else if (!strcasecmp(v->name, "mwiblink")) {
06857          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06858             CDEV_OPTS->mwiblink = ast_true(v->value);
06859             continue;
06860          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06861             CLINE_OPTS->mwiblink = ast_true(v->value);
06862             continue;
06863          }
06864       } else if (!strcasecmp(v->name, "linelabel")) {
06865          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06866             ast_copy_string(CLINE_OPTS->label, v->value, sizeof(CLINE_OPTS->label));
06867             continue;
06868          }
06869       } else if (!strcasecmp(v->name, "callerid")) {
06870          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06871             if (!strcasecmp(v->value, "asreceived")) {
06872                CLINE_OPTS->cid_num[0] = '\0';
06873                CLINE_OPTS->cid_name[0] = '\0';
06874             } else {
06875                ast_callerid_split(v->value, CLINE_OPTS->cid_name, sizeof(CLINE_OPTS->cid_name), CLINE_OPTS->cid_num, sizeof(CLINE_OPTS->cid_num));
06876             }
06877             continue;
06878          }
06879       } else if (!strcasecmp(v->name, "amaflags")) {
06880          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06881             int tempamaflags = ast_cdr_amaflags2int(v->value);
06882             if (tempamaflags < 0) {
06883                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
06884             } else {
06885                CLINE_OPTS->amaflags = tempamaflags;
06886             }
06887             continue;
06888          }
06889       } else if (!strcasecmp(v->name, "regexten")) {
06890          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06891             ast_copy_string(CLINE_OPTS->regexten, v->value, sizeof(CLINE_OPTS->regexten));
06892             continue;
06893          }
06894       } else if (!strcasecmp(v->name, "language")) {
06895          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06896             ast_copy_string(CLINE_OPTS->language, v->value, sizeof(CLINE_OPTS->language));
06897             continue;
06898          }
06899       } else if (!strcasecmp(v->name, "accountcode")) {
06900          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06901             ast_copy_string(CLINE_OPTS->accountcode, v->value, sizeof(CLINE_OPTS->accountcode));
06902             continue;
06903          }
06904       } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
06905          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06906             ast_copy_string(CLINE_OPTS->mohinterpret, v->value, sizeof(CLINE_OPTS->mohinterpret));
06907             continue;
06908          }
06909       } else if (!strcasecmp(v->name, "mohsuggest")) {
06910          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06911             ast_copy_string(CLINE_OPTS->mohsuggest, v->value, sizeof(CLINE_OPTS->mohsuggest));
06912             continue;
06913          }
06914       } else if (!strcasecmp(v->name, "callgroup")) {
06915          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06916             CLINE_OPTS->callgroup = ast_get_group(v->value);
06917             continue;
06918          }
06919       } else if (!strcasecmp(v->name, "pickupgroup")) {
06920          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06921             CLINE_OPTS->pickupgroup = ast_get_group(v->value);
06922             continue;
06923          }
06924       } else if (!strcasecmp(v->name, "immediate")) {
06925          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE | TYPE_DEF_LINE | TYPE_LINE)) {
06926             CLINE_OPTS->immediate = ast_true(v->value);
06927             continue;
06928          }
06929       } else if (!strcasecmp(v->name, "cancallforward")) {
06930          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06931             CLINE_OPTS->cancallforward = ast_true(v->value);
06932             continue;
06933          }
06934       } else if (!strcasecmp(v->name, "mailbox")) {
06935          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06936             ast_copy_string(CLINE_OPTS->mailbox, v->value, sizeof(CLINE_OPTS->mailbox));
06937             continue;
06938          }
06939       } else if ( !strcasecmp(v->name, "parkinglot")) {
06940          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06941             ast_copy_string(CLINE_OPTS->parkinglot, v->value, sizeof(CLINE_OPTS->parkinglot));
06942             continue;
06943          }
06944       } else if (!strcasecmp(v->name, "hasvoicemail")) {
06945          if (type & (TYPE_LINE)) {
06946             if (ast_true(v->value) && ast_strlen_zero(CLINE->mailbox)) {
06947                ast_copy_string(CLINE->mailbox, CLINE->name, sizeof(CLINE->mailbox));
06948             }
06949             continue;
06950          }
06951       } else if (!strcasecmp(v->name, "callreturn")) {
06952          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06953             CLINE_OPTS->callreturn = ast_true(v->value);
06954             continue;
06955          }
06956       } else if (!strcasecmp(v->name, "threewaycalling")) {
06957          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06958             CLINE_OPTS->threewaycalling = ast_true(v->value);
06959             continue;
06960          }
06961       } else if (!strcasecmp(v->name, "setvar")) {
06962          if (type & (TYPE_LINE)) {
06963             CLINE->chanvars = add_var(v->value, CLINE->chanvars);
06964             continue;
06965          }
06966       } else if (!strcasecmp(v->name, "earlyrtp")) {
06967          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06968             CDEV_OPTS->earlyrtp = ast_true(v->value);
06969             continue;
06970          }
06971       } else if (!strcasecmp(v->name, "host")) {
06972          if (type & (TYPE_DEVICE)) {
06973             struct ast_sockaddr CDEV_addr_tmp;
06974 
06975             CDEV_addr_tmp.ss.ss_family = AF_INET;
06976             if (ast_get_ip(&CDEV_addr_tmp, v->value)) {
06977                ast_log(LOG_WARNING, "Bad IP '%s' at line %d.\n", v->value, v->lineno);
06978             }
06979             ast_sockaddr_to_sin(&CDEV_addr_tmp,
06980                       &CDEV->addr);
06981             continue;
06982          }
06983       } else if (!strcasecmp(v->name, "port")) {
06984          if (type & (TYPE_DEF_DEVICE)) {
06985             CDEV->addr.sin_port = htons(atoi(v->value));
06986             continue;
06987          }
06988       } else if (!strcasecmp(v->name, "device")) {
06989          if (type & (TYPE_DEVICE)) {
06990             ast_copy_string(CDEV_OPTS->id, v->value, sizeof(CDEV_OPTS->id));
06991             continue;
06992          }
06993       } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06994          if (type & (TYPE_DEVICE)) {
06995             CDEV->ha = ast_append_ha(v->name, v->value, CDEV->ha, NULL);
06996             continue;
06997          }
06998       } else if (!strcasecmp(v->name, "allow")) {
06999          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
07000             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 1);
07001             continue;
07002          }
07003          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
07004             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 1);
07005             continue;
07006          }
07007       } else if (!strcasecmp(v->name, "disallow")) {
07008          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
07009             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 0);
07010             continue;
07011          }
07012          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
07013             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 0);
07014             continue;
07015          }
07016       } else if (!strcasecmp(v->name, "version")) {
07017          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
07018             ast_copy_string(CDEV_OPTS->version_id, v->value, sizeof(CDEV_OPTS->version_id));
07019             continue;
07020          }
07021       } else if (!strcasecmp(v->name, "line")) {
07022          if (type & (TYPE_DEVICE)) {
07023             struct skinny_line *l;
07024             AST_LIST_TRAVERSE(&lines, l, all) {
07025                if (!strcasecmp(v->value, l->name) && !l->prune) {
07026 
07027                   /* FIXME: temp solution about line conflicts */
07028                   struct skinny_device *d;
07029                   struct skinny_line *l2;
07030                   int lineinuse = 0;
07031                   AST_LIST_TRAVERSE(&devices, d, list) {
07032                      AST_LIST_TRAVERSE(&d->lines, l2, list) {
07033                         if (l2 == l && strcasecmp(d->id, CDEV->id)) {
07034                            ast_log(LOG_WARNING, "Line %s already used by %s. Not connecting to %s.\n", l->name, d->name, CDEV->name);
07035                            lineinuse++;
07036                         }
07037                      }
07038                   }
07039                   if (!lineinuse) {
07040                      if (!AST_LIST_FIRST(&CDEV->lines)) {
07041                         CDEV->activeline = l;
07042                      }
07043                      lineInstance++;
07044                      AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
07045                   }
07046                   break;
07047                }
07048             }
07049             continue;
07050          }
07051       } else if (!strcasecmp(v->name, "speeddial")) {
07052          if (type & (TYPE_DEVICE)) {
07053             struct skinny_speeddial *sd;
07054             if (!(sd = ast_calloc(1, sizeof(*sd)))) {
07055                ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name);
07056                continue;
07057             } else {
07058                char buf[256];
07059                char *stringp = buf, *exten, *context, *label;
07060                   ast_copy_string(buf, v->value, sizeof(buf));
07061                exten = strsep(&stringp, ",");
07062                if ((context = strchr(exten, '@'))) {
07063                   *context++ = '\0';
07064                }
07065                label = stringp;
07066                ast_mutex_init(&sd->lock);
07067                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
07068                if (!ast_strlen_zero(context)) {
07069                   sd->isHint = 1;
07070                   sd->instance = lineInstance++;
07071                   ast_copy_string(sd->context, context, sizeof(sd->context));
07072                } else {
07073                   sd->isHint = 0;
07074                   sd->instance = speeddialInstance++;
07075                   sd->context[0] = '\0';
07076                }
07077                ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
07078                sd->parent = CDEV;
07079                AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
07080             }
07081             continue;
07082          }
07083       } else if (!strcasecmp(v->name, "addon")) {
07084          if (type & (TYPE_DEVICE)) {
07085             struct skinny_addon *a;
07086             if (!(a = ast_calloc(1, sizeof(*a)))) {
07087                ast_log(LOG_WARNING, "Unable to allocate memory for addon %s. Ignoring addon.\n", v->name);
07088                continue;
07089             } else {
07090                ast_mutex_init(&a->lock);
07091                ast_copy_string(a->type, v->value, sizeof(a->type));
07092                AST_LIST_INSERT_HEAD(&CDEV->addons, a, list);
07093             }
07094             continue;
07095          }
07096 
07097       } else {
07098          ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
07099          continue;
07100       }
07101       ast_log(LOG_WARNING, "Invalid category used: %s at line %d\n", v->name, v->lineno);
07102    }
07103  }

static char* control2str ( int  ind  )  [static]

Definition at line 4263 of file chan_skinny.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, 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_SRCUPDATE, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, AST_CONTROL_WINK, ast_threadstorage_get(), and CONTROL2STR_BUFSIZE.

Referenced by skinny_indicate().

04263                                   {
04264    char *tmp;
04265 
04266    switch (ind) {
04267    case AST_CONTROL_HANGUP:
04268       return "Other end has hungup";
04269    case AST_CONTROL_RING:
04270       return "Local ring";
04271    case AST_CONTROL_RINGING:
04272       return "Remote end is ringing";
04273    case AST_CONTROL_ANSWER:
04274       return "Remote end has answered";
04275    case AST_CONTROL_BUSY:
04276       return "Remote end is busy";
04277    case AST_CONTROL_TAKEOFFHOOK:
04278       return "Make it go off hook";
04279    case AST_CONTROL_OFFHOOK:
04280       return "Line is off hook";
04281    case AST_CONTROL_CONGESTION:
04282       return "Congestion (circuits busy)";
04283    case AST_CONTROL_FLASH:
04284       return "Flash hook";
04285    case AST_CONTROL_WINK:
04286       return "Wink";
04287    case AST_CONTROL_OPTION:
04288       return "Set a low-level option";
04289    case AST_CONTROL_RADIO_KEY:
04290       return "Key Radio";
04291    case AST_CONTROL_RADIO_UNKEY:
04292       return "Un-Key Radio";
04293    case AST_CONTROL_PROGRESS:
04294       return "Remote end is making Progress";
04295    case AST_CONTROL_PROCEEDING:
04296       return "Remote end is proceeding";
04297    case AST_CONTROL_HOLD:
04298       return "Hold";
04299    case AST_CONTROL_UNHOLD:
04300       return "Unhold";
04301    case AST_CONTROL_SRCUPDATE:
04302       return "Media Source Update";
04303    case AST_CONTROL_CONNECTED_LINE:
04304       return "Connected Line";
04305    case AST_CONTROL_REDIRECTING:
04306       return "Redirecting";
04307    case AST_CONTROL_INCOMPLETE:
04308       return "Incomplete";
04309    case -1:
04310       return "Stop tone";
04311    default:
04312       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
04313                         return "Unknown";
04314       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
04315       return tmp;
04316    }
04317 }

static void delete_devices ( void   )  [static]

Definition at line 7366 of file chan_skinny.c.

References AST_LIST_LOCK, AST_LIST_REMOVE, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, devices, and free.

Referenced by unload_module().

07367 {
07368    struct skinny_device *d;
07369    struct skinny_line *l;
07370    struct skinny_speeddial *sd;
07371    struct skinny_addon *a;
07372 
07373    AST_LIST_LOCK(&devices);
07374    AST_LIST_LOCK(&lines);
07375 
07376    /* Delete all devices */
07377    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
07378       /* Delete all lines for this device */
07379       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07380          AST_LIST_REMOVE(&lines, l, all);
07381          free(l);
07382       }
07383       /* Delete all speeddials for this device */
07384       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07385          free(sd);
07386       }
07387       /* Delete all addons for this device */
07388       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07389          free(a);
07390       } 
07391       free(d);
07392    }
07393    AST_LIST_UNLOCK(&lines);
07394    AST_LIST_UNLOCK(&devices);
07395 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 6362 of file chan_skinny.c.

References ast_atomic_fetchadd_int(), ast_free, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), ast_mutex_destroy, skinnysession::device, skinnysession::fd, skinnysession::lock, LOG_WARNING, and sessions.

Referenced by accept_thread(), and skinny_session().

06363 {
06364    struct skinnysession *cur;
06365    AST_LIST_LOCK(&sessions);
06366    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
06367       if (cur == s) {
06368          AST_LIST_REMOVE_CURRENT(list);
06369          if (s->fd > -1) 
06370             close(s->fd);
06371          
06372          if (!s->device)
06373             ast_atomic_fetchadd_int(&unauth_sessions, -1);
06374 
06375          ast_mutex_destroy(&s->lock);
06376          
06377          ast_free(s);
06378       } else {
06379          ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
06380       }
06381    }
06382    AST_LIST_TRAVERSE_SAFE_END
06383    AST_LIST_UNLOCK(&sessions);
06384 }

static char* device2str ( int  type  )  [static]

Definition at line 3033 of file chan_skinny.c.

References ast_threadstorage_get(), DEVICE2STR_BUFSIZE, 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().

03034 {
03035    char *tmp;
03036 
03037    switch (type) {
03038    case SKINNY_DEVICE_NONE:
03039       return "No Device";
03040    case SKINNY_DEVICE_30SPPLUS:
03041       return "30SP Plus";
03042    case SKINNY_DEVICE_12SPPLUS:
03043       return "12SP Plus";
03044    case SKINNY_DEVICE_12SP:
03045       return "12SP";
03046    case SKINNY_DEVICE_12:
03047       return "12";
03048    case SKINNY_DEVICE_30VIP:
03049       return "30VIP";
03050    case SKINNY_DEVICE_7910:
03051       return "7910";
03052    case SKINNY_DEVICE_7960:
03053       return "7960";
03054    case SKINNY_DEVICE_7940:
03055       return "7940";
03056    case SKINNY_DEVICE_7935:
03057       return "7935";
03058    case SKINNY_DEVICE_ATA186:
03059       return "ATA186";
03060    case SKINNY_DEVICE_7941:
03061       return "7941";
03062    case SKINNY_DEVICE_7971:
03063       return "7971";
03064    case SKINNY_DEVICE_7914:
03065       return "7914";
03066    case SKINNY_DEVICE_7985:
03067       return "7985";
03068    case SKINNY_DEVICE_7911:
03069       return "7911";
03070    case SKINNY_DEVICE_7961GE:
03071       return "7961GE";
03072    case SKINNY_DEVICE_7941GE:
03073       return "7941GE";
03074    case SKINNY_DEVICE_7931:
03075       return "7931";
03076    case SKINNY_DEVICE_7921:
03077       return "7921";
03078    case SKINNY_DEVICE_7906:
03079       return "7906";
03080    case SKINNY_DEVICE_7962:
03081       return "7962";
03082    case SKINNY_DEVICE_7937:
03083       return "7937";
03084    case SKINNY_DEVICE_7942:
03085       return "7942";
03086    case SKINNY_DEVICE_7945:
03087       return "7945";
03088    case SKINNY_DEVICE_7965:
03089       return "7965";
03090    case SKINNY_DEVICE_7975:
03091       return "7975";
03092    case SKINNY_DEVICE_7905:
03093       return "7905";
03094    case SKINNY_DEVICE_7920:
03095       return "7920";
03096    case SKINNY_DEVICE_7970:
03097       return "7970";
03098    case SKINNY_DEVICE_7912:
03099       return "7912";
03100    case SKINNY_DEVICE_7902:
03101       return "7902";
03102    case SKINNY_DEVICE_CIPC:
03103       return "IP Communicator";
03104    case SKINNY_DEVICE_7961:
03105       return "7961";
03106    case SKINNY_DEVICE_7936:
03107       return "7936";
03108    case SKINNY_DEVICE_SCCPGATEWAY_AN:
03109       return "SCCPGATEWAY_AN";
03110    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
03111       return "SCCPGATEWAY_BRI";
03112    case SKINNY_DEVICE_UNKNOWN:
03113       return "Unknown";
03114    default:
03115       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
03116          return "Unknown";
03117       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
03118       return tmp;
03119    }
03120 }

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

Definition at line 6604 of file chan_skinny.c.

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

Referenced by restart_monitor().

06605 {
06606    int res;
06607 
06608    /* This thread monitors all the interfaces which are not yet in use
06609       (and thus do not have a separate thread) indefinitely */
06610    /* From here on out, we die whenever asked */
06611    for(;;) {
06612       pthread_testcancel();
06613       /* Wait for sched or io */
06614       res = ast_sched_wait(sched);
06615       if ((res < 0) || (res > 1000)) {
06616          res = 1000;
06617       }
06618       res = ast_io_wait(io, res);
06619       ast_mutex_lock(&monlock);
06620       if (res >= 0) {
06621          ast_sched_runq(sched);
06622       }
06623       ast_mutex_unlock(&monlock);
06624    }
06625    /* Never reached */
06626    return NULL;
06627 
06628 }

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

Definition at line 1565 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_log(), and LOG_WARNING.

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

01566 {
01567    struct skinny_line *l;
01568 
01569    /*Dialing from on hook or on a 7920 uses instance 0 in requests
01570      but we need to start looking at instance 1 */
01571 
01572    if (!instance)
01573       instance = 1;
01574 
01575    AST_LIST_TRAVERSE(&d->lines, l, list){
01576       if (l->instance == instance)
01577          break;
01578    }
01579 
01580    if (!l) {
01581       ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
01582    }
01583    return l;
01584 }

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

Definition at line 1586 of file chan_skinny.c.

References ast_copy_string(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_strlen_zero(), ast_verb, and devices.

Referenced by skinny_devicestate(), and skinny_request().

01587 {
01588    struct skinny_line *l;
01589    struct skinny_line *tmpl = NULL;
01590    struct skinny_device *d;
01591    char line[256];
01592    char *at;
01593    char *device;
01594    int checkdevice = 0;
01595 
01596    ast_copy_string(line, dest, sizeof(line));
01597    at = strchr(line, '@');
01598    if (at)
01599       *at++ = '\0';
01600    device = at;
01601 
01602    if (!ast_strlen_zero(device))
01603       checkdevice = 1;
01604 
01605    AST_LIST_LOCK(&devices);
01606    AST_LIST_TRAVERSE(&devices, d, list){
01607       if (checkdevice && tmpl)
01608          break;
01609       else if (!checkdevice) {
01610          /* This is a match, since we're checking for line on every device. */
01611       } else if (!strcasecmp(d->name, device)) {
01612          if (skinnydebug)
01613             ast_verb(2, "Found device: %s\n", d->name);
01614       } else
01615          continue;
01616 
01617       /* Found the device (or we don't care which device) */
01618       AST_LIST_TRAVERSE(&d->lines, l, list){
01619          /* Search for the right line */
01620          if (!strcasecmp(l->name, line)) {
01621             if (tmpl) {
01622                ast_verb(2, "Ambiguous line name: %s\n", line);
01623                AST_LIST_UNLOCK(&devices);
01624                return NULL;
01625             } else
01626                tmpl = l;
01627          }
01628       }
01629    }
01630    AST_LIST_UNLOCK(&devices);
01631    return tmpl;
01632 }

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

Definition at line 1704 of file chan_skinny.c.

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

Referenced by handle_message(), and handle_stimulus_message().

01705 {
01706    struct skinny_speeddial *sd;
01707 
01708    AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01709       if (sd->isHint == isHint && sd->instance == instance)
01710          break;
01711    }
01712 
01713    if (!sd) {
01714       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01715    }
01716    return sd;
01717 }

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

Definition at line 1653 of file chan_skinny.c.

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

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

01654 {
01655    struct skinny_line *l = find_line_by_instance(d, instance);
01656    struct skinny_subchannel *sub;
01657 
01658    if (!l) {
01659       return NULL;
01660    }
01661 
01662    /* 7920 phones set call reference to 0, so use the first
01663       sub-channel on the list.
01664            This MIGHT need more love to be right */
01665    if (!reference)
01666       sub = AST_LIST_FIRST(&l->sub);
01667    else {
01668       AST_LIST_TRAVERSE(&l->sub, sub, list) {
01669          if (sub->callid == reference)
01670             break;
01671       }
01672    }
01673    if (!sub) {
01674       ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
01675    }
01676    return sub;
01677 }

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

Definition at line 1680 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_log(), skinny_subchannel::callid, and LOG_WARNING.

Referenced by handle_open_receive_channel_ack_message().

01681 {
01682    struct skinny_line *l;
01683    struct skinny_subchannel *sub = NULL;
01684 
01685    AST_LIST_TRAVERSE(&d->lines, l, list){
01686       AST_LIST_TRAVERSE(&l->sub, sub, list){
01687          if (sub->callid == reference)
01688             break;
01689       }
01690       if (sub)
01691          break;
01692    }
01693 
01694    if (!l) {
01695       ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
01696    } else {
01697       if (!sub) {
01698          ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
01699       }
01700    }
01701    return sub;
01702 }

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

Definition at line 1414 of file chan_skinny.c.

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

01415 {
01416    struct skinny_device *d = s->device;
01417    struct skinny_addon *a;
01418    int i;
01419 
01420    switch (d->type) {
01421       case SKINNY_DEVICE_30SPPLUS:
01422       case SKINNY_DEVICE_30VIP:
01423          /* 13 rows, 2 columns */
01424          for (i = 0; i < 4; i++)
01425             (btn++)->buttonDefinition = BT_CUST_LINE;
01426          (btn++)->buttonDefinition = BT_REDIAL;
01427          (btn++)->buttonDefinition = BT_VOICEMAIL;
01428          (btn++)->buttonDefinition = BT_CALLPARK;
01429          (btn++)->buttonDefinition = BT_FORWARDALL;
01430          (btn++)->buttonDefinition = BT_CONFERENCE;
01431          for (i = 0; i < 4; i++)
01432             (btn++)->buttonDefinition = BT_NONE;
01433          for (i = 0; i < 13; i++)
01434             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01435          
01436          break;
01437       case SKINNY_DEVICE_12SPPLUS:
01438       case SKINNY_DEVICE_12SP:
01439       case SKINNY_DEVICE_12:
01440          /* 6 rows, 2 columns */
01441          for (i = 0; i < 2; i++)
01442             (btn++)->buttonDefinition = BT_CUST_LINE;
01443          for (i = 0; i < 4; i++)
01444             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01445          (btn++)->buttonDefinition = BT_HOLD;
01446          (btn++)->buttonDefinition = BT_REDIAL;
01447          (btn++)->buttonDefinition = BT_TRANSFER;
01448          (btn++)->buttonDefinition = BT_FORWARDALL;
01449          (btn++)->buttonDefinition = BT_CALLPARK;
01450          (btn++)->buttonDefinition = BT_VOICEMAIL;
01451          break;
01452       case SKINNY_DEVICE_7910:
01453          (btn++)->buttonDefinition = BT_LINE;
01454          (btn++)->buttonDefinition = BT_HOLD;
01455          (btn++)->buttonDefinition = BT_TRANSFER;
01456          (btn++)->buttonDefinition = BT_DISPLAY;
01457          (btn++)->buttonDefinition = BT_VOICEMAIL;
01458          (btn++)->buttonDefinition = BT_CONFERENCE;
01459          (btn++)->buttonDefinition = BT_FORWARDALL;
01460          for (i = 0; i < 2; i++)
01461             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01462          (btn++)->buttonDefinition = BT_REDIAL;
01463          break;
01464       case SKINNY_DEVICE_7960:
01465       case SKINNY_DEVICE_7961:
01466       case SKINNY_DEVICE_7961GE:
01467       case SKINNY_DEVICE_7962:
01468       case SKINNY_DEVICE_7965:
01469          for (i = 0; i < 6; i++)
01470             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01471          break;
01472       case SKINNY_DEVICE_7940:
01473       case SKINNY_DEVICE_7941:
01474       case SKINNY_DEVICE_7941GE:
01475       case SKINNY_DEVICE_7942:
01476       case SKINNY_DEVICE_7945:
01477          for (i = 0; i < 2; i++)
01478             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01479          break;
01480       case SKINNY_DEVICE_7935:
01481       case SKINNY_DEVICE_7936:
01482          for (i = 0; i < 2; i++)
01483             (btn++)->buttonDefinition = BT_LINE;
01484          break;
01485       case SKINNY_DEVICE_ATA186:
01486          (btn++)->buttonDefinition = BT_LINE;
01487          break;
01488       case SKINNY_DEVICE_7970:
01489       case SKINNY_DEVICE_7971:
01490       case SKINNY_DEVICE_7975:
01491       case SKINNY_DEVICE_CIPC:
01492          for (i = 0; i < 8; i++)
01493             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01494          break;
01495       case SKINNY_DEVICE_7985:
01496          /* XXX I have no idea what the buttons look like on these. */
01497          ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
01498          break;
01499       case SKINNY_DEVICE_7912:
01500       case SKINNY_DEVICE_7911:
01501       case SKINNY_DEVICE_7905:
01502          (btn++)->buttonDefinition = BT_LINE;
01503          (btn++)->buttonDefinition = BT_HOLD;
01504          break;
01505       case SKINNY_DEVICE_7920:
01506          /* XXX I don't know if this is right. */
01507          for (i = 0; i < 4; i++)
01508             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01509          break;
01510       case SKINNY_DEVICE_7921:
01511          for (i = 0; i < 6; i++)
01512             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01513          break;
01514       case SKINNY_DEVICE_7902:
01515          ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
01516          break;
01517       case SKINNY_DEVICE_7906:
01518          ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
01519          break;
01520       case SKINNY_DEVICE_7931:
01521          ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
01522          break;
01523       case SKINNY_DEVICE_7937:
01524          ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
01525          break;
01526       case SKINNY_DEVICE_7914:
01527          ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n", d->type);
01528          break;
01529       case SKINNY_DEVICE_SCCPGATEWAY_AN:
01530       case SKINNY_DEVICE_SCCPGATEWAY_BRI:
01531          ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
01532          break;
01533       default:
01534          ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
01535          break;
01536    }
01537 
01538    AST_LIST_LOCK(&d->addons);
01539    AST_LIST_TRAVERSE(&d->addons, a, list) {
01540       if (!strcasecmp(a->type, "7914")) {
01541          for (i = 0; i < 14; i++)
01542             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01543       } else {
01544          ast_log(LOG_WARNING, "Unknown addon type '%s' found.  Skipping.\n", a->type);
01545       }
01546    }
01547    AST_LIST_UNLOCK(&d->addons);
01548 
01549    return btn;
01550 }

static int get_devicestate ( struct skinny_line l  )  [static]

Definition at line 4234 of file chan_skinny.c.

References AST_DEVICE_BUSY, AST_DEVICE_INUSE, AST_DEVICE_INVALID, AST_DEVICE_NOT_INUSE, AST_DEVICE_ONHOLD, AST_DEVICE_UNAVAILABLE, AST_DEVICE_UNKNOWN, AST_LIST_TRAVERSE, skinny_subchannel::onhold, and SKINNY_ONHOOK.

Referenced by skinny_devicestate(), and skinny_new().

04235 {
04236    struct skinny_subchannel *sub;
04237    int res = AST_DEVICE_UNKNOWN;
04238 
04239    if (!l)
04240       res = AST_DEVICE_INVALID;
04241    else if (!l->device)
04242       res = AST_DEVICE_UNAVAILABLE;
04243    else if (l->dnd)
04244       res = AST_DEVICE_BUSY;
04245    else {
04246       if (l->hookstate == SKINNY_ONHOOK) {
04247          res = AST_DEVICE_NOT_INUSE;
04248       } else {
04249          res = AST_DEVICE_INUSE;
04250       }
04251 
04252       AST_LIST_TRAVERSE(&l->sub, sub, list) {
04253          if (sub->onhold) {
04254             res = AST_DEVICE_ONHOLD;
04255             break;
04256          }
04257       }
04258    }
04259 
04260    return res;
04261 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 6386 of file chan_skinny.c.

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

Referenced by skinny_session().

06387 {
06388    int res;
06389    int dlen = 0;
06390    int timeout = keep_alive * 1100;
06391    time_t now;
06392    int *bufaddr;
06393    struct pollfd fds[1];
06394 
06395    if (!s->device) {
06396       if(time(&now) == -1) {
06397          ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
06398          return -1;
06399       }
06400 
06401       timeout = (auth_timeout - (now - s->start)) * 1000;
06402       if (timeout < 0) {
06403          /* we have timed out */
06404          if (skinnydebug)
06405             ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
06406          return -1;
06407       }
06408    }
06409 
06410    fds[0].fd = s->fd;
06411    fds[0].events = POLLIN;
06412    fds[0].revents = 0;
06413    res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */
06414                    /* we add 10% to the keep_alive to deal */
06415                    /* with network delays, etc */
06416    if (res < 0) {
06417       if (errno != EINTR) {
06418          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
06419          return res;
06420       }
06421    } else if (res == 0) {
06422       if (skinnydebug) {
06423          if (s->device) {
06424             ast_verb(1, "Skinny Client was lost, unregistering\n");
06425          } else {
06426             ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
06427          }
06428       }
06429       skinny_unregister(NULL, s);
06430       return -1;
06431    }
06432            
06433    if (fds[0].revents) {
06434       ast_mutex_lock(&s->lock);
06435       memset(s->inbuf, 0, sizeof(s->inbuf));
06436       res = read(s->fd, s->inbuf, 4);
06437       if (res < 0) {
06438          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06439 
06440          if (skinnydebug)
06441             ast_verb(1, "Skinny Client was lost, unregistering\n");
06442 
06443          skinny_unregister(NULL, s);
06444          ast_mutex_unlock(&s->lock);
06445          return res;
06446       } else if (res != 4) {
06447          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
06448          ast_mutex_unlock(&s->lock);
06449          
06450          if (res == 0) {
06451             if (skinnydebug)
06452                ast_verb(1, "Skinny Client was lost, unregistering\n");
06453             skinny_unregister(NULL, s);
06454          }
06455 
06456          return -1;
06457       }
06458 
06459       bufaddr = (int *)s->inbuf;
06460       dlen = letohl(*bufaddr);
06461       if (dlen < 4) {
06462          ast_debug(1, "Skinny Client sent invalid data.\n");
06463          ast_mutex_unlock(&s->lock);
06464          return -1;
06465       }
06466       if (dlen+8 > sizeof(s->inbuf)) {
06467          dlen = sizeof(s->inbuf) - 8;
06468       }
06469       *bufaddr = htolel(dlen);
06470 
06471       res = read(s->fd, s->inbuf+4, dlen+4);
06472       ast_mutex_unlock(&s->lock);
06473       if (res < 0) {
06474          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06475          return res;
06476       } else if (res != (dlen+4)) {
06477          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
06478          return -1;
06479       }
06480       return res;
06481    }
06482    return 0;
06483 }

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

Definition at line 5546 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_verb, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_LINE, BT_NONE, BT_SPEEDDIAL, BUTTON_TEMPLATE_RES_MESSAGE, button_template_res_message::buttonCount, button_definition::buttonDefinition, button_definition_template::buttonDefinition, button_template_res_message::buttonOffset, skinny_data::buttontemplate, skinny_req::data, button_template_res_message::definition, skinnysession::device, get_button_template(), htolel, skinny_speeddial::instance, button_definition::instanceNumber, skinny_speeddial::isHint, req_alloc(), button_template_res_message::totalButtonCount, and transmit_response().

Referenced by handle_message().

05547 {
05548    struct skinny_device *d = s->device;
05549    struct skinny_line *l;
05550    int i;
05551 
05552    struct skinny_speeddial *sd;
05553    struct button_definition_template btn[42];
05554    int lineInstance = 1;
05555    int speeddialInstance = 1;
05556    int buttonCount = 0;
05557 
05558    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
05559       return -1;
05560 
05561    memset(&btn, 0, sizeof(btn));
05562 
05563    get_button_template(s, btn);
05564 
05565    for (i=0; i<42; i++) {
05566       int btnSet = 0;
05567       switch (btn[i].buttonDefinition) {
05568          case BT_CUST_LINE:
05569             /* assume failure */
05570             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05571             req->data.buttontemplate.definition[i].instanceNumber = 0;
05572 
05573             AST_LIST_TRAVERSE(&d->lines, l, list) {
05574                if (l->instance == lineInstance) {
05575                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05576                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05577                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05578                   lineInstance++;
05579                   buttonCount++;
05580                   btnSet = 1;
05581                   break;
05582                }
05583             }
05584 
05585             if (!btnSet) {
05586                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05587                   if (sd->isHint && sd->instance == lineInstance) {
05588                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05589                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05590                      req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05591                      lineInstance++;
05592                      buttonCount++;
05593                      btnSet = 1;
05594                      break;
05595                   }
05596                }
05597             }
05598             break;
05599          case BT_CUST_LINESPEEDDIAL:
05600             /* assume failure */
05601             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05602             req->data.buttontemplate.definition[i].instanceNumber = 0;
05603 
05604             AST_LIST_TRAVERSE(&d->lines, l, list) {
05605                if (l->instance == lineInstance) {
05606                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05607                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05608                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05609                   lineInstance++;
05610                   buttonCount++;
05611                   btnSet = 1;
05612                   break;
05613                }
05614             }
05615 
05616             if (!btnSet) {
05617                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05618                   if (sd->isHint && sd->instance == lineInstance) {
05619                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05620                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05621                      req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05622                      lineInstance++;
05623                      buttonCount++;
05624                      btnSet = 1;
05625                      break;
05626                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
05627                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05628                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05629                      req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance;
05630                      speeddialInstance++;
05631                      buttonCount++;
05632                      btnSet = 1;
05633                      break;
05634                   }
05635                }
05636             }
05637             break;
05638          case BT_LINE:
05639             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
05640             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05641 
05642             AST_LIST_TRAVERSE(&d->lines, l, list) {
05643                if (l->instance == lineInstance) {
05644                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05645                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05646                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05647                   lineInstance++;
05648                   buttonCount++;
05649                   btnSet = 1;
05650                   break;
05651                }
05652             }
05653             break;
05654          case BT_SPEEDDIAL:
05655             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05656             req->data.buttontemplate.definition[i].instanceNumber = 0;
05657 
05658             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05659                if (!sd->isHint && sd->instance == speeddialInstance) {
05660                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05661                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05662                   req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance - 1;
05663                   speeddialInstance++;
05664                   buttonCount++;
05665                   btnSet = 1;
05666                   break;
05667                }
05668             }
05669             break;
05670          case BT_NONE:
05671             break;
05672          default:
05673             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
05674             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
05675             req->data.buttontemplate.definition[i].instanceNumber = 0;
05676             buttonCount++;
05677             btnSet = 1;
05678             break;
05679       }
05680    }
05681 
05682    req->data.buttontemplate.buttonOffset = 0;
05683    req->data.buttontemplate.buttonCount = htolel(buttonCount);
05684    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
05685 
05686    if (skinnydebug)
05687       ast_verb(1, "Sending %d template to %s\n",
05688                d->type,
05689                d->name);
05690    transmit_response(d, req);
05691    return 1;
05692 }

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

Definition at line 4852 of file chan_skinny.c.

References ast_channel::_state, ast_hangup(), ast_indicate(), ast_log(), ast_pthread_create, ast_safe_sleep(), AST_STATE_UP, skinny_subchannel::callid, errno, KEYDEF_ONHOOK, KEYDEF_RINGOUT, LOG_WARNING, skinny_subchannel::owner, set_callforwards(), SKINNY_DIALTONE, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), transmit_activatecallplane(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), and transmit_stopmediatransmission().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04853 {
04854    struct skinny_line *l = sub->parent;
04855    struct skinny_device *d = l->device;
04856    struct ast_channel *c = sub->owner;
04857    pthread_t t;
04858 
04859    if (!d) {
04860       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04861       return 0;
04862    }
04863 
04864    if (l->hookstate == SKINNY_ONHOOK) {
04865       l->hookstate = SKINNY_OFFHOOK;
04866       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04867       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
04868       transmit_activatecallplane(d, l);
04869    }
04870    transmit_clear_display_message(d, l->instance, sub->callid);
04871 
04872    if (l->cfwdtype & cfwdtype) {
04873       set_callforwards(l, NULL, cfwdtype);
04874       ast_safe_sleep(c, 500);
04875       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04876       transmit_closereceivechannel(d, sub);
04877       transmit_stopmediatransmission(d, sub);
04878       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04879       transmit_clearpromptmessage(d, l->instance, sub->callid);
04880       transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
04881       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
04882       transmit_activatecallplane(d, l);
04883       transmit_displaynotify(d, "CFwd disabled", 10);
04884       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04885          ast_indicate(c, -1);
04886          ast_hangup(c);
04887       }
04888       transmit_cfwdstate(d, l);
04889    } else {
04890       l->getforward = cfwdtype;
04891       transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04892       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04893       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04894          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04895          ast_hangup(c);
04896       }
04897    }
04898    return 0;
04899 }

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

Definition at line 5510 of file chan_skinny.c.

References ast_getformatname_multiple(), AST_LIST_TRAVERSE, ast_log(), ast_mutex_lock, ast_mutex_unlock, ast_verb, capabilities_res_message::caps, skinny_data::caps, station_capabilities::codec, codec_skinny2ast(), capabilities_res_message::count, skinny_req::data, skinnysession::device, letohl, skinny_line::lock, LOG_WARNING, and SKINNY_MAX_CAPABILITIES.

Referenced by handle_message().

05511 {
05512    struct skinny_device *d = s->device;
05513    struct skinny_line *l;
05514    uint32_t count = 0;
05515    format_t codecs = 0;
05516    int i;
05517    char buf[256];
05518 
05519    count = letohl(req->data.caps.count);
05520    if (count > SKINNY_MAX_CAPABILITIES) {
05521       count = SKINNY_MAX_CAPABILITIES;
05522       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
05523    }
05524 
05525    for (i = 0; i < count; i++) {
05526       format_t acodec = 0;
05527       int scodec = 0;
05528       scodec = letohl(req->data.caps.caps[i].codec);
05529       acodec = codec_skinny2ast(scodec);
05530       if (skinnydebug)
05531          ast_verb(1, "Adding codec capability '%" PRId64 " (%d)'\n", acodec, scodec);
05532       codecs |= acodec;
05533    }
05534 
05535    d->capability = d->confcapability & codecs;
05536    ast_verb(0, "Device capability set to '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), d->capability));
05537    AST_LIST_TRAVERSE(&d->lines, l, list) {
05538       ast_mutex_lock(&l->lock);
05539       l->capability = l->confcapability & d->capability;
05540       ast_mutex_unlock(&l->lock);
05541    }
05542 
05543    return 1;
05544 }

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

Definition at line 5755 of file chan_skinny.c.

References skinny_line::activesub, ast_copy_string(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verb, enbloc_call_message::calledParty, skinny_subchannel::callid, ast_channel::context, skinny_req::data, skinnysession::device, skinny_data::enbloccallmessage, errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), LOG_WARNING, SKINNY_DIALTONE, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_start_tone(), and transmit_stop_tone().

Referenced by handle_message().

05756 {
05757    struct skinny_device *d = s->device;
05758    struct skinny_line *l;
05759    struct skinny_subchannel *sub = NULL;
05760    struct ast_channel *c;
05761    pthread_t t;
05762 
05763    if (skinnydebug)
05764       ast_verb(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
05765 
05766    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05767 
05768    if (!sub) {
05769       l = find_line_by_instance(d, d->lastlineinstance);
05770       if (!l) {
05771          return 0;
05772       }
05773    } else {
05774       l = sub->parent;
05775    }
05776 
05777    c = skinny_new(l, AST_STATE_DOWN, NULL);
05778 
05779    if(!c) {
05780       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05781    } else {
05782       l->hookstate = SKINNY_OFFHOOK;
05783 
05784       sub = c->tech_pvt;
05785       l->activesub = sub;
05786       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05787       transmit_activatecallplane(d, l);
05788       transmit_clear_display_message(d, l->instance, sub->callid);
05789       transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05790 
05791       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
05792          transmit_stop_tone(d, l->instance, sub->callid);
05793       }
05794       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
05795       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05796          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05797          ast_hangup(c);
05798       }
05799    }
05800    
05801    return 1;
05802 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4687 of file chan_skinny.c.

References skinny_subchannel::callid, KEYDEF_CONNECTED, KEYDEF_ONHOLD, skinny_subchannel::onhold, skinny_hold(), skinny_unhold(), and transmit_selectsoftkeys().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04688 {
04689    if (!sub)
04690       return -1;
04691    if (sub->related) {
04692       skinny_hold(sub);
04693       skinny_unhold(sub->related);
04694       sub->parent->activesub = sub->related;
04695    } else {
04696       if (sub->onhold) {
04697          skinny_unhold(sub);
04698          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04699       } else {
04700          skinny_hold(sub);
04701          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04702       }
04703    }
04704    return 1;
04705 }

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

Definition at line 4900 of file chan_skinny.c.

Referenced by handle_message().

04901 {
04902    /* no response necessary */
04903    return 1;
04904 }

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

Definition at line 4776 of file chan_skinny.c.

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

Referenced by handle_message().

04777 {
04778    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04779       return -1;
04780 
04781    transmit_response(s->device, req);
04782    return 1;
04783 }

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

Definition at line 4906 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, AST_LIST_NEXT, ast_log(), ast_queue_frame(), ast_verb, keypad_button_message::button, keypad_button_message::callReference, skinny_req::data, skinnysession::device, find_subchannel_by_instance_reference(), ast_frame::frametype, ast_frame_subclass::integer, skinny_data::keypad, letohl, keypad_button_message::lineInstance, LOG_WARNING, skinny_subchannel::owner, ast_frame::src, and ast_frame::subclass.

Referenced by handle_message().

04907 {
04908    struct skinny_subchannel *sub = NULL;
04909    struct skinny_line *l;
04910    struct skinny_device *d = s->device;
04911    struct ast_frame f = { 0, };
04912    char dgt;
04913    int digit;
04914    int lineInstance;
04915    int callReference;
04916 
04917    digit = letohl(req->data.keypad.button);
04918    lineInstance = letohl(req->data.keypad.lineInstance);
04919    callReference = letohl(req->data.keypad.callReference);
04920 
04921    if (digit == 14) {
04922       dgt = '*';
04923    } else if (digit == 15) {
04924       dgt = '#';
04925    } else if (digit >= 0 && digit <= 9) {
04926       dgt = '0' + digit;
04927    } else {
04928       /* digit=10-13 (A,B,C,D ?), or
04929        * digit is bad value
04930        *
04931        * probably should not end up here, but set
04932        * value for backward compatibility, and log
04933        * a warning.
04934        */
04935       dgt = '0' + digit;
04936       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04937    }
04938 
04939    f.subclass.integer = dgt;
04940 
04941    f.src = "skinny";
04942 
04943    if (lineInstance && callReference)
04944       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04945    else
04946       sub = d->activeline->activesub;
04947       //sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04948 
04949    if (!sub)
04950       return 0;
04951 
04952    l = sub->parent;
04953    if (sub->owner) {
04954       if (sub->owner->_state == 0) {
04955          f.frametype = AST_FRAME_DTMF_BEGIN;
04956          ast_queue_frame(sub->owner, &f);
04957       }
04958       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04959       f.frametype = AST_FRAME_DTMF_END;
04960       ast_queue_frame(sub->owner, &f);
04961       /* XXX This seriously needs to be fixed */
04962       if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
04963          if (sub->owner->_state == 0) {
04964             f.frametype = AST_FRAME_DTMF_BEGIN;
04965             ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04966          }
04967          f.frametype = AST_FRAME_DTMF_END;
04968          ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04969       }
04970    } else {
04971       if (skinnydebug)
04972          ast_verb(1, "No owner: %s\n", l->name);
04973    }
04974    return 1;
04975 }

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

Definition at line 6178 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, skinny_data::alarm, ALARM_MESSAGE, ast_free, ast_log(), AST_LOG_WARNING, AST_STATE_UP, ast_verb, keypad_button_message::button, BUTTON_TEMPLATE_REQ_MESSAGE, keypad_button_message::callReference, CAPABILITIES_RES_MESSAGE, skinny_req::data, skinnysession::device, alarm_message::displayMessage, skinny_req::e, ENBLOC_CALL_MESSAGE, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_ip_port_message(), handle_keep_alive_message(), handle_keypad_button_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_soft_key_event_message(), handle_stimulus_message(), HEADSET_STATUS_MESSAGE, IP_PORT_MESSAGE, KEEP_ALIVE_MESSAGE, KEYDEF_ONHOOK, skinny_data::keypad, KEYPAD_BUTTON_MESSAGE, len(), letohl, skinny_data::line, LINE_STATE_REQ_MESSAGE, keypad_button_message::lineInstance, line_state_req_message::lineNumber, LOG_WARNING, register_message::name, OFFHOOK_MESSAGE, skinny_subchannel::onhold, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, skinny_subchannel::owner, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, SERVER_REQUEST_MESSAGE, SKINNY_DEVONLY, 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_definetimedate(), transmit_linestatres(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speeddialstatres(), transmit_versionres(), UNREGISTER_MESSAGE, and VERSION_REQ_MESSAGE.

Referenced by skinny_session().

06179 {
06180    int res = 0;
06181    struct skinny_speeddial *sd;
06182    struct skinny_line *l;
06183    struct skinny_device *d = s->device;
06184    size_t len;
06185 
06186    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
06187       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
06188       ast_free(req);
06189       return 0;
06190    }
06191 
06192    SKINNY_DEVONLY(if (skinnydebug > 1) {
06193       ast_verb(4, "Received %s from %s\n", message2str(req->e), s->device->name);
06194    })
06195 
06196    switch(letohl(req->e)) {
06197    case KEEP_ALIVE_MESSAGE:
06198       res = handle_keep_alive_message(req, s);
06199       break;
06200    case REGISTER_MESSAGE:
06201       if (skinnydebug)
06202          ast_verb(1, "Device %s is attempting to register\n", req->data.reg.name);
06203 
06204       res = handle_register_message(req, s);
06205       break;
06206    case IP_PORT_MESSAGE:
06207       res = handle_ip_port_message(req, s);
06208       break;
06209    case KEYPAD_BUTTON_MESSAGE:
06210        {
06211       struct skinny_device *d = s->device;
06212       struct skinny_subchannel *sub;
06213       int lineInstance;
06214       int callReference;
06215 
06216       if (skinnydebug)
06217          ast_verb(1, "Collected digit: [%u]\n", letohl(req->data.keypad.button));
06218 
06219       lineInstance = letohl(req->data.keypad.lineInstance);
06220       callReference = letohl(req->data.keypad.callReference);
06221 
06222       if (lineInstance) {
06223          sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
06224       } else {
06225          sub = d->activeline->activesub;
06226       }
06227 
06228       if (sub && ((sub->owner && sub->owner->_state <  AST_STATE_UP) || sub->onhold)) {
06229          char dgt;
06230          int digit = letohl(req->data.keypad.button);
06231 
06232          if (digit == 14) {
06233             dgt = '*';
06234          } else if (digit == 15) {
06235             dgt = '#';
06236          } else if (digit >= 0 && digit <= 9) {
06237             dgt = '0' + digit;
06238          } else {
06239             /* digit=10-13 (A,B,C,D ?), or
06240             * digit is bad value
06241             *
06242             * probably should not end up here, but set
06243             * value for backward compatibility, and log
06244             * a warning.
06245             */
06246             dgt = '0' + digit;
06247             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
06248          }
06249 
06250          len = strlen(d->exten);
06251          if (len < sizeof(d->exten) - 1) {
06252             d->exten[len] = dgt;
06253             d->exten[len + 1] = '\0';
06254          } else {
06255             ast_log(AST_LOG_WARNING, "Dropping digit with value %d because digit queue is full\n", dgt);
06256          }
06257       } else
06258          res = handle_keypad_button_message(req, s);
06259       }
06260       break;
06261    case ENBLOC_CALL_MESSAGE:
06262       res = handle_enbloc_call_message(req, s);
06263       break;
06264    case STIMULUS_MESSAGE:
06265       res = handle_stimulus_message(req, s);
06266       break;
06267    case OFFHOOK_MESSAGE:
06268       res = handle_offhook_message(req, s);
06269       break;
06270    case ONHOOK_MESSAGE:
06271       res = handle_onhook_message(req, s);
06272       break;
06273    case CAPABILITIES_RES_MESSAGE:
06274       if (skinnydebug)
06275          ast_verb(1, "Received CapabilitiesRes\n");
06276 
06277       res = handle_capabilities_res_message(req, s);
06278       break;
06279    case SPEED_DIAL_STAT_REQ_MESSAGE:
06280       if (skinnydebug)
06281          ast_verb(1, "Received SpeedDialStatRequest\n");
06282       if ( (sd = find_speeddial_by_instance(s->device, letohl(req->data.speeddialreq.speedDialNumber), 0)) ) {
06283          transmit_speeddialstatres(d, sd);
06284       }
06285       break;
06286    case LINE_STATE_REQ_MESSAGE:
06287       if (skinnydebug)
06288          ast_verb(1, "Received LineStatRequest\n");
06289       if ((l = find_line_by_instance(d, letohl(req->data.line.lineNumber)))) {
06290          transmit_linestatres(d, l);
06291       }
06292       break;
06293    case TIME_DATE_REQ_MESSAGE:
06294       if (skinnydebug)
06295          ast_verb(1, "Received Time/Date Request\n");
06296 
06297       transmit_definetimedate(d);
06298       break;
06299    case BUTTON_TEMPLATE_REQ_MESSAGE:
06300       if (skinnydebug)
06301          ast_verb(1, "Buttontemplate requested\n");
06302 
06303       res = handle_button_template_req_message(req, s);
06304       break;
06305    case VERSION_REQ_MESSAGE:
06306       if (skinnydebug)
06307          ast_verb(1, "Version Request\n");
06308       transmit_versionres(d);
06309       break;
06310    case SERVER_REQUEST_MESSAGE:
06311       if (skinnydebug)
06312          ast_verb(1, "Received Server Request\n");
06313       transmit_serverres(d);
06314       break;
06315    case ALARM_MESSAGE:
06316       /* no response necessary */
06317       if (skinnydebug)
06318          ast_verb(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
06319       break;
06320    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
06321       if (skinnydebug)
06322          ast_verb(1, "Received Open Receive Channel Ack\n");
06323 
06324       res = handle_open_receive_channel_ack_message(req, s);
06325       break;
06326    case SOFT_KEY_SET_REQ_MESSAGE:
06327       if (skinnydebug)
06328          ast_verb(1, "Received SoftKeySetReq\n");
06329       transmit_softkeysetres(d);
06330       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
06331       break;
06332    case SOFT_KEY_EVENT_MESSAGE:
06333       res = handle_soft_key_event_message(req, s);
06334       break;
06335    case UNREGISTER_MESSAGE:
06336       if (skinnydebug)
06337          ast_verb(1, "Received Unregister Request\n");
06338 
06339       res = skinny_unregister(req, s);
06340       break;
06341    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
06342       if (skinnydebug)
06343          ast_verb(1, "Received SoftKey Template Request\n");
06344       transmit_softkeytemplateres(d);
06345       break;
06346    case HEADSET_STATUS_MESSAGE:
06347       /* XXX umm...okay?  Why do I care? */
06348       break;
06349    case REGISTER_AVAILABLE_LINES_MESSAGE:
06350       /* XXX I have no clue what this is for, but my phone was sending it, so... */
06351       break;
06352    default:
06353       if (skinnydebug)
06354          ast_verb(1, "RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", (unsigned)letohl(req->e));
06355       break;
06356    }
06357    if (res >= 0 && req)
06358       ast_free(req);
06359    return res;
06360 }

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

Definition at line 5329 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, AST_CONTROL_ANSWER, ast_debug, AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_hangup(), AST_LIST_TRAVERSE, ast_log(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose, skinny_subchannel::callid, skinny_req::data, skinnysession::device, errno, find_line_by_instance(), find_subchannel_by_instance_reference(), offhook_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, letohl, LOG_WARNING, skinny_data::offhook, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, skinny_ss(), start_rtp(), STIMULUS_LINE, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_definetimedate(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_start_tone(), transmit_stop_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

05330 {
05331    struct skinny_device *d = s->device;
05332    struct skinny_line *l;
05333    struct skinny_subchannel *sub;
05334    struct ast_channel *c;
05335    struct skinny_line *tmp;
05336    pthread_t t;
05337    int instance;
05338 
05339    /* if any line on a device is offhook, than the device must be offhook, 
05340       unless we have shared lines CCM seems that it would never get here, 
05341       but asterisk does, so we may need to do more work.  Ugly, we should 
05342       probably move hookstate from line to device, afterall, it's actually
05343        a device that changes hookstates */
05344 
05345    AST_LIST_TRAVERSE(&d->lines, tmp, list) {
05346       if (tmp->hookstate == SKINNY_OFFHOOK) {
05347          ast_verbose(VERBOSE_PREFIX_3 "Got offhook message when device (%s@%s) already offhook\n", tmp->name, d->name);
05348          return 0;
05349       }
05350    }
05351 
05352    instance = letohl(req->data.offhook.instance);
05353 
05354    if (instance) {
05355       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05356       if (!sub) {
05357          l = find_line_by_instance(d, d->lastlineinstance);
05358          if (!l) {
05359             return 0;
05360          }
05361       } else {
05362          l = sub->parent;
05363       }
05364    } else {
05365       l = d->activeline;
05366       sub = l->activesub;
05367    }
05368 
05369    /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
05370    transmit_definetimedate(d);
05371    
05372    transmit_ringer_mode(d, SKINNY_RING_OFF);
05373    l->hookstate = SKINNY_OFFHOOK;
05374 
05375    ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
05376 
05377    if (sub && sub->onhold) {
05378       return 1;
05379    }
05380 
05381    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05382 
05383    if (sub && sub->outgoing) {
05384       /* We're answering a ringing call */
05385       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05386       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05387       transmit_activatecallplane(d, l);
05388       transmit_stop_tone(d, l->instance, sub->callid);
05389       transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
05390       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05391       start_rtp(sub);
05392       ast_setstate(sub->owner, AST_STATE_UP);
05393    } else {
05394       if (sub && sub->owner) {
05395          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
05396       } else {
05397          c = skinny_new(l, AST_STATE_DOWN, NULL);
05398          if (c) {
05399             sub = c->tech_pvt;
05400             l->activesub = sub;
05401             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05402             transmit_activatecallplane(d, l);
05403             transmit_clear_display_message(d, l->instance, sub->callid);
05404             transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05405             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05406 
05407             /* start the switch thread */
05408             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05409                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05410                ast_hangup(c);
05411             }
05412          } else {
05413             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05414          }
05415       }
05416    }
05417    return 1;
05418 }

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

Definition at line 5420 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, skinny_subchannel::alreadygone, ast_debug, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), AST_LIST_NEXT, AST_LIST_REMOVE, ast_log(), ast_queue_hangup(), AST_STATE_RING, skinny_subchannel::blindxfer, skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_req::data, skinnysession::device, find_subchannel_by_instance_reference(), handle_transfer_button(), onhook_message::instance, KEYDEF_ONHOOK, letohl, LOG_WARNING, skinny_subchannel::onhold, skinny_data::onhook, skinny_subchannel::owner, onhook_message::reference, SKINNY_CX_RECVONLY, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, transmit_activatecallplane(), transmit_callstate(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_definetimedate(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and skinny_subchannel::xferor.

Referenced by handle_message().

05421 {
05422    struct skinny_device *d = s->device;
05423    struct skinny_line *l;
05424    struct skinny_subchannel *sub;
05425    int instance;
05426    int reference;
05427    int onlysub = 0;
05428 
05429    instance = letohl(req->data.onhook.instance);
05430    reference = letohl(req->data.onhook.reference);
05431 
05432    if (instance && reference) {
05433       sub = find_subchannel_by_instance_reference(d, instance, reference);
05434       if (!sub) {
05435          return 0;
05436       }
05437       l = sub->parent;
05438    } else {
05439       l = d->activeline;
05440       sub = l->activesub;
05441       if (!sub) {
05442          return 0;
05443       }
05444    }
05445 
05446    if (l->hookstate == SKINNY_ONHOOK) {
05447       /* Something else already put us back on hook */
05448       return 0;
05449    }
05450 
05451    ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
05452 
05453    if (sub->onhold) {
05454       return 0;
05455    }
05456 
05457    if (!AST_LIST_NEXT(sub, list)) {
05458       onlysub = 1;
05459    } else {
05460       AST_LIST_REMOVE(&l->sub, sub, list);
05461    }
05462 
05463    sub->cxmode = SKINNY_CX_RECVONLY;
05464    if (onlysub || sub->xferor){  /* is this the only call to this device? */
05465       l->hookstate = SKINNY_ONHOOK;
05466       if (skinnydebug)
05467          ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
05468    }
05469 
05470    if (l->hookstate == SKINNY_ONHOOK) {
05471       transmit_closereceivechannel(d, sub);
05472       transmit_stopmediatransmission(d, sub);
05473       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05474       transmit_clearpromptmessage(d, instance, sub->callid);
05475       transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
05476       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05477       transmit_activatecallplane(d, l);
05478    } else if (l->hookstate == SKINNY_OFFHOOK) {
05479       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05480       transmit_activatecallplane(d, l);
05481    } else {
05482       transmit_callstate(d, l->instance, sub->callid, l->hookstate);
05483    }
05484 
05485    if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05486       /* We're allowed to transfer, we have two active calls and
05487          we made at least one of the calls.  Let's try and transfer */
05488       handle_transfer_button(sub);
05489    } else {
05490       /* Hangup the current call */
05491       /* If there is another active call, skinny_hangup will ring the phone with the other call */
05492       if (sub->xferor && sub->related){
05493          sub->related->related = NULL;
05494          sub->related->blindxfer = 0;
05495       }
05496 
05497       if (sub->owner) {
05498          sub->alreadygone = 1;
05499          ast_queue_hangup(sub->owner);
05500       } else {
05501          ast_log(LOG_WARNING, "Skinny(%s@%s-%u) channel already destroyed\n",
05502             l->name, d->name, sub->callid);
05503       }
05504       /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
05505       transmit_definetimedate(d);
05506    }
05507    return 1;
05508 }

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

Definition at line 5694 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, ast_verb, ast_format_list::bits, ast_format_list::cur_ms, skinny_req::data, skinnysession::device, find_subchannel_by_reference(), open_receive_channel_ack_message::ipAddr, letohl, LOG_ERROR, skinny_data::openreceivechannelack, skinny_device::ourip, open_receive_channel_ack_message::passThruId, open_receive_channel_ack_message::port, skinny_subchannel::rtp, open_receive_channel_ack_message::status, status, and transmit_startmediatransmission().

Referenced by handle_message().

05695 {
05696    struct skinny_device *d = s->device;
05697    struct skinny_line *l;
05698    struct skinny_subchannel *sub;
05699    struct ast_format_list fmt;
05700    struct sockaddr_in sin = { 0, };
05701    struct sockaddr_in us = { 0, };
05702    struct ast_sockaddr sin_tmp;
05703    struct ast_sockaddr us_tmp;
05704    uint32_t addr;
05705    int port;
05706    int status;
05707    int passthruid;
05708 
05709    status = letohl(req->data.openreceivechannelack.status);
05710    if (status) {
05711       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
05712       return 0;
05713    }
05714    addr = req->data.openreceivechannelack.ipAddr;
05715    port = letohl(req->data.openreceivechannelack.port);
05716    passthruid = letohl(req->data.openreceivechannelack.passThruId);
05717 
05718    sin.sin_family = AF_INET;
05719    sin.sin_addr.s_addr = addr;
05720    sin.sin_port = htons(port);
05721 
05722    sub = find_subchannel_by_reference(d, passthruid);
05723 
05724    if (!sub)
05725       return 0;
05726 
05727    l = sub->parent;
05728 
05729    if (sub->rtp) {
05730       ast_sockaddr_from_sin(&sin_tmp, &sin);
05731       ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
05732       ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
05733       ast_sockaddr_to_sin(&us_tmp, &us);
05734       us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
05735    } else {
05736       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
05737       return 0;
05738    }
05739 
05740    if (skinnydebug) {
05741       ast_verb(1, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
05742       ast_verb(1, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port));
05743    }
05744 
05745    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
05746 
05747    if (skinnydebug)
05748       ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
05749 
05750    transmit_startmediatransmission(d, sub, us, fmt);
05751 
05752    return 1;
05753 }

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

Definition at line 4785 of file chan_skinny.c.

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

Referenced by handle_message().

04786 {
04787    struct skinny_device *d = NULL;
04788    char name[16];
04789    int res;
04790 
04791    memcpy(&name, req->data.reg.name, sizeof(name));
04792 
04793    res = skinny_register(req, s);
04794    if (!res) {
04795       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
04796       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
04797          return -1;
04798 
04799       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
04800 
04801       /* transmit_respons in line as we don't have a valid d */
04802       ast_mutex_lock(&s->lock);
04803 
04804       if (letohl(req->len) > SKINNY_MAX_PACKET || letohl(req->len) < 0) {
04805          ast_log(LOG_WARNING, "transmit_response: the length (%d) of the request is out of bounds (%d) \n",  letohl(req->len), SKINNY_MAX_PACKET);
04806          ast_mutex_unlock(&s->lock);
04807          return -1;
04808       }
04809 
04810       memset(s->outbuf, 0, sizeof(s->outbuf));
04811       memcpy(s->outbuf, req, skinny_header_size);
04812       memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
04813 
04814       res = write(s->fd, s->outbuf, letohl(req->len)+8);
04815 
04816       if (res != letohl(req->len)+8) {
04817          ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
04818       }
04819    
04820       ast_mutex_unlock(&s->lock);
04821 
04822       return 0;
04823    }
04824    ast_atomic_fetchadd_int(&unauth_sessions, -1);
04825 
04826    ast_verb(3, "Device '%s' successfully registered\n", name);
04827 
04828    d = s->device;
04829    
04830    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
04831       return -1;
04832 
04833    req->data.regack.res[0] = '0';
04834    req->data.regack.res[1] = '\0';
04835    req->data.regack.keepAlive = htolel(keep_alive);
04836    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
04837    req->data.regack.res2[0] = '0';
04838    req->data.regack.res2[1] = '\0';
04839    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
04840    transmit_response(d, req);
04841    if (skinnydebug)
04842       ast_verb(1, "Requesting capabilities\n");
04843 
04844    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
04845       return -1;
04846 
04847    transmit_response(d, req);
04848 
04849    return res;
04850 }

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

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

02924 {
02925    switch (cmd) {
02926    case CLI_INIT:
02927       e->command = "skinny reload";
02928       e->usage =
02929          "Usage: skinny reload\n"
02930          "       Reloads the chan_skinny configuration\n";
02931       return NULL;
02932    case CLI_GENERATE:
02933       return NULL;
02934    }
02935    
02936    if (a->argc != e->args)
02937       return CLI_SHOWUSAGE;
02938 
02939    skinny_reload();
02940    return CLI_SUCCESS;
02941 
02942 }

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

Definition at line 2988 of file chan_skinny.c.

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

02989 {
02990    struct skinny_device *d;
02991    struct skinny_req *req;
02992 
02993    switch (cmd) {
02994    case CLI_INIT:
02995       e->command = "skinny reset";
02996       e->usage =
02997          "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
02998          "       Causes a Skinny device to reset itself, optionally with a full restart\n";
02999       return NULL;
03000    case CLI_GENERATE:
03001       return complete_skinny_reset(a->line, a->word, a->pos, a->n);
03002    }
03003 
03004    if (a->argc < 3 || a->argc > 4)
03005       return CLI_SHOWUSAGE;
03006 
03007    AST_LIST_LOCK(&devices);
03008    AST_LIST_TRAVERSE(&devices, d, list) {
03009       int fullrestart = 0;
03010       if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
03011          if (!(d->session))
03012             continue;
03013 
03014          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
03015             continue;
03016 
03017          if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
03018             fullrestart = 1;
03019 
03020          if (fullrestart)
03021             req->data.reset.resetType = 2;
03022          else
03023             req->data.reset.resetType = 1;
03024 
03025          ast_verb(3, "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
03026          transmit_response(d, req);
03027       }
03028    }
03029    AST_LIST_UNLOCK(&devices);
03030    return CLI_SUCCESS;
03031 }

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

Definition at line 2881 of file chan_skinny.c.

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

02882 {
02883    switch (cmd) {
02884    case CLI_INIT:
02885 #ifdef SKINNY_DEVMODE
02886       e->command = "skinny set debug {off|on|packet}";
02887       e->usage =
02888          "Usage: skinny set debug {off|on|packet}\n"
02889          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02890 #else
02891       e->command = "skinny set debug {off|on}";
02892       e->usage =
02893          "Usage: skinny set debug {off|on}\n"
02894          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02895 #endif
02896       return NULL;
02897    case CLI_GENERATE:
02898       return NULL;
02899    }
02900    
02901    if (a->argc != e->args)
02902       return CLI_SHOWUSAGE;
02903 
02904    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
02905       skinnydebug = 1;
02906       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02907       return CLI_SUCCESS;
02908    } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
02909       skinnydebug = 0;
02910       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02911       return CLI_SUCCESS;
02912 #ifdef SKINNY_DEVMODE
02913    } else if (!strncasecmp(a->argv[e->args - 1], "packet", 6)) {
02914       skinnydebug = 2;
02915       ast_cli(a->fd, "Skinny Debugging Enabled including Packets\n");
02916       return CLI_SUCCESS;
02917 #endif
02918    } else {
02919       return CLI_SHOWUSAGE;
02920    }
02921 }

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

03369 {
03370    switch (cmd) {
03371    case CLI_INIT:
03372       e->command = "skinny show device";
03373       e->usage =
03374          "Usage: skinny show device <DeviceId|DeviceName>\n"
03375          "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
03376       return NULL;
03377    case CLI_GENERATE:
03378       return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
03379    }
03380 
03381    return _skinny_show_device(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03382 }

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

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

03235 {
03236 
03237    switch (cmd) {
03238    case CLI_INIT:
03239       e->command = "skinny show devices";
03240       e->usage =
03241          "Usage: skinny show devices\n"
03242          "       Lists all devices known to the Skinny subsystem.\n";
03243       return NULL;
03244    case CLI_GENERATE:
03245       return NULL;
03246    }
03247 
03248    return _skinny_show_devices(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03249 }

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

03662 {
03663    switch (cmd) {
03664    case CLI_INIT:
03665       e->command = "skinny show line";
03666       e->usage =
03667          "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
03668          "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
03669       return NULL;
03670    case CLI_GENERATE:
03671       return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
03672    }
03673 
03674    return _skinny_show_line(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03675 }

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

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

03483 {
03484    switch (cmd) {
03485    case CLI_INIT:
03486       e->command = "skinny show lines [verbose]";
03487       e->usage =
03488          "Usage: skinny show lines\n"
03489          "       Lists all lines known to the Skinny subsystem.\n"
03490          "       If 'verbose' is specified, the output includes\n"
03491          "       information about subs for each line.\n";
03492       return NULL;
03493    case CLI_GENERATE:
03494       return NULL;
03495    }
03496 
03497    if (a->argc == e->args) {
03498       if (strcasecmp(a->argv[e->args-1], "verbose")) {
03499          return CLI_SHOWUSAGE;
03500       }
03501    } else if (a->argc != e->args - 1) {
03502       return CLI_SHOWUSAGE;
03503    }
03504 
03505    return _skinny_show_lines(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03506 }

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

03679 {
03680    switch (cmd) {
03681    case CLI_INIT:
03682       e->command = "skinny show settings";
03683       e->usage =
03684          "Usage: skinny show settings\n"
03685          "       Lists all global configuration settings of the Skinny subsystem.\n";
03686       return NULL;
03687    case CLI_GENERATE:
03688       return NULL;
03689    }  
03690 
03691    if (a->argc != 3)
03692       return CLI_SHOWUSAGE;
03693 
03694    ast_cli(a->fd, "\nGlobal Settings:\n");
03695    ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
03696    ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
03697    ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
03698    ast_cli(a->fd, "  Date Format:            %s\n", date_format);
03699    ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(global_vmexten, "(not set)"));
03700    ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
03701    ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_ENABLED)));
03702     if (ast_test_flag(&global_jbconf, AST_JB_ENABLED)) {
03703       ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_FORCED)));
03704       ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
03705       ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
03706       ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
03707       if (!strcasecmp(global_jbconf.impl, "adaptive")) {
03708          ast_cli(a->fd, "  Jitterbuffer tgt extra: %ld\n", global_jbconf.target_extra);
03709       }
03710       ast_cli(a->fd, "  Jitterbuffer log:       %s\n", AST_CLI_YESNO(ast_test_flag(&global_jbconf, AST_JB_LOG)));
03711    }
03712 
03713    return CLI_SUCCESS;
03714 }

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

Definition at line 5805 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, skinny_subchannel::alreadygone, ast_bridged_channel(), AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, AST_DEVICE_INUSE, AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_hangup(), ast_ignore_pattern(), AST_LIST_NEXT, AST_LIST_REMOVE, ast_log(), ast_masq_park_call(), ast_pthread_create, ast_queue_control(), ast_queue_hangup(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, soft_key_event_message::callreference, ast_channel::context, skinny_subchannel::cxmode, skinny_req::data, skinnysession::device, errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), handle_callforward_button(), handle_hold_button(), handle_transfer_button(), soft_key_event_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_ONHOLD, KEYDEF_ONHOOK, KEYDEF_RINGOUT, letohl, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::rtp, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), SOFTKEY_ANSWER, SOFTKEY_BKSPC, SOFTKEY_CFWDALL, SOFTKEY_CFWDBUSY, SOFTKEY_CFWDNOANSWER, SOFTKEY_CONFRN, SOFTKEY_DND, SOFTKEY_ENDCALL, SOFTKEY_GPICKUP, SOFTKEY_HOLD, SOFTKEY_INFO, SOFTKEY_JOIN, SOFTKEY_MEETME, SOFTKEY_NEWCALL, SOFTKEY_NONE, SOFTKEY_PARK, SOFTKEY_PICKUP, SOFTKEY_REDIAL, SOFTKEY_RESUME, SOFTKEY_TRNSFER, soft_key_event_message::softKeyEvent, skinny_data::softkeyeventmessage, start_rtp(), STIMULUS_DND, STIMULUS_LINE, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), transmit_stop_tone(), transmit_stopmediatransmission(), and skinny_subchannel::xferor.

Referenced by handle_message().

05806 {
05807    struct skinny_device *d = s->device;
05808    struct skinny_line *l;
05809    struct skinny_subchannel *sub = NULL;
05810    struct ast_channel *c;
05811    pthread_t t;
05812    int event;
05813    int instance;
05814    int callreference;
05815 
05816    event = letohl(req->data.softkeyeventmessage.softKeyEvent);
05817    instance = letohl(req->data.softkeyeventmessage.instance);
05818    callreference = letohl(req->data.softkeyeventmessage.callreference);
05819 
05820    if (instance) {
05821       l = find_line_by_instance(d, instance);
05822       if (callreference) {
05823          sub = find_subchannel_by_instance_reference(d, instance, callreference);
05824       } else {
05825          sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
05826       }
05827    } else {
05828       l = find_line_by_instance(d, d->lastlineinstance);
05829    }
05830 
05831    if (!l) {
05832       if (skinnydebug)
05833          ast_verb(1, "Received Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05834       return 0;
05835    }
05836 
05837    ast_devstate_changed(AST_DEVICE_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
05838 
05839    switch(event) {
05840    case SOFTKEY_NONE:
05841       if (skinnydebug)
05842          ast_verb(1, "Received Softkey Event: None(%d/%d)\n", instance, callreference);
05843       break;
05844    case SOFTKEY_REDIAL:
05845       if (skinnydebug)
05846          ast_verb(1, "Received Softkey Event: Redial(%d/%d)\n", instance, callreference);
05847 
05848       if (ast_strlen_zero(l->lastnumberdialed)) {
05849          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found. Ignoring button.\n");
05850          break;
05851       }
05852 
05853       if (!sub || !sub->owner) {
05854          c = skinny_new(l, AST_STATE_DOWN, NULL);
05855       } else {
05856          c = sub->owner;
05857       }
05858 
05859       if (!c) {
05860          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05861       } else {
05862          sub = c->tech_pvt;
05863          l->activesub = sub;
05864          if (l->hookstate == SKINNY_ONHOOK) {
05865             l->hookstate = SKINNY_OFFHOOK;
05866             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05867             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05868             transmit_activatecallplane(d, l);
05869          }
05870          transmit_clear_display_message(d, l->instance, sub->callid);
05871          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05872          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05873 
05874          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
05875             transmit_stop_tone(d, l->instance, sub->callid);
05876          }
05877          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
05878          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05879             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05880             ast_hangup(c);
05881          }
05882       }
05883       break;
05884    case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
05885       if (skinnydebug)
05886          ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
05887 
05888       /* New Call ALWAYS gets a new sub-channel */
05889       c = skinny_new(l, AST_STATE_DOWN, NULL);
05890       sub = c->tech_pvt;
05891    
05892       /* transmit_ringer_mode(d, SKINNY_RING_OFF);
05893       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON); */
05894 
05895       /* l->hookstate = SKINNY_OFFHOOK; */
05896 
05897       if (!c) {
05898          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05899       } else {
05900          sub = c->tech_pvt;
05901          l->activesub = sub;
05902          if (l->hookstate == SKINNY_ONHOOK) {
05903             l->hookstate = SKINNY_OFFHOOK;
05904             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05905          }
05906          ast_verb(1, "Call-id: %u\n", sub->callid);
05907 
05908          transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05909          transmit_activatecallplane(d, l);
05910 
05911          transmit_clear_display_message(d, l->instance, sub->callid);
05912          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05913          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05914 
05915          /* start the switch thread */
05916          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05917             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05918             ast_hangup(c);
05919          }
05920       }
05921       break;
05922    case SOFTKEY_HOLD:
05923       if (skinnydebug)
05924          ast_verb(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
05925       handle_hold_button(sub);   
05926       break;
05927    case SOFTKEY_TRNSFER:
05928       if (skinnydebug)
05929          ast_verb(1, "Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
05930       if (l->transfer)
05931          handle_transfer_button(sub);
05932       else
05933          transmit_displaynotify(d, "Transfer disabled", 10);
05934 
05935       break;
05936    case SOFTKEY_DND:
05937       if (skinnydebug)
05938          ast_verb(1, "Received Softkey Event: DND(%d/%d)\n", instance, callreference);
05939 
05940       /* Do not disturb */
05941       if (l->dnd != 0){
05942          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
05943          l->dnd = 0;
05944          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
05945          transmit_displaynotify(d, "DnD disabled", 10);
05946       } else {
05947          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
05948          l->dnd = 1;
05949          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
05950          transmit_displaynotify(d, "DnD enabled", 10);
05951       }
05952       break;
05953    case SOFTKEY_CFWDALL:
05954       if (skinnydebug)
05955          ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
05956 
05957       if (!sub || !sub->owner) {
05958          c = skinny_new(l, AST_STATE_DOWN, NULL);
05959       } else {
05960          c = sub->owner;
05961       }
05962 
05963       if (!c) {
05964          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05965       } else {
05966          sub = c->tech_pvt;
05967          l->activesub = sub;
05968          handle_callforward_button(sub, SKINNY_CFWD_ALL);
05969       }
05970       break;
05971    case SOFTKEY_CFWDBUSY:
05972       if (skinnydebug)
05973          ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
05974 
05975       if (!sub || !sub->owner) {
05976          c = skinny_new(l, AST_STATE_DOWN, NULL);
05977       } else {
05978          c = sub->owner;
05979       }
05980 
05981       if (!c) {
05982          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05983       } else {
05984          sub = c->tech_pvt;
05985          l->activesub = sub;
05986          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
05987       }
05988       break;
05989    case SOFTKEY_CFWDNOANSWER:
05990       if (skinnydebug)
05991          ast_verb(1, "Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
05992 
05993 #if 0 /* Not sure how to handle this yet */
05994       if (!sub || !sub->owner) {
05995          c = skinny_new(l, AST_STATE_DOWN, NULL);
05996       } else {
05997          c = sub->owner;
05998       }
05999 
06000       if (!c) {
06001          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
06002       } else {
06003          sub = c->tech_pvt;
06004          l->activesub = sub;
06005          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
06006       }
06007 #endif
06008       break;
06009    case SOFTKEY_BKSPC:
06010       if (skinnydebug)
06011          ast_verb(1, "Received Softkey Event: Backspace(%d/%d)\n", instance, callreference);
06012       break;
06013    case SOFTKEY_ENDCALL:
06014       if (skinnydebug)
06015          ast_verb(1, "Received Softkey Event: End Call(%d/%d)\n", instance, callreference);
06016 
06017       if (l->hookstate == SKINNY_ONHOOK) {
06018          /* Something else already put us back on hook */
06019          break;
06020       }
06021       if (sub) {
06022          int onlysub = 0;
06023 
06024          if (!AST_LIST_NEXT(sub, list)) {
06025             onlysub = 1;
06026          } else {
06027             AST_LIST_REMOVE(&l->sub, sub, list);
06028          }
06029 
06030          sub->cxmode = SKINNY_CX_RECVONLY;
06031          if (onlysub || sub->xferor){    /*Are there other calls to this device */
06032             l->hookstate = SKINNY_ONHOOK;
06033             if (skinnydebug)
06034                ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, callreference);
06035          }
06036 
06037          if (l->hookstate == SKINNY_ONHOOK) {
06038             transmit_closereceivechannel(d, sub);
06039             transmit_stopmediatransmission(d, sub);
06040             transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
06041             transmit_clearpromptmessage(d, instance, sub->callid);
06042             transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
06043             transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
06044             transmit_activatecallplane(d, l);
06045          } else if (l->hookstate == SKINNY_OFFHOOK) {
06046             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
06047             transmit_activatecallplane(d, l);
06048          } else {
06049             transmit_callstate(d, l->instance, sub->callid, l->hookstate);
06050          }
06051 
06052          ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
06053          if (skinnydebug)
06054             ast_verb(1, "Skinny %s@%s went on hook\n", l->name, d->name);
06055          if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
06056             /* We're allowed to transfer, we have two active calls and
06057                we made at least one of the calls.  Let's try and transfer */
06058             handle_transfer_button(sub);
06059          } else {
06060             /* Hangup the current call */
06061             /* If there is another active call, skinny_hangup will ring the phone with the other call */
06062             if (sub->xferor && sub->related){
06063                sub->related->related = NULL;
06064                sub->related->blindxfer = 0;
06065             }
06066 
06067             if (sub->owner) {
06068                sub->alreadygone = 1;
06069                ast_queue_hangup(sub->owner);
06070             } else {
06071                ast_log(LOG_WARNING, "Skinny(%s@%s-%u) channel already destroyed\n",
06072                   l->name, d->name, sub->callid);
06073             }
06074          }
06075          if ((l->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) && !AST_LIST_NEXT(sub, list)->rtp)) {
06076             ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
06077          }
06078       }
06079       break;
06080    case SOFTKEY_RESUME:
06081       if (skinnydebug)
06082          ast_verb(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
06083 
06084       if (sub) {
06085          if (sub->onhold) {
06086             skinny_unhold(sub);
06087             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
06088          } else {
06089             skinny_hold(sub);
06090             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
06091          }
06092       }
06093 
06094       break;
06095    case SOFTKEY_ANSWER:
06096       if (skinnydebug)
06097          ast_verb(1, "Received Softkey Event: Answer(%d/%d)\n", instance, callreference);
06098 
06099       transmit_ringer_mode(d, SKINNY_RING_OFF);
06100       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
06101       if (l->hookstate == SKINNY_ONHOOK) {
06102          transmit_speaker_mode(d, SKINNY_SPEAKERON);
06103          l->hookstate = SKINNY_OFFHOOK;
06104       }
06105 
06106       if (sub && sub->outgoing) {
06107          /* We're answering a ringing call */
06108          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
06109          transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
06110          transmit_activatecallplane(d, l);
06111          transmit_stop_tone(d, l->instance, sub->callid);
06112          transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
06113          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
06114          start_rtp(sub);
06115          ast_setstate(sub->owner, AST_STATE_UP);
06116       }
06117       break;
06118    case SOFTKEY_INFO:
06119       if (skinnydebug)
06120          ast_verb(1, "Received Softkey Event: Info(%d/%d)\n", instance, callreference);
06121       break;
06122    case SOFTKEY_CONFRN:
06123       if (skinnydebug)
06124          ast_verb(1, "Received Softkey Event: Conference(%d/%d)\n", instance, callreference);
06125       /* XXX determine the best way to pull off a conference.  Meetme? */
06126       break;
06127    case SOFTKEY_PARK:
06128       {
06129       int extout;
06130       char message[32];
06131 
06132       if (skinnydebug)
06133          ast_verb(1, "Received Softkey Event: Park Call(%d/%d)\n", instance, callreference);
06134 
06135       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
06136          c = sub->owner;
06137          if (ast_bridged_channel(c)) {
06138             if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
06139                snprintf(message, sizeof(message), "Call Parked at: %d", extout);
06140                transmit_displaynotify(d, message, 10);
06141             } else {
06142                transmit_displaynotify(d, "Call Park failed", 10);
06143             }
06144          } else {
06145             transmit_displaynotify(d, "Call Park not available", 10);
06146          }
06147       } else {
06148          transmit_displaynotify(d, "Call Park not available", 10);
06149       }
06150       break;
06151       }
06152    case SOFTKEY_JOIN:
06153       if (skinnydebug)
06154          ast_verb(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference);
06155       break;
06156    case SOFTKEY_MEETME:
06157       /* XXX How is this different from CONFRN? */
06158       if (skinnydebug)
06159          ast_verb(1, "Received Softkey Event: Meetme(%d/%d)\n", instance, callreference);
06160       break;
06161    case SOFTKEY_PICKUP:
06162       if (skinnydebug)
06163          ast_verb(1, "Received Softkey Event: Pickup(%d/%d)\n", instance, callreference);
06164       break;
06165    case SOFTKEY_GPICKUP:
06166       if (skinnydebug)
06167          ast_verb(1, "Received Softkey Event: Group Pickup(%d/%d)\n", instance, callreference);
06168       break;
06169    default:
06170       if (skinnydebug)
06171          ast_verb(1, "Received unknown Softkey Event: %d(%d/%d)\n", event, instance, callreference);
06172       break;
06173    }
06174 
06175    return 1;
06176 }

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

Definition at line 4977 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, ast_bridged_channel(), AST_CONTROL_ANSWER, ast_copy_string(), ast_debug, AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, ast_devstate_changed(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_masq_park_call(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::callid, stimulus_message::callreference, ast_channel::context, skinny_req::data, skinnysession::device, errno, skinny_speeddial::exten, ast_channel::exten, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), handle_callforward_button(), handle_hold_button(), handle_transfer_button(), KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_ONHOOK, KEYDEF_RINGOUT, letohl, LOG_WARNING, skinny_subchannel::outgoing, skinny_subchannel::owner, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), start_rtp(), stimulus_message::stimulus, skinny_data::stimulus, STIMULUS_CALLPARK, STIMULUS_CONFERENCE, STIMULUS_DISPLAY, STIMULUS_DND, STIMULUS_FORWARDALL, STIMULUS_FORWARDBUSY, STIMULUS_FORWARDNOANSWER, STIMULUS_HOLD, STIMULUS_LINE, STIMULUS_REDIAL, STIMULUS_SPEEDDIAL, STIMULUS_TRANSFER, STIMULUS_VOICEMAIL, stimulus_message::stimulusInstance, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), transmit_stop_tone(), and transmit_stopmediatransmission().

Referenced by handle_message().

04978 {
04979    struct skinny_device *d = s->device;
04980    struct skinny_line *l;
04981    struct skinny_subchannel *sub;
04982    /*struct skinny_speeddial *sd;*/
04983    struct ast_channel *c;
04984    pthread_t t;
04985    int event;
04986    int instance;
04987    int callreference;
04988    /*int res = 0;*/
04989 
04990    event = letohl(req->data.stimulus.stimulus);
04991    instance = letohl(req->data.stimulus.stimulusInstance);
04992    callreference = letohl(req->data.stimulus.callreference); 
04993    if (skinnydebug)
04994       ast_verb(1, "callreference in handle_stimulus_message is '%d'\n", callreference);
04995 
04996    /*  Note that this call should be using the passed in instance and callreference */
04997    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04998 
04999    if (!sub) {
05000       l = find_line_by_instance(d, d->lastlineinstance);
05001       if (!l) {
05002          return 0;
05003       }
05004       sub = l->activesub;
05005    } else {
05006       l = sub->parent;
05007    }
05008 
05009    switch(event) {
05010    case STIMULUS_REDIAL:
05011       if (skinnydebug)
05012          ast_verb(1, "Received Stimulus: Redial(%d/%d)\n", instance, callreference);
05013 
05014       if (ast_strlen_zero(l->lastnumberdialed)) {
05015          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
05016          l->hookstate = SKINNY_ONHOOK;
05017          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05018          transmit_closereceivechannel(d, sub);
05019          transmit_stopmediatransmission(d, sub);
05020          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05021          transmit_clearpromptmessage(d, l->instance, sub->callid);
05022          transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
05023          transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05024          transmit_activatecallplane(d, l);
05025          break;
05026       }
05027 
05028       c = skinny_new(l, AST_STATE_DOWN, NULL);
05029       if (!c) {
05030          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05031       } else {
05032          sub = c->tech_pvt;
05033          l = sub->parent;
05034          l->activesub = sub;
05035          if (l->hookstate == SKINNY_ONHOOK) {
05036             l->hookstate = SKINNY_OFFHOOK;
05037             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05038             transmit_activatecallplane(d, l);
05039          }
05040          transmit_clear_display_message(d, l->instance, sub->callid);
05041          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05042          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05043 
05044          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
05045             transmit_stop_tone(d, l->instance, sub->callid);
05046          }
05047          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
05048          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05049             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05050             ast_hangup(c);
05051          }
05052       }
05053       break;
05054    case STIMULUS_SPEEDDIAL:
05055        {
05056       struct skinny_speeddial *sd;
05057 
05058       if (skinnydebug)
05059          ast_verb(1, "Received Stimulus: SpeedDial(%d/%d)\n", instance, callreference);
05060       if (!(sd = find_speeddial_by_instance(d, instance, 0))) {
05061          return 0;
05062       }
05063 
05064       if (!sub || !sub->owner)
05065          c = skinny_new(l, AST_STATE_DOWN, NULL);
05066       else
05067          c = sub->owner;
05068 
05069       if (!c) {
05070          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05071       } else {
05072          sub = c->tech_pvt;
05073          l = sub->parent;
05074          l->activesub = sub;
05075          if (l->hookstate == SKINNY_ONHOOK) {
05076             l->hookstate = SKINNY_OFFHOOK;
05077             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05078             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05079             transmit_activatecallplane(d, l);
05080          }
05081          transmit_clear_display_message(d, l->instance, sub->callid);
05082          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05083          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05084 
05085          if (!ast_ignore_pattern(c->context, sd->exten)) {
05086             transmit_stop_tone(d, l->instance, sub->callid);
05087          }
05088          if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
05089             ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
05090             ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
05091 
05092             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05093                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05094                ast_hangup(c);
05095             }
05096             break;
05097          }
05098       }
05099        }
05100       break;
05101    case STIMULUS_HOLD:
05102       if (skinnydebug)
05103          ast_verb(1, "Received Stimulus: Hold(%d/%d)\n", instance, callreference);
05104       handle_hold_button(sub);
05105       break;
05106    case STIMULUS_TRANSFER:
05107       if (skinnydebug)
05108          ast_verb(1, "Received Stimulus: Transfer(%d/%d)\n", instance, callreference);
05109       if (l->transfer)
05110          handle_transfer_button(sub);
05111       else
05112          transmit_displaynotify(d, "Transfer disabled", 10);
05113       break;
05114    case STIMULUS_CONFERENCE:
05115       if (skinnydebug)
05116          ast_verb(1, "Received Stimulus: Conference(%d/%d)\n", instance, callreference);
05117       /* XXX determine the best way to pull off a conference.  Meetme? */
05118       break;
05119    case STIMULUS_VOICEMAIL:
05120       if (skinnydebug)
05121          ast_verb(1, "Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
05122 
05123       if (!sub || !sub->owner) {
05124          c = skinny_new(l, AST_STATE_DOWN, NULL);
05125       } else {
05126          c = sub->owner;
05127       }
05128       if (!c) {
05129          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05130       } else {
05131          sub = c->tech_pvt;
05132          l = sub->parent;
05133          l->activesub = sub;
05134 
05135          if (ast_strlen_zero(l->vmexten))  /* Exit the call if no VM pilot */
05136             break;
05137 
05138          if (l->hookstate == SKINNY_ONHOOK){
05139             l->hookstate = SKINNY_OFFHOOK;
05140             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05141             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05142             transmit_activatecallplane(d, l);
05143          }
05144 
05145          transmit_clear_display_message(d, l->instance, sub->callid);
05146          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05147          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05148 
05149          if (!ast_ignore_pattern(c->context, l->vmexten)) {
05150             transmit_stop_tone(d, l->instance, sub->callid);
05151          }
05152 
05153          if (ast_exists_extension(c, c->context, l->vmexten, 1, l->cid_num)) {
05154             ast_copy_string(c->exten, l->vmexten, sizeof(c->exten));
05155             ast_copy_string(l->lastnumberdialed, l->vmexten, sizeof(l->lastnumberdialed));
05156             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05157                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05158                ast_hangup(c);
05159             }
05160             break;
05161          }
05162       }
05163       break;
05164    case STIMULUS_CALLPARK:
05165       {
05166       int extout;
05167       char message[32];
05168 
05169       if (skinnydebug)
05170          ast_verb(1, "Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
05171 
05172       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
05173          c = sub->owner;
05174          if (ast_bridged_channel(c)) {
05175             if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
05176                snprintf(message, sizeof(message), "Call Parked at: %d", extout);
05177                transmit_displaynotify(d, message, 10);
05178             } else {
05179                transmit_displaynotify(d, "Call Park failed", 10);
05180             }
05181          } else {
05182             transmit_displaynotify(d, "Call Park not available", 10);
05183          }
05184       } else {
05185          transmit_displaynotify(d, "Call Park not available", 10);
05186       }
05187       break;
05188       }
05189    case STIMULUS_DND:
05190       if (skinnydebug)
05191          ast_verb(1, "Received Stimulus: DND (%d/%d)\n", instance, callreference);
05192 
05193       /* Do not disturb */
05194       if (l->dnd != 0){
05195          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
05196          l->dnd = 0;
05197          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
05198          transmit_displaynotify(d, "DnD disabled", 10);
05199       } else {
05200          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
05201          l->dnd = 1;
05202          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
05203          transmit_displaynotify(d, "DnD enabled", 10);
05204       }
05205       break;
05206    case STIMULUS_FORWARDALL:
05207       if (skinnydebug)
05208          ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
05209 
05210       if (!sub || !sub->owner) {
05211          c = skinny_new(l, AST_STATE_DOWN, NULL);
05212       } else {
05213          c = sub->owner;
05214       }
05215 
05216       if (!c) {
05217          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05218       } else {
05219          sub = c->tech_pvt;
05220          handle_callforward_button(sub, SKINNY_CFWD_ALL);
05221       }
05222       break;
05223    case STIMULUS_FORWARDBUSY:
05224       if (skinnydebug)
05225          ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
05226 
05227       if (!sub || !sub->owner) {
05228          c = skinny_new(l, AST_STATE_DOWN, NULL);
05229       } else {
05230          c = sub->owner;
05231       }
05232 
05233       if (!c) {
05234          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05235       } else {
05236          sub = c->tech_pvt;
05237          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
05238       }
05239       break;
05240    case STIMULUS_FORWARDNOANSWER:
05241       if (skinnydebug)
05242          ast_verb(1, "Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
05243 
05244 #if 0 /* Not sure how to handle this yet */
05245       if (!sub || !sub->owner) {
05246          c = skinny_new(l, AST_STATE_DOWN, NULL);
05247       } else {
05248          c = sub->owner;
05249       }
05250 
05251       if (!c) {
05252          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05253       } else {
05254          sub = c->tech_pvt;
05255          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
05256       }
05257 #endif
05258       break;
05259    case STIMULUS_DISPLAY:
05260       /* Not sure what this is */
05261       if (skinnydebug)
05262          ast_verb(1, "Received Stimulus: Display(%d/%d)\n", instance, callreference);
05263       break;
05264    case STIMULUS_LINE:
05265       if (skinnydebug)
05266          ast_verb(1, "Received Stimulus: Line(%d/%d)\n", instance, callreference);
05267 
05268       l = find_line_by_instance(d, instance);
05269 
05270       if (!l) {
05271          return 0;
05272       }
05273 
05274       d->activeline = l;
05275 
05276       /* turn the speaker on */
05277       transmit_speaker_mode(d, SKINNY_SPEAKERON);
05278       transmit_ringer_mode(d, SKINNY_RING_OFF);
05279       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05280 
05281       l->hookstate = SKINNY_OFFHOOK;
05282 
05283       if (sub && sub->outgoing) {
05284          /* We're answering a ringing call */
05285          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05286          transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05287          transmit_activatecallplane(d, l);
05288          transmit_stop_tone(d, l->instance, sub->callid);
05289          transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
05290          transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
05291          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05292          start_rtp(sub);
05293          ast_setstate(sub->owner, AST_STATE_UP);
05294       } else {
05295          if (sub && sub->owner) {
05296             ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
05297          } else {
05298             c = skinny_new(l, AST_STATE_DOWN, NULL);
05299             if (c) {
05300                sub = c->tech_pvt;
05301                l->activesub = sub;
05302                transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05303                transmit_activatecallplane(d, l);
05304                transmit_clear_display_message(d, l->instance, sub->callid);
05305                transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05306                transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05307 
05308                /* start the switch thread */
05309                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05310                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05311                   ast_hangup(c);
05312                }
05313             } else {
05314                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05315             }
05316          }
05317       }
05318       break;
05319    default:
05320       if (skinnydebug)
05321          ast_verb(1, "RECEIVED UNKNOWN STIMULUS:  %d(%d/%d)\n", event, instance, callreference);
05322       break;
05323    }
05324    ast_devstate_changed(AST_DEVICE_UNKNOWN, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
05325 
05326    return 1;
05327 }

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4707 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verbose, skinny_subchannel::blindxfer, skinny_subchannel::callid, errno, KEYDEF_OFFHOOKWITHFEAT, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::owner, SKINNY_DIALTONE, skinny_hold(), skinny_new(), SKINNY_OFFHOOK, skinny_ss(), skinny_transfer(), ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_selectsoftkeys(), transmit_start_tone(), and skinny_subchannel::xferor.

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

04708 {
04709    struct skinny_line *l;
04710    struct skinny_device *d;
04711    struct skinny_subchannel *newsub;
04712    struct ast_channel *c;
04713    pthread_t t;
04714 
04715    if (!sub) {
04716       ast_verbose("Transfer: No subchannel to transfer\n");
04717       return -1;
04718    }
04719 
04720    l = sub->parent;
04721    d = l->device;
04722 
04723    if (!d) {
04724       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04725       return -1;
04726    }
04727 
04728    if (!sub->related) {
04729       /* Another sub has not been created so this must be first XFER press */
04730       if (!sub->onhold) {
04731          skinny_hold(sub);
04732       }
04733       c = skinny_new(l, AST_STATE_DOWN, NULL);
04734       if (c) {
04735          newsub = c->tech_pvt;
04736          /* point the sub and newsub at each other so we know they are related */
04737          newsub->related = sub;
04738          sub->related = newsub;
04739          newsub->xferor = 1;
04740          l->activesub = newsub;
04741          transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
04742          transmit_activatecallplane(d, l);
04743          transmit_clear_display_message(d, l->instance, newsub->callid);
04744          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, newsub->callid);
04745          transmit_selectsoftkeys(d, l->instance, newsub->callid, KEYDEF_OFFHOOKWITHFEAT);
04746          /* start the switch thread */
04747          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04748             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04749             ast_hangup(c);
04750          }
04751       } else {
04752          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04753       }
04754    } else {
04755       /* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
04756       if (sub->blindxfer) {
04757          /* toggle blindxfer off */
04758          sub->blindxfer = 0;
04759          sub->related->blindxfer = 0;
04760          /* we really need some indications */
04761       } else {
04762          /* We were doing attended transfer */
04763          if (sub->owner->_state == AST_STATE_DOWN || sub->related->owner->_state == AST_STATE_DOWN) {
04764             /* one of the subs so we cant transfer yet, toggle blindxfer on */
04765             sub->blindxfer = 1;
04766             sub->related->blindxfer = 1;
04767          } else {
04768             /* big assumption we have two channels, lets transfer */
04769             skinny_transfer(sub);
04770          }
04771       }
04772    }
04773    return 0;
04774 }

static int load_module ( void   )  [static]

Definition at line 7479 of file chan_skinny.c.

References ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_log(), ast_manager_register_xml, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_glue_register, cli_skinny, config_load(), EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, htolel, io_context_create(), LOG_ERROR, LOG_WARNING, manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), skinny_req::res, restart_monitor(), sched_context_create(), skinny_rtp_glue, skinny_tech, and soft_key_template_definition::softKeyEvent.

07480 {
07481    int res = 0;
07482 
07483    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
07484       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
07485    }
07486    /* load and parse config */
07487    res = config_load();
07488    if (res == -1) {
07489       return AST_MODULE_LOAD_DECLINE;
07490    }
07491 
07492    /* Make sure we can register our skinny channel type */
07493    if (ast_channel_register(&skinny_tech)) {
07494       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
07495       return -1;
07496    }
07497 
07498    ast_rtp_glue_register(&skinny_rtp_glue);
07499    ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07500 
07501    ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
07502    ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
07503    ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
07504    ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
07505 
07506    sched = sched_context_create();
07507    if (!sched) {
07508       ast_log(LOG_WARNING, "Unable to create schedule context\n");
07509    }
07510    io = io_context_create();
07511    if (!io) {
07512       ast_log(LOG_WARNING, "Unable to create I/O context\n");
07513    }
07514    /* And start the monitor for the first time */
07515    restart_monitor();
07516 
07517    return AST_MODULE_LOAD_SUCCESS;
07518 }

static int manager_skinny_show_device ( struct mansession s,
const struct message m 
) [static]

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

03348 {
03349    const char *a[4];
03350    const char *device;
03351 
03352    device = astman_get_header(m, "Device");
03353    if (ast_strlen_zero(device)) {
03354       astman_send_error(s, m, "Device: <name> missing.");
03355       return 0;
03356    }
03357    a[0] = "skinny";
03358    a[1] = "show";
03359    a[2] = "device";
03360    a[3] = device;
03361 
03362    _skinny_show_device(1, -1, s, m, 4, a);
03363    astman_append(s, "\r\n\r\n" );
03364    return 0;
03365 }

static int manager_skinny_show_devices ( struct mansession s,
const struct message m 
) [static]

Show SKINNY devices in the manager API.

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

03212 {
03213    const char *id = astman_get_header(m, "ActionID");
03214    const char *a[] = {"skinny", "show", "devices"};
03215    char idtext[256] = "";
03216    int total = 0;
03217 
03218    if (!ast_strlen_zero(id))
03219       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03220 
03221    astman_send_listack(s, m, "Device status list will follow", "start");
03222    /* List the devices in separate manager events */
03223    _skinny_show_devices(-1, &total, s, m, 3, a);
03224    /* Send final confirmation */
03225    astman_append(s,
03226    "Event: DevicelistComplete\r\n"
03227    "EventList: Complete\r\n"
03228    "ListItems: %d\r\n"
03229    "%s"
03230    "\r\n", total, idtext);
03231    return 0;
03232 }

static int manager_skinny_show_line ( struct mansession s,
const struct message m 
) [static]

Definition at line 3640 of file chan_skinny.c.

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

Referenced by load_module().

03641 {
03642    const char *a[4];
03643    const char *line;
03644 
03645    line = astman_get_header(m, "Line");
03646    if (ast_strlen_zero(line)) {
03647       astman_send_error(s, m, "Line: <name> missing.");
03648       return 0;
03649    }
03650    a[0] = "skinny";
03651    a[1] = "show";
03652    a[2] = "line";
03653    a[3] = line;
03654 
03655    _skinny_show_line(1, -1, s, m, 4, a);
03656    astman_append(s, "\r\n\r\n" );
03657    return 0;
03658 }

static int manager_skinny_show_lines ( struct mansession s,
const struct message m 
) [static]

Show Skinny lines in the manager API.

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

03460 {
03461    const char *id = astman_get_header(m, "ActionID");
03462    const char *a[] = {"skinny", "show", "lines"};
03463    char idtext[256] = "";
03464    int total = 0;
03465 
03466    if (!ast_strlen_zero(id))
03467       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03468 
03469    astman_send_listack(s, m, "Line status list will follow", "start");
03470    /* List the lines in separate manager events */
03471    _skinny_show_lines(-1, &total, s, m, 3, a);
03472    /* Send final confirmation */
03473    astman_append(s,
03474    "Event: LinelistComplete\r\n"
03475    "EventList: Complete\r\n"
03476    "ListItems: %d\r\n"
03477    "%s"
03478    "\r\n", total, idtext);
03479    return 0;
03480 }

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

Definition at line 2730 of file chan_skinny.c.

References ast_event_get_ie_uint(), AST_EVENT_IE_NEWMSGS, AST_LIST_TRAVERSE, ast_verb, 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().

02731 {
02732    struct skinny_line *l = userdata;
02733    struct skinny_device *d = l->device;
02734    if (d) {
02735       struct skinnysession *s = d->session;
02736       struct skinny_line *l2;
02737       int new_msgs = 0;
02738       int dev_msgs = 0;
02739 
02740       if (s) {
02741          if (event) {
02742             l->newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02743          }
02744 
02745          if (l->newmsgs) {
02746             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02747          } else {
02748             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
02749          }
02750 
02751          /* find out wether the device lamp should be on or off */
02752          AST_LIST_TRAVERSE(&d->lines, l2, list) {
02753             if (l2->newmsgs) {
02754                dev_msgs++;
02755             }
02756          }
02757 
02758          if (dev_msgs) {
02759             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, d->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02760          } else {
02761             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_OFF);
02762          }
02763          ast_verb(3, "Skinny mwi_event_cb found %d new messages\n", new_msgs);
02764       }
02765    }
02766 }

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

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

Referenced by _skinny_show_line().

03124 {
03125    int x, codec;
03126 
03127    for(x = 0; x < 32 ; x++) {
03128       codec = ast_codec_pref_index(pref, x);
03129       if (!codec)
03130          break;
03131       ast_cli(fd, "%s", ast_getformatname(codec));
03132       ast_cli(fd, ":%d", pref->framing[x]);
03133       if (x < 31 && ast_codec_pref_index(pref, x + 1))
03134          ast_cli(fd, ",");
03135    }
03136    if (!x)
03137       ast_cli(fd, "none");
03138 }

static void register_exten ( struct skinny_line l  )  [static]

Definition at line 1821 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, and S_OR.

Referenced by skinny_register().

01822 {
01823    char multi[256];
01824    char *stringp, *ext, *context;
01825 
01826    if (ast_strlen_zero(regcontext))
01827       return;
01828 
01829    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01830    stringp = multi;
01831    while ((ext = strsep(&stringp, "&"))) {
01832       if ((context = strchr(ext, '@'))) {
01833          *context++ = '\0'; /* split ext@context */
01834          if (!ast_context_find(context)) {
01835             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01836             continue;
01837          }
01838       } else {
01839          context = regcontext;
01840       }
01841       ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
01842           ast_strdup(l->name), ast_free_ptr, "Skinny");
01843    }
01844 }

static int reload ( void   )  [static]

Definition at line 7597 of file chan_skinny.c.

References skinny_reload().

07598 {
07599    skinny_reload();
07600    return 0;
07601 }

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

Definition at line 6630 of file chan_skinny.c.

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

Referenced by load_module(), and skinny_request().

06631 {
06632    /* If we're supposed to be stopped -- stay stopped */
06633    if (monitor_thread == AST_PTHREADT_STOP)
06634       return 0;
06635 
06636    ast_mutex_lock(&monlock);
06637    if (monitor_thread == pthread_self()) {
06638       ast_mutex_unlock(&monlock);
06639       ast_log(LOG_WARNING, "Cannot kill myself\n");
06640       return -1;
06641    }
06642    if (monitor_thread != AST_PTHREADT_NULL) {
06643       /* Wake up the thread */
06644       pthread_kill(monitor_thread, SIGURG);
06645    } else {
06646       /* Start a new monitor */
06647       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06648          ast_mutex_unlock(&monlock);
06649          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06650          return -1;
06651       }
06652    }
06653    ast_mutex_unlock(&monlock);
06654    return 0;
06655 }

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

Definition at line 1763 of file chan_skinny.c.

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

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

01764 {
01765    if (!l)
01766       return 0;
01767 
01768    if (!ast_strlen_zero(cfwd)) {
01769       if (cfwdtype & SKINNY_CFWD_ALL) {
01770          l->cfwdtype |= SKINNY_CFWD_ALL;
01771          ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
01772       }
01773       if (cfwdtype & SKINNY_CFWD_BUSY) {
01774          l->cfwdtype |= SKINNY_CFWD_BUSY;
01775          ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
01776       }
01777       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01778          l->cfwdtype |= SKINNY_CFWD_NOANSWER;
01779          ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
01780       }
01781    } else {
01782       if (cfwdtype & SKINNY_CFWD_ALL) {
01783          l->cfwdtype &= ~SKINNY_CFWD_ALL;
01784          memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
01785       }
01786       if (cfwdtype & SKINNY_CFWD_BUSY) {
01787          l->cfwdtype &= ~SKINNY_CFWD_BUSY;
01788          memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
01789       }
01790       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01791          l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
01792          memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
01793       }
01794    }
01795    return l->cfwdtype;
01796 }

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 4071 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_debug, ast_setstate(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, ast_channel::connected, skinny_subchannel::cxmode, ast_party_connected_line::id, KEYDEF_CONNECTED, ast_party_id::name, ast_party_id::number, skinny_subchannel::rtp, S_COR, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, skinny_transfer(), start_rtp(), ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), transmit_stop_tone(), ast_party_number::valid, and ast_party_name::valid.

04072 {
04073    int res = 0;
04074    struct skinny_subchannel *sub = ast->tech_pvt;
04075    struct skinny_line *l = sub->parent;
04076    struct skinny_device *d = l->device;
04077 
04078    if (sub->blindxfer) {
04079       if (skinnydebug)
04080          ast_debug(1, "skinny_answer(%s) on %s@%s-%u with BlindXFER, transferring\n",
04081             ast->name, l->name, d->name, sub->callid);
04082       ast_setstate(ast, AST_STATE_UP);
04083       skinny_transfer(sub);
04084       return 0;
04085    }
04086 
04087    sub->cxmode = SKINNY_CX_SENDRECV;
04088    if (!sub->rtp) {
04089       start_rtp(sub);
04090    }
04091    if (skinnydebug)
04092       ast_verb(1, "skinny_answer(%s) on %s@%s-%u\n", ast->name, l->name, d->name, sub->callid);
04093    if (ast->_state != AST_STATE_UP) {
04094       ast_setstate(ast, AST_STATE_UP);
04095    }
04096 
04097    transmit_stop_tone(d, l->instance, sub->callid);
04098    /* order matters here...
04099       for some reason, transmit_callinfo must be before transmit_callstate,
04100       or you won't get keypad messages in some situations. */
04101    transmit_callinfo(d,
04102       S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
04103       S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
04104       l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
04105    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
04106    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
04107    transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
04108    transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
04109    l->activesub = sub;
04110    return res;
04111 }

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

Definition at line 3918 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, AST_CONTROL_BUSY, AST_CONTROL_RINGING, AST_LIST_NEXT, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_verb, skinny_subchannel::callid, ast_channel::connected, ast_party_connected_line::id, KEYDEF_RINGIN, LOG_ERROR, LOG_WARNING, ast_party_id::name, ast_party_id::number, skinny_subchannel::outgoing, S_COR, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, STIMULUS_LINE, ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), ast_party_number::valid, and ast_party_name::valid.

03919 {
03920    int res = 0;
03921    struct skinny_subchannel *sub = ast->tech_pvt;
03922    struct skinny_line *l = sub->parent;
03923    struct skinny_device *d = l->device;
03924 
03925    if (!d || !d->registered) {
03926       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03927       return -1;
03928    }
03929 
03930    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03931       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
03932       return -1;
03933    }
03934 
03935    if (skinnydebug)
03936       ast_verb(3, "skinny_call(%s)\n", ast->name);
03937 
03938    if (l->dnd) {
03939       ast_queue_control(ast, AST_CONTROL_BUSY);
03940       return -1;
03941    }
03942 
03943    if (AST_LIST_NEXT(sub,list) && !l->callwaiting) {
03944       ast_queue_control(ast, AST_CONTROL_BUSY);
03945       return -1;
03946    }
03947    
03948    switch (l->hookstate) {
03949    case SKINNY_OFFHOOK:
03950       break;
03951    case SKINNY_ONHOOK:
03952       l->activesub = sub;
03953       break;
03954    default:
03955       ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
03956       break;
03957    }
03958 
03959    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGIN);
03960    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
03961    transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
03962    transmit_callinfo(d,
03963       S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
03964       S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""),
03965       l->cid_name, l->cid_num, l->instance, sub->callid, 1);
03966    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03967    transmit_ringer_mode(d, SKINNY_RING_INSIDE);
03968 
03969    ast_setstate(ast, AST_STATE_RINGING);
03970    ast_queue_control(ast, AST_CONTROL_RINGING);
03971    sub->outgoing = 1;
03972    return res;
03973 }

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6657 of file chan_skinny.c.

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

06658 {
06659    struct skinny_line *l;
06660    char *tmp;
06661 
06662    tmp = ast_strdupa(data);
06663 
06664    l = find_line_by_name(tmp);
06665 
06666    return get_devicestate(l);
06667 }

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

Definition at line 2626 of file chan_skinny.c.

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

Referenced by skinny_register().

02627 {
02628    struct skinny_speeddial *sd = data;
02629    struct skinny_device *d = sd->parent;
02630    char hint[AST_MAX_EXTENSION];
02631 
02632    if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
02633       /* If they are not registered, we will override notification and show no availability */
02634       if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
02635          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_FLASH);
02636          transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
02637       }
02638    } else {
02639       switch (state) {
02640       case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
02641       case AST_EXTENSION_REMOVED:     /* Extension is gone */
02642          ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
02643          sd->stateid = -1;
02644          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
02645          transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
02646          break;
02647       case AST_EXTENSION_RINGING:
02648       case AST_EXTENSION_UNAVAILABLE:
02649          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_BLINK);
02650          transmit_callstate(d, sd->instance, SKINNY_RINGIN, 0);
02651          break;
02652       case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
02653       case AST_EXTENSION_INUSE:
02654          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_ON);
02655          transmit_callstate(d, sd->instance, SKINNY_CALLREMOTEMULTILINE, 0);
02656          break;
02657       case AST_EXTENSION_ONHOLD:
02658          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_WINK);
02659          transmit_callstate(d, sd->instance, SKINNY_HOLD, 0);
02660          break;
02661       case AST_EXTENSION_NOT_INUSE:
02662       default:
02663          transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, SKINNY_LAMP_OFF);
02664          transmit_callstate(d, sd->instance, SKINNY_ONHOOK, 0);
02665          break;
02666       }
02667    }
02668 
02669    sd->laststate = state;
02670 
02671    return 0;
02672 }

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

Definition at line 4203 of file chan_skinny.c.

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

04204 {
04205    struct skinny_subchannel *sub = newchan->tech_pvt;
04206    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
04207    if (sub->owner != oldchan) {
04208       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
04209       return -1;
04210    }
04211    sub->owner = newchan;
04212    return 0;
04213 }

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

Definition at line 2784 of file chan_skinny.c.

References ao2_ref, ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, ast_verb, skinny_subchannel::lock, skinny_subchannel::rtp, and ast_channel::tech_pvt.

02785 {
02786    struct skinny_subchannel *sub = NULL;
02787    struct skinny_line *l;
02788    enum ast_rtp_glue_result res = AST_RTP_GLUE_RESULT_REMOTE;
02789 
02790    if (skinnydebug)
02791       ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
02792 
02793 
02794    if (!(sub = c->tech_pvt))
02795       return AST_RTP_GLUE_RESULT_FORBID;
02796 
02797    ast_mutex_lock(&sub->lock);
02798 
02799    if (!(sub->rtp)){
02800       ast_mutex_unlock(&sub->lock);
02801       return AST_RTP_GLUE_RESULT_FORBID;
02802    }
02803 
02804    ao2_ref(sub->rtp, +1);
02805    *instance = sub->rtp;
02806 
02807    l = sub->parent;
02808 
02809    if (!l->directmedia || l->nat){
02810       res = AST_RTP_GLUE_RESULT_LOCAL;
02811       if (skinnydebug)
02812          ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_GLUE_RESULT_LOCAL \n");
02813    }
02814 
02815    ast_mutex_unlock(&sub->lock);
02816 
02817    return res;
02818 
02819 }

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

Definition at line 2771 of file chan_skinny.c.

References ao2_ref, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_REMOTE, ast_channel::tech_pvt, and skinny_subchannel::vrtp.

02772 {
02773    struct skinny_subchannel *sub = NULL;
02774 
02775    if (!(sub = c->tech_pvt) || !(sub->vrtp))
02776       return AST_RTP_GLUE_RESULT_FORBID;
02777 
02778    ao2_ref(sub->vrtp, +1);
02779    *instance = sub->vrtp;
02780 
02781    return AST_RTP_GLUE_RESULT_REMOTE;
02782 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3975 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, skinny_subchannel::alreadygone, ast_debug, ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_NEXT, AST_LIST_REMOVE, ast_log(), ast_module_unref(), ast_mutex_lock, ast_mutex_unlock, ast_rtp_instance_destroy(), ast_verb, skinny_subchannel::callid, KEYDEF_ONHOOK, skinny_subchannel::lock, LOG_WARNING, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::rtp, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SPEAKEROFF, STIMULUS_LINE, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stop_tone(), and transmit_stopmediatransmission().

03976 {
03977    struct skinny_subchannel *sub = ast->tech_pvt;
03978    struct skinny_line *l;
03979    struct skinny_device *d;
03980 
03981    if (!sub) {
03982       ast_debug(1, "Asked to hangup channel not connected\n");
03983       return 0;
03984    }
03985 
03986    l = sub->parent;
03987    d = l->device;
03988 
03989    if (!d) {
03990       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
03991       return 0;
03992    }
03993 
03994    if (skinnydebug)
03995       ast_verb(3,"Hanging up %s/%u\n", d->name, sub->callid);
03996 
03997    AST_LIST_REMOVE(&l->sub, sub, list);
03998 
03999    if (d->registered) {
04000       /* Ignoring l->type, doesn't seem relevant and previous code 
04001          assigned rather than tested, ie always true */
04002       if (!AST_LIST_EMPTY(&l->sub)) {
04003          if (sub->related) {
04004             sub->related->related = NULL;
04005 
04006          }
04007          if (sub == l->activesub) {      /* we are killing the active sub, but there are other subs on the line*/
04008             ast_verb(4,"Killing active sub %u\n", sub->callid);
04009             if (sub->related) {
04010                l->activesub = sub->related;
04011             } else {
04012                if (AST_LIST_NEXT(sub, list)) {
04013                   l->activesub = AST_LIST_NEXT(sub, list);
04014                } else {
04015                   l->activesub = AST_LIST_FIRST(&l->sub);
04016                }
04017             }
04018             //transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
04019             transmit_activatecallplane(d, l);
04020             transmit_closereceivechannel(d, sub);
04021             transmit_stopmediatransmission(d, sub);
04022             transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
04023             transmit_stop_tone(d, l->instance, sub->callid);
04024          } else {    /* we are killing a background sub on the line with other subs*/
04025             ast_verb(4,"Killing inactive sub %u\n", sub->callid);
04026             if (AST_LIST_NEXT(sub, list)) {
04027                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
04028             } else {
04029                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04030             }
04031          }
04032       } else {                                                /* no more subs on line so make idle */
04033          ast_verb(4,"Killing only sub %u\n", sub->callid);
04034          l->hookstate = SKINNY_ONHOOK;
04035          transmit_closereceivechannel(d, sub);
04036          transmit_stopmediatransmission(d, sub);
04037          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04038          transmit_clearpromptmessage(d, l->instance, sub->callid);
04039          transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
04040          transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
04041          transmit_activatecallplane(d, l);
04042          l->activesub = NULL;
04043          transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
04044          if (sub->parent == d->activeline) {
04045             transmit_activatecallplane(d, l);
04046             transmit_closereceivechannel(d, sub);
04047             transmit_stopmediatransmission(d, sub);
04048             transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04049             transmit_ringer_mode(d, SKINNY_RING_OFF);
04050             transmit_clear_display_message(d, l->instance, sub->callid);
04051             transmit_stop_tone(d, l->instance, sub->callid);
04052             /* we should check to see if we can start the ringer if another line is ringing */
04053          }
04054       }
04055    }
04056    ast_mutex_lock(&sub->lock);
04057    sub->owner = NULL;
04058    ast->tech_pvt = NULL;
04059    sub->alreadygone = 0;
04060    sub->outgoing = 0;
04061    if (sub->rtp) {
04062       ast_rtp_instance_destroy(sub->rtp);
04063       sub->rtp = NULL;
04064    }
04065    ast_mutex_unlock(&sub->lock);
04066    ast_free(sub);
04067    ast_module_unref(ast_module_info->self);
04068    return 0;
04069 }

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 4625 of file chan_skinny.c.

References AST_CONTROL_HOLD, ast_log(), ast_queue_control_data(), ast_strlen_zero(), ast_verb, skinny_subchannel::callid, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::owner, S_OR, SKINNY_HOLD, SKINNY_LAMP_WINK, STIMULUS_LINE, transmit_activatecallplane(), transmit_callstate(), transmit_closereceivechannel(), transmit_lamp_indication(), and transmit_stopmediatransmission().

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

04626 {
04627    struct skinny_line *l = sub->parent;
04628    struct skinny_device *d = l->device;
04629 
04630    /* Don't try to hold a channel that doesn't exist */
04631    if (!sub || !sub->owner) {
04632       return 0;
04633    }
04634    if (!d) {
04635       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04636       return 0;
04637    }
04638 
04639    /* Channel needs to be put on hold */
04640    if (skinnydebug)
04641       ast_verb(1, "Putting on Hold(%d)\n", l->instance);
04642 
04643    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
04644       S_OR(l->mohsuggest, NULL),
04645       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
04646 
04647    transmit_activatecallplane(d, l);
04648    transmit_closereceivechannel(d, sub);
04649    transmit_stopmediatransmission(d, sub);
04650 
04651    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_HOLD);
04652    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
04653    sub->onhold = 1;
04654    return 1;
04655 }

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

Definition at line 4386 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_CONNECTED_LINE, AST_CONTROL_HOLD, AST_CONTROL_INCOMPLETE, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_instance_change_source(), ast_rtp_instance_update_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, ast_channel::caller, skinny_subchannel::callid, ast_channel::connected, control2str(), ast_party_connected_line::id, ast_party_caller::id, LOG_NOTICE, LOG_WARNING, ast_party_id::name, ast_party_id::number, skinny_subchannel::outgoing, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_subchannel::rtp, S_COR, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, skinny_transfer(), ast_party_number::str, ast_party_name::str, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_start_tone(), transmit_stop_tone(), update_connectedline(), ast_party_number::valid, and ast_party_name::valid.

04387 {
04388    struct skinny_subchannel *sub = ast->tech_pvt;
04389    struct skinny_line *l = sub->parent;
04390    struct skinny_device *d = l->device;
04391    struct skinnysession *s;
04392 
04393    if (!d) {
04394       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04395       return -1;
04396    }
04397    s = d->session;
04398 
04399    if (!s) {
04400       ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
04401       return -1;
04402    }
04403 
04404    if (skinnydebug)
04405       ast_verb(3, "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
04406    switch(ind) {
04407    case AST_CONTROL_RINGING:
04408       if (sub->blindxfer) {
04409          if (skinnydebug)
04410             ast_debug(1, "Channel %s set up for Blind Xfer, so Xfer rather than ring device\n", ast->name);
04411          skinny_transfer(sub);
04412          break;
04413       }
04414       if (ast->_state != AST_STATE_UP) {
04415          if (!sub->progress) {
04416             if (!d->earlyrtp) {
04417                transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
04418             }
04419             transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_RINGOUT);
04420             transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
04421             transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
04422             transmit_callinfo(d,
04423                S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
04424                S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
04425                S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed),
04426                S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed),
04427                l->instance, sub->callid, 2); /* 2 = outgoing from phone */
04428             sub->ringing = 1;
04429             if (!d->earlyrtp) {
04430                break;
04431             }
04432          }
04433       }
04434       return -1; /* Tell asterisk to provide inband signalling */
04435    case AST_CONTROL_BUSY:
04436       if (ast->_state != AST_STATE_UP) {
04437          if (!d->earlyrtp) {
04438             transmit_start_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
04439          }
04440          transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_BUSY);
04441          sub->alreadygone = 1;
04442          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
04443          if (!d->earlyrtp) {
04444             break;
04445          }
04446       }
04447       return -1; /* Tell asterisk to provide inband signalling */
04448    case AST_CONTROL_INCOMPLETE:
04449       /* Support for incomplete not supported for chan_skinny; treat as congestion */
04450    case AST_CONTROL_CONGESTION:
04451       if (ast->_state != AST_STATE_UP) {
04452          if (!d->earlyrtp) {
04453             transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
04454          }
04455          transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONGESTION);
04456          sub->alreadygone = 1;
04457          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
04458          if (!d->earlyrtp) {
04459             break;
04460          }
04461       }
04462       return -1; /* Tell asterisk to provide inband signalling */
04463    case AST_CONTROL_PROGRESS:
04464       if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
04465          if (!d->earlyrtp) {
04466             transmit_start_tone(d, SKINNY_ALERT, l->instance, sub->callid);
04467          }
04468          transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_PROGRESS);
04469          transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
04470          transmit_callinfo(d,
04471             S_COR(ast->caller.id.name.valid, ast->caller.id.name.str, ""),
04472             S_COR(ast->caller.id.number.valid, ast->caller.id.number.str, ""),
04473             S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, l->lastnumberdialed),
04474             S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, l->lastnumberdialed),
04475             l->instance, sub->callid, 2); /* 2 = outgoing from phone */
04476          sub->progress = 1;
04477          if (!d->earlyrtp) {
04478             break;
04479          }
04480       }
04481       return -1; /* Tell asterisk to provide inband signalling */
04482    case -1:  /* STOP_TONE */
04483       transmit_stop_tone(d, l->instance, sub->callid);
04484       break;
04485    case AST_CONTROL_HOLD:
04486       ast_moh_start(ast, data, l->mohinterpret);
04487       break;
04488    case AST_CONTROL_UNHOLD:
04489       ast_moh_stop(ast);
04490       break;
04491    case AST_CONTROL_PROCEEDING:
04492       break;
04493    case AST_CONTROL_SRCUPDATE:
04494       ast_rtp_instance_update_source(sub->rtp);
04495       break;
04496    case AST_CONTROL_SRCCHANGE:
04497       ast_rtp_instance_change_source(sub->rtp);
04498       break;
04499    case AST_CONTROL_CONNECTED_LINE:
04500       update_connectedline(sub, data, datalen);
04501       break;
04502    default:
04503       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
04504       return -1; /* Tell asterisk to provide inband signalling */
04505    }
04506    return 0;
04507 }

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

Definition at line 4509 of file chan_skinny.c.

References accountcode, ast_channel::adsicpe, ast_channel::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), AST_DEVICE_NOT_INUSE, 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_string_field_set, ast_strlen_zero(), ast_verb, skinny_subchannel::blindxfer, ast_channel::caller, ast_channel::callgroup, skinny_subchannel::callid, ast_channel::context, skinny_subchannel::cxmode, ast_channel::exten, get_devicestate(), global_jbconf, language, skinny_subchannel::lock, LOG_WARNING, ast_variable::name, skinny_subchannel::nat, ast_channel::nativeformats, ast_variable::next, ast_party_id::number, skinny_subchannel::onhold, skinny_subchannel::owner, parkinglot, pbx_builtin_setvar_helper(), ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, skinny_subchannel::rtp, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, skinny_tech, ast_party_number::str, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, ast_channel::writeformat, and skinny_subchannel::xferor.

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

04510 {
04511    struct ast_channel *tmp;
04512    struct skinny_subchannel *sub;
04513    struct skinny_device *d = l->device;
04514    struct ast_variable *v = NULL;
04515    int fmt;
04516 
04517    if (!l->device) {
04518       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04519       return NULL;
04520    }
04521 
04522    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);
04523    if (!tmp) {
04524       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
04525       return NULL;
04526    } else {
04527       sub = ast_calloc(1, sizeof(*sub));
04528       if (!sub) {
04529          ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
04530          return NULL;
04531       } else {
04532          ast_mutex_init(&sub->lock);
04533 
04534          sub->owner = tmp;
04535          sub->callid = callnums++;
04536          d->lastlineinstance = l->instance;
04537          d->lastcallreference = sub->callid;
04538          sub->cxmode = SKINNY_CX_INACTIVE;
04539          sub->nat = l->nat;
04540          sub->parent = l;
04541          sub->onhold = 0;
04542          sub->blindxfer = 0;
04543          sub->xferor = 0;
04544          sub->related = NULL;
04545 
04546          AST_LIST_INSERT_HEAD(&l->sub, sub, list);
04547          //l->activesub = sub;
04548       }
04549       tmp->tech = &skinny_tech;
04550       tmp->tech_pvt = sub;
04551       tmp->nativeformats = l->capability;
04552       if (!tmp->nativeformats)
04553          // Should throw an error
04554          tmp->nativeformats = default_capability;
04555       fmt = ast_best_codec(tmp->nativeformats);
04556       if (skinnydebug) {
04557          char buf[256];
04558          ast_verb(1, "skinny_new: tmp->nativeformats=%s fmt=%s\n",
04559             ast_getformatname_multiple(buf, sizeof(buf), tmp->nativeformats),
04560             ast_getformatname(fmt));
04561       }
04562       if (sub->rtp) {
04563          ast_channel_set_fd(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
04564       }
04565       if (state == AST_STATE_RING) {
04566          tmp->rings = 1;
04567       }
04568       tmp->writeformat = fmt;
04569       tmp->rawwriteformat = fmt;
04570       tmp->readformat = fmt;
04571       tmp->rawreadformat = fmt;
04572       if (!ast_strlen_zero(l->language))
04573          ast_string_field_set(tmp, language, l->language);
04574       if (!ast_strlen_zero(l->accountcode))
04575          ast_string_field_set(tmp, accountcode, l->accountcode);
04576       if (!ast_strlen_zero(l->parkinglot))
04577          ast_string_field_set(tmp, parkinglot, l->parkinglot);
04578       if (l->amaflags)
04579          tmp->amaflags = l->amaflags;
04580 
04581       ast_module_ref(ast_module_info->self);
04582       tmp->callgroup = l->callgroup;
04583       tmp->pickupgroup = l->pickupgroup;
04584 
04585       /* XXX Need to figure out how to handle CFwdNoAnswer */
04586       if (l->cfwdtype & SKINNY_CFWD_ALL) {
04587          ast_string_field_set(tmp, call_forward, l->call_forward_all);
04588       } else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
04589          if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
04590             ast_string_field_set(tmp, call_forward, l->call_forward_busy);
04591          }
04592       }
04593 
04594       ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
04595       ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
04596 
04597       /* Don't use ast_set_callerid() here because it will
04598        * generate a needless NewCallerID event */
04599       if (!ast_strlen_zero(l->cid_num)) {
04600          tmp->caller.ani.number.valid = 1;
04601          tmp->caller.ani.number.str = ast_strdup(l->cid_num);
04602       }
04603 
04604       tmp->priority = 1;
04605       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04606 
04607       if (sub->rtp)
04608          ast_jb_configure(tmp, &global_jbconf);
04609 
04610       /* Set channel variables for this call from configuration */
04611       for (v = l->chanvars ; v ; v = v->next)
04612          pbx_builtin_setvar_helper(tmp, v->name, v->value);
04613 
04614       if (state != AST_STATE_DOWN) {
04615          if (ast_pbx_start(tmp)) {
04616             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04617             ast_hangup(tmp);
04618             tmp = NULL;
04619          }
04620       }
04621    }
04622    return tmp;
04623 }

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

Definition at line 3773 of file chan_skinny.c.

References ast_party_caller::ani, ast_copy_string(), 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_channel::caller, skinny_subchannel::callid, ast_channel::connected, ast_channel::exten, ast_party_connected_line::id, LOG_WARNING, ast_party_id::name, ast_party_id::number, skinny_subchannel::rtp, SKINNY_REORDER, start_rtp(), ast_party_number::str, ast_channel::tech_pvt, transmit_start_tone(), and ast_party_number::valid.

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

03774 {
03775    struct ast_channel *c = data;
03776    struct skinny_subchannel *sub = c->tech_pvt;
03777    struct skinny_line *l = sub->parent;
03778    struct skinny_device *d = l->device;
03779    int res = 0;
03780 
03781    ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
03782    ast_set_callerid(c,
03783       l->hidecallerid ? "" : l->cid_num,
03784       l->hidecallerid ? "" : l->cid_name,
03785       c->caller.ani.number.valid ? NULL : l->cid_num);
03786 #if 1 /* XXX This code is probably not necessary */
03787    ast_party_number_free(&c->connected.id.number);
03788    ast_party_number_init(&c->connected.id.number);
03789    c->connected.id.number.valid = 1;
03790    c->connected.id.number.str = ast_strdup(c->exten);
03791    ast_party_name_free(&c->connected.id.name);
03792    ast_party_name_init(&c->connected.id.name);
03793 #endif
03794    ast_setstate(c, AST_STATE_RING);
03795    if (!sub->rtp) {
03796       start_rtp(sub);
03797    }
03798    res = ast_pbx_run(c);
03799    if (res) {
03800       ast_log(LOG_WARNING, "PBX exited non-zero\n");
03801       transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03802    }
03803    return NULL;
03804 }

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

Definition at line 4161 of file chan_skinny.c.

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

04162 {
04163    struct ast_frame *fr;
04164    struct skinny_subchannel *sub = ast->tech_pvt;
04165    ast_mutex_lock(&sub->lock);
04166    fr = skinny_rtp_read(sub);
04167    ast_mutex_unlock(&sub->lock);
04168    return fr;
04169 }

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

Definition at line 1870 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_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_sockaddr_from_sin, ast_strlen_zero(), ast_verb, skinny_speeddial::context, skinny_req::data, skinnysession::device, devices, EVENT_FLAG_SYSTEM, skinny_speeddial::exten, skinnysession::fd, skinny_device::ha, letohl, LOG_WARNING, manager_event, mwi_event_cb(), register_message::name, skinny_device::ourip, skinny_data::reg, register_exten(), skinny_device::session, set_callforwards(), skinnysession::sin, skinny_extensionstate_cb(), skinny_speeddial::stateid, and register_message::type.

Referenced by handle_register_message().

01871 {
01872    struct skinny_device *d;
01873    struct skinny_line *l;
01874    struct skinny_speeddial *sd;
01875    struct sockaddr_in sin;
01876    socklen_t slen;
01877    int instance;
01878 
01879    AST_LIST_LOCK(&devices);
01880    AST_LIST_TRAVERSE(&devices, d, list){
01881       struct ast_sockaddr addr;
01882       ast_sockaddr_from_sin(&addr, &s->sin);
01883       if (!strcasecmp(req->data.reg.name, d->id)
01884             && ast_apply_ha(d->ha, &addr)) {
01885          s->device = d;
01886          d->type = letohl(req->data.reg.type);
01887          if (ast_strlen_zero(d->version_id)) {
01888             ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
01889          }
01890          d->registered = 1;
01891          d->session = s;
01892 
01893          slen = sizeof(sin);
01894          if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
01895             ast_log(LOG_WARNING, "Cannot get socket name\n");
01896             sin.sin_addr = __ourip;
01897          }
01898          d->ourip = sin.sin_addr;
01899 
01900          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01901             sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd);
01902          }
01903          instance = 0;
01904          AST_LIST_TRAVERSE(&d->lines, l, list) {
01905             instance++;
01906          }
01907          AST_LIST_TRAVERSE(&d->lines, l, list) {
01908             /* FIXME: All sorts of issues will occur if this line is already connected to a device */
01909             if (l->device) {
01910                manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Rejected\r\nCause: LINE_ALREADY_CONNECTED\r\n", l->name, l->device->name); 
01911                ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name);
01912             } else {
01913                l->device = d;
01914                l->capability = l->confcapability & d->capability;
01915                l->prefs = l->confprefs;
01916                if (!l->prefs.order[0]) {
01917                   l->prefs = d->confprefs;
01918                }
01919                /* l->capability = d->capability;
01920                l->prefs = d->prefs; */
01921                l->instance = instance;
01922                l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
01923                set_callforwards(l, NULL, 0);
01924                manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Registered\r\n", l->name, d->name);
01925                register_exten(l);
01926                /* initialize MWI on line and device */
01927                mwi_event_cb(0, l);
01928                ast_devstate_changed(AST_DEVICE_NOT_INUSE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
01929             }
01930             --instance;
01931          }
01932          break;
01933       }
01934    }
01935    AST_LIST_UNLOCK(&devices);
01936    if (!d) {
01937       return 0;
01938    }
01939    return 1;
01940 }

int skinny_reload ( void   )  [static]

Definition at line 7397 of file chan_skinny.c.

References 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(), skinny_req::data, devices, free, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, skinny_device::session, and transmit_response().

Referenced by handle_skinny_reload(), and reload().

07398 {
07399    struct skinny_device *d;
07400    struct skinny_line *l;
07401    struct skinny_speeddial *sd;
07402    struct skinny_addon *a;
07403    struct skinny_req *req;
07404 
07405    if (skinnyreload) {
07406       ast_verb(3, "Chan_skinny is already reloading.\n");
07407       return 0;
07408    }
07409 
07410    skinnyreload = 1;
07411 
07412    /* Mark all devices and lines as candidates to be pruned */
07413    AST_LIST_LOCK(&devices);
07414    AST_LIST_TRAVERSE(&devices, d, list) {
07415       d->prune = 1;
07416    }
07417    AST_LIST_UNLOCK(&devices);
07418 
07419    AST_LIST_LOCK(&lines);
07420    AST_LIST_TRAVERSE(&lines, l, all) {
07421       l->prune = 1;
07422    }
07423    AST_LIST_UNLOCK(&lines);
07424 
07425         config_load();
07426 
07427    /* Remove any devices that no longer exist in the config */
07428    AST_LIST_LOCK(&devices);
07429    AST_LIST_TRAVERSE_SAFE_BEGIN(&devices, d, list) {
07430       if (!d->prune) {
07431          continue;
07432       }
07433       ast_verb(3, "Removing device '%s'\n", d->name);
07434       /* Delete all lines for this device. 
07435          We do not want to free the line here, that
07436          will happen below. */
07437       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07438       }
07439       /* Delete all speeddials for this device */
07440       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07441          free(sd);
07442       }
07443       /* Delete all addons for this device */
07444       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07445          free(a);
07446       }
07447       AST_LIST_REMOVE_CURRENT(list);
07448       free(d);
07449    }
07450    AST_LIST_TRAVERSE_SAFE_END;
07451    AST_LIST_UNLOCK(&devices);
07452 
07453    AST_LIST_LOCK(&lines);  
07454    AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) {
07455       if (l->prune) {
07456          AST_LIST_REMOVE_CURRENT(all);
07457          free(l);
07458       }
07459    }
07460    AST_LIST_TRAVERSE_SAFE_END;
07461    AST_LIST_UNLOCK(&lines);  
07462 
07463    AST_LIST_TRAVERSE(&devices, d, list) {
07464       /* Do a soft reset to re-register the devices after
07465          cleaning up the removed devices and lines */
07466       if (d->session) {
07467          ast_verb(3, "Restarting device '%s'\n", d->name);
07468          if ((req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE))) {
07469             req->data.reset.resetType = 2;
07470             transmit_response(d, req);
07471          }
07472       }
07473    }
07474    
07475    skinnyreload = 0;
07476         return 0;
07477 }

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

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

06486 {
06487    struct skinny_req *req;
06488    int *bufaddr;
06489 
06490    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
06491       return NULL;
06492 
06493    ast_mutex_lock(&s->lock);
06494    memcpy(req, s->inbuf, skinny_header_size);
06495    bufaddr = (int *)(s->inbuf);
06496    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
06497 
06498    ast_mutex_unlock(&s->lock);
06499 
06500    if (letohl(req->e) < 0) {
06501       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
06502       ast_free(req);
06503       return NULL;
06504    }
06505 
06506    return req;
06507 }

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

Definition at line 6669 of file chan_skinny.c.

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

06670 {
06671    struct skinny_line *l;
06672    struct ast_channel *tmpc = NULL;
06673    char tmp[256];
06674    char *dest = data;
06675 
06676    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
06677       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
06678       return NULL;
06679    }
06680 
06681    ast_copy_string(tmp, dest, sizeof(tmp));
06682    if (ast_strlen_zero(tmp)) {
06683       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
06684       return NULL;
06685    }
06686    l = find_line_by_name(tmp);
06687    if (!l) {
06688       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
06689       return NULL;
06690    }
06691    ast_verb(3, "skinny_request(%s)\n", tmp);
06692    tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
06693    if (!tmpc) {
06694       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
06695    }
06696    restart_monitor();
06697    return tmpc;
06698 }

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

Definition at line 4114 of file chan_skinny.c.

References ast_debug, AST_FRAME_VOICE, ast_getformatname(), ast_null_frame, ast_rtp_instance_read(), ast_set_read_format(), ast_set_write_format(), ast_udptl_read(), ast_frame_subclass::codec, f, ast_channel::fdno, ast_frame::frametype, ast_channel::nativeformats, skinny_subchannel::owner, ast_channel::readformat, skinny_subchannel::rtp, ast_frame::subclass, skinny_subchannel::vrtp, and ast_channel::writeformat.

Referenced by skinny_read().

04115 {
04116    struct ast_channel *ast = sub->owner;
04117    struct ast_frame *f;
04118 
04119    if (!sub->rtp) {
04120       /* We have no RTP allocated for this channel */
04121       return &ast_null_frame;
04122    }
04123 
04124    switch(ast->fdno) {
04125    case 0:
04126       f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
04127       break;
04128    case 1:
04129       f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
04130       break;
04131    case 2:
04132       f = ast_rtp_instance_read(sub->vrtp, 0); /* RTP Video */
04133       break;
04134    case 3:
04135       f = ast_rtp_instance_read(sub->vrtp, 1); /* RTCP Control Channel for video */
04136       break;
04137 #if 0
04138    case 5:
04139       /* Not yet supported */
04140       f = ast_udptl_read(sub->udptl); /* UDPTL for T.38 */
04141       break;
04142 #endif
04143    default:
04144       f = &ast_null_frame;
04145    }
04146 
04147    if (ast) {
04148       /* We already hold the channel lock */
04149       if (f->frametype == AST_FRAME_VOICE) {
04150          if (f->subclass.codec != ast->nativeformats) {
04151             ast_debug(1, "Oooh, format changed to %s\n", ast_getformatname(f->subclass.codec));
04152             ast->nativeformats = f->subclass.codec;
04153             ast_set_read_format(ast, ast->readformat);
04154             ast_set_write_format(ast, ast->writeformat);
04155          }
04156       }
04157    }
04158    return f;
04159 }

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

Definition at line 4215 of file chan_skinny.c.

04216 {
04217    return -1; /* Start inband indications */
04218 }

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

Definition at line 4220 of file chan_skinny.c.

References ast_channel::tech_pvt.

04221 {
04222 #if 0
04223    struct skinny_subchannel *sub = ast->tech_pvt;
04224    struct skinny_line *l = sub->parent;
04225    struct skinny_device *d = l->device;
04226    int tmp;
04227    /* not right */
04228    sprintf(tmp, "%d", digit);
04229    //transmit_tone(d, digit, l->instance, sub->callid);
04230 #endif
04231    return -1; /* Stop inband indications */
04232 }

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

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

06510 {
06511    int res;
06512    struct skinny_req *req;
06513    struct skinnysession *s = data;
06514 
06515    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
06516 
06517    for (;;) {
06518       res = get_input(s);
06519       if (res < 0) {
06520          break;
06521       }
06522 
06523       if (res > 0)
06524       {
06525          if (!(req = skinny_req_parse(s))) {
06526             destroy_session(s);
06527             return NULL;
06528          }
06529 
06530          res = handle_message(req, s);
06531          if (res < 0) {
06532             destroy_session(s);
06533             return NULL;
06534          }
06535       }
06536    }
06537    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06538 
06539    if (s) 
06540       destroy_session(s);
06541    
06542    return 0;
06543 }

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,
format_t  codecs,
int  nat_active 
) [static]

Definition at line 2821 of file chan_skinny.c.

References ast_channel::_state, ast_best_codec(), 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, ast_verb, ast_format_list::bits, ast_format_list::cur_ms, skinny_device::ourip, ast_channel::tech_pvt, transmit_startmediatransmission(), and transmit_stopmediatransmission().

02822 {
02823    struct skinny_subchannel *sub;
02824    struct skinny_line *l;
02825    struct skinny_device *d;
02826    struct ast_format_list fmt;
02827    struct sockaddr_in us = { 0, };
02828    struct sockaddr_in them = { 0, };
02829    struct ast_sockaddr them_tmp;
02830    struct ast_sockaddr us_tmp;
02831    
02832    sub = c->tech_pvt;
02833 
02834    if (c->_state != AST_STATE_UP)
02835       return 0;
02836 
02837    if (!sub) {
02838       return -1;
02839    }
02840 
02841    l = sub->parent;
02842    d = l->device;
02843 
02844    if (rtp){
02845       ast_rtp_instance_get_remote_address(rtp, &them_tmp);
02846       ast_sockaddr_to_sin(&them_tmp, &them);
02847 
02848       /* Shutdown any early-media or previous media on re-invite */
02849       transmit_stopmediatransmission(d, sub);
02850       
02851       if (skinnydebug)
02852          ast_verb(1, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
02853 
02854       fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
02855 
02856       if (skinnydebug)
02857          ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
02858 
02859       if (!(l->directmedia) || (l->nat)){
02860          ast_rtp_instance_get_local_address(rtp, &us_tmp);
02861          ast_sockaddr_to_sin(&us_tmp, &us);
02862          us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
02863          transmit_startmediatransmission(d, sub, us, fmt);
02864       } else {
02865          transmit_startmediatransmission(d, sub, them, fmt);
02866       }
02867 
02868       return 0;
02869    }
02870    /* Need a return here to break the bridge */
02871    return 0;
02872 }

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

Definition at line 3806 of file chan_skinny.c.

References ast_channel::_state, ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_safe_sleep(), AST_STATE_UP, ast_strlen_zero(), ast_verb, ast_channel::caller, skinny_subchannel::callid, ast_channel::context, ast_channel::exten, ast_party_caller::id, len(), LOG_WARNING, ast_party_id::number, skinny_subchannel::owner, S_COR, set_callforwards(), SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_newcall(), SKINNY_OFFHOOK, SKINNY_REORDER, STIMULUS_FORWARDALL, ast_party_number::str, ast_channel::tech_pvt, transmit_cfwdstate(), transmit_displaynotify(), transmit_lamp_indication(), transmit_start_tone(), transmit_stop_tone(), and ast_party_number::valid.

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

03807 {
03808    struct ast_channel *c = data;
03809    struct skinny_subchannel *sub = c->tech_pvt;
03810    struct skinny_line *l = sub->parent;
03811    struct skinny_device *d = l->device;
03812    int len = 0;
03813    int timeout = firstdigittimeout;
03814    int res = 0;
03815    int loop_pause = 100;
03816 
03817    if (!d) {
03818       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
03819       return NULL;
03820    }
03821 
03822    ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
03823 
03824    len = strlen(d->exten);
03825 
03826    while (len < AST_MAX_EXTENSION-1) {
03827       res = 1;  /* Assume that we will get a digit */
03828       while (strlen(d->exten) == len){
03829          ast_safe_sleep(c, loop_pause);
03830          timeout -= loop_pause;
03831          if ( (timeout -= loop_pause) <= 0){
03832              res = 0;
03833              break;
03834          }
03835       res = 1;
03836       }
03837 
03838       timeout = 0;
03839       len = strlen(d->exten);
03840 
03841       if (!ast_ignore_pattern(c->context, d->exten)) {
03842          transmit_stop_tone(d, l->instance, sub->callid);
03843       }
03844       if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
03845          if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
03846             if (l->getforward) {
03847                /* Record this as the forwarding extension */
03848                set_callforwards(l, d->exten, l->getforward);
03849                ast_verb(3, "Setting call forward (%d) to '%s' on channel %s\n",
03850                      l->cfwdtype, d->exten, c->name);
03851                transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
03852                transmit_lamp_indication(d, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
03853                transmit_displaynotify(d, "CFwd enabled", 10);
03854                transmit_cfwdstate(d, l);
03855                ast_safe_sleep(c, 500);
03856                ast_indicate(c, -1);
03857                ast_safe_sleep(c, 1000);
03858                memset(d->exten, 0, sizeof(d->exten));
03859                len = 0;
03860                l->getforward = 0;
03861                if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03862                   ast_indicate(c, -1);
03863                   ast_hangup(c);
03864                }
03865                return NULL;
03866             } else {
03867                ast_copy_string(c->exten, d->exten, sizeof(c->exten));
03868                ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
03869                memset(d->exten, 0, sizeof(d->exten));
03870                skinny_newcall(c);
03871                return NULL;
03872             }
03873          } else {
03874             /* It's a match, but they just typed a digit, and there is an ambiguous match,
03875                so just set the timeout to matchdigittimeout and wait some more */
03876             timeout = matchdigittimeout;
03877          }
03878       } else if (res == 0) {
03879          ast_debug(1, "Not enough digits (%s) (and no ambiguous match)...\n", d->exten);
03880          memset(d->exten, 0, sizeof(d->exten));
03881          if (l->hookstate == SKINNY_OFFHOOK) {
03882             transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03883          }
03884          if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03885             ast_indicate(c, -1);
03886             ast_hangup(c);
03887          }
03888          return NULL;
03889       } else if (!ast_canmatch_extension(c, c->context, d->exten, 1,
03890          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))
03891          && ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
03892          ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten,
03893             S_COR(c->caller.id.number.valid, c->caller.id.number.str, "<Unknown Caller>"),
03894             c->context);
03895          memset(d->exten, 0, sizeof(d->exten));
03896          if (l->hookstate == SKINNY_OFFHOOK) {
03897             transmit_start_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03898             /* hang out for 3 seconds to let congestion play */
03899             ast_safe_sleep(c, 3000);
03900          }
03901          break;
03902       }
03903       if (!timeout) {
03904          timeout = gendigittimeout;
03905       }
03906       if (len && !ast_ignore_pattern(c->context, d->exten)) {
03907          ast_indicate(c, -1);
03908       }
03909    }
03910    if (c)
03911       ast_hangup(c);
03912    memset(d->exten, 0, sizeof(d->exten));
03913    return NULL;
03914 }

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

Definition at line 4319 of file chan_skinny.c.

References ast_channel::_state, ast_bridged_channel(), ast_channel_masquerade(), AST_CONTROL_UNHOLD, ast_debug, ast_get_indication_tone(), ast_log(), ast_playtones_start(), ast_queue_control(), AST_STATE_RING, ast_tone_zone_sound_unref(), ast_tone_zone_sound::data, LOG_DEBUG, LOG_WARNING, option_debug, skinny_subchannel::owner, skinny_subchannel::xferor, and ast_channel::zone.

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

04320 {
04321    struct skinny_subchannel *xferor; /* the sub doing the transferring */
04322    struct skinny_subchannel *xferee; /* the sub being transferred */
04323    struct ast_tone_zone_sound *ts = NULL;
04324       
04325    if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
04326       if (sub->xferor) {
04327          xferor = sub;
04328          xferee = sub->related;
04329       } else {
04330          xferor = sub;
04331          xferee = sub->related;
04332       }
04333       
04334       if (skinnydebug) {
04335          ast_debug(1, "Transferee channels (local/remote): %s and %s\n",
04336             xferee->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
04337          ast_debug(1, "Transferor channels (local/remote): %s and %s\n",
04338             xferor->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
04339       }
04340       if (ast_bridged_channel(xferor->owner)) {
04341          if (ast_bridged_channel(xferee->owner)) {
04342             ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
04343          }
04344          if (xferor->owner->_state == AST_STATE_RING) {
04345             /* play ringing inband */
04346             if ((ts = ast_get_indication_tone(xferor->owner->zone, "ring"))) {
04347                ast_playtones_start(xferor->owner, 0, ts->data, 1);
04348                ts = ast_tone_zone_sound_unref(ts);
04349             }
04350          }
04351          if (skinnydebug)
04352             ast_debug(1, "Transfer Masquerading %s to %s\n",
04353                xferee->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
04354          if (ast_channel_masquerade(xferee->owner, ast_bridged_channel(xferor->owner))) {
04355             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04356                ast_bridged_channel(xferor->owner)->name, xferee->owner->name);
04357             return -1;
04358          }
04359       } else if (ast_bridged_channel(xferee->owner)) {
04360          ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
04361          if (xferor->owner->_state == AST_STATE_RING) {
04362             /* play ringing inband */
04363             if ((ts = ast_get_indication_tone(xferor->owner->zone, "ring"))) {
04364                ast_playtones_start(xferor->owner, 0, ts->data, 1);
04365                ts = ast_tone_zone_sound_unref(ts);
04366             }
04367          }
04368          if (skinnydebug)
04369             ast_debug(1, "Transfer Masquerading %s to %s\n",
04370                xferor->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
04371          if (ast_channel_masquerade(xferor->owner, ast_bridged_channel(xferee->owner))) {
04372             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04373                ast_bridged_channel(xferee->owner)->name, xferor->owner->name);
04374             return -1;
04375          }
04376          return 0;
04377       } else {
04378          if (option_debug)
04379             ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04380                xferor->owner->name, xferee->owner->name);
04381       }
04382    }
04383    return 0;
04384 }

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 4657 of file chan_skinny.c.

References AST_CONTROL_UNHOLD, ast_log(), ast_queue_control(), ast_verb, skinny_subchannel::callid, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::owner, SKINNY_CONNECTED, SKINNY_LAMP_ON, SKINNY_OFFHOOK, STIMULUS_LINE, transmit_activatecallplane(), transmit_callstate(), transmit_connect(), and transmit_lamp_indication().

Referenced by handle_hold_button(), and handle_soft_key_event_message().

04658 {
04659    struct skinny_line *l = sub->parent;
04660    struct skinny_device *d = l->device;
04661 
04662    /* Don't try to unhold a channel that doesn't exist */
04663    if (!sub || !sub->owner) {
04664       return 0;
04665    }
04666    if (!d) {
04667       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04668       return 0;
04669    }
04670 
04671    /* Channel is on hold, so we will unhold */
04672    if (skinnydebug)
04673       ast_verb(1, "Taking off Hold(%d)\n", l->instance);
04674 
04675    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
04676 
04677    transmit_activatecallplane(d, l);
04678 
04679    transmit_connect(d, sub);
04680    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
04681    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04682    l->hookstate = SKINNY_OFFHOOK;
04683    sub->onhold = 0;
04684    return 1;
04685 }

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

Definition at line 1942 of file chan_skinny.c.

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

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

01943 {
01944    struct skinny_device *d;
01945    struct skinny_line *l;
01946    struct skinny_speeddial *sd;
01947 
01948    d = s->device;
01949 
01950    if (d) {
01951       d->session = NULL;
01952       d->registered = 0;
01953 
01954       AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01955          if (sd->stateid > -1)
01956             ast_extension_state_del(sd->stateid, NULL);
01957       }
01958       AST_LIST_TRAVERSE(&d->lines, l, list) {
01959          if (l->device == d) {
01960             l->device = NULL;
01961             l->capability = 0;
01962             ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0);       
01963             l->instance = 0;
01964             manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
01965             unregister_exten(l);
01966             ast_devstate_changed(AST_DEVICE_UNAVAILABLE, AST_DEVSTATE_CACHABLE, "Skinny/%s@%s", l->name, d->name);
01967          }
01968       }
01969    }
01970 
01971    return -1; /* main loop will destroy the session */
01972 }

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

Definition at line 4171 of file chan_skinny.c.

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

04172 {
04173    struct skinny_subchannel *sub = ast->tech_pvt;
04174    int res = 0;
04175    if (frame->frametype != AST_FRAME_VOICE) {
04176       if (frame->frametype == AST_FRAME_IMAGE) {
04177          return 0;
04178       } else {
04179          ast_log(LOG_WARNING, "Can't send %u type frames with skinny_write\n", frame->frametype);
04180          return 0;
04181       }
04182    } else {
04183       if (!(frame->subclass.codec & ast->nativeformats)) {
04184          char buf[256];
04185          ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
04186             ast_getformatname(frame->subclass.codec),
04187             ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
04188             ast_getformatname(ast->readformat),
04189             ast_getformatname(ast->writeformat));
04190          return -1;
04191       }
04192    }
04193    if (sub) {
04194       ast_mutex_lock(&sub->lock);
04195       if (sub->rtp) {
04196          res = ast_rtp_instance_write(sub->rtp, frame);
04197       }
04198       ast_mutex_unlock(&sub->lock);
04199    }
04200    return res;
04201 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3727 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_subchannel::lock, skinny_subchannel::owner, qos, skinny_subchannel::rtp, transmit_connect(), and skinny_subchannel::vrtp.

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

03728 {
03729    struct skinny_line *l = sub->parent;
03730    struct skinny_device *d = l->device;
03731    int hasvideo = 0;
03732    struct ast_sockaddr bindaddr_tmp;
03733 
03734    ast_mutex_lock(&sub->lock);
03735    /* Allocate the RTP */
03736    ast_sockaddr_from_sin(&bindaddr_tmp, &bindaddr);
03737    sub->rtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
03738    if (hasvideo)
03739       sub->vrtp = ast_rtp_instance_new("asterisk", sched, &bindaddr_tmp, NULL);
03740 
03741    if (sub->rtp) {
03742       ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
03743    }
03744    if (sub->vrtp) {
03745       ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_RTCP, 1);
03746    }
03747 
03748    if (sub->rtp && sub->owner) {
03749       ast_channel_set_fd(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
03750       ast_channel_set_fd(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
03751    }
03752    if (hasvideo && sub->vrtp && sub->owner) {
03753       ast_channel_set_fd(sub->owner, 2, ast_rtp_instance_fd(sub->vrtp, 0));
03754       ast_channel_set_fd(sub->owner, 3, ast_rtp_instance_fd(sub->vrtp, 1));
03755    }
03756    if (sub->rtp) {
03757       ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
03758       ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, l->nat);
03759    }
03760    if (sub->vrtp) {
03761       ast_rtp_instance_set_qos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
03762       ast_rtp_instance_set_prop(sub->vrtp, AST_RTP_PROPERTY_NAT, l->nat);
03763    }
03764    /* Set Frame packetization */
03765    if (sub->rtp)
03766       ast_rtp_codecs_packetization_set(ast_rtp_instance_get_codecs(sub->rtp), sub->rtp, &l->prefs);
03767 
03768    /* Create the RTP connection */
03769    transmit_connect(d, sub);
03770    ast_mutex_unlock(&sub->lock);
03771 }

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

Definition at line 2169 of file chan_skinny.c.

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

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

02170 {
02171    struct skinny_req *req;
02172 
02173    /* We should not be able to get here without a device */
02174    if (!d)
02175       return;
02176 
02177    if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
02178       return;
02179 
02180    if (skinnydebug)
02181          ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) on %s(%d)\n", fromname, fromnum, toname, tonum, d->name, instance);
02182 
02183    if (fromname) {
02184       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
02185    }
02186    if (fromnum) {
02187       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
02188    }
02189    if (toname) {
02190       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
02191    }
02192    if (tonum) {
02193       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
02194    }
02195    req->data.callinfo.instance = htolel(instance);
02196    req->data.callinfo.reference = htolel(callid);
02197    req->data.callinfo.type = htolel(calltype);
02198    transmit_response(d, req);
02199 }

static void transmit_callstate ( struct skinny_device d,
int  buttonInstance,
unsigned  callid,
int  state 
) [static]
static void transmit_cfwdstate ( struct skinny_device d,
struct skinny_line l 
) [static]

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

Referenced by handle_callforward_button(), and skinny_ss().

02462 {
02463    struct skinny_req *req;
02464    int anyon = 0;
02465 
02466    if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
02467       return;
02468 
02469    if (l->cfwdtype & SKINNY_CFWD_ALL) {
02470       if (!ast_strlen_zero(l->call_forward_all)) {
02471          ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
02472          req->data.forwardstat.fwdall = htolel(1);
02473          anyon++;
02474       } else {
02475          req->data.forwardstat.fwdall = htolel(0);
02476       }
02477    }
02478    if (l->cfwdtype & SKINNY_CFWD_BUSY) {
02479       if (!ast_strlen_zero(l->call_forward_busy)) {
02480          ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
02481          req->data.forwardstat.fwdbusy = htolel(1);
02482          anyon++;
02483       } else {
02484          req->data.forwardstat.fwdbusy = htolel(0);
02485       }
02486    }
02487    if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
02488       if (!ast_strlen_zero(l->call_forward_noanswer)) {
02489          ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
02490          req->data.forwardstat.fwdnoanswer = htolel(1);
02491          anyon++;
02492       } else {
02493          req->data.forwardstat.fwdnoanswer = htolel(0);
02494       }
02495    }
02496    req->data.forwardstat.lineNumber = htolel(l->instance);
02497    if (anyon)
02498       req->data.forwardstat.activeforward = htolel(7);
02499    else
02500       req->data.forwardstat.activeforward = htolel(0);
02501 
02502    transmit_response(d, req);
02503 }

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

Definition at line 2294 of file chan_skinny.c.

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

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

02295 {
02296    struct skinny_req *req;
02297    if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
02298       return;
02299 
02300    //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
02301    //if we are clearing the display, it appears there is no instance and refernece info (size 0)
02302    //req->data.clearpromptstatus.lineInstance = instance;
02303    //req->data.clearpromptstatus.callReference = reference;
02304 
02305    if (skinnydebug)
02306       ast_verb(1, "Clearing Display\n");
02307    transmit_response(d, req);
02308 }

static void transmit_clearpromptmessage ( struct skinny_device d,
int  instance,
int  callid 
) [static]
static void transmit_closereceivechannel ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_connect ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_definetimedate ( struct skinny_device d  )  [static]

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

02533 {
02534    struct skinny_req *req;
02535    struct timeval now = ast_tvnow();
02536    struct ast_tm cmtime;
02537 
02538    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
02539       return;
02540 
02541    ast_localtime(&now, &cmtime, NULL);
02542    req->data.definetimedate.year = htolel(cmtime.tm_year+1900);
02543    req->data.definetimedate.month = htolel(cmtime.tm_mon+1);
02544    req->data.definetimedate.dayofweek = htolel(cmtime.tm_wday);
02545    req->data.definetimedate.day = htolel(cmtime.tm_mday);
02546    req->data.definetimedate.hour = htolel(cmtime.tm_hour);
02547    req->data.definetimedate.minute = htolel(cmtime.tm_min);
02548    req->data.definetimedate.seconds = htolel(cmtime.tm_sec);
02549    req->data.definetimedate.milliseconds = htolel(cmtime.tm_usec / 1000);
02550    req->data.definetimedate.timestamp = htolel(now.tv_sec);
02551    transmit_response(d, req);
02552 }

static void transmit_dialednumber ( struct skinny_device d,
const char *  text,
int  instance,
int  callid 
) [static]
static void transmit_displaynotify ( struct skinny_device d,
const char *  text,
int  t 
) [static]
static void transmit_displaypromptstatus ( struct skinny_device d,
const char *  text,
int  t,
int  instance,
int  callid 
) [static]
static void transmit_lamp_indication ( struct skinny_device d,
int  stimulus,
int  instance,
int  indication 
) [static]
static void transmit_linestatres ( struct skinny_device d,
struct skinny_line l 
) [static]

Definition at line 2519 of file chan_skinny.c.

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

Referenced by handle_message().

02520 {
02521    struct skinny_req *req;
02522 
02523    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
02524       return;
02525 
02526    req->data.linestat.lineNumber = letohl(l->instance);
02527    memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
02528    memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
02529    transmit_response(d, req);
02530 }

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

Definition at line 2105 of file chan_skinny.c.

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

Referenced by handle_button_template_req_message(), handle_keep_alive_message(), handle_register_message(), handle_skinny_reset(), skinny_reload(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_linestatres(), 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(), and transmit_versionres().

02106 {
02107    struct skinnysession *s = d->session;
02108    int res = 0;
02109 
02110    if (!s) {
02111       ast_log(LOG_WARNING, "Asked to transmit to a non-existent session!\n");
02112       return -1;
02113    }
02114 
02115    ast_mutex_lock(&s->lock);
02116 
02117    SKINNY_DEVONLY(if (skinnydebug>1) ast_verb(4, "Transmitting %s to %s\n", message2str(req->e), d->name);)
02118 
02119    if ((letohl(req->len) > SKINNY_MAX_PACKET) || (letohl(req->len) < 0)) {
02120       ast_log(LOG_WARNING, "transmit_response: the length of the request (%d) is out of bounds (%d)\n", letohl(req->len), SKINNY_MAX_PACKET);
02121       ast_mutex_unlock(&s->lock);
02122       return -1;
02123    }
02124 
02125    memset(s->outbuf, 0, sizeof(s->outbuf));
02126    memcpy(s->outbuf, req, skinny_header_size);
02127    memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
02128 
02129    res = write(s->fd, s->outbuf, letohl(req->len)+8);
02130    
02131    if (res != letohl(req->len)+8) {
02132       ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
02133       if (res == -1) {
02134          if (skinnydebug)
02135             ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
02136          skinny_unregister(NULL, s);
02137       }
02138       
02139    }
02140    
02141    ast_free(req);
02142    ast_mutex_unlock(&s->lock);
02143    return 1;
02144 }

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

Definition at line 2269 of file chan_skinny.c.

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

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

02270 {
02271    struct skinny_req *req;
02272 
02273    if (skinnydebug)
02274       ast_verb(1, "Setting ringer mode to '%d'.\n", mode);
02275 
02276    if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
02277       return;
02278 
02279    req->data.setringer.ringerMode = htolel(mode);
02280    /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
02281       Note: The phone will always show as ringing on the display.
02282 
02283       1: phone will audibly ring over and over
02284       2: phone will audibly ring only once
02285       any other value, will NOT cause the phone to audibly ring
02286    */
02287    req->data.setringer.unknown1 = htolel(1);
02288    /* XXX the value here doesn't seem to change anything.  Must be higher than 0.
02289       Perhaps a packet capture can shed some light on this. */
02290    req->data.setringer.unknown2 = htolel(1);
02291    transmit_response(d, req);
02292 }

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

Definition at line 2577 of file chan_skinny.c.

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

Referenced by handle_message().

02578 {
02579    struct skinny_req *req;
02580    int i;
02581    int x;
02582    int y;
02583    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
02584 
02585    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
02586       return;
02587 
02588    req->data.softkeysets.softKeySetOffset = htolel(0);
02589    req->data.softkeysets.softKeySetCount = htolel(11);
02590    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
02591    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
02592       const uint8_t *defaults = softkeymode->defaults;
02593       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
02594          This will have to do for now. */
02595       for (y = 0; y < softkeymode->count; y++) {
02596          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
02597             if (defaults[y] == i+1) {
02598                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = (i+1);
02599                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htoles(i+301);
02600                     if (skinnydebug)   
02601                   ast_verbose("softKeySetDefinition : softKeyTemplateIndex: %d softKeyInfoIndex: %d\n", i+1, i+301);
02602             }
02603          }
02604       }
02605       softkeymode++;
02606    }
02607    transmit_response(d, req);
02608 }

static void transmit_softkeytemplateres ( struct skinny_device d  )  [static]
static void transmit_speaker_mode ( struct skinny_device d,
int  mode 
) [static]
static void transmit_speeddialstatres ( struct skinny_device d,
struct skinny_speeddial sd 
) [static]
static void transmit_start_tone ( struct skinny_device d,
int  tone,
int  instance,
int  reference 
) [static]
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 2417 of file chan_skinny.c.

References media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, codec_ast2skinny(), start_media_transmission_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, htolel, media_qualifier::packets, start_media_transmission_message::packetSize, start_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, media_qualifier::precedence, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, transmit_response(), and media_qualifier::vad.

Referenced by handle_open_receive_channel_ack_message(), and skinny_set_rtp_peer().

02418 {
02419    struct skinny_req *req;
02420 
02421    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
02422       return;
02423 
02424    req->data.startmedia.conferenceId = htolel(sub->callid);
02425    req->data.startmedia.passThruPartyId = htolel(sub->callid);
02426    req->data.startmedia.remoteIp = dest.sin_addr.s_addr;
02427    req->data.startmedia.remotePort = htolel(ntohs(dest.sin_port));
02428    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
02429    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
02430    req->data.startmedia.qualifier.precedence = htolel(127);
02431    req->data.startmedia.qualifier.vad = htolel(0);
02432    req->data.startmedia.qualifier.packets = htolel(0);
02433    req->data.startmedia.qualifier.bitRate = htolel(0);
02434    transmit_response(d, req);
02435 }

static void transmit_stop_tone ( struct skinny_device d,
int  instance,
int  reference 
) [static]
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 2554 of file chan_skinny.c.

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

Referenced by handle_message().

02555 {
02556    struct skinny_req *req;
02557    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
02558       return;
02559 
02560    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
02561    transmit_response(d, req);
02562 }

static int unload_module ( void   )  [static]

Definition at line 7520 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_event_unsubscribe(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_lock, ast_mutex_unlock, AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_glue_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_skinny, delete_devices(), skinnysession::device, EVENT_FLAG_SYSTEM, skinnysession::fd, free, skinny_subchannel::lock, skinny_line::lock, manager_event, skinny_line::mwi_event_sub, skinny_subchannel::owner, sched_context_destroy(), sessions, skinny_rtp_glue, skinny_tech, skinnysession::t, and unregister_exten().

07521 {
07522    struct skinnysession *s;
07523    struct skinny_device *d;
07524    struct skinny_line *l;
07525    struct skinny_subchannel *sub;
07526    struct ast_context *con;
07527 
07528    ast_rtp_glue_unregister(&skinny_rtp_glue);
07529    ast_channel_unregister(&skinny_tech);
07530    ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07531 
07532    ast_manager_unregister("SKINNYdevices");
07533    ast_manager_unregister("SKINNYshowdevice");
07534    ast_manager_unregister("SKINNYlines");
07535    ast_manager_unregister("SKINNYshowline");
07536    
07537    AST_LIST_LOCK(&sessions);
07538    /* Destroy all the interfaces and free their memory */
07539    while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
07540       d = s->device;
07541       AST_LIST_TRAVERSE(&d->lines, l, list){
07542          ast_mutex_lock(&l->lock);
07543          AST_LIST_TRAVERSE(&l->sub, sub, list) {
07544             ast_mutex_lock(&sub->lock);
07545             if (sub->owner) {
07546                sub->alreadygone = 1;
07547                ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
07548             }
07549             ast_mutex_unlock(&sub->lock);
07550          }
07551          if (l->mwi_event_sub)
07552             ast_event_unsubscribe(l->mwi_event_sub);
07553          ast_mutex_unlock(&l->lock);
07554          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
07555          unregister_exten(l);
07556       }
07557       if (s->fd > -1)
07558          close(s->fd);
07559       pthread_cancel(s->t);
07560       pthread_kill(s->t, SIGURG);
07561       pthread_join(s->t, NULL);
07562       free(s);
07563    }
07564    AST_LIST_UNLOCK(&sessions);
07565 
07566    delete_devices();
07567 
07568    ast_mutex_lock(&monlock);
07569    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
07570       pthread_cancel(monitor_thread);
07571       pthread_kill(monitor_thread, SIGURG);
07572       pthread_join(monitor_thread, NULL);
07573    }
07574    monitor_thread = AST_PTHREADT_STOP;
07575    ast_mutex_unlock(&monlock);
07576 
07577    ast_mutex_lock(&netlock);
07578    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
07579       pthread_cancel(accept_t);
07580       pthread_kill(accept_t, SIGURG);
07581       pthread_join(accept_t, NULL);
07582    }
07583    accept_t = AST_PTHREADT_STOP;
07584    ast_mutex_unlock(&netlock);
07585 
07586    close(skinnysock);
07587    if (sched)
07588       sched_context_destroy(sched);
07589 
07590    con = ast_context_find(used_context);
07591    if (con)
07592       ast_context_destroy(con, "Skinny");
07593    
07594    return 0;
07595 }

static void unregister_exten ( struct skinny_line l  )  [static]

Definition at line 1846 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, and S_OR.

Referenced by skinny_unregister(), and unload_module().

01847 {
01848    char multi[256];
01849    char *stringp, *ext, *context;
01850 
01851    if (ast_strlen_zero(regcontext))
01852       return;
01853 
01854    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01855    stringp = multi;
01856    while ((ext = strsep(&stringp, "&"))) {
01857       if ((context = strchr(ext, '@'))) {
01858          *context++ = '\0'; /* split ext@context */
01859          if (!ast_context_find(context)) {
01860             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01861             continue;
01862          }
01863       } else {
01864          context = regcontext;
01865       }
01866       ast_context_remove_extension(context, ext, 1, NULL);
01867    }
01868 }

static void update_connectedline ( struct skinny_subchannel sub,
const void *  data,
size_t  datalen 
) [static]

Definition at line 2674 of file chan_skinny.c.

References ast_channel::_state, AST_STATE_UP, ast_strlen_zero(), ast_channel::caller, skinny_subchannel::callid, ast_channel::connected, ast_party_connected_line::id, ast_party_caller::id, ast_party_id::name, ast_party_id::number, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::progress, skinny_subchannel::ringing, S_COR, SKINNY_CONNECTED, SKINNY_PROGRESS, SKINNY_RINGIN, SKINNY_RINGOUT, ast_party_name::str, ast_party_number::str, transmit_callinfo(), transmit_callstate(), transmit_displaypromptstatus(), ast_party_name::valid, and ast_party_number::valid.

Referenced by skinny_indicate().

02675 {
02676    struct ast_channel *c = sub->owner;
02677    struct skinny_line *l = sub->parent;
02678    struct skinny_device *d = l->device;
02679 
02680    if (!d) {
02681       return;
02682    }
02683 
02684    if (!c->caller.id.number.valid
02685       || ast_strlen_zero(c->caller.id.number.str)
02686       || !c->connected.id.number.valid
02687       || ast_strlen_zero(c->connected.id.number.str))
02688       return;
02689 
02690    if (sub->owner->_state == AST_STATE_UP) {
02691       transmit_callstate(d, l->instance, sub->callid, SKINNY_CONNECTED);
02692       transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
02693       if (sub->outgoing)
02694          transmit_callinfo(d,
02695             S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
02696             c->connected.id.number.str,
02697             l->cid_name, l->cid_num, l->instance, sub->callid, 1);
02698       else
02699          transmit_callinfo(d, l->cid_name, l->cid_num,
02700             S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
02701             c->connected.id.number.str,
02702             l->instance, sub->callid, 2);
02703    } else {
02704       if (sub->outgoing) {
02705          transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGIN);
02706          transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
02707          transmit_callinfo(d,
02708             S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
02709             c->connected.id.number.str,
02710             l->cid_name, l->cid_num, l->instance, sub->callid, 1);
02711       } else {
02712          if (!sub->ringing) {
02713             transmit_callstate(d, l->instance, sub->callid, SKINNY_RINGOUT);
02714             transmit_displaypromptstatus(d, "Ring-Out", 0, l->instance, sub->callid);
02715             sub->ringing = 1;
02716          } else {
02717             transmit_callstate(d, l->instance, sub->callid, SKINNY_PROGRESS);
02718             transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
02719             sub->progress = 1;
02720          }
02721 
02722          transmit_callinfo(d, l->cid_name, l->cid_num,
02723             S_COR(c->connected.id.name.valid, c->connected.id.name.str, ""),
02724             c->connected.id.number.str,
02725             l->instance, sub->callid, 2);
02726       }
02727    }
02728 }


Variable Documentation

struct in_addr __ourip [static]

Definition at line 1046 of file chan_skinny.c.

Referenced by config_load(), and skinny_register().

pthread_t accept_t [static]

Definition at line 1050 of file chan_skinny.c.

struct ast_hostent ahp [static]

Definition at line 1047 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

int auth_limit = DEFAULT_AUTH_LIMIT [static]

Definition at line 177 of file chan_skinny.c.

int auth_timeout = DEFAULT_AUTH_TIMEOUT [static]

Definition at line 176 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 1043 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 1051 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 3716 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

Definition at line 145 of file chan_skinny.c.

unsigned int cos

Definition at line 170 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 171 of file chan_skinny.c.

unsigned int cos_video

Definition at line 172 of file chan_skinny.c.

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

Definition at line 182 of file chan_skinny.c.

format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 147 of file chan_skinny.c.

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

Definition at line 1287 of file chan_skinny.c.

Referenced by config_line(), and config_load().

struct ast_codec_pref default_prefs [static]

Definition at line 148 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

int firstdigittimeout = 16000 [static]

Definition at line 1170 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1173 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]
char global_vmexten[AST_MAX_EXTENSION] [static]

Definition at line 179 of file chan_skinny.c.

struct hostent* hp [static]
struct io_context* io [static]

Definition at line 1157 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 175 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1176 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1167 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 1044 of file chan_skinny.c.

int ourport [static]

Definition at line 1045 of file chan_skinny.c.

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

Definition at line 181 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 1156 of file chan_skinny.c.

int skinny_header_size = 12 [static]

Definition at line 1033 of file chan_skinny.c.

struct ast_rtp_glue skinny_rtp_glue [static]

Definition at line 2874 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1392 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 1039 of file chan_skinny.c.

int skinnyreload = 0 [static]

Definition at line 1040 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 1049 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 828 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]
Initial value:

Definition at line 872 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 858 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]
Initial value:

Definition at line 867 of file chan_skinny.c.

Definition at line 891 of file chan_skinny.c.

const uint8_t soft_key_default_offhook[] [static]

Definition at line 850 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]
Initial value:

Definition at line 881 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 837 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 818 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]
Initial value:

Definition at line 844 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]
Initial value:

Definition at line 876 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]
Initial value:

Definition at line 887 of file chan_skinny.c.

Definition at line 655 of file chan_skinny.c.

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

Definition at line 144 of file chan_skinny.c.

unsigned int tos

Definition at line 167 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 168 of file chan_skinny.c.

unsigned int tos_video

Definition at line 169 of file chan_skinny.c.

int unauth_sessions = 0 [static]

Definition at line 178 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 180 of file chan_skinny.c.

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

Definition at line 183 of file chan_skinny.c.


Generated on 31 Aug 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.6.1