Wed Oct 28 13:32:17 2009

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

#include "asterisk.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <signal.h>
#include <ctype.h>
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp_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"

Include dependency graph for chan_skinny.c:

Go to the source code of this file.

Data Structures

struct  activate_call_plane_message
struct  alarm_message
struct  button_definition
struct  button_definition_template
struct  button_template_res_message
struct  call_info_message
struct  call_state_message
struct  capabilities_res_message
struct  clear_prompt_message
struct  close_receive_channel_message
struct  definetimedate_message
struct  devices
struct  dialed_number_message
struct  display_notify_message
struct  display_prompt_status_message
struct  displaytext_message
struct  enbloc_call_message
struct  forward_stat_message
struct  keypad_button_message
struct  line_stat_res_message
struct  line_state_req_message
struct  lines
struct  media_qualifier
struct  offhook_message
struct  onhook_message
struct  open_receive_channel_ack_message
struct  open_receive_channel_message
struct  register_ack_message
struct  register_message
struct  register_rej_message
struct  reset_message
struct  select_soft_keys_message
struct  server_identifier
struct  server_res_message
struct  sessions
struct  set_lamp_message
struct  set_microphone_message
struct  set_ringer_message
struct  set_speaker_message
struct  skinny_addon
union  skinny_data
struct  skinny_device
struct  skinny_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 __bswap_16(x)
#define __bswap_32(x)
#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_SKINNY_BACKLOG   2
#define DEFAULT_SKINNY_PORT   2000
#define DEFINETIMEDATE_MESSAGE   0x0094
#define DEVICE2STR_BUFSIZE   15
#define DIALED_NUMBER_MESSAGE   0x011D
#define DISPLAY_NOTIFY_MESSAGE   0x0114
#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112
#define DISPLAYTEXT_MESSAGE   0x0099
#define ENBLOC_CALL_MESSAGE   0x0004
#define FORWARD_STAT_MESSAGE   0x0090
#define HEADSET_STATUS_MESSAGE   0x002B
#define htolel(x)   __bswap_32(x)
#define htoles(x)   __bswap_16(x)
#define IP_PORT_MESSAGE   0x0002
#define KEEP_ALIVE_ACK_MESSAGE   0x0100
#define KEEP_ALIVE_MESSAGE   0x0000
#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7
#define KEYDEF_CONNWITHTRANS   5
#define KEYDEF_DADFD   6
#define KEYDEF_OFFHOOK   4
#define KEYDEF_OFFHOOKWITHFEAT   9
#define KEYDEF_ONHOLD   2
#define KEYDEF_ONHOOK   0
#define KEYDEF_RINGIN   3
#define KEYDEF_RINGOUT   8
#define KEYDEF_UNKNOWN   10
#define KEYPAD_BUTTON_MESSAGE   0x0003
#define letohl(x)   __bswap_32(x)
#define letohs(x)   __bswap_16(x)
#define LINE_STAT_RES_MESSAGE   0x0092
#define LINE_STATE_REQ_MESSAGE   0x000B
#define OFFHOOK_MESSAGE   0x0006
#define ONHOOK_MESSAGE   0x0007
#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022
#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105
#define REGISTER_ACK_MESSAGE   0x0081
#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D
#define REGISTER_MESSAGE   0x0001
#define REGISTER_REJ_MESSAGE   0x009D
#define RESET_MESSAGE   0x009F
#define SELECT_SOFT_KEYS_MESSAGE   0x0110
#define SERVER_REQUEST_MESSAGE   0x0012
#define SERVER_RES_MESSAGE   0x009E
#define SET_LAMP_MESSAGE   0x0086
#define SET_MICROPHONE_MESSAGE   0x0089
#define SET_RINGER_MESSAGE   0x0085
#define SET_SPEAKER_MESSAGE   0x0088
#define SKINNY_ALERT   0x24
#define SKINNY_BUSY   6
#define SKINNY_BUSYTONE   0x23
#define SKINNY_CALLREMOTEMULTILINE   13
#define SKINNY_CALLWAIT   9
#define SKINNY_CALLWAITTONE   0x2D
#define SKINNY_CFWD_ALL   (1 << 0)
#define SKINNY_CFWD_BUSY   (1 << 1)
#define SKINNY_CFWD_NOANSWER   (1 << 2)
#define SKINNY_CONGESTION   7
#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3
#define SKINNY_CX_CONFERENCE   3
#define SKINNY_CX_INACTIVE   4
#define SKINNY_CX_MUTE   4
#define SKINNY_CX_RECVONLY   1
#define SKINNY_CX_SENDONLY   0
#define SKINNY_CX_SENDRECV   2
#define SKINNY_DEVICE_12   4
#define SKINNY_DEVICE_12SP   3
#define SKINNY_DEVICE_12SPPLUS   2
#define SKINNY_DEVICE_30SPPLUS   1
#define SKINNY_DEVICE_30VIP   5
#define SKINNY_DEVICE_7902   30008
#define SKINNY_DEVICE_7905   20000
#define SKINNY_DEVICE_7906   369
#define SKINNY_DEVICE_7910   6
#define SKINNY_DEVICE_7911   307
#define SKINNY_DEVICE_7912   30007
#define SKINNY_DEVICE_7914   124
#define SKINNY_DEVICE_7920   30002
#define SKINNY_DEVICE_7921   365
#define SKINNY_DEVICE_7931   348
#define SKINNY_DEVICE_7935   9
#define SKINNY_DEVICE_7936   30019
#define SKINNY_DEVICE_7937   431
#define SKINNY_DEVICE_7940   8
#define SKINNY_DEVICE_7941   115
#define SKINNY_DEVICE_7941GE   309
#define SKINNY_DEVICE_7942   434
#define SKINNY_DEVICE_7945   435
#define SKINNY_DEVICE_7960   7
#define SKINNY_DEVICE_7961   30018
#define SKINNY_DEVICE_7961GE   308
#define SKINNY_DEVICE_7962   404
#define SKINNY_DEVICE_7965   436
#define SKINNY_DEVICE_7970   30006
#define SKINNY_DEVICE_7971   119
#define SKINNY_DEVICE_7975   437
#define SKINNY_DEVICE_7985   302
#define SKINNY_DEVICE_ATA186   12
#define SKINNY_DEVICE_CIPC   30016
#define SKINNY_DEVICE_NONE   0
#define SKINNY_DEVICE_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 void __init_control2str_threadbuf (void)
static void __init_device2str_threadbuf (void)
static void __reg_module (void)
static void __unreg_module (void)
static char * _skinny_show_device (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_devices (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_line (int type, int fd, struct mansession *s, const struct message *m, int argc, const char *argv[])
static char * _skinny_show_lines (int fd, int *total, struct mansession *s, const struct message *m, int argc, const char *argv[])
static void * accept_thread (void *ignore)
static struct ast_variableadd_var (const char *buf, struct ast_variable *list)
static void cleanup_stale_contexts (char *new, char *old)
static int codec_ast2skinny (int astcodec)
static int codec_skinny2ast (enum skinny_codecs skinnycodec)
static char * complete_skinny_devices (const char *word, int state)
static char * complete_skinny_reset (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_device (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_line (const char *line, const char *word, int pos, int state)
static 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_alarm_message (struct skinny_req *req, struct skinnysession *s)
static int handle_button_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_callforward_button (struct skinny_subchannel *sub, int cfwdtype)
static int handle_capabilities_res_message (struct skinny_req *req, struct skinnysession *s)
static int handle_enbloc_call_message (struct skinny_req *req, struct skinnysession *s)
static int handle_headset_status_message (struct skinny_req *req, struct skinnysession *s)
static int handle_hold_button (struct skinny_subchannel *sub)
static int handle_ip_port_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keep_alive_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_message (struct skinny_req *req, struct skinnysession *s)
static int handle_line_state_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_message (struct skinny_req *req, struct skinnysession *s)
static int handle_offhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_onhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_open_receive_channel_ack_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_available_lines_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_message (struct skinny_req *req, struct skinnysession *s)
static int handle_server_request_message (struct skinny_req *req, struct skinnysession *s)
static char * handle_skinny_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_soft_key_set_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_speed_dial_stat_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_stimulus_message (struct skinny_req *req, struct skinnysession *s)
static int handle_time_date_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_transfer_button (struct skinny_subchannel *sub)
static int handle_unregister_message (struct skinny_req *req, struct skinnysession *s)
static int handle_version_req_message (struct skinny_req *req, struct skinnysession *s)
static int 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, int 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, int codecs, int nat_active)
static void * skinny_ss (void *data)
static int skinny_transfer (struct skinny_subchannel *sub)
static int skinny_unhold (struct skinny_subchannel *sub)
static int skinny_unregister (struct skinny_req *req, struct skinnysession *s)
static int skinny_write (struct ast_channel *ast, struct ast_frame *frame)
static void start_rtp (struct skinny_subchannel *sub)
static void transmit_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_callinfo (struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinny_device *d, int instance, int state, unsigned callid)
static void transmit_callstateonly (struct skinny_device *d, struct skinny_subchannel *sub, int state)
static void transmit_cfwdstate (struct skinny_device *d, struct skinny_line *l)
static void transmit_closereceivechannel (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_connect (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_dialednumber (struct skinny_device *d, const char *text, int instance, int callid)
static void transmit_displaymessage (struct skinny_device *d, const char *text, int instance, int reference)
static void transmit_displaynotify (struct skinny_device *d, const char *text, int t)
static void transmit_displaypromptstatus (struct skinny_device *d, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static int transmit_response (struct skinny_device *d, struct skinny_req *req)
static void transmit_ringer_mode (struct skinny_device *d, int mode)
static void transmit_selectsoftkeys (struct skinny_device *d, int instance, int callid, int softkey)
static void transmit_speaker_mode (struct skinny_device *d, int mode)
static void transmit_stopmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_tone (struct skinny_device *d, int tone, int instance, int reference)
static int unload_module (void)
static void unregister_exten (struct skinny_line *l)
static void update_connectedline (struct skinny_subchannel *sub, const void *data, size_t datalen)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static pthread_t accept_t
static struct ast_hostent ahp
static struct ast_module_infoast_module_info = &__mod_info
static struct sockaddr_in bindaddr
static int callnums = 1
static struct ast_cli_entry cli_skinny []
static const char config [] = "skinny.conf"
static struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_control2str_threadbuf , .custom_init = NULL , }
static char date_format [6] = "D-M-Y"
static int 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 struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT, .key_init = __init_device2str_threadbuf , .custom_init = NULL , }
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
static 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 ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
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 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 __bswap_16 (  ) 

Value:

((((x) & 0xff00) >> 8) | \
    (((x) & 0x00ff) << 8))

Definition at line 202 of file chan_skinny.c.

#define __bswap_32 (  ) 

Value:

((((x) & 0xff000000) >> 24) | \
    (((x) & 0x00ff0000) >>  8) | \
    (((x) & 0x0000ff00) <<  8) | \
    (((x) & 0x000000ff) << 24))

Definition at line 205 of file chan_skinny.c.

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116

Definition at line 954 of file chan_skinny.c.

Referenced by transmit_activatecallplane(), and transmit_callstate().

#define ALARM_MESSAGE   0x0020

Definition at line 321 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 528 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 531 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 532 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 530 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 539 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 538 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 525 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 529 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 522 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 523 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 524 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 520 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 526 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 533 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 518 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 519 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 521 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 527 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 317 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 488 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 426 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 925 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_callstateonly().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 561 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 289 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6623 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6622 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 559 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 558 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 942 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6621 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6620 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 597 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 236 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 158 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 157 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 475 of file chan_skinny.c.

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 233 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 959 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 948 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 933 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 553 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 265 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 448 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 348 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     __bswap_32(x)

#define htoles (  )     __bswap_16(x)

Definition at line 213 of file chan_skinny.c.

#define IP_PORT_MESSAGE   0x0002

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 584 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 242 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

#define KEYDEF_CONNWITHCONF   7

Definition at line 618 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 616 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 617 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 620 of file chan_skinny.c.

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 613 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

Definition at line 611 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 614 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

#define KEYDEF_UNKNOWN   10

Definition at line 621 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 257 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     __bswap_32(x)

#define letohs (  )     __bswap_16(x)

Definition at line 211 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 467 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 311 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 277 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 283 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 329 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 586 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 351 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 349 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 245 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 563 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 579 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 917 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 319 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 568 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 382 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 395 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 374 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 389 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1106 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1093 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1105 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1100 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1096 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1108 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

#define SKINNY_CFWD_BUSY   (1 << 1)

#define SKINNY_CFWD_NOANSWER   (1 << 2)

#define SKINNY_CONGESTION   7

Definition at line 1094 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

#define SKINNY_CX_CONF   3

Definition at line 1130 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1131 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1133 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1132 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1128 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1127 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1129 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1048 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1047 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1046 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1045 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1049 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1075 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1071 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1064 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1050 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1059 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1074 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1057 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1072 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1063 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1062 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1053 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1078 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1066 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1052 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1055 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1061 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1067 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1068 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1051 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1077 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1060 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1065 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1069 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1073 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1056 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1070 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1058 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1054 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1076 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1044 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1302 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1079 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1080 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 1043 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVONLY ( code   ) 

Definition at line 135 of file chan_skinny.c.

Referenced by handle_message(), and transmit_response().

#define SKINNY_DIALTONE   0x21

#define SKINNY_HOLD   8

Definition at line 1095 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1101 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1115 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 1114 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 1113 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1192 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 299 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 159 of file chan_skinny.c.

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

#define SKINNY_MICOFF   2

Definition at line 1086 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1085 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1109 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

#define SKINNY_ONHOOK   2

#define SKINNY_PARK   11

Definition at line 1098 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1099 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_REORDER   0x25

Definition at line 1107 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1120 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1118 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

#define SKINNY_RING_OUTSIDE   3

Definition at line 1119 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1091 of file chan_skinny.c.

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

#define SKINNY_RINGOUT   3

Definition at line 1090 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_SILENCE   0x00

#define SKINNY_SPEAKEROFF   2

#define SKINNY_SPEAKERON   1

#define SKINNY_TRANSFER   10

Definition at line 1097 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 339 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 337 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 902 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 347 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 604 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 634 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 631 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 628 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 629 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 630 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 636 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 642 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 632 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 641 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 626 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 643 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 635 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 639 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 625 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 623 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 637 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 640 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 624 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 627 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 306 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 460 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 400 of file chan_skinny.c.

Referenced by handle_open_receive_channel_ack_message(), and skinny_set_rtp_peer().

#define START_TONE_MESSAGE   0x0082

Definition at line 360 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 510 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 513 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 514 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 512 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 507 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 511 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 504 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 505 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 506 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 502 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

#define STIMULUS_MESSAGE   0x0005

Definition at line 270 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 515 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 500 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 501 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 503 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 509 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

#define STOP_TONE_MESSAGE   0x0083

Definition at line 368 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 316 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6615 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6616 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6617 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6614 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6618 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 346 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 318 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 548 of file chan_skinny.c.

Referenced by handle_version_req_message().


Enumeration Type Documentation

Enumerator:
SKINNY_CODEC_ALAW 
SKINNY_CODEC_ULAW 
SKINNY_CODEC_G723_1 
SKINNY_CODEC_G729A 
SKINNY_CODEC_G726_32 
SKINNY_CODEC_H261 
SKINNY_CODEC_H263 

Definition at line 147 of file chan_skinny.c.

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


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 235 of file chan_skinny.c.

00246 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 232 of file chan_skinny.c.

00246 {

static void __reg_module ( void   )  [static]

Definition at line 7498 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 7498 of file chan_skinny.c.

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

Definition at line 3154 of file chan_skinny.c.

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

Referenced by handle_skinny_show_device(), and manager_skinny_show_device().

03155 {
03156    struct skinny_device *d;
03157    struct skinny_line *l;
03158    struct skinny_speeddial *sd;
03159    struct skinny_addon *sa;
03160    char codec_buf[512];
03161 
03162    if (argc < 4) {
03163       return CLI_SHOWUSAGE;
03164    }
03165 
03166    AST_LIST_LOCK(&devices);
03167    AST_LIST_TRAVERSE(&devices, d, list) {
03168       if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
03169          int numlines = 0, numaddons = 0, numspeeddials = 0;
03170 
03171          AST_LIST_TRAVERSE(&d->lines, l, list){
03172             numlines++;
03173          }
03174 
03175          AST_LIST_TRAVERSE(&d->addons, sa, list) {
03176             numaddons++;
03177          }
03178 
03179          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03180             numspeeddials++;
03181          }
03182 
03183          if (type == 0) { /* CLI */
03184             ast_cli(fd, "Name:        %s\n", d->name);
03185             ast_cli(fd, "Id:          %s\n", d->id);
03186             ast_cli(fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
03187             ast_cli(fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03188             ast_cli(fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03189             ast_cli(fd, "Device Type: %s\n", device2str(d->type));
03190             ast_cli(fd, "Conf Codecs:");
03191             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcapability);
03192             ast_cli(fd, "%s\n", codec_buf);
03193             ast_cli(fd, "Neg Codecs: ");
03194             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->capability);
03195             ast_cli(fd, "%s\n", codec_buf);
03196             ast_cli(fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
03197             ast_cli(fd, "Lines:       %d\n", numlines);
03198             AST_LIST_TRAVERSE(&d->lines, l, list) {
03199                ast_cli(fd, "  %s (%s)\n", l->name, l->label);
03200             }
03201             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03202                numaddons++;
03203             }  
03204             ast_cli(fd, "Addons:      %d\n", numaddons);
03205             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03206                ast_cli(fd, "  %s\n", sa->type);
03207             }
03208             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03209                numspeeddials++;
03210             }
03211             ast_cli(fd, "Speeddials:  %d\n", numspeeddials);
03212             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03213                ast_cli(fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
03214             }
03215          } else { /* manager */
03216             astman_append(s, "Channeltype: SKINNY\r\n");
03217             astman_append(s, "ObjectName: %s\r\n", d->name);
03218             astman_append(s, "ChannelObjectType: device\r\n");
03219             astman_append(s, "Id: %s\r\n", d->id);
03220             astman_append(s, "version: %s\r\n", S_OR(d->version_id, "Unknown"));
03221             astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03222             astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03223             astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
03224             astman_append(s, "Codecs: ");
03225             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcapability);
03226             astman_append(s, "%s\r\n", codec_buf);
03227             astman_append(s, "CodecOrder: ");
03228             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->capability);
03229             astman_append(s, "%s\r\n", codec_buf);
03230             astman_append(s, "Devicestatus: %s\r\n", (d->registered?"registered":"unregistered"));
03231             astman_append(s, "NumberOfLines: %d\r\n", numlines);
03232             AST_LIST_TRAVERSE(&d->lines, l, list) {
03233                astman_append(s, "Line: %s (%s)\r\n", l->name, l->label);
03234             }
03235             astman_append(s, "NumberOfAddons: %d\r\n", numaddons);
03236             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03237                astman_append(s, "Addon: %s\r\n", sa->type);
03238             }
03239             astman_append(s, "NumberOfSpeeddials: %d\r\n", numspeeddials);
03240             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03241                astman_append(s, "Speeddial: %s (%s) ishint: %d\r\n", sd->exten, sd->label, sd->isHint);
03242             }
03243          }
03244       }
03245    }
03246    AST_LIST_UNLOCK(&devices);
03247    return CLI_SUCCESS;
03248 }

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

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

Referenced by handle_skinny_show_devices(), and manager_skinny_show_devices().

03044 {
03045    struct skinny_device *d;
03046    struct skinny_line *l;
03047    const char *id;
03048    char idtext[256] = "";
03049    int total_devices = 0;
03050 
03051    if (s) { /* Manager - get ActionID */
03052       id = astman_get_header(m, "ActionID");
03053       if (!ast_strlen_zero(id))
03054          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03055    }
03056 
03057    switch (argc) {
03058    case 3:
03059       break;
03060    default:
03061       return CLI_SHOWUSAGE;
03062    }
03063 
03064    if (!s) {
03065       ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
03066       ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
03067    }
03068 
03069    AST_LIST_LOCK(&devices);
03070    AST_LIST_TRAVERSE(&devices, d, list) {
03071       int numlines = 0;
03072       total_devices++;
03073       AST_LIST_TRAVERSE(&d->lines, l, list) {
03074          numlines++;
03075       }
03076       if (!s) {
03077          ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
03078             d->name,
03079             d->id,
03080             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
03081             device2str(d->type),
03082             d->registered?'Y':'N',
03083             numlines);
03084       } else {
03085          astman_append(s,
03086             "Event: DeviceEntry\r\n%s"
03087             "Channeltype: SKINNY\r\n"
03088             "ObjectName: %s\r\n"
03089             "ChannelObjectType: device\r\n"
03090             "DeviceId: %s\r\n"
03091             "IPaddress: %s\r\n"
03092             "Type: %s\r\n"
03093             "Devicestatus: %s\r\n"
03094             "NumberOfLines: %d\r\n",
03095             idtext,
03096             d->name,
03097             d->id,
03098             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"-none-",
03099             device2str(d->type),
03100             d->registered?"registered":"unregistered",
03101             numlines);
03102       }
03103    }
03104    AST_LIST_UNLOCK(&devices);
03105 
03106    if (total)
03107       *total = total_devices;
03108    
03109    return CLI_SUCCESS;
03110 }

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 3415 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, skinny_device::lines, 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().

03416 {
03417    struct skinny_device *d;
03418    struct skinny_line *l;
03419    struct ast_codec_pref *pref;
03420    int x = 0, codec = 0;
03421    char codec_buf[512];
03422    char group_buf[256];
03423    char cbuf[256];
03424 
03425    switch (argc) {
03426    case 4:
03427       break;
03428    case 6:
03429       break;
03430    default:
03431       return CLI_SHOWUSAGE;
03432    }
03433 
03434    AST_LIST_LOCK(&devices);
03435 
03436    /* Show all lines matching the one supplied */
03437    AST_LIST_TRAVERSE(&devices, d, list) {
03438       if (argc == 6 && (strcasecmp(argv[5], d->id) && strcasecmp(argv[5], d->name))) {
03439          continue;
03440       }
03441       AST_LIST_TRAVERSE(&d->lines, l, list) {
03442          if (strcasecmp(argv[3], l->name)) {
03443             continue;
03444          }
03445          if (type == 0) { /* CLI */
03446             ast_cli(fd, "Line:             %s\n", l->name);
03447             ast_cli(fd, "On Device:        %s\n", d->name);
03448             ast_cli(fd, "Line Label:       %s\n", l->label);
03449             ast_cli(fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
03450             ast_cli(fd, "Context:          %s\n", l->context);
03451             ast_cli(fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03452             ast_cli(fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03453             ast_cli(fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
03454             ast_cli(fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
03455             ast_cli(fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
03456             ast_cli(fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
03457             ast_cli(fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
03458             ast_cli(fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
03459             ast_cli(fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03460             ast_cli(fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03461             ast_cli(fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03462             ast_cli(fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
03463             ast_cli(fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
03464             ast_cli(fd, "MWIblink:         %d\n", l->mwiblink);
03465             ast_cli(fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
03466             ast_cli(fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
03467             ast_cli(fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
03468             ast_cli(fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
03469             ast_cli(fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03470             ast_cli(fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
03471             ast_cli(fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
03472             ast_cli(fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
03473             ast_cli(fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
03474             ast_cli(fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
03475             ast_cli(fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
03476             ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
03477             ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
03478             ast_cli(fd, "Group:            %d\n", l->group);
03479             ast_cli(fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
03480             ast_cli(fd, "Conf Codecs:      ");
03481             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03482             ast_cli(fd, "%s\n", codec_buf);
03483             ast_cli(fd, "Neg Codecs:       ");
03484             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
03485             ast_cli(fd, "%s\n", codec_buf);
03486             ast_cli(fd, "Codec Order:      (");
03487             print_codec_to_cli(fd, &l->prefs);
03488             ast_cli(fd, ")\n");
03489             ast_cli(fd, "\n");
03490          } else { /* manager */
03491             astman_append(s, "Channeltype: SKINNY\r\n");
03492             astman_append(s, "ObjectName: %s\r\n", l->name);
03493             astman_append(s, "ChannelObjectType: line\r\n");
03494             astman_append(s, "Device: %s\r\n", d->name);
03495             astman_append(s, "LineLabel: %s\r\n", l->label);
03496             astman_append(s, "Extension: %s\r\n", S_OR(l->exten, "<not set>"));
03497             astman_append(s, "Context: %s\r\n", l->context);
03498             astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03499             astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03500             astman_append(s, "Language: %s\r\n", S_OR(l->language, "<not set>"));
03501             astman_append(s, "Accountcode: %s\r\n", S_OR(l->accountcode, "<not set>"));
03502             astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(l->amaflags));
03503             astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), l->cid_name, l->cid_num, ""));
03504             astman_append(s, "HideCallerId: %s\r\n", (l->hidecallerid ? "Yes" : "No"));
03505             astman_append(s, "CFwdAll: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03506             astman_append(s, "CFwdBusy: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03507             astman_append(s, "CFwdNoAnswer: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03508             astman_append(s, "VoicemailBox: %s\r\n", S_OR(l->mailbox, "<not set>"));
03509             astman_append(s, "VoicemailNumber: %s\r\n", S_OR(l->vmexten, "<not set>"));
03510             astman_append(s, "MWIblink: %d\r\n", l->mwiblink);
03511             astman_append(s, "RegExtension: %s\r\n", S_OR(l->regexten, "<not set>"));
03512             astman_append(s, "Regcontext: %s\r\n", S_OR(l->regcontext, "<not set>"));
03513             astman_append(s, "MoHInterpret: %s\r\n", S_OR(l->mohinterpret, "<not set>"));
03514             astman_append(s, "MoHSuggest: %s\r\n", S_OR(l->mohsuggest, "<not set>"));
03515             astman_append(s, "LastDialedNr: %s\r\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03516             astman_append(s, "LastCallerID: %s\r\n", S_OR(l->lastcallerid, "<not set>"));
03517             astman_append(s, "Transfer: %s\r\n", (l->transfer ? "Yes" : "No"));
03518             astman_append(s, "Callwaiting: %s\r\n", (l->callwaiting ? "Yes" : "No"));
03519             astman_append(s, "3WayCalling: %s\r\n", (l->threewaycalling ? "Yes" : "No"));
03520             astman_append(s, "CanForward: %s\r\n", (l->cancallforward ? "Yes" : "No"));
03521             astman_append(s, "DoNotDisturb: %s\r\n", (l->dnd ? "Yes" : "No"));
03522             astman_append(s, "NAT: %s\r\n", (l->nat ? "Yes" : "No"));
03523             astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
03524             astman_append(s, "Group: %d\r\n", l->group);
03525             astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
03526             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03527             astman_append(s, "Codecs: %s\r\n", codec_buf);
03528             astman_append(s, "CodecOrder: ");
03529             pref = &l->prefs;
03530             for(x = 0; x < 32 ; x++) {
03531                codec = ast_codec_pref_index(pref, x);
03532                if (!codec)
03533                   break;
03534                astman_append(s, "%s", ast_getformatname(codec));
03535                if (x < 31 && ast_codec_pref_index(pref, x+1))
03536                   astman_append(s, ",");
03537             }
03538             astman_append(s, "\r\n");
03539          }
03540       }
03541    }
03542    
03543    AST_LIST_UNLOCK(&devices);
03544    return CLI_SUCCESS;
03545 }

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 3287 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, skinny_line::device, id, ast_channel::name, skinny_subchannel::owner, and skinny_line::sub.

Referenced by handle_skinny_show_lines(), and manager_skinny_show_lines().

03288 {
03289    struct skinny_line *l;
03290    struct skinny_subchannel *sub;
03291    int total_lines = 0;
03292    int verbose = 0;
03293    const char *id;
03294    char idtext[256] = "";
03295 
03296    if (s) { /* Manager - get ActionID */
03297       id = astman_get_header(m, "ActionID");
03298       if (!ast_strlen_zero(id))
03299          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03300    }
03301 
03302    switch (argc) {
03303    case 4:
03304       verbose = 1;
03305       break;
03306    case 3:
03307       verbose = 0;
03308       break;
03309    default:
03310       return CLI_SHOWUSAGE;
03311    }
03312 
03313    if (!s) {
03314       ast_cli(fd, "Name                 Device Name          Instance Label               \n");
03315       ast_cli(fd, "-------------------- -------------------- -------- --------------------\n");
03316    }
03317    AST_LIST_LOCK(&lines);
03318    AST_LIST_TRAVERSE(&lines, l, all) {
03319       total_lines++;
03320       if (!s) {
03321          ast_cli(fd, "%-20s %-20s %8d %-20s\n",
03322             l->name,
03323             (l->device ? l->device->name : "Not connected"),
03324             l->instance,
03325             l->label);
03326          if (verbose) {
03327             AST_LIST_TRAVERSE(&l->sub, sub, list) {
03328                ast_cli(fd, "  %s> %s to %s\n",
03329                   (sub == l->activesub?"Active  ":"Inactive"),
03330                   sub->owner->name,
03331                   (ast_bridged_channel(sub->owner)?ast_bridged_channel(sub->owner)->name:"")
03332                );
03333             }
03334          }
03335       } else {
03336          astman_append(s,
03337             "Event: LineEntry\r\n%s"
03338             "Channeltype: SKINNY\r\n"
03339             "ObjectName: %s\r\n"
03340             "ChannelObjectType: line\r\n"
03341             "Device: %s\r\n"
03342             "Instance: %d\r\n"
03343             "Label: %s\r\n",
03344             idtext,
03345             l->name,
03346             (l->device?l->device->name:"None"),
03347             l->instance,
03348             l->label);
03349       }
03350       AST_LIST_UNLOCK(&lines);
03351    }
03352 
03353    if (total) {
03354       *total = total_lines;
03355    }
03356 
03357    return CLI_SUCCESS;
03358 }

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

Definition at line 6472 of file chan_skinny.c.

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

Referenced by config_load().

06473 {
06474    int as;
06475    struct sockaddr_in sin;
06476    socklen_t sinlen;
06477    struct skinnysession *s;
06478    struct protoent *p;
06479    int arg = 1;
06480 
06481    for (;;) {
06482       sinlen = sizeof(sin);
06483       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
06484       if (as < 0) {
06485          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
06486          continue;
06487       }
06488       p = getprotobyname("tcp");
06489       if(p) {
06490          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
06491             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
06492          }
06493       }
06494       if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
06495          continue;
06496 
06497       memcpy(&s->sin, &sin, sizeof(sin));
06498       ast_mutex_init(&s->lock);
06499       s->fd = as;
06500       AST_LIST_LOCK(&sessions);
06501       AST_LIST_INSERT_HEAD(&sessions, s, list);
06502       AST_LIST_UNLOCK(&sessions);
06503 
06504       if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
06505          destroy_session(s);
06506       }
06507    }
06508    if (skinnydebug)
06509       ast_verb(1, "killing accept thread\n");
06510    close(as);
06511    return 0;
06512 }

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

implement the setvar config line

Definition at line 1636 of file chan_skinny.c.

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

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

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

Definition at line 1797 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( int  astcodec  )  [static]

Definition at line 1740 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message(), skinny_set_rtp_peer(), and transmit_connect().

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

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

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

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

Definition at line 2847 of file chan_skinny.c.

References AST_LIST_TRAVERSE, and ast_strdup.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

02848 {
02849    struct skinny_device *d;
02850    char *result = NULL;
02851    int wordlen = strlen(word), which = 0;
02852 
02853    AST_LIST_TRAVERSE(&devices, d, list) {
02854       if (!strncasecmp(word, d->id, wordlen) && ++which > state)
02855          result = ast_strdup(d->id);
02856    }
02857 
02858    return result;
02859 }

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

Definition at line 2866 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

02867 {
02868    return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02869 }

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

Definition at line 2861 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02862 {
02863    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02864 }

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

Definition at line 2871 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and skinny_device::lines.

Referenced by handle_skinny_show_line().

02872 {
02873    struct skinny_device *d;
02874    struct skinny_line *l;
02875    char *result = NULL;
02876    int wordlen = strlen(word), which = 0;
02877 
02878    if (pos != 3)
02879       return NULL;
02880    
02881    AST_LIST_TRAVERSE(&devices, d, list) {
02882       AST_LIST_TRAVERSE(&d->lines, l, list) {
02883          if (!strncasecmp(word, l->name, wordlen) && ++which > state)
02884             result = ast_strdup(l->name);
02885       }
02886    }
02887 
02888    return result;
02889 }

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

Definition at line 7052 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, skinny_line::device, skinnysession::device, skinny_device::lines, skinny_line::lock, skinny_device::lock, LOG_ERROR, LOG_NOTICE, skinny_subchannel::parent, skinny_device::session, skinny_line::sub, TYPE_DEVICE, and update().

Referenced by config_load().

07053  {
07054    struct skinny_device *d, *temp;
07055    struct skinny_line *l, *ltemp;
07056    struct skinny_subchannel *sub;
07057    int update = 0;
07058  
07059    ast_log(LOG_NOTICE, "Configuring skinny device %s.\n", dname);
07060 
07061    AST_LIST_LOCK(&devices);
07062    AST_LIST_TRAVERSE(&devices, temp, list) {
07063       if (!strcasecmp(dname, temp->name) && temp->prune) {
07064          update = 1;
07065          break;
07066       }
07067    }
07068 
07069    if (!(d = ast_calloc(1, sizeof(*d)))) {
07070       ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
07071       AST_LIST_UNLOCK(&devices);
07072       return NULL;
07073    }
07074    memcpy(d, default_device, sizeof(*default_device));
07075    ast_mutex_init(&d->lock);
07076    ast_copy_string(d->name, dname, sizeof(d->name));
07077    AST_LIST_INSERT_TAIL(&devices, d, list);
07078 
07079    ast_mutex_lock(&d->lock);
07080    AST_LIST_UNLOCK(&devices);
07081  
07082    config_parse_variables(TYPE_DEVICE, d, v);
07083  
07084    if (!AST_LIST_FIRST(&d->lines)) {
07085       ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
07086       ast_mutex_unlock(&d->lock);
07087       return NULL;
07088    }
07089    if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
07090       d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
07091    }
07092  
07093    if (skinnyreload){
07094       AST_LIST_LOCK(&devices);
07095       AST_LIST_TRAVERSE(&devices, temp, list) {
07096          if (strcasecmp(d->id, temp->id) || !temp->prune || !temp->session) {
07097             continue;
07098          }
07099          ast_mutex_lock(&d->lock);
07100          d->session = temp->session;
07101          d->session->device = d;
07102 
07103          AST_LIST_LOCK(&d->lines);
07104          AST_LIST_TRAVERSE(&d->lines, l, list){
07105             l->device = d; 
07106 
07107             AST_LIST_LOCK(&temp->lines);
07108             AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
07109                if (strcasecmp(l->name, ltemp->name)) {
07110                   continue;
07111                }
07112                ast_mutex_lock(&ltemp->lock);
07113                l->instance = ltemp->instance;
07114                l->hookstate = ltemp->hookstate;
07115                if (!AST_LIST_EMPTY(&ltemp->sub)) {
07116                   ast_mutex_lock(&l->lock);
07117                   l->sub = ltemp->sub;
07118                   AST_LIST_TRAVERSE(&l->sub, sub, list) {
07119                      sub->parent = l;
07120                   }
07121                   ast_mutex_unlock(&l->lock);
07122                }
07123                ast_mutex_unlock(&ltemp->lock);
07124             }
07125             AST_LIST_UNLOCK(&temp->lines);
07126          }
07127          AST_LIST_UNLOCK(&d->lines);
07128          ast_mutex_unlock(&d->lock);
07129       }
07130       AST_LIST_UNLOCK(&devices);
07131    }
07132 
07133    ast_mutex_unlock(&d->lock);
07134 
07135    ast_verb(3, "%s config for device '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), d->name);
07136    
07137    return d;
07138 
07139  }

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

Definition at line 6994 of file chan_skinny.c.

References skinny_line::all, 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, strsep(), TYPE_LINE, and update().

Referenced by config_load().

06995  {
06996    struct skinny_line *l, *temp;
06997    int update = 0;
06998  
06999    ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);
07000 
07001    /* We find the old line and remove it just before the new
07002       line is created */
07003    AST_LIST_LOCK(&lines);
07004    AST_LIST_TRAVERSE(&lines, temp, all) {
07005       if (!strcasecmp(lname, temp->name) && temp->prune) {
07006          update = 1;
07007          break;
07008       }
07009    }
07010 
07011    if (!(l=ast_calloc(1, sizeof(*l)))) {
07012       ast_verb(1, "Unable to allocate memory for line %s.\n", lname);
07013       AST_LIST_UNLOCK(&lines);
07014       return NULL;
07015    }
07016 
07017    memcpy(l, default_line, sizeof(*default_line));
07018    ast_mutex_init(&l->lock);
07019    ast_copy_string(l->name, lname, sizeof(l->name));
07020    AST_LIST_INSERT_TAIL(&lines, l, all);
07021 
07022    ast_mutex_lock(&l->lock);
07023    AST_LIST_UNLOCK(&lines);
07024 
07025    config_parse_variables(TYPE_LINE, l, v);
07026          
07027    if (!ast_strlen_zero(l->mailbox)) {
07028       char *cfg_mailbox, *cfg_context;
07029       cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
07030       ast_verb(3, "Setting mailbox '%s' on line %s\n", cfg_mailbox, l->name);
07031       strsep(&cfg_context, "@");
07032       if (ast_strlen_zero(cfg_context))
07033           cfg_context = "default";
07034       l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "skinny MWI subsciption", l,
07035          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
07036          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
07037          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
07038          AST_EVENT_IE_END);
07039    }
07040  
07041    ast_mutex_unlock(&l->lock);
07042    
07043    /* We do not want to unlink or free the line yet, it needs
07044       to be available to detect a device reconfig when we load the
07045       devices.  Old lines will be pruned after the reload completes */
07046 
07047    ast_verb(3, "%s config for line '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), l->name);
07048 
07049    return l;
07050  }

static int config_load ( void   )  [static]

Definition at line 7141 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, netlock, qos, TYPE_DEF_DEVICE, TYPE_DEF_LINE, and TYPE_GENERAL.

Referenced by load_module(), and skinny_reload().

07142  {
07143    int on = 1;
07144    struct ast_config *cfg;
07145    char *cat;
07146    struct skinny_device *d;
07147    struct skinny_line *l;
07148    int oldport = ntohs(bindaddr.sin_port);
07149    struct ast_flags config_flags = { 0 };
07150    
07151    ast_log(LOG_NOTICE, "Configuring skinny from %s\n", config);
07152   
07153    if (gethostname(ourhost, sizeof(ourhost))) {
07154       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled.\n");
07155       return 0;
07156    }
07157    cfg = ast_config_load(config, config_flags);
07158   
07159    /* We *must* have a config file otherwise stop immediately */
07160    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
07161       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled.\n", config);
07162       return -1;
07163    }
07164    memset(&bindaddr, 0, sizeof(bindaddr));
07165    memset(&default_prefs, 0, sizeof(default_prefs));
07166 
07167    /* Copy the default jb config over global_jbconf */
07168    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
07169 
07170    /* load the general section */
07171    cat = ast_category_browse(cfg, "general");
07172    config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));
07173 
07174    if (ntohl(bindaddr.sin_addr.s_addr)) {
07175       __ourip = bindaddr.sin_addr;
07176    } else {
07177       hp = ast_gethostbyname(ourhost, &ahp);
07178       if (!hp) {
07179          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
07180          ast_config_destroy(cfg);
07181          return 0;
07182       }
07183       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
07184    }
07185    if (!ntohs(bindaddr.sin_port)) {
07186       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
07187    }
07188    bindaddr.sin_family = AF_INET;
07189 
07190    /* load the lines sections */
07191    default_line->confcapability = default_capability;
07192    default_line->confprefs = default_prefs;
07193    config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
07194    cat = ast_category_browse(cfg, "lines");
07195    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
07196       l = config_line(cat, ast_variable_browse(cfg, cat));
07197       cat = ast_category_browse(cfg, cat);
07198    }
07199       
07200    /* load the devices sections */
07201    default_device->confcapability = default_capability;
07202    default_device->confprefs = default_prefs;
07203    config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
07204    cat = ast_category_browse(cfg, "devices");
07205    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
07206       d = config_device(cat, ast_variable_browse(cfg, cat));
07207       cat = ast_category_browse(cfg, cat);
07208    }
07209 
07210    ast_mutex_lock(&netlock);
07211    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
07212       close(skinnysock);
07213       skinnysock = -1;
07214    }
07215    if (skinnysock < 0) {
07216       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
07217       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
07218          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
07219          ast_config_destroy(cfg);
07220          ast_mutex_unlock(&netlock);
07221          return 0;
07222       }
07223       if (skinnysock < 0) {
07224          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
07225       } else {
07226          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
07227             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
07228                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07229                      strerror(errno));
07230             close(skinnysock);
07231             skinnysock = -1;
07232             ast_config_destroy(cfg);
07233             ast_mutex_unlock(&netlock);
07234             return 0;
07235          }
07236          if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
07237                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
07238                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07239                      strerror(errno));
07240                close(skinnysock);
07241                skinnysock = -1;
07242                ast_config_destroy(cfg);
07243                ast_mutex_unlock(&netlock);
07244                return 0;
07245          }
07246          ast_verb(2, "Skinny listening on %s:%d\n",
07247                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
07248          ast_netsock_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
07249          ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
07250       }
07251    }
07252    ast_mutex_unlock(&netlock);
07253    ast_config_destroy(cfg);
07254    return 1;
07255 }

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

Definition at line 6625 of file chan_skinny.c.

References add_var(), ahp, skinny_line::all, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_context_find_or_create(), ast_copy_string(), ast_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_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_true(), bindaddr, buf, CDEV, CDEV_OPTS, cleanup_stale_contexts(), CLINE, CLINE_OPTS, skinny_speeddial::context, context, default_prefs, skinny_speeddial::exten, exten, global_jbconf, skinny_speeddial::instance, skinny_speeddial::isHint, skinny_speeddial::label, ast_variable::lineno, skinny_device::lines, skinny_addon::lock, skinny_speeddial::lock, LOG_WARNING, ast_variable::name, ast_variable::next, skinny_speeddial::parent, qos, S_OR, strsep(), 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().

06626  {
06627    struct ast_variable *v;
06628    int lineInstance = 1;
06629    int speeddialInstance = 1;
06630    
06631    while(vptr) {
06632       v = vptr;
06633       vptr = vptr->next;
06634  
06635       if (type & (TYPE_GENERAL)) {
06636          char newcontexts[AST_MAX_CONTEXT];
06637          char oldcontexts[AST_MAX_CONTEXT];
06638          char *stringp, *context, *oldregcontext;
06639          if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06640             v = v->next;
06641             continue;
06642          }
06643          if (!strcasecmp(v->name, "bindaddr")) {
06644             if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06645                ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06646             } else {
06647                memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
06648             }
06649             continue;
06650          } else if (!strcasecmp(v->name, "keepalive")) {
06651             keep_alive = atoi(v->value);
06652             continue;
06653          } else if (!strcasecmp(v->name, "regcontext")) {
06654             ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
06655             stringp = newcontexts;
06656             /* Initialize copy of current global_regcontext for later use in removing stale contexts */
06657             ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
06658             oldregcontext = oldcontexts;
06659             /* Let's remove any contexts that are no longer defined in regcontext */
06660             cleanup_stale_contexts(stringp, oldregcontext);
06661             /* Create contexts if they don't exist already */
06662             while ((context = strsep(&stringp, "&"))) {
06663                ast_copy_string(used_context, context, sizeof(used_context));
06664                ast_context_find_or_create(NULL, NULL, context, "Skinny");
06665             }
06666             ast_copy_string(regcontext, v->value, sizeof(regcontext));
06667             continue;
06668          } else if (!strcasecmp(v->name, "dateformat")) {
06669             memcpy(date_format, v->value, sizeof(date_format));
06670             continue;
06671          } else if (!strcasecmp(v->name, "tos")) {
06672             if (ast_str2tos(v->value, &qos.tos))
06673                ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06674             continue;
06675          } else if (!strcasecmp(v->name, "tos_audio")) {
06676             if (ast_str2tos(v->value, &qos.tos_audio))
06677                ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06678             continue;
06679          } else if (!strcasecmp(v->name, "tos_video")) {
06680             if (ast_str2tos(v->value, &qos.tos_video))
06681                ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
06682             continue;
06683          } else if (!strcasecmp(v->name, "cos")) {
06684             if (ast_str2cos(v->value, &qos.cos))
06685                ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06686             continue;
06687          } else if (!strcasecmp(v->name, "cos_audio")) {
06688             if (ast_str2cos(v->value, &qos.cos_audio))
06689                ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06690             continue;
06691          } else if (!strcasecmp(v->name, "cos_video")) {
06692             if (ast_str2cos(v->value, &qos.cos_video))
06693                ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
06694             continue;
06695          } else if (!strcasecmp(v->name, "bindport")) {
06696             if (sscanf(v->value, "%5d", &ourport) == 1) {
06697                bindaddr.sin_port = htons(ourport);
06698             } else {
06699                ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
06700             }
06701             continue;
06702          } else if (!strcasecmp(v->name, "allow")) {
06703             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
06704             continue;
06705          } else if (!strcasecmp(v->name, "disallow")) {
06706             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
06707             continue;
06708          } 
06709       }
06710  
06711       if (!strcasecmp(v->name, "transfer")) {
06712          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06713             CDEV_OPTS->transfer = ast_true(v->value);
06714             continue;
06715          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06716             CLINE_OPTS->transfer = ast_true(v->value);
06717             continue;
06718          }
06719       } else if (!strcasecmp(v->name, "callwaiting")) {
06720          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06721             CDEV_OPTS->callwaiting = ast_true(v->value);
06722             continue;
06723          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06724             CLINE_OPTS->callwaiting = ast_true(v->value);
06725             continue;
06726          }
06727       } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
06728          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06729             CLINE_OPTS->directmedia = ast_true(v->value);
06730             continue;
06731          }
06732       } else if (!strcasecmp(v->name, "nat")) {
06733          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06734             CLINE_OPTS->nat = ast_true(v->value);
06735             continue;
06736          }
06737       } else if (!strcasecmp(v->name, "context")) {
06738          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06739             ast_copy_string(CLINE_OPTS->context, v->value, sizeof(CLINE_OPTS->context));
06740             continue;
06741          }
06742       }else if (!strcasecmp(v->name, "vmexten")) {
06743          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06744             ast_copy_string(CDEV_OPTS->vmexten, v->value, sizeof(CDEV_OPTS->vmexten));
06745             continue;
06746          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06747             ast_copy_string(CLINE_OPTS->vmexten, v->value, sizeof(CLINE_OPTS->vmexten));
06748             continue;
06749          }
06750       } else if (!strcasecmp(v->name, "mwiblink")) {
06751          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06752             CDEV_OPTS->mwiblink = ast_true(v->value);
06753             continue;
06754          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06755             CLINE_OPTS->mwiblink = ast_true(v->value);
06756             continue;
06757          }
06758       } else if (!strcasecmp(v->name, "linelabel")) {
06759          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06760             ast_copy_string(CLINE_OPTS->label, v->value, sizeof(CLINE_OPTS->label));
06761             continue;
06762          }
06763       } else if (!strcasecmp(v->name, "callerid")) {
06764          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06765             if (!strcasecmp(v->value, "asreceived")) {
06766                CLINE_OPTS->cid_num[0] = '\0';
06767                CLINE_OPTS->cid_name[0] = '\0';
06768             } else {
06769                ast_callerid_split(v->value, CLINE_OPTS->cid_name, sizeof(CLINE_OPTS->cid_name), CLINE_OPTS->cid_num, sizeof(CLINE_OPTS->cid_num));
06770             }
06771             continue;
06772          }
06773       } else if (!strcasecmp(v->name, "amaflags")) {
06774          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06775             int tempamaflags = ast_cdr_amaflags2int(v->value);
06776             if (tempamaflags < 0) {
06777                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
06778             } else {
06779                CLINE_OPTS->amaflags = tempamaflags;
06780             }
06781             continue;
06782          }
06783       } else if (!strcasecmp(v->name, "regexten")) {
06784          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06785             ast_copy_string(CLINE_OPTS->regexten, v->value, sizeof(CLINE_OPTS->regexten));
06786             continue;
06787          }
06788       } else if (!strcasecmp(v->name, "language")) {
06789          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06790             ast_copy_string(CLINE_OPTS->language, v->value, sizeof(CLINE_OPTS->language));
06791             continue;
06792          }
06793       } else if (!strcasecmp(v->name, "accountcode")) {
06794          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06795             ast_copy_string(CLINE_OPTS->accountcode, v->value, sizeof(CLINE_OPTS->accountcode));
06796             continue;
06797          }
06798       } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
06799          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06800             ast_copy_string(CLINE_OPTS->mohinterpret, v->value, sizeof(CLINE_OPTS->mohinterpret));
06801             continue;
06802          }
06803       } else if (!strcasecmp(v->name, "mohsuggest")) {
06804          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06805             ast_copy_string(CLINE_OPTS->mohsuggest, v->value, sizeof(CLINE_OPTS->mohsuggest));
06806             continue;
06807          }
06808       } else if (!strcasecmp(v->name, "callgroup")) {
06809          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06810             CLINE_OPTS->callgroup = ast_get_group(v->value);
06811             continue;
06812          }
06813       } else if (!strcasecmp(v->name, "pickupgroup")) {
06814          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06815             CLINE_OPTS->pickupgroup = ast_get_group(v->value);
06816             continue;
06817          }
06818       } else if (!strcasecmp(v->name, "immediate")) {
06819          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE | TYPE_DEF_LINE | TYPE_LINE)) {
06820             CLINE_OPTS->immediate = ast_true(v->value);
06821             continue;
06822          }
06823       } else if (!strcasecmp(v->name, "cancallforward")) {
06824          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06825             CLINE_OPTS->cancallforward = ast_true(v->value);
06826             continue;
06827          }
06828       } else if (!strcasecmp(v->name, "mailbox")) {
06829          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06830             ast_copy_string(CLINE_OPTS->mailbox, v->value, sizeof(CLINE_OPTS->mailbox));
06831             continue;
06832          }
06833       } else if ( !strcasecmp(v->name, "parkinglot")) {
06834          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06835             ast_copy_string(CLINE_OPTS->parkinglot, v->value, sizeof(CLINE_OPTS->parkinglot));
06836             continue;
06837          }
06838       } else if (!strcasecmp(v->name, "hasvoicemail")) {
06839          if (type & (TYPE_LINE)) {
06840             if (ast_true(v->value) && ast_strlen_zero(CLINE->mailbox)) {
06841                ast_copy_string(CLINE->mailbox, CLINE->name, sizeof(CLINE->mailbox));
06842             }
06843             continue;
06844          }
06845       } else if (!strcasecmp(v->name, "callreturn")) {
06846          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06847             CLINE_OPTS->callreturn = ast_true(v->value);
06848             continue;
06849          }
06850       } else if (!strcasecmp(v->name, "threewaycalling")) {
06851          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06852             CLINE_OPTS->threewaycalling = ast_true(v->value);
06853             continue;
06854          }
06855       } else if (!strcasecmp(v->name, "setvar")) {
06856          if (type & (TYPE_LINE)) {
06857             CLINE->chanvars = add_var(v->value, CLINE->chanvars);
06858             continue;
06859          }
06860       } else if (!strcasecmp(v->name, "earlyrtp")) {
06861          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06862             CDEV_OPTS->earlyrtp = ast_true(v->value);
06863             continue;
06864          }
06865       } else if (!strcasecmp(v->name, "host")) {
06866          if (type & (TYPE_DEVICE)) {
06867             if (ast_get_ip(&CDEV->addr, v->value)) {
06868                ast_log(LOG_WARNING, "Bad IP '%s' at line %d.\n", v->value, v->lineno);
06869             }
06870             continue;
06871          }
06872       } else if (!strcasecmp(v->name, "port")) {
06873          if (type & (TYPE_DEF_DEVICE)) {
06874             CDEV->addr.sin_port = htons(atoi(v->value));
06875             continue;
06876          }
06877       } else if (!strcasecmp(v->name, "device")) {
06878          if (type & (TYPE_DEVICE)) {
06879             ast_copy_string(CDEV_OPTS->id, v->value, sizeof(CDEV_OPTS->id));
06880             continue;
06881          }
06882       } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06883          if (type & (TYPE_DEVICE)) {
06884             CDEV->ha = ast_append_ha(v->name, v->value, CDEV->ha, NULL);
06885             continue;
06886          }
06887       } else if (!strcasecmp(v->name, "allow")) {
06888          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06889             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 1);
06890             continue;
06891          }
06892          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06893             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 1);
06894             continue;
06895          }
06896       } else if (!strcasecmp(v->name, "disallow")) {
06897          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06898             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 0);
06899             continue;
06900          }
06901          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06902             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 0);
06903             continue;
06904          }
06905       } else if (!strcasecmp(v->name, "version")) {
06906          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06907             ast_copy_string(CDEV_OPTS->version_id, v->value, sizeof(CDEV_OPTS->version_id));
06908             continue;
06909          }
06910       } else if (!strcasecmp(v->name, "line")) {
06911          if (type & (TYPE_DEVICE)) {
06912             struct skinny_line *l;
06913             AST_LIST_TRAVERSE(&lines, l, all) {
06914                if (!strcasecmp(v->value, l->name) && !l->prune) {
06915 
06916                   /* FIXME: temp solution about line conflicts */
06917                   struct skinny_device *d;
06918                   struct skinny_line *l2;
06919                   int lineinuse = 0;
06920                   AST_LIST_TRAVERSE(&devices, d, list) {
06921                      AST_LIST_TRAVERSE(&d->lines, l2, list) {
06922                         if (l2 == l && strcasecmp(d->id, CDEV->id)) {
06923                            ast_log(LOG_WARNING, "Line %s already used by %s. Not connecting to %s.\n", l->name, d->name, CDEV->name);
06924                            lineinuse++;
06925                         }
06926                      }
06927                   }
06928                   if (!lineinuse) {
06929                      if (!AST_LIST_FIRST(&CDEV->lines)) {
06930                         CDEV->activeline = l;
06931                      }
06932                      lineInstance++;
06933                      AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
06934                   }
06935                   break;
06936                }
06937             }
06938             continue;
06939          }
06940       } else if (!strcasecmp(v->name, "speeddial")) {
06941          if (type & (TYPE_DEVICE)) {
06942             struct skinny_speeddial *sd;
06943             if (!(sd = ast_calloc(1, sizeof(*sd)))) {
06944                ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name);
06945                continue;
06946             } else {
06947                char buf[256];
06948                char *stringp = buf, *exten, *context, *label;
06949                   ast_copy_string(buf, v->value, sizeof(buf));
06950                exten = strsep(&stringp, ",");
06951                if ((context = strchr(exten, '@'))) {
06952                   *context++ = '\0';
06953                }
06954                label = stringp;
06955                ast_mutex_init(&sd->lock);
06956                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
06957                if (!ast_strlen_zero(context)) {
06958                   sd->isHint = 1;
06959                   sd->instance = lineInstance++;
06960                   ast_copy_string(sd->context, context, sizeof(sd->context));
06961                } else {
06962                   sd->isHint = 0;
06963                   sd->instance = speeddialInstance++;
06964                   sd->context[0] = '\0';
06965                }
06966                ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
06967                sd->parent = CDEV;
06968                AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
06969             }
06970             continue;
06971          }
06972       } else if (!strcasecmp(v->name, "addon")) {
06973          if (type & (TYPE_DEVICE)) {
06974             struct skinny_addon *a;
06975             if (!(a = ast_calloc(1, sizeof(*a)))) {
06976                ast_log(LOG_WARNING, "Unable to allocate memory for addon %s. Ignoring addon.\n", v->name);
06977                continue;
06978             } else {
06979                ast_mutex_init(&a->lock);
06980                ast_copy_string(a->type, v->value, sizeof(a->type));
06981                AST_LIST_INSERT_HEAD(&CDEV->addons, a, list);
06982             }
06983             continue;
06984          }
06985 
06986       } else {
06987          ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
06988          continue;
06989       }
06990       ast_log(LOG_WARNING, "Invalid category used: %s at line %d\n", v->name, v->lineno);
06991    }
06992  }

static char* control2str ( int  ind  )  [static]

Definition at line 4133 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_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(), CONTROL2STR_BUFSIZE, and control2str_threadbuf.

04133                                   {
04134    char *tmp;
04135 
04136    switch (ind) {
04137    case AST_CONTROL_HANGUP:
04138       return "Other end has hungup";
04139    case AST_CONTROL_RING:
04140       return "Local ring";
04141    case AST_CONTROL_RINGING:
04142       return "Remote end is ringing";
04143    case AST_CONTROL_ANSWER:
04144       return "Remote end has answered";
04145    case AST_CONTROL_BUSY:
04146       return "Remote end is busy";
04147    case AST_CONTROL_TAKEOFFHOOK:
04148       return "Make it go off hook";
04149    case AST_CONTROL_OFFHOOK:
04150       return "Line is off hook";
04151    case AST_CONTROL_CONGESTION:
04152       return "Congestion (circuits busy)";
04153    case AST_CONTROL_FLASH:
04154       return "Flash hook";
04155    case AST_CONTROL_WINK:
04156       return "Wink";
04157    case AST_CONTROL_OPTION:
04158       return "Set a low-level option";
04159    case AST_CONTROL_RADIO_KEY:
04160       return "Key Radio";
04161    case AST_CONTROL_RADIO_UNKEY:
04162       return "Un-Key Radio";
04163    case AST_CONTROL_PROGRESS:
04164       return "Remote end is making Progress";
04165    case AST_CONTROL_PROCEEDING:
04166       return "Remote end is proceeding";
04167    case AST_CONTROL_HOLD:
04168       return "Hold";
04169    case AST_CONTROL_UNHOLD:
04170       return "Unhold";
04171    case AST_CONTROL_SRCUPDATE:
04172       return "Media Source Update";
04173    case AST_CONTROL_CONNECTED_LINE:
04174       return "Connected Line";
04175    case AST_CONTROL_REDIRECTING:
04176       return "Redirecting";
04177    case -1:
04178       return "Stop tone";
04179    default:
04180       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
04181                         return "Unknown";
04182       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
04183       return tmp;
04184    }
04185 }

static void delete_devices ( void   )  [static]

Definition at line 7257 of file chan_skinny.c.

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

Referenced by unload_module().

07258 {
07259    struct skinny_device *d;
07260    struct skinny_line *l;
07261    struct skinny_speeddial *sd;
07262    struct skinny_addon *a;
07263 
07264    AST_LIST_LOCK(&devices);
07265    AST_LIST_LOCK(&lines);
07266 
07267    /* Delete all devices */
07268    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
07269       /* Delete all lines for this device */
07270       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07271          AST_LIST_REMOVE(&lines, l, all);
07272          free(l);
07273       }
07274       /* Delete all speeddials for this device */
07275       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07276          free(sd);
07277       }
07278       /* Delete all addons for this device */
07279       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07280          free(a);
07281       } 
07282       free(d);
07283    }
07284    AST_LIST_UNLOCK(&lines);
07285    AST_LIST_UNLOCK(&devices);
07286 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 6314 of file chan_skinny.c.

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

Referenced by accept_thread(), and skinny_session().

06315 {
06316    struct skinnysession *cur;
06317    AST_LIST_LOCK(&sessions);
06318    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
06319       if (cur == s) {
06320          AST_LIST_REMOVE_CURRENT(list);
06321          if (s->fd > -1) 
06322             close(s->fd);
06323          
06324          ast_mutex_destroy(&s->lock);
06325          
06326          ast_free(s);
06327       } else {
06328          ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
06329       }
06330    }
06331    AST_LIST_TRAVERSE_SAFE_END
06332    AST_LIST_UNLOCK(&sessions);
06333 }

static char* device2str ( int  type  )  [static]

Definition at line 2936 of file chan_skinny.c.

References ast_threadstorage_get(), DEVICE2STR_BUFSIZE, device2str_threadbuf, SKINNY_DEVICE_12, SKINNY_DEVICE_12SP, SKINNY_DEVICE_12SPPLUS, SKINNY_DEVICE_30SPPLUS, SKINNY_DEVICE_30VIP, SKINNY_DEVICE_7902, SKINNY_DEVICE_7905, SKINNY_DEVICE_7906, SKINNY_DEVICE_7910, SKINNY_DEVICE_7911, SKINNY_DEVICE_7912, SKINNY_DEVICE_7914, SKINNY_DEVICE_7920, SKINNY_DEVICE_7921, SKINNY_DEVICE_7931, SKINNY_DEVICE_7935, SKINNY_DEVICE_7936, SKINNY_DEVICE_7937, SKINNY_DEVICE_7940, SKINNY_DEVICE_7941, SKINNY_DEVICE_7941GE, SKINNY_DEVICE_7942, SKINNY_DEVICE_7945, SKINNY_DEVICE_7960, SKINNY_DEVICE_7961, SKINNY_DEVICE_7961GE, SKINNY_DEVICE_7962, SKINNY_DEVICE_7965, SKINNY_DEVICE_7970, SKINNY_DEVICE_7971, SKINNY_DEVICE_7975, SKINNY_DEVICE_7985, SKINNY_DEVICE_ATA186, SKINNY_DEVICE_CIPC, SKINNY_DEVICE_NONE, SKINNY_DEVICE_SCCPGATEWAY_AN, SKINNY_DEVICE_SCCPGATEWAY_BRI, and SKINNY_DEVICE_UNKNOWN.

Referenced by _skinny_show_device(), and _skinny_show_devices().

02937 {
02938    char *tmp;
02939 
02940    switch (type) {
02941    case SKINNY_DEVICE_NONE:
02942       return "No Device";
02943    case SKINNY_DEVICE_30SPPLUS:
02944       return "30SP Plus";
02945    case SKINNY_DEVICE_12SPPLUS:
02946       return "12SP Plus";
02947    case SKINNY_DEVICE_12SP:
02948       return "12SP";
02949    case SKINNY_DEVICE_12:
02950       return "12";
02951    case SKINNY_DEVICE_30VIP:
02952       return "30VIP";
02953    case SKINNY_DEVICE_7910:
02954       return "7910";
02955    case SKINNY_DEVICE_7960:
02956       return "7960";
02957    case SKINNY_DEVICE_7940:
02958       return "7940";
02959    case SKINNY_DEVICE_7935:
02960       return "7935";
02961    case SKINNY_DEVICE_ATA186:
02962       return "ATA186";
02963    case SKINNY_DEVICE_7941:
02964       return "7941";
02965    case SKINNY_DEVICE_7971:
02966       return "7971";
02967    case SKINNY_DEVICE_7914:
02968       return "7914";
02969    case SKINNY_DEVICE_7985:
02970       return "7985";
02971    case SKINNY_DEVICE_7911:
02972       return "7911";
02973    case SKINNY_DEVICE_7961GE:
02974       return "7961GE";
02975    case SKINNY_DEVICE_7941GE:
02976       return "7941GE";
02977    case SKINNY_DEVICE_7931:
02978       return "7931";
02979    case SKINNY_DEVICE_7921:
02980       return "7921";
02981    case SKINNY_DEVICE_7906:
02982       return "7906";
02983    case SKINNY_DEVICE_7962:
02984       return "7962";
02985    case SKINNY_DEVICE_7937:
02986       return "7937";
02987    case SKINNY_DEVICE_7942:
02988       return "7942";
02989    case SKINNY_DEVICE_7945:
02990       return "7945";
02991    case SKINNY_DEVICE_7965:
02992       return "7965";
02993    case SKINNY_DEVICE_7975:
02994       return "7975";
02995    case SKINNY_DEVICE_7905:
02996       return "7905";
02997    case SKINNY_DEVICE_7920:
02998       return "7920";
02999    case SKINNY_DEVICE_7970:
03000       return "7970";
03001    case SKINNY_DEVICE_7912:
03002       return "7912";
03003    case SKINNY_DEVICE_7902:
03004       return "7902";
03005    case SKINNY_DEVICE_CIPC:
03006       return "IP Communicator";
03007    case SKINNY_DEVICE_7961:
03008       return "7961";
03009    case SKINNY_DEVICE_7936:
03010       return "7936";
03011    case SKINNY_DEVICE_SCCPGATEWAY_AN:
03012       return "SCCPGATEWAY_AN";
03013    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
03014       return "SCCPGATEWAY_BRI";
03015    case SKINNY_DEVICE_UNKNOWN:
03016       return "Unknown";
03017    default:
03018       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
03019          return "Unknown";
03020       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
03021       return tmp;
03022    }
03023 }

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

Definition at line 6514 of file chan_skinny.c.

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

06515 {
06516    int res;
06517 
06518    /* This thread monitors all the interfaces which are not yet in use
06519       (and thus do not have a separate thread) indefinitely */
06520    /* From here on out, we die whenever asked */
06521    for(;;) {
06522       pthread_testcancel();
06523       /* Wait for sched or io */
06524       res = ast_sched_wait(sched);
06525       if ((res < 0) || (res > 1000)) {
06526          res = 1000;
06527       }
06528       res = ast_io_wait(io, res);
06529       ast_mutex_lock(&monlock);
06530       if (res >= 0) {
06531          ast_sched_runq(sched);
06532       }
06533       ast_mutex_unlock(&monlock);
06534    }
06535    /* Never reached */
06536    return NULL;
06537 
06538 }

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

Definition at line 1564 of file chan_skinny.c.

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

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

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

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

Definition at line 1585 of file chan_skinny.c.

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

Referenced by skinny_devicestate(), and skinny_request().

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

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

Definition at line 1703 of file chan_skinny.c.

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

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

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

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

Definition at line 1652 of file chan_skinny.c.

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

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

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

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

Definition at line 1679 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message().

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

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

Definition at line 1413 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), BT_CALLPARK, BT_CONFERENCE, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_DISPLAY, BT_FORWARDALL, BT_HOLD, BT_LINE, BT_NONE, BT_REDIAL, BT_SPEEDDIAL, BT_TRANSFER, BT_VOICEMAIL, skinnysession::device, LOG_WARNING, SKINNY_DEVICE_12, SKINNY_DEVICE_12SP, SKINNY_DEVICE_12SPPLUS, SKINNY_DEVICE_30SPPLUS, SKINNY_DEVICE_30VIP, SKINNY_DEVICE_7902, SKINNY_DEVICE_7905, SKINNY_DEVICE_7906, SKINNY_DEVICE_7910, SKINNY_DEVICE_7911, SKINNY_DEVICE_7912, SKINNY_DEVICE_7914, SKINNY_DEVICE_7920, SKINNY_DEVICE_7921, SKINNY_DEVICE_7931, SKINNY_DEVICE_7935, SKINNY_DEVICE_7936, SKINNY_DEVICE_7937, SKINNY_DEVICE_7940, SKINNY_DEVICE_7941, SKINNY_DEVICE_7941GE, SKINNY_DEVICE_7942, SKINNY_DEVICE_7945, SKINNY_DEVICE_7960, SKINNY_DEVICE_7961, SKINNY_DEVICE_7961GE, SKINNY_DEVICE_7962, SKINNY_DEVICE_7965, SKINNY_DEVICE_7970, SKINNY_DEVICE_7971, SKINNY_DEVICE_7975, SKINNY_DEVICE_7985, SKINNY_DEVICE_ATA186, SKINNY_DEVICE_CIPC, SKINNY_DEVICE_SCCPGATEWAY_AN, SKINNY_DEVICE_SCCPGATEWAY_BRI, and skinny_addon::type.

Referenced by handle_button_template_req_message().

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

static int get_devicestate ( struct skinny_line l  )  [static]

Definition at line 4104 of file chan_skinny.c.

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

Referenced by skinny_devicestate(), and skinny_new().

04105 {
04106    struct skinny_subchannel *sub;
04107    int res = AST_DEVICE_UNKNOWN;
04108 
04109    if (!l)
04110       res = AST_DEVICE_INVALID;
04111    else if (!l->device)
04112       res = AST_DEVICE_UNAVAILABLE;
04113    else if (l->dnd)
04114       res = AST_DEVICE_BUSY;
04115    else {
04116       if (l->hookstate == SKINNY_ONHOOK) {
04117          res = AST_DEVICE_NOT_INUSE;
04118       } else {
04119          res = AST_DEVICE_INUSE;
04120       }
04121 
04122       AST_LIST_TRAVERSE(&l->sub, sub, list) {
04123          if (sub->onhold) {
04124             res = AST_DEVICE_ONHOLD;
04125             break;
04126          }
04127       }
04128    }
04129 
04130    return res;
04131 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 6335 of file chan_skinny.c.

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

Referenced by do_message(), and skinny_session().

06336 {
06337    int res;
06338    int dlen = 0;
06339    int *bufaddr;
06340    struct pollfd fds[1];
06341 
06342    fds[0].fd = s->fd;
06343    fds[0].events = POLLIN;
06344    fds[0].revents = 0;
06345    res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
06346                    /* we add 10% to the keep_alive to deal */
06347                    /* with network delays, etc */
06348    if (res < 0) {
06349       if (errno != EINTR) {
06350          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
06351          return res;
06352       }
06353    } else if (res == 0) {
06354       if (skinnydebug)
06355          ast_verb(1, "Skinny Client was lost, unregistering\n");
06356       skinny_unregister(NULL, s);
06357       return -1;
06358    }
06359            
06360    if (fds[0].revents) {
06361       ast_mutex_lock(&s->lock);
06362       memset(s->inbuf, 0, sizeof(s->inbuf));
06363       res = read(s->fd, s->inbuf, 4);
06364       if (res < 0) {
06365          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06366 
06367          if (skinnydebug)
06368             ast_verb(1, "Skinny Client was lost, unregistering\n");
06369 
06370          skinny_unregister(NULL, s);
06371          ast_mutex_unlock(&s->lock);
06372          return res;
06373       } else if (res != 4) {
06374          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
06375          ast_mutex_unlock(&s->lock);
06376          
06377          if (res == 0) {
06378             if (skinnydebug)
06379                ast_verb(1, "Skinny Client was lost, unregistering\n");
06380             skinny_unregister(NULL, s);
06381          }
06382 
06383          return -1;
06384       }
06385 
06386       bufaddr = (int *)s->inbuf;
06387       dlen = letohl(*bufaddr);
06388       if (dlen < 4) {
06389          ast_debug(1, "Skinny Client sent invalid data.\n");
06390          ast_mutex_unlock(&s->lock);
06391          return -1;
06392       }
06393       if (dlen+8 > sizeof(s->inbuf)) {
06394          dlen = sizeof(s->inbuf) - 8;
06395       }
06396       *bufaddr = htolel(dlen);
06397 
06398       res = read(s->fd, s->inbuf+4, dlen+4);
06399       ast_mutex_unlock(&s->lock);
06400       if (res < 0) {
06401          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06402          return res;
06403       } else if (res != (dlen+4)) {
06404          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
06405          return -1;
06406       }
06407       return res;
06408    }
06409    return 0;
06410 }

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

Definition at line 5590 of file chan_skinny.c.

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

Referenced by handle_message().

05591 {
05592    /* no response necessary */
05593    if (skinnydebug)
05594       ast_verb(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
05595 
05596    return 1;
05597 }

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

Definition at line 5417 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, skinny_device::lines, req_alloc(), skinny_device::speeddials, button_template_res_message::totalButtonCount, and transmit_response().

Referenced by handle_message().

05418 {
05419    struct skinny_device *d = s->device;
05420    struct skinny_line *l;
05421    int i;
05422 
05423    struct skinny_speeddial *sd;
05424    struct button_definition_template btn[42];
05425    int lineInstance = 1;
05426    int speeddialInstance = 1;
05427    int buttonCount = 0;
05428 
05429    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
05430       return -1;
05431 
05432    memset(&btn, 0, sizeof(btn));
05433 
05434    get_button_template(s, btn);
05435 
05436    for (i=0; i<42; i++) {
05437       int btnSet = 0;
05438       switch (btn[i].buttonDefinition) {
05439          case BT_CUST_LINE:
05440             /* assume failure */
05441             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05442             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05443 
05444             AST_LIST_TRAVERSE(&d->lines, l, list) {
05445                if (l->instance == lineInstance) {
05446                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05447                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05448                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05449                   lineInstance++;
05450                   buttonCount++;
05451                   btnSet = 1;
05452                   break;
05453                }
05454             }
05455 
05456             if (!btnSet) {
05457                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05458                   if (sd->isHint && sd->instance == lineInstance) {
05459                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05460                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05461                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05462                      lineInstance++;
05463                      buttonCount++;
05464                      btnSet = 1;
05465                      break;
05466                   }
05467                }
05468             }
05469             break;
05470          case BT_CUST_LINESPEEDDIAL:
05471             /* assume failure */
05472             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05473             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05474 
05475             AST_LIST_TRAVERSE(&d->lines, l, list) {
05476                if (l->instance == lineInstance) {
05477                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05478                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05479                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05480                   lineInstance++;
05481                   buttonCount++;
05482                   btnSet = 1;
05483                   break;
05484                }
05485             }
05486 
05487             if (!btnSet) {
05488                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05489                   if (sd->isHint && sd->instance == lineInstance) {
05490                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05491                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05492                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05493                      lineInstance++;
05494                      buttonCount++;
05495                      btnSet = 1;
05496                      break;
05497                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
05498                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05499                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05500                      req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
05501                      speeddialInstance++;
05502                      buttonCount++;
05503                      btnSet = 1;
05504                      break;
05505                   }
05506                }
05507             }
05508             break;
05509          case BT_LINE:
05510             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
05511             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05512 
05513             AST_LIST_TRAVERSE(&d->lines, l, list) {
05514                if (l->instance == lineInstance) {
05515                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05516                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05517                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05518                   lineInstance++;
05519                   buttonCount++;
05520                   btnSet = 1;
05521                   break;
05522                }
05523             }
05524             break;
05525          case BT_SPEEDDIAL:
05526             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05527             req->data.buttontemplate.definition[i].instanceNumber = 0;
05528 
05529             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05530                if (!sd->isHint && sd->instance == speeddialInstance) {
05531                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05532                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05533                   req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance - 1);
05534                   speeddialInstance++;
05535                   buttonCount++;
05536                   btnSet = 1;
05537                   break;
05538                }
05539             }
05540             break;
05541          case BT_NONE:
05542             break;
05543          default:
05544             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
05545             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
05546             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05547             buttonCount++;
05548             btnSet = 1;
05549             break;
05550       }
05551    }
05552 
05553    req->data.buttontemplate.buttonOffset = htolel(0);
05554    req->data.buttontemplate.buttonCount = htolel(buttonCount);
05555    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
05556 
05557    if (skinnydebug)
05558       ast_verb(1, "Sending %d template to %s\n",
05559                d->type,
05560                d->name);
05561    transmit_response(d, req);
05562    return 1;
05563 }

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

Definition at line 4672 of file chan_skinny.c.

References ast_channel::_state, ast_hangup(), ast_indicate(), ast_log(), ast_pthread_create, ast_safe_sleep(), AST_STATE_UP, ast_verb, skinny_subchannel::callid, skinny_line::device, errno, KEYDEF_RINGOUT, LOG_WARNING, skinny_subchannel::owner, skinny_subchannel::parent, set_callforwards(), SKINNY_DIALTONE, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), transmit_callstate(), transmit_cfwdstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04673 {
04674    struct skinny_line *l = sub->parent;
04675    struct skinny_device *d = l->device;
04676    struct ast_channel *c = sub->owner;
04677    pthread_t t;
04678 
04679    if (l->hookstate == SKINNY_ONHOOK) {
04680       l->hookstate = SKINNY_OFFHOOK;
04681       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04682       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04683    }
04684    if (skinnydebug)
04685       ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04686    transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04687 
04688    if (l->cfwdtype & cfwdtype) {
04689       set_callforwards(l, NULL, cfwdtype);
04690       ast_safe_sleep(c, 500);
04691       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04692       transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
04693       transmit_displaynotify(d, "CFwd disabled", 10);
04694       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04695          ast_indicate(c, -1);
04696          ast_hangup(c);
04697       }
04698       transmit_cfwdstate(d, l);
04699    } else {
04700       l->getforward = cfwdtype;
04701       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04702       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04703       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04704          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04705          ast_hangup(c);
04706       }
04707    }
04708    return 0;
04709 }

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

Definition at line 5297 of file chan_skinny.c.

References 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_device::lines, skinny_line::lock, LOG_WARNING, and SKINNY_MAX_CAPABILITIES.

Referenced by handle_message().

05298 {
05299    struct skinny_device *d = s->device;
05300    struct skinny_line *l;
05301    uint32_t count = 0;
05302    int codecs = 0;
05303    int i;
05304 
05305    count = letohl(req->data.caps.count);
05306    if (count > SKINNY_MAX_CAPABILITIES) {
05307       count = SKINNY_MAX_CAPABILITIES;
05308       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
05309    }
05310 
05311    for (i = 0; i < count; i++) {
05312       int acodec = 0;
05313       int scodec = 0;
05314       scodec = letohl(req->data.caps.caps[i].codec);
05315       acodec = codec_skinny2ast(scodec);
05316       if (skinnydebug)
05317          ast_verb(1, "Adding codec capability '%d (%d)'\n", acodec, scodec);
05318       codecs |= acodec;
05319    }
05320 
05321    d->capability = d->confcapability & codecs;
05322    ast_verb(0, "Device capability set to '%d'\n", d->capability);
05323    AST_LIST_TRAVERSE(&d->lines, l, list) {
05324       ast_mutex_lock(&l->lock);
05325       l->capability = l->confcapability & d->capability;
05326       ast_mutex_unlock(&l->lock);
05327    }
05328 
05329    return 1;
05330 }

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

Definition at line 5666 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_subchannel::parent, SKINNY_DIALTONE, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_SILENCE, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), and transmit_tone().

Referenced by handle_message().

05667 {
05668    struct skinny_device *d = s->device;
05669    struct skinny_line *l;
05670    struct skinny_subchannel *sub = NULL;
05671    struct ast_channel *c;
05672    pthread_t t;
05673 
05674    if (skinnydebug)
05675       ast_verb(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
05676 
05677    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05678 
05679    if (!sub) {
05680       l = find_line_by_instance(d, d->lastlineinstance);
05681       if (!l) {
05682          return 0;
05683       }
05684    } else {
05685       l = sub->parent;
05686    }
05687 
05688    c = skinny_new(l, AST_STATE_DOWN, NULL);
05689 
05690    if(!c) {
05691       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05692    } else {
05693       l->hookstate = SKINNY_OFFHOOK;
05694 
05695       sub = c->tech_pvt;
05696       l->activesub = sub;
05697       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05698       if (skinnydebug)
05699          ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05700       transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05701       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05702 
05703       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
05704          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05705       }
05706       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
05707       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05708          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05709          ast_hangup(c);
05710       }
05711    }
05712    
05713    return 1;
05714 }

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

Definition at line 6129 of file chan_skinny.c.

Referenced by handle_message().

06130 {
06131    /* XXX umm...okay?  Why do I care? */
06132    return 1;
06133 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4517 of file chan_skinny.c.

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

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04518 {
04519    if (!sub)
04520       return -1;
04521    if (sub->related) {
04522       skinny_hold(sub);
04523       skinny_unhold(sub->related);
04524       sub->parent->activesub = sub->related;
04525    } else {
04526       if (sub->onhold) {
04527          skinny_unhold(sub);
04528          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04529       } else {
04530          skinny_hold(sub);
04531          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04532       }
04533    }
04534    return 1;
04535 }

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

Definition at line 4710 of file chan_skinny.c.

Referenced by handle_message().

04711 {
04712    /* no response necessary */
04713    return 1;
04714 }

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

Definition at line 4598 of file chan_skinny.c.

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

Referenced by handle_message().

04599 {
04600    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04601       return -1;
04602 
04603    transmit_response(s->device, req);
04604    return 1;
04605 }

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

Definition at line 4716 of file chan_skinny.c.

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

Referenced by handle_message().

04717 {
04718    struct skinny_subchannel *sub = NULL;
04719    struct skinny_line *l;
04720    struct skinny_device *d = s->device;
04721    struct ast_frame f = { 0, };
04722    char dgt;
04723    int digit;
04724    int lineInstance;
04725    int callReference;
04726 
04727    digit = letohl(req->data.keypad.button);
04728    lineInstance = letohl(req->data.keypad.lineInstance);
04729    callReference = letohl(req->data.keypad.callReference);
04730 
04731    if (digit == 14) {
04732       dgt = '*';
04733    } else if (digit == 15) {
04734       dgt = '#';
04735    } else if (digit >= 0 && digit <= 9) {
04736       dgt = '0' + digit;
04737    } else {
04738       /* digit=10-13 (A,B,C,D ?), or
04739        * digit is bad value
04740        *
04741        * probably should not end up here, but set
04742        * value for backward compatibility, and log
04743        * a warning.
04744        */
04745       dgt = '0' + digit;
04746       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04747    }
04748 
04749    f.subclass = dgt;
04750 
04751    f.src = "skinny";
04752 
04753    if (lineInstance && callReference)
04754       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04755    else
04756       sub = d->activeline->activesub;
04757       //sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04758 
04759    if (!sub)
04760       return 0;
04761 
04762    l = sub->parent;
04763    if (sub->owner) {
04764       if (sub->owner->_state == 0) {
04765          f.frametype = AST_FRAME_DTMF_BEGIN;
04766          ast_queue_frame(sub->owner, &f);
04767       }
04768       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04769       f.frametype = AST_FRAME_DTMF_END;
04770       ast_queue_frame(sub->owner, &f);
04771       /* XXX This seriously needs to be fixed */
04772       if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
04773          if (sub->owner->_state == 0) {
04774             f.frametype = AST_FRAME_DTMF_BEGIN;
04775             ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04776          }
04777          f.frametype = AST_FRAME_DTMF_END;
04778          ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04779       }
04780    } else {
04781       if (skinnydebug)
04782          ast_verb(1, "No owner: %s\n", l->name);
04783    }
04784    return 1;
04785 }

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

Definition at line 5357 of file chan_skinny.c.

References AST_LIST_LOCK, AST_LIST_UNLOCK, skinny_req::data, skinnysession::device, find_line_by_instance(), find_speeddial_by_instance(), skinny_speeddial::instance, skinny_speeddial::label, letohl, skinny_data::line, LINE_STAT_RES_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::lineNumber, line_state_req_message::lineNumber, skinny_data::linestat, req_alloc(), and transmit_response().

Referenced by handle_message().

05358 {
05359    struct skinny_device *d = s->device;
05360    struct skinny_line *l;
05361    struct skinny_speeddial *sd = NULL;
05362    int instance;
05363 
05364    instance = letohl(req->data.line.lineNumber);
05365 
05366    AST_LIST_LOCK(&devices);
05367 
05368    l = find_line_by_instance(d, instance);
05369 
05370    if (!l) {
05371       sd = find_speeddial_by_instance(d, instance, 1);
05372    }
05373 
05374    if (!l && !sd) {
05375       return 0;
05376    }
05377 
05378    AST_LIST_UNLOCK(&devices);
05379 
05380    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
05381       return -1;
05382 
05383    req->data.linestat.lineNumber = letohl(instance);
05384    if (!l) {
05385       memcpy(req->data.linestat.lineDirNumber, sd->label, sizeof(req->data.linestat.lineDirNumber));
05386       memcpy(req->data.linestat.lineDisplayName, sd->label, sizeof(req->data.linestat.lineDisplayName));
05387    } else {
05388       memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
05389       memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
05390    }
05391    transmit_response(d, req);
05392    return 1;
05393 }

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

Definition at line 6141 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, ALARM_MESSAGE, ast_free, ast_log(), AST_STATE_UP, ast_verb, keypad_button_message::button, BUTTON_TEMPLATE_REQ_MESSAGE, keypad_button_message::callReference, CAPABILITIES_RES_MESSAGE, skinny_req::data, skinnysession::device, skinny_req::e, ENBLOC_CALL_MESSAGE, find_subchannel_by_instance_reference(), handle_alarm_message(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_headset_status_message(), handle_ip_port_message(), handle_keep_alive_message(), handle_keypad_button_message(), handle_line_state_req_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_available_lines_message(), handle_register_message(), handle_server_request_message(), handle_soft_key_event_message(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_stimulus_message(), handle_time_date_req_message(), handle_unregister_message(), handle_version_req_message(), HEADSET_STATUS_MESSAGE, IP_PORT_MESSAGE, KEEP_ALIVE_MESSAGE, skinny_data::keypad, KEYPAD_BUTTON_MESSAGE, letohl, LINE_STATE_REQ_MESSAGE, keypad_button_message::lineInstance, LOG_WARNING, register_message::name, OFFHOOK_MESSAGE, skinny_subchannel::onhold, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, skinny_subchannel::owner, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, SERVER_REQUEST_MESSAGE, SKINNY_DEVONLY, SOFT_KEY_EVENT_MESSAGE, SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SPEED_DIAL_STAT_REQ_MESSAGE, STIMULUS_MESSAGE, TIME_DATE_REQ_MESSAGE, UNREGISTER_MESSAGE, and VERSION_REQ_MESSAGE.

Referenced by skinny_session().

06142 {
06143    int res = 0;
06144 
06145    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
06146       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
06147       ast_free(req);
06148       return 0;
06149    }
06150 
06151    SKINNY_DEVONLY(if (skinnydebug > 1) {
06152       ast_verb(4, "Received %s from %s\n", message2str(req->e), s->device->name);
06153    })
06154 
06155    switch(letohl(req->e)) {
06156    case KEEP_ALIVE_MESSAGE:
06157       res = handle_keep_alive_message(req, s);
06158       break;
06159    case REGISTER_MESSAGE:
06160       if (skinnydebug)
06161          ast_verb(1, "Device %s is attempting to register\n", req->data.reg.name);
06162 
06163       res = handle_register_message(req, s);
06164       break;
06165    case IP_PORT_MESSAGE:
06166       res = handle_ip_port_message(req, s);
06167       break;
06168    case KEYPAD_BUTTON_MESSAGE:
06169        {
06170       struct skinny_device *d = s->device;
06171       struct skinny_subchannel *sub;
06172       int lineInstance;
06173       int callReference;
06174 
06175       if (skinnydebug)
06176          ast_verb(1, "Collected digit: [%d]\n", letohl(req->data.keypad.button));
06177 
06178       lineInstance = letohl(req->data.keypad.lineInstance);
06179       callReference = letohl(req->data.keypad.callReference);
06180 
06181       if (lineInstance) {
06182          sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
06183       } else {
06184          sub = d->activeline->activesub;
06185       }
06186 
06187       if (sub && ((sub->owner && sub->owner->_state <  AST_STATE_UP) || sub->onhold)) {
06188          char dgt;
06189          int digit = letohl(req->data.keypad.button);
06190 
06191          if (digit == 14) {
06192             dgt = '*';
06193          } else if (digit == 15) {
06194             dgt = '#';
06195          } else if (digit >= 0 && digit <= 9) {
06196             dgt = '0' + digit;
06197          } else {
06198             /* digit=10-13 (A,B,C,D ?), or
06199             * digit is bad value
06200             *
06201             * probably should not end up here, but set
06202             * value for backward compatibility, and log
06203             * a warning.
06204             */
06205             dgt = '0' + digit;
06206             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
06207          }
06208 
06209          d->exten[strlen(d->exten)] = dgt;
06210          d->exten[strlen(d->exten)+1] = '\0';
06211       } else
06212          res = handle_keypad_button_message(req, s);
06213       }
06214       break;
06215    case ENBLOC_CALL_MESSAGE:
06216       res = handle_enbloc_call_message(req, s);
06217       break;
06218    case STIMULUS_MESSAGE:
06219       res = handle_stimulus_message(req, s);
06220       break;
06221    case OFFHOOK_MESSAGE:
06222       res = handle_offhook_message(req, s);
06223       break;
06224    case ONHOOK_MESSAGE:
06225       res = handle_onhook_message(req, s);
06226       break;
06227    case CAPABILITIES_RES_MESSAGE:
06228       if (skinnydebug)
06229          ast_verb(1, "Received CapabilitiesRes\n");
06230 
06231       res = handle_capabilities_res_message(req, s);
06232       break;
06233    case SPEED_DIAL_STAT_REQ_MESSAGE:
06234       if (skinnydebug)
06235          ast_verb(1, "Received SpeedDialStatRequest\n");
06236 
06237       res = handle_speed_dial_stat_req_message(req, s);
06238       break;
06239    case LINE_STATE_REQ_MESSAGE:
06240       if (skinnydebug)
06241          ast_verb(1, "Received LineStatRequest\n");
06242       res = handle_line_state_req_message(req, s);
06243       break;
06244    case TIME_DATE_REQ_MESSAGE:
06245       if (skinnydebug)
06246          ast_verb(1, "Received Time/Date Request\n");
06247 
06248       res = handle_time_date_req_message(req, s);
06249       break;
06250    case BUTTON_TEMPLATE_REQ_MESSAGE:
06251       if (skinnydebug)
06252          ast_verb(1, "Buttontemplate requested\n");
06253 
06254       res = handle_button_template_req_message(req, s);
06255       break;
06256    case VERSION_REQ_MESSAGE:
06257       if (skinnydebug)
06258          ast_verb(1, "Version Request\n");
06259 
06260       res = handle_version_req_message(req, s);
06261       break;
06262    case SERVER_REQUEST_MESSAGE:
06263       if (skinnydebug)
06264          ast_verb(1, "Received Server Request\n");
06265 
06266       res = handle_server_request_message(req, s);
06267       break;
06268    case ALARM_MESSAGE:
06269       res = handle_alarm_message(req, s);
06270       break;
06271    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
06272       if (skinnydebug)
06273          ast_verb(1, "Received Open Receive Channel Ack\n");
06274 
06275       res = handle_open_receive_channel_ack_message(req, s);
06276       break;
06277    case SOFT_KEY_SET_REQ_MESSAGE:
06278       if (skinnydebug)
06279          ast_verb(1, "Received SoftKeySetReq\n");
06280 
06281       res = handle_soft_key_set_req_message(req, s);
06282       break;
06283    case SOFT_KEY_EVENT_MESSAGE:
06284       res = handle_soft_key_event_message(req, s);
06285       break;
06286    case UNREGISTER_MESSAGE:
06287       if (skinnydebug)
06288          ast_verb(1, "Received Unregister Request\n");
06289 
06290       res = handle_unregister_message(req, s);
06291       break;
06292    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
06293       if (skinnydebug)
06294          ast_verb(1, "Received SoftKey Template Request\n");
06295 
06296       res = handle_soft_key_template_req_message(req, s);
06297       break;
06298    case HEADSET_STATUS_MESSAGE:
06299       res = handle_headset_status_message(req, s);
06300       break;
06301    case REGISTER_AVAILABLE_LINES_MESSAGE:
06302       res = handle_register_available_lines_message(req, s);
06303       break;
06304    default:
06305       if (skinnydebug)
06306          ast_verb(1, "RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
06307       break;
06308    }
06309    if (res >= 0 && req)
06310       ast_free(req);
06311    return res;
06312 }

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

Definition at line 5133 of file chan_skinny.c.

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

Referenced by handle_message().

05134 {
05135    struct skinny_device *d = s->device;
05136    struct skinny_line *l;
05137    struct skinny_subchannel *sub;
05138    struct ast_channel *c;
05139    struct skinny_line *tmp;
05140    pthread_t t;
05141    int instance;
05142    int reference;
05143 
05144    /* if any line on a device is offhook, than the device must be offhook, 
05145       unless we have shared lines CCM seems that it would never get here, 
05146       but asterisk does, so we may need to do more work.  Ugly, we should 
05147       probably move hookstate from line to device, afterall, it's actually
05148        a device that changes hookstates */
05149 
05150    AST_LIST_TRAVERSE(&d->lines, tmp, list) {
05151       if (tmp->hookstate == SKINNY_OFFHOOK) {
05152          ast_verbose(VERBOSE_PREFIX_3 "Got offhook message when device (%s@%s) already offhook\n", tmp->name, d->name);
05153          return 0;
05154       }
05155    }
05156 
05157    instance = letohl(req->data.offhook.instance);
05158    reference = letohl(req->data.offhook.reference);
05159 
05160    if (instance) {
05161       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05162       if (!sub) {
05163          l = find_line_by_instance(d, d->lastlineinstance);
05164          if (!l) {
05165             return 0;
05166          }
05167       } else {
05168          l = sub->parent;
05169       }
05170    } else {
05171       l = d->activeline;
05172       sub = l->activesub;
05173    }
05174 
05175    transmit_ringer_mode(d, SKINNY_RING_OFF);
05176    l->hookstate = SKINNY_OFFHOOK;
05177 
05178    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
05179 
05180    if (sub && sub->onhold) {
05181       return 1;
05182    }
05183 
05184    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05185 
05186    if (sub && sub->outgoing) {
05187       /* We're answering a ringing call */
05188       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05189       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05190       transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05191       transmit_callstateonly(d, sub, SKINNY_CONNECTED);
05192       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05193       start_rtp(sub);
05194       ast_setstate(sub->owner, AST_STATE_UP);
05195    } else {
05196       if (sub && sub->owner) {
05197          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
05198       } else {
05199          c = skinny_new(l, AST_STATE_DOWN, NULL);
05200          if (c) {
05201             sub = c->tech_pvt;
05202             l->activesub = sub;
05203             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05204             if (skinnydebug)
05205                ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05206             transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05207             transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05208             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05209 
05210             /* start the switch thread */
05211             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05212                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05213                ast_hangup(c);
05214             }
05215          } else {
05216             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05217          }
05218       }
05219    }
05220    return 1;
05221 }

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

Definition at line 5223 of file chan_skinny.c.

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

Referenced by handle_message().

05224 {
05225    struct skinny_device *d = s->device;
05226    struct skinny_line *l;
05227    struct skinny_subchannel *sub;
05228    int instance;
05229    int reference;
05230    int onlysub = 0;
05231 
05232    instance = letohl(req->data.onhook.instance);
05233    reference = letohl(req->data.onhook.reference);
05234 
05235    if (instance && reference) {
05236       sub = find_subchannel_by_instance_reference(d, instance, reference);
05237       if (!sub) {
05238          return 0;
05239       }
05240       l = sub->parent;
05241    } else {
05242       l = d->activeline;
05243       sub = l->activesub;
05244       if (!sub) {
05245          return 0;
05246       }
05247    }
05248 
05249    if (l->hookstate == SKINNY_ONHOOK) {
05250       /* Something else already put us back on hook */
05251       return 0;
05252    }
05253 
05254    ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05255 
05256    if (sub->onhold) {
05257       return 0;
05258    }
05259 
05260    if (!AST_LIST_NEXT(sub, list)) {
05261       onlysub = 1;
05262    } else {
05263       AST_LIST_REMOVE(&l->sub, sub, list);
05264    }
05265 
05266    sub->cxmode = SKINNY_CX_RECVONLY;
05267    if (onlysub || sub->xferor){  /* is this the only call to this device? */
05268       l->hookstate = SKINNY_ONHOOK;
05269       if (skinnydebug)
05270          ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
05271    }
05272 
05273    transmit_callstate(d, l->instance, l->hookstate, sub->callid);
05274    if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05275       /* We're allowed to transfer, we have two active calls and
05276          we made at least one of the calls.  Let's try and transfer */
05277       handle_transfer_button(sub);
05278    } else {
05279       /* Hangup the current call */
05280       /* If there is another active call, skinny_hangup will ring the phone with the other call */
05281       if (sub->xferor && sub->related){
05282          sub->related->related = NULL;
05283          sub->related->blindxfer = 0;
05284       }
05285 
05286       if (sub->owner) {
05287          sub->alreadygone = 1;
05288          ast_queue_hangup(sub->owner);
05289       } else {
05290          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05291             l->name, d->name, sub->callid);
05292       }
05293    }
05294    return 1;
05295 }

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

Definition at line 5599 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_set_remote_address(), ast_verb, 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, skinnysession::device, find_subchannel_by_reference(), htolel, open_receive_channel_ack_message::ipAddr, letohl, LOG_ERROR, skinny_data::openreceivechannelack, skinny_device::ourip, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_subchannel::parent, open_receive_channel_ack_message::passThruId, start_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, open_receive_channel_ack_message::port, media_qualifier::precedence, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), skinny_subchannel::rtp, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, open_receive_channel_ack_message::status, status, transmit_response(), and media_qualifier::vad.

Referenced by handle_message().

05600 {
05601    struct skinny_device *d = s->device;
05602    struct skinny_line *l;
05603    struct skinny_subchannel *sub;
05604    struct ast_format_list fmt;
05605    struct sockaddr_in sin = { 0, };
05606    struct sockaddr_in us = { 0, };
05607    uint32_t addr;
05608    int port;
05609    int status;
05610    int passthruid;
05611 
05612    status = letohl(req->data.openreceivechannelack.status);
05613    if (status) {
05614       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
05615       return 0;
05616    }
05617    addr = letohl(req->data.openreceivechannelack.ipAddr);
05618    port = letohl(req->data.openreceivechannelack.port);
05619    passthruid = letohl(req->data.openreceivechannelack.passThruId);
05620 
05621    sin.sin_family = AF_INET;
05622    sin.sin_addr.s_addr = addr;
05623    sin.sin_port = htons(port);
05624 
05625    sub = find_subchannel_by_reference(d, passthruid);
05626 
05627    if (!sub)
05628       return 0;
05629 
05630    l = sub->parent;
05631 
05632    if (sub->rtp) {
05633       ast_rtp_instance_set_remote_address(sub->rtp, &sin);
05634       ast_rtp_instance_get_local_address(sub->rtp, &us);
05635    } else {
05636       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
05637       return 0;
05638    }
05639 
05640    if (skinnydebug)
05641       ast_verb(1, "ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
05642 
05643    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
05644       return -1;
05645 
05646    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
05647 
05648    if (skinnydebug)
05649       ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
05650 
05651    req->data.startmedia.conferenceId = htolel(sub->callid);
05652    req->data.startmedia.passThruPartyId = htolel(sub->callid);
05653    req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
05654    req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
05655    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
05656    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
05657    req->data.startmedia.qualifier.precedence = htolel(127);
05658    req->data.startmedia.qualifier.vad = htolel(0);
05659    req->data.startmedia.qualifier.packets = htolel(0);
05660    req->data.startmedia.qualifier.bitRate = htolel(0);
05661    transmit_response(d, req);
05662 
05663    return 1;
05664 }

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

Definition at line 6135 of file chan_skinny.c.

Referenced by handle_message().

06136 {
06137    /* XXX I have no clue what this is for, but my phone was sending it, so... */
06138    return 1;
06139 }

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

Definition at line 4607 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verb, CAPABILITIES_REQ_MESSAGE, skinny_req::data, register_ack_message::dateTemplate, skinnysession::device, register_rej_message::errMsg, errno, skinnysession::fd, htolel, register_ack_message::keepAlive, skinny_req::len, letohl, skinnysession::lock, LOG_ERROR, LOG_WARNING, register_message::name, 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().

04608 {
04609    struct skinny_device *d = NULL;
04610    char name[16];
04611    int res;
04612 
04613    memcpy(&name, req->data.reg.name, sizeof(name));
04614 
04615    res = skinny_register(req, s);
04616    if (!res) {
04617       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
04618       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
04619          return -1;
04620 
04621       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
04622 
04623       /* transmit_respons in line as we don't have a valid d */
04624       ast_mutex_lock(&s->lock);
04625 
04626       if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
04627          ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
04628          ast_mutex_unlock(&s->lock);
04629          return -1;
04630       }
04631 
04632       memset(s->outbuf, 0, sizeof(s->outbuf));
04633       memcpy(s->outbuf, req, skinny_header_size);
04634       memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
04635 
04636       res = write(s->fd, s->outbuf, letohl(req->len)+8);
04637 
04638       if (res != letohl(req->len)+8) {
04639          ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
04640       }
04641    
04642       ast_mutex_unlock(&s->lock);
04643 
04644       return 0;
04645    }
04646    ast_verb(3, "Device '%s' successfully registered\n", name);
04647 
04648    d = s->device;
04649    
04650    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
04651       return -1;
04652 
04653    req->data.regack.res[0] = '0';
04654    req->data.regack.res[1] = '\0';
04655    req->data.regack.keepAlive = htolel(keep_alive);
04656    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
04657    req->data.regack.res2[0] = '0';
04658    req->data.regack.res2[1] = '\0';
04659    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
04660    transmit_response(d, req);
04661    if (skinnydebug)
04662       ast_verb(1, "Requesting capabilities\n");
04663 
04664    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
04665       return -1;
04666 
04667    transmit_response(d, req);
04668 
04669    return res;
04670 }

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

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

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

02827 {
02828    switch (cmd) {
02829    case CLI_INIT:
02830       e->command = "skinny reload";
02831       e->usage =
02832          "Usage: skinny reload\n"
02833          "       Reloads the chan_skinny configuration\n";
02834       return NULL;
02835    case CLI_GENERATE:
02836       return NULL;
02837    }
02838    
02839    if (a->argc != e->args)
02840       return CLI_SHOWUSAGE;
02841 
02842    skinny_reload();
02843    return CLI_SUCCESS;
02844 
02845 }

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

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

02892 {
02893    struct skinny_device *d;
02894    struct skinny_req *req;
02895 
02896    switch (cmd) {
02897    case CLI_INIT:
02898       e->command = "skinny reset";
02899       e->usage =
02900          "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
02901          "       Causes a Skinny device to reset itself, optionally with a full restart\n";
02902       return NULL;
02903    case CLI_GENERATE:
02904       return complete_skinny_reset(a->line, a->word, a->pos, a->n);
02905    }
02906 
02907    if (a->argc < 3 || a->argc > 4)
02908       return CLI_SHOWUSAGE;
02909 
02910    AST_LIST_LOCK(&devices);
02911    AST_LIST_TRAVERSE(&devices, d, list) {
02912       int fullrestart = 0;
02913       if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
02914          if (!(d->session))
02915             continue;
02916 
02917          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
02918             continue;
02919 
02920          if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
02921             fullrestart = 1;
02922 
02923          if (fullrestart)
02924             req->data.reset.resetType = 2;
02925          else
02926             req->data.reset.resetType = 1;
02927 
02928          ast_verb(3, "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
02929          transmit_response(d, req);
02930       }
02931    }
02932    AST_LIST_UNLOCK(&devices);
02933    return CLI_SUCCESS;
02934 }

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

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

02785 {
02786    switch (cmd) {
02787    case CLI_INIT:
02788 #ifdef SKINNY_DEVMODE
02789       e->command = "skinny set debug {off|on|packet}";
02790       e->usage =
02791          "Usage: skinny set debug {off|on|packet}\n"
02792          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02793 #else
02794       e->command = "skinny set debug {off|on}";
02795       e->usage =
02796          "Usage: skinny set debug {off|on}\n"
02797          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02798 #endif
02799       return NULL;
02800    case CLI_GENERATE:
02801       return NULL;
02802    }
02803    
02804    if (a->argc != e->args)
02805       return CLI_SHOWUSAGE;
02806 
02807    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
02808       skinnydebug = 1;
02809       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02810       return CLI_SUCCESS;
02811    } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
02812       skinnydebug = 0;
02813       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02814       return CLI_SUCCESS;
02815 #ifdef SKINNY_DEVMODE
02816    } else if (!strncasecmp(a->argv[e->args - 1], "packet", 6)) {
02817       skinnydebug = 2;
02818       ast_cli(a->fd, "Skinny Debugging Enabled including Packets\n");
02819       return CLI_SUCCESS;
02820 #endif
02821    } else {
02822       return CLI_SHOWUSAGE;
02823    }
02824 }

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

03272 {
03273    switch (cmd) {
03274    case CLI_INIT:
03275       e->command = "skinny show device";
03276       e->usage =
03277          "Usage: skinny show device <DeviceId|DeviceName>\n"
03278          "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
03279       return NULL;
03280    case CLI_GENERATE:
03281       return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
03282    }
03283 
03284    return _skinny_show_device(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03285 }

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

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

03138 {
03139 
03140    switch (cmd) {
03141    case CLI_INIT:
03142       e->command = "skinny show devices";
03143       e->usage =
03144          "Usage: skinny show devices\n"
03145          "       Lists all devices known to the Skinny subsystem.\n";
03146       return NULL;
03147    case CLI_GENERATE:
03148       return NULL;
03149    }
03150 
03151    return _skinny_show_devices(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03152 }

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

03569 {
03570    switch (cmd) {
03571    case CLI_INIT:
03572       e->command = "skinny show line";
03573       e->usage =
03574          "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
03575          "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
03576       return NULL;
03577    case CLI_GENERATE:
03578       return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
03579    }
03580 
03581    return _skinny_show_line(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03582 }

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

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

03386 {
03387    int verbose = 0;
03388 
03389    switch (cmd) {
03390    case CLI_INIT:
03391       e->command = "skinny show lines [verbose]";
03392       e->usage =
03393          "Usage: skinny show lines\n"
03394          "       Lists all lines known to the Skinny subsystem.\n"
03395          "       If 'verbose' is specified, the output includes\n"
03396          "       information about subs for each line.\n";
03397       return NULL;
03398    case CLI_GENERATE:
03399       return NULL;
03400    }
03401 
03402    if (a->argc == e->args) {
03403       if (!strcasecmp(a->argv[e->args-1], "verbose")) {
03404          verbose = 1;
03405       } else {
03406          return CLI_SHOWUSAGE;
03407       }
03408    } else if (a->argc != e->args - 1) {
03409       return CLI_SHOWUSAGE;
03410    }
03411 
03412    return _skinny_show_lines(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03413 }

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

References ast_cli_args::argc, ast_cli(), ast_inet_ntoa(), AST_JB_ENABLED, AST_JB_FORCED, AST_JB_LOG, ast_test_flag, bindaddr, CLI_GENERATE, CLI_INIT, CLI_SHOWUSAGE, CLI_SUCCESS, ast_cli_entry::command, ast_cli_args::fd, global_jbconf, ast_jb_conf::impl, ast_jb_conf::max_size, ast_jb_conf::resync_threshold, S_OR, and ast_cli_entry::usage.

03586 {
03587    switch (cmd) {
03588    case CLI_INIT:
03589       e->command = "skinny show settings";
03590       e->usage =
03591          "Usage: skinny show settings\n"
03592          "       Lists all global configuration settings of the Skinny subsystem.\n";
03593       return NULL;
03594    case CLI_GENERATE:
03595       return NULL;
03596    }  
03597 
03598    if (a->argc != 3)
03599       return CLI_SHOWUSAGE;
03600 
03601    ast_cli(a->fd, "\nGlobal Settings:\n");
03602    ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
03603    ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
03604    ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
03605    ast_cli(a->fd, "  Date Format:            %s\n", date_format);
03606    ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(global_vmexten, "(not set)"));
03607    ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
03608    ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
03609    ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
03610    ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
03611    ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
03612    ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
03613    ast_cli(a->fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
03614 
03615    return CLI_SUCCESS;
03616 }

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

Definition at line 5750 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_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_RINGOUT, letohl, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::related, skinny_subchannel::rtp, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), SOFTKEY_ANSWER, SOFTKEY_BKSPC, SOFTKEY_CFWDALL, SOFTKEY_CFWDBUSY, SOFTKEY_CFWDNOANSWER, SOFTKEY_CONFRN, SOFTKEY_DND, SOFTKEY_ENDCALL, SOFTKEY_GPICKUP, SOFTKEY_HOLD, SOFTKEY_INFO, SOFTKEY_JOIN, SOFTKEY_MEETME, SOFTKEY_NEWCALL, SOFTKEY_NONE, SOFTKEY_PARK, SOFTKEY_PICKUP, SOFTKEY_REDIAL, SOFTKEY_RESUME, SOFTKEY_TRNSFER, soft_key_event_message::softKeyEvent, skinny_data::softkeyeventmessage, start_rtp(), STIMULUS_DND, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_callstate(), transmit_callstateonly(), transmit_displaymessage(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), and skinny_subchannel::xferor.

Referenced by handle_message().

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

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

Definition at line 5717 of file chan_skinny.c.

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

Referenced by handle_message().

05718 {
05719    int i;
05720    int x;
05721    int y;
05722    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
05723    struct skinny_device *d = s->device;
05724 
05725    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
05726       return -1;
05727 
05728    req->data.softkeysets.softKeySetOffset = htolel(0);
05729    req->data.softkeysets.softKeySetCount = htolel(11);
05730    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
05731    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
05732       const uint8_t *defaults = softkeymode->defaults;
05733       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
05734          This will have to do for now. */
05735       for (y = 0; y < softkeymode->count; y++) {
05736          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
05737             if (defaults[y] == i+1) {
05738                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
05739                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
05740             }
05741          }
05742       }
05743       softkeymode++;
05744    }
05745    transmit_response(d, req);
05746    transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05747    return 1;
05748 }

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