Fri Nov 12 11:57:28 2010

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

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

Go to the source code of this file.

Data Structures

struct  activate_call_plane_message
struct  alarm_message
struct  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 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_get_result skinny_get_rtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static enum ast_rtp_get_result skinny_get_vrtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static int skinny_hangup (struct ast_channel *ast)
static int skinny_hold (struct skinny_subchannel *sub)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelskinny_new (struct skinny_line *l, int state)
static void * skinny_newcall (void *data)
static struct ast_frameskinny_read (struct ast_channel *ast)
static int skinny_register (struct skinny_req *req, struct skinnysession *s)
static int skinny_reload (void)
static struct skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, int format, void *data, int *cause)
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_senddigit_begin (struct ast_channel *ast, char digit)
static int skinny_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void * skinny_session (void *data)
static int skinny_set_rtp_peer (struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
static void * skinny_ss (void *data)
static int skinny_transfer (struct skinny_subchannel *sub)
static int skinny_unhold (struct skinny_subchannel *sub)
static int skinny_unregister (struct skinny_req *req, struct skinnysession *s)
static int skinny_write (struct ast_channel *ast, struct ast_frame *frame)
static void start_rtp (struct skinny_subchannel *sub)
static void transmit_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_callinfo (struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinny_device *d, int instance, int state, unsigned callid)
static void transmit_callstateonly (struct skinny_device *d, struct skinny_subchannel *sub, int state)
static void transmit_cfwdstate (struct skinny_device *d, struct skinny_line *l)
static void transmit_closereceivechannel (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_connect (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_dialednumber (struct skinny_device *d, const char *text, int instance, int callid)
static void transmit_displaymessage (struct skinny_device *d, const char *text, int instance, int reference)
static void transmit_displaynotify (struct skinny_device *d, const char *text, int t)
static void transmit_displaypromptstatus (struct skinny_device *d, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static int transmit_response (struct skinny_device *d, struct skinny_req *req)
static void transmit_ringer_mode (struct skinny_device *d, int mode)
static void transmit_selectsoftkeys (struct skinny_device *d, int instance, int callid, int softkey)
static void transmit_speaker_mode (struct skinny_device *d, int mode)
static void transmit_stopmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_tone (struct skinny_device *d, int tone, int instance, int reference)
static int unload_module (void)
static void unregister_exten (struct skinny_line *l)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, }
static struct in_addr __ourip
static pthread_t accept_t
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
struct skinny_device_optionsdefault_device = &default_device_struct
struct skinny_device_options default_device_struct
static struct ast_jb_conf default_jbconf
struct skinny_line_optionsdefault_line = &default_line_struct
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]
struct hostent * hp
static struct io_contextio
static int keep_alive = 120
static char mandescr_show_device []
static char mandescr_show_devices []
static char mandescr_show_line []
static char mandescr_show_lines []
static int matchdigittimeout = 3000
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP )
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
int skinny_header_size = 12
static struct ast_rtp_protocol skinny_rtp
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
static int 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 []
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 ACTIVATE_CALL_PLANE_MESSAGE   0x0116

Definition at line 898 of file chan_skinny.c.

Referenced by transmit_activatecallplane(), and transmit_callstate().

#define ALARM_MESSAGE   0x0020

Definition at line 265 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 472 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 475 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 476 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 474 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 483 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 482 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 469 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 473 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 466 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 467 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 468 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 464 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 470 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 477 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 462 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 463 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 465 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 471 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 261 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 432 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 370 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 869 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_callstateonly().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 505 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 233 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6535 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6534 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 503 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 502 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 886 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6533 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6532 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 541 of file chan_skinny.c.

Referenced by transmit_callstate(), and transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 180 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 101 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 100 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 419 of file chan_skinny.c.

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 177 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 903 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 892 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 877 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 497 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 209 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 392 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 292 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)
#define htoles (  )     bswap_16(x)

Definition at line 131 of file chan_skinny.c.

#define IP_PORT_MESSAGE   0x0002

Definition at line 199 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 528 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 186 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7

Definition at line 562 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 560 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 561 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4
#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 564 of file chan_skinny.c.

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 557 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

Definition at line 555 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 558 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8
#define KEYDEF_UNKNOWN   10

Definition at line 565 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 201 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)
#define letohs (  )     bswap_16(x)

Definition at line 129 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 411 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 221 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 227 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 273 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 530 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 295 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 293 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 189 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 507 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 523 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 861 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 263 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 512 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 326 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 339 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 318 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 333 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1050 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1037 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1049 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1044 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1040 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

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

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3

Definition at line 1074 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1075 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1077 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1076 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1072 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1071 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1073 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 992 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 991 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 990 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 989 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 993 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1019 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1015 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1008 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 994 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1003 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1018 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1001 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1016 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1007 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1006 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 997 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1022 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1010 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 996 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 999 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1005 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1011 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1012 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 995 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1021 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1004 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1009 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1013 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1017 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1000 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1014 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1002 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 998 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1020 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 988 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1246 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1023 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1024 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 987 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVONLY ( code   ) 

Definition at line 78 of file chan_skinny.c.

Referenced by handle_message(), and transmit_response().

#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8

Definition at line 1039 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1045 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1136 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 243 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 102 of file chan_skinny.c.

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

#define SKINNY_MICOFF   2

Definition at line 1030 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1029 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1053 of file chan_skinny.c.

Referenced by transmit_tone().

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

Definition at line 1042 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1043 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 1051 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1064 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1062 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1
#define SKINNY_RING_OUTSIDE   3

Definition at line 1063 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1035 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_extensionstate_cb().

#define SKINNY_RINGOUT   3

Definition at line 1034 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_TRANSFER   10

Definition at line 1041 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 283 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 281 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 846 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 291 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 548 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 578 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 575 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 572 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 573 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 574 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 580 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 586 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 576 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 585 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 570 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 587 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 579 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 582 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 583 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 569 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 567 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 581 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 584 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 568 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 577 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 571 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 250 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 404 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

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

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 454 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 457 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 458 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 456 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 451 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 455 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 448 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 449 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 450 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 446 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09
#define STIMULUS_MESSAGE   0x0005

Definition at line 214 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 459 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 444 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 445 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 447 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

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

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 260 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6527 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6528 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6529 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6526 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6530 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 290 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 262 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

00090                    {
00091    SKINNY_CODEC_ALAW = 2,
00092    SKINNY_CODEC_ULAW = 4,
00093    SKINNY_CODEC_G723_1 = 9,
00094    SKINNY_CODEC_G729A = 12,
00095    SKINNY_CODEC_G726_32 = 82, /* XXX Which packing order does this translate to? */
00096    SKINNY_CODEC_H261 = 100,
00097    SKINNY_CODEC_H263 = 101
00098 };


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 179 of file chan_skinny.c.

00190 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 176 of file chan_skinny.c.

00190 {

static void __reg_module ( void   )  [static]

Definition at line 7413 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

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

03064 {
03065    struct skinny_device *d;
03066    struct skinny_line *l;
03067    struct skinny_speeddial *sd;
03068    struct skinny_addon *sa;
03069    char codec_buf[512];
03070 
03071    if (argc < 4) {
03072       return CLI_SHOWUSAGE;
03073    }
03074 
03075    AST_LIST_LOCK(&devices);
03076    AST_LIST_TRAVERSE(&devices, d, list) {
03077       if (!strcasecmp(argv[3], d->id) || !strcasecmp(argv[3], d->name)) {
03078          int numlines = 0, numaddons = 0, numspeeddials = 0;
03079 
03080          AST_LIST_TRAVERSE(&d->lines, l, list){
03081             numlines++;
03082          }
03083 
03084          AST_LIST_TRAVERSE(&d->addons, sa, list) {
03085             numaddons++;
03086          }
03087 
03088          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03089             numspeeddials++;
03090          }
03091 
03092          if (type == 0) { /* CLI */
03093             ast_cli(fd, "Name:        %s\n", d->name);
03094             ast_cli(fd, "Id:          %s\n", d->id);
03095             ast_cli(fd, "version:     %s\n", S_OR(d->version_id, "Unknown"));
03096             ast_cli(fd, "Ip address:  %s\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03097             ast_cli(fd, "Port:        %d\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03098             ast_cli(fd, "Device Type: %s\n", device2str(d->type));
03099             ast_cli(fd, "Conf Codecs:");
03100             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->confcapability);
03101             ast_cli(fd, "%s\n", codec_buf);
03102             ast_cli(fd, "Neg Codecs: ");
03103             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, d->capability);
03104             ast_cli(fd, "%s\n", codec_buf);
03105             ast_cli(fd, "Registered:  %s\n", (d->registered ? "Yes" : "No"));
03106             ast_cli(fd, "Lines:       %d\n", numlines);
03107             AST_LIST_TRAVERSE(&d->lines, l, list) {
03108                ast_cli(fd, "  %s (%s)\n", l->name, l->label);
03109             }
03110             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03111                numaddons++;
03112             }  
03113             ast_cli(fd, "Addons:      %d\n", numaddons);
03114             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03115                ast_cli(fd, "  %s\n", sa->type);
03116             }
03117             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03118                numspeeddials++;
03119             }
03120             ast_cli(fd, "Speeddials:  %d\n", numspeeddials);
03121             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03122                ast_cli(fd, "  %s (%s) ishint: %d\n", sd->exten, sd->label, sd->isHint);
03123             }
03124          } else { /* manager */
03125             astman_append(s, "Channeltype: SKINNY\r\n");
03126             astman_append(s, "ObjectName: %s\r\n", d->name);
03127             astman_append(s, "ChannelObjectType: device\r\n");
03128             astman_append(s, "Id: %s\r\n", d->id);
03129             astman_append(s, "version: %s\r\n", S_OR(d->version_id, "Unknown"));
03130             astman_append(s, "Ipaddress: %s\r\n", (d->session ? ast_inet_ntoa(d->session->sin.sin_addr) : "Unknown"));
03131             astman_append(s, "Port: %d\r\n", (d->session ? ntohs(d->session->sin.sin_port) : 0));
03132             astman_append(s, "DeviceType: %s\r\n", device2str(d->type));
03133             astman_append(s, "Codecs: ");
03134             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->confcapability);
03135             astman_append(s, "%s\r\n", codec_buf);
03136             astman_append(s, "CodecOrder: ");
03137             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) -1, d->capability);
03138             astman_append(s, "%s\r\n", codec_buf);
03139             astman_append(s, "Devicestatus: %s\r\n", (d->registered?"registered":"unregistered"));
03140             astman_append(s, "NumberOfLines: %d\r\n", numlines);
03141             AST_LIST_TRAVERSE(&d->lines, l, list) {
03142                astman_append(s, "Line: %s (%s)\r\n", l->name, l->label);
03143             }
03144             astman_append(s, "NumberOfAddons: %d\r\n", numaddons);
03145             AST_LIST_TRAVERSE(&d->addons, sa, list) {
03146                astman_append(s, "Addon: %s\r\n", sa->type);
03147             }
03148             astman_append(s, "NumberOfSpeeddials: %d\r\n", numspeeddials);
03149             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
03150                astman_append(s, "Speeddial: %s (%s) ishint: %d\r\n", sd->exten, sd->label, sd->isHint);
03151             }
03152          }
03153       }
03154    }
03155    AST_LIST_UNLOCK(&devices);
03156    return CLI_SUCCESS;
03157 }

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

02946 {
02947    struct skinny_device *d;
02948    struct skinny_line *l;
02949    const char *id;
02950    char idtext[256] = "";
02951    int total_devices = 0;
02952 
02953    if (s) { /* Manager - get ActionID */
02954       id = astman_get_header(m, "ActionID");
02955       if (!ast_strlen_zero(id))
02956          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
02957    }
02958 
02959    switch (argc) {
02960    case 3:
02961       break;
02962    default:
02963       return CLI_SHOWUSAGE;
02964    }
02965 
02966    if (!s) {
02967       ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
02968       ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
02969    }
02970 
02971    AST_LIST_LOCK(&devices);
02972    AST_LIST_TRAVERSE(&devices, d, list) {
02973       int numlines = 0;
02974       total_devices++;
02975       AST_LIST_TRAVERSE(&d->lines, l, list) {
02976          numlines++;
02977       }
02978       if (!s) {
02979          ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
02980             d->name,
02981             d->id,
02982             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
02983             device2str(d->type),
02984             d->registered?'Y':'N',
02985             numlines);
02986       } else {
02987          astman_append(s,
02988             "Event: DeviceEntry\r\n%s"
02989             "Channeltype: SKINNY\r\n"
02990             "ObjectName: %s\r\n"
02991             "ChannelObjectType: device\r\n"
02992             "DeviceId: %s\r\n"
02993             "IPaddress: %s\r\n"
02994             "Type: %s\r\n"
02995             "Devicestatus: %s\r\n"
02996             "NumberOfLines: %d\r\n",
02997             idtext,
02998             d->name,
02999             d->id,
03000             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"-none-",
03001             device2str(d->type),
03002             d->registered?"registered":"unregistered",
03003             numlines);
03004       }
03005    }
03006    AST_LIST_UNLOCK(&devices);
03007 
03008    if (total)
03009       *total = total_devices;
03010    
03011    return CLI_SUCCESS;
03012 }

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

03338 {
03339    struct skinny_device *d;
03340    struct skinny_line *l;
03341    struct ast_codec_pref *pref;
03342    int x = 0, codec = 0;
03343    char codec_buf[512];
03344    char group_buf[256];
03345    char cbuf[256];
03346 
03347    switch (argc) {
03348    case 4:
03349       break;
03350    case 6:
03351       break;
03352    default:
03353       return CLI_SHOWUSAGE;
03354    }
03355 
03356    AST_LIST_LOCK(&devices);
03357 
03358    /* Show all lines matching the one supplied */
03359    AST_LIST_TRAVERSE(&devices, d, list) {
03360       if (argc == 6 && (strcasecmp(argv[5], d->id) && strcasecmp(argv[5], d->name))) {
03361          continue;
03362       }
03363       AST_LIST_TRAVERSE(&d->lines, l, list) {
03364          if (strcasecmp(argv[3], l->name)) {
03365             continue;
03366          }
03367          if (type == 0) { /* CLI */
03368             ast_cli(fd, "Line:             %s\n", l->name);
03369             ast_cli(fd, "On Device:        %s\n", d->name);
03370             ast_cli(fd, "Line Label:       %s\n", l->label);
03371             ast_cli(fd, "Extension:        %s\n", S_OR(l->exten, "<not set>"));
03372             ast_cli(fd, "Context:          %s\n", l->context);
03373             ast_cli(fd, "CallGroup:        %s\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03374             ast_cli(fd, "PickupGroup:      %s\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03375             ast_cli(fd, "Language:         %s\n", S_OR(l->language, "<not set>"));
03376             ast_cli(fd, "Accountcode:      %s\n", S_OR(l->accountcode, "<not set>"));
03377             ast_cli(fd, "AmaFlag:          %s\n", ast_cdr_flags2str(l->amaflags));
03378             ast_cli(fd, "CallerId Number:  %s\n", S_OR(l->cid_num, "<not set>"));
03379             ast_cli(fd, "CallerId Name:    %s\n", S_OR(l->cid_name, "<not set>"));
03380             ast_cli(fd, "Hide CallerId:    %s\n", (l->hidecallerid ? "Yes" : "No"));
03381             ast_cli(fd, "CFwdAll:          %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03382             ast_cli(fd, "CFwdBusy:         %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03383             ast_cli(fd, "CFwdNoAnswer:     %s\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03384             ast_cli(fd, "VoicemailBox:     %s\n", S_OR(l->mailbox, "<not set>"));
03385             ast_cli(fd, "VoicemailNumber:  %s\n", S_OR(l->vmexten, "<not set>"));
03386             ast_cli(fd, "MWIblink:         %d\n", l->mwiblink);
03387             ast_cli(fd, "Regextension:     %s\n", S_OR(l->regexten, "<not set>"));
03388             ast_cli(fd, "Regcontext:       %s\n", S_OR(l->regcontext, "<not set>"));
03389             ast_cli(fd, "MoHInterpret:     %s\n", S_OR(l->mohinterpret, "<not set>"));
03390             ast_cli(fd, "MoHSuggest:       %s\n", S_OR(l->mohsuggest, "<not set>"));
03391             ast_cli(fd, "Last dialed nr:   %s\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03392             ast_cli(fd, "Last CallerID:    %s\n", S_OR(l->lastcallerid, "<not set>"));
03393             ast_cli(fd, "Transfer enabled: %s\n", (l->transfer ? "Yes" : "No"));
03394             ast_cli(fd, "Callwaiting:      %s\n", (l->callwaiting ? "Yes" : "No"));
03395             ast_cli(fd, "3Way Calling:     %s\n", (l->threewaycalling ? "Yes" : "No"));
03396             ast_cli(fd, "Can forward:      %s\n", (l->cancallforward ? "Yes" : "No"));
03397             ast_cli(fd, "Do Not Disturb:   %s\n", (l->dnd ? "Yes" : "No"));
03398             ast_cli(fd, "NAT:              %s\n", (l->nat ? "Yes" : "No"));
03399             ast_cli(fd, "immediate:        %s\n", (l->immediate ? "Yes" : "No"));
03400             ast_cli(fd, "Group:            %d\n", l->group);
03401             ast_cli(fd, "Parkinglot:       %s\n", S_OR(l->parkinglot, "<not set>"));
03402             ast_cli(fd, "Conf Codecs:      ");
03403             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03404             ast_cli(fd, "%s\n", codec_buf);
03405             ast_cli(fd, "Neg Codecs:       ");
03406             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->capability);
03407             ast_cli(fd, "%s\n", codec_buf);
03408             ast_cli(fd, "Codec Order:      (");
03409             print_codec_to_cli(fd, &l->prefs);
03410             ast_cli(fd, ")\n");
03411             ast_cli(fd, "\n");
03412          } else { /* manager */
03413             astman_append(s, "Channeltype: SKINNY\r\n");
03414             astman_append(s, "ObjectName: %s\r\n", l->name);
03415             astman_append(s, "ChannelObjectType: line\r\n");
03416             astman_append(s, "Device: %s\r\n", d->name);
03417             astman_append(s, "LineLabel: %s\r\n", l->label);
03418             astman_append(s, "Extension: %s\r\n", S_OR(l->exten, "<not set>"));
03419             astman_append(s, "Context: %s\r\n", l->context);
03420             astman_append(s, "CallGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->callgroup));
03421             astman_append(s, "PickupGroup: %s\r\n", ast_print_group(group_buf, sizeof(group_buf), l->pickupgroup));
03422             astman_append(s, "Language: %s\r\n", S_OR(l->language, "<not set>"));
03423             astman_append(s, "Accountcode: %s\r\n", S_OR(l->accountcode, "<not set>"));
03424             astman_append(s, "AMAflags: %s\r\n", ast_cdr_flags2str(l->amaflags));
03425             astman_append(s, "Callerid: %s\r\n", ast_callerid_merge(cbuf, sizeof(cbuf), l->cid_name, l->cid_num, ""));
03426             astman_append(s, "HideCallerId: %s\r\n", (l->hidecallerid ? "Yes" : "No"));
03427             astman_append(s, "CFwdAll: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_ALL), l->call_forward_all, "<not set>"));
03428             astman_append(s, "CFwdBusy: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_BUSY), l->call_forward_busy, "<not set>"));
03429             astman_append(s, "CFwdNoAnswer: %s\r\n", S_COR((l->cfwdtype & SKINNY_CFWD_NOANSWER), l->call_forward_noanswer, "<not set>"));
03430             astman_append(s, "VoicemailBox: %s\r\n", S_OR(l->mailbox, "<not set>"));
03431             astman_append(s, "VoicemailNumber: %s\r\n", S_OR(l->vmexten, "<not set>"));
03432             astman_append(s, "MWIblink: %d\r\n", l->mwiblink);
03433             astman_append(s, "RegExtension: %s\r\n", S_OR(l->regexten, "<not set>"));
03434             astman_append(s, "Regcontext: %s\r\n", S_OR(l->regcontext, "<not set>"));
03435             astman_append(s, "MoHInterpret: %s\r\n", S_OR(l->mohinterpret, "<not set>"));
03436             astman_append(s, "MoHSuggest: %s\r\n", S_OR(l->mohsuggest, "<not set>"));
03437             astman_append(s, "LastDialedNr: %s\r\n", S_OR(l->lastnumberdialed, "<no calls made yet>"));
03438             astman_append(s, "LastCallerID: %s\r\n", S_OR(l->lastcallerid, "<not set>"));
03439             astman_append(s, "Transfer: %s\r\n", (l->transfer ? "Yes" : "No"));
03440             astman_append(s, "Callwaiting: %s\r\n", (l->callwaiting ? "Yes" : "No"));
03441             astman_append(s, "3WayCalling: %s\r\n", (l->threewaycalling ? "Yes" : "No"));
03442             astman_append(s, "CanForward: %s\r\n", (l->cancallforward ? "Yes" : "No"));
03443             astman_append(s, "DoNotDisturb: %s\r\n", (l->dnd ? "Yes" : "No"));
03444             astman_append(s, "NAT: %s\r\n", (l->nat ? "Yes" : "No"));
03445             astman_append(s, "immediate: %s\r\n", (l->immediate ? "Yes" : "No"));
03446             astman_append(s, "Group: %d\r\n", l->group);
03447             astman_append(s, "Parkinglot: %s\r\n", S_OR(l->parkinglot, "<not set>"));
03448             ast_getformatname_multiple(codec_buf, sizeof(codec_buf) - 1, l->confcapability);
03449             astman_append(s, "Codecs: %s\r\n", codec_buf);
03450             astman_append(s, "CodecOrder: ");
03451             pref = &l->prefs;
03452             for(x = 0; x < 32 ; x++) {
03453                codec = ast_codec_pref_index(pref, x);
03454                if (!codec)
03455                   break;
03456                astman_append(s, "%s", ast_getformatname(codec));
03457                if (x < 31 && ast_codec_pref_index(pref, x+1))
03458                   astman_append(s, ",");
03459             }
03460             astman_append(s, "\r\n");
03461          }
03462       }
03463    }
03464    
03465    AST_LIST_UNLOCK(&devices);
03466    return CLI_SUCCESS;
03467 }

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

03203 {
03204    struct skinny_line *l;
03205    struct skinny_subchannel *sub;
03206    int total_lines = 0;
03207    int verbose = 0;
03208    const char *id;
03209    char idtext[256] = "";
03210 
03211    if (s) { /* Manager - get ActionID */
03212       id = astman_get_header(m, "ActionID");
03213       if (!ast_strlen_zero(id))
03214          snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03215    }
03216 
03217    switch (argc) {
03218    case 4:
03219       verbose = 1;
03220       break;
03221    case 3:
03222       verbose = 0;
03223       break;
03224    default:
03225       return CLI_SHOWUSAGE;
03226    }
03227 
03228    if (!s) {
03229       ast_cli(fd, "Name                 Device Name          Instance Label               \n");
03230       ast_cli(fd, "-------------------- -------------------- -------- --------------------\n");
03231    }
03232    AST_LIST_LOCK(&lines);
03233    AST_LIST_TRAVERSE(&lines, l, all) {
03234       total_lines++;
03235       if (!s) {
03236          ast_cli(fd, "%-20s %-20s %8d %-20s\n",
03237             l->name,
03238             (l->device ? l->device->name : "Not connected"),
03239             l->instance,
03240             l->label);
03241          if (verbose) {
03242             AST_LIST_TRAVERSE(&l->sub, sub, list) {
03243                ast_cli(fd, "  %s> %s to %s\n",
03244                   (sub == l->activesub?"Active  ":"Inactive"),
03245                   sub->owner->name,
03246                   (ast_bridged_channel(sub->owner)?ast_bridged_channel(sub->owner)->name:"")
03247                );
03248             }
03249          }
03250       } else {
03251          astman_append(s,
03252             "Event: LineEntry\r\n%s"
03253             "Channeltype: SKINNY\r\n"
03254             "ObjectName: %s\r\n"
03255             "ChannelObjectType: line\r\n"
03256             "Device: %s\r\n"
03257             "Instance: %d\r\n"
03258             "Label: %s\r\n",
03259             idtext,
03260             l->name,
03261             (l->device?l->device->name:"None"),
03262             l->instance,
03263             l->label);
03264       }
03265       AST_LIST_UNLOCK(&lines);
03266    }
03267 
03268    if (total) {
03269       *total = total_lines;
03270    }
03271 
03272    return CLI_SUCCESS;
03273 }

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

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

06385 {
06386    int as;
06387    struct sockaddr_in sin;
06388    socklen_t sinlen;
06389    struct skinnysession *s;
06390    struct protoent *p;
06391    int arg = 1;
06392 
06393    for (;;) {
06394       sinlen = sizeof(sin);
06395       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
06396       if (as < 0) {
06397          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
06398          continue;
06399       }
06400       p = getprotobyname("tcp");
06401       if(p) {
06402          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
06403             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
06404          }
06405       }
06406       if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
06407          continue;
06408 
06409       memcpy(&s->sin, &sin, sizeof(sin));
06410       ast_mutex_init(&s->lock);
06411       s->fd = as;
06412       AST_LIST_LOCK(&sessions);
06413       AST_LIST_INSERT_HEAD(&sessions, s, list);
06414       AST_LIST_UNLOCK(&sessions);
06415 
06416       if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
06417          destroy_session(s);
06418       }
06419    }
06420    if (skinnydebug)
06421       ast_verb(1, "killing accept thread\n");
06422    close(as);
06423    return 0;
06424 }

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

implement the setvar config line

Definition at line 1580 of file chan_skinny.c.

References ast_variable_new(), and ast_variable::next.

Referenced by config_parse_variables().

01581 {
01582    struct ast_variable *tmpvar = NULL;
01583    char *varname = ast_strdupa(buf), *varval = NULL;
01584 
01585    if ((varval = strchr(varname,'='))) {
01586       *varval++ = '\0';
01587       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
01588          tmpvar->next = list;
01589          list = tmpvar;
01590       }
01591    }
01592    return list;
01593 }

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

Definition at line 1741 of file chan_skinny.c.

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

Referenced by config_parse_variables().

01742 {
01743    char *oldcontext, *newcontext, *stalecontext, *stringp, newlist[AST_MAX_CONTEXT];
01744 
01745    while ((oldcontext = strsep(&old, "&"))) {
01746       stalecontext = '\0';
01747       ast_copy_string(newlist, new, sizeof(newlist));
01748       stringp = newlist;
01749       while ((newcontext = strsep(&stringp, "&"))) {
01750          if (strcmp(newcontext, oldcontext) == 0) {
01751             /* This is not the context you're looking for */
01752             stalecontext = '\0';
01753             break;
01754          } else if (strcmp(newcontext, oldcontext)) {
01755             stalecontext = oldcontext;
01756          }
01757          
01758       }
01759       if (stalecontext)
01760          ast_context_destroy(ast_context_find(stalecontext), "Skinny");
01761    }
01762 }

static int codec_ast2skinny ( int  astcodec  )  [static]

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

01685 {
01686    switch (astcodec) {
01687    case AST_FORMAT_ALAW:
01688       return SKINNY_CODEC_ALAW;
01689    case AST_FORMAT_ULAW:
01690       return SKINNY_CODEC_ULAW;
01691    case AST_FORMAT_G723_1:
01692       return SKINNY_CODEC_G723_1;
01693    case AST_FORMAT_G729A:
01694       return SKINNY_CODEC_G729A;
01695    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01696       return SKINNY_CODEC_G726_32;
01697    case AST_FORMAT_H261:
01698       return SKINNY_CODEC_H261;
01699    case AST_FORMAT_H263:
01700       return SKINNY_CODEC_H263;
01701    default:
01702       return 0;
01703    }
01704 }

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

01663 {
01664    switch (skinnycodec) {
01665    case SKINNY_CODEC_ALAW:
01666       return AST_FORMAT_ALAW;
01667    case SKINNY_CODEC_ULAW:
01668       return AST_FORMAT_ULAW;
01669    case SKINNY_CODEC_G723_1:
01670       return AST_FORMAT_G723_1;
01671    case SKINNY_CODEC_G729A:
01672       return AST_FORMAT_G729A;
01673    case SKINNY_CODEC_G726_32:
01674       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01675    case SKINNY_CODEC_H261:
01676       return AST_FORMAT_H261;
01677    case SKINNY_CODEC_H263:
01678       return AST_FORMAT_H263;
01679    default:
01680       return 0;
01681    }
01682 }

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

Definition at line 2749 of file chan_skinny.c.

References AST_LIST_TRAVERSE, and ast_strdup.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

02750 {
02751    struct skinny_device *d;
02752    char *result = NULL;
02753    int wordlen = strlen(word), which = 0;
02754 
02755    AST_LIST_TRAVERSE(&devices, d, list) {
02756       if (!strncasecmp(word, d->id, wordlen) && ++which > state)
02757          result = ast_strdup(d->id);
02758    }
02759 
02760    return result;
02761 }

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

Definition at line 2768 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

02769 {
02770    return (pos == 2 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02771 }

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

Definition at line 2763 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02764 {
02765    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02766 }

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

Definition at line 2773 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and skinny_device::lines.

Referenced by handle_skinny_show_line().

02774 {
02775    struct skinny_device *d;
02776    struct skinny_line *l;
02777    char *result = NULL;
02778    int wordlen = strlen(word), which = 0;
02779 
02780    if (pos != 3)
02781       return NULL;
02782    
02783    AST_LIST_TRAVERSE(&devices, d, list) {
02784       AST_LIST_TRAVERSE(&d->lines, l, list) {
02785          if (!strncasecmp(word, l->name, wordlen) && ++which > state)
02786             result = ast_strdup(l->name);
02787       }
02788    }
02789 
02790    return result;
02791 }

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

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

06965  {
06966    struct skinny_device *d, *temp;
06967    struct skinny_line *l, *ltemp;
06968    struct skinny_subchannel *sub;
06969    int update = 0;
06970  
06971    ast_log(LOG_NOTICE, "Configuring skinny device %s.\n", dname);
06972 
06973    AST_LIST_LOCK(&devices);
06974    AST_LIST_TRAVERSE(&devices, temp, list) {
06975       if (!strcasecmp(dname, temp->name) && temp->prune) {
06976          update = 1;
06977          break;
06978       }
06979    }
06980 
06981    if (!(d = ast_calloc(1, sizeof(*d)))) {
06982       ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
06983       AST_LIST_UNLOCK(&devices);
06984       return NULL;
06985    }
06986    memcpy(d, default_device, sizeof(*default_device));
06987    ast_mutex_init(&d->lock);
06988    ast_copy_string(d->name, dname, sizeof(d->name));
06989    AST_LIST_INSERT_TAIL(&devices, d, list);
06990 
06991    ast_mutex_lock(&d->lock);
06992    AST_LIST_UNLOCK(&devices);
06993  
06994    config_parse_variables(TYPE_DEVICE, d, v);
06995  
06996    if (!AST_LIST_FIRST(&d->lines)) {
06997       ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
06998       ast_mutex_unlock(&d->lock);
06999       return NULL;
07000    }
07001    if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
07002       d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
07003    }
07004  
07005    if (skinnyreload){
07006       AST_LIST_LOCK(&devices);
07007       AST_LIST_TRAVERSE(&devices, temp, list) {
07008          if (strcasecmp(d->id, temp->id) || !temp->prune || !temp->session) {
07009             continue;
07010          }
07011          ast_mutex_lock(&d->lock);
07012          d->session = temp->session;
07013          d->session->device = d;
07014 
07015          AST_LIST_LOCK(&d->lines);
07016          AST_LIST_TRAVERSE(&d->lines, l, list){
07017             l->device = d; 
07018 
07019             AST_LIST_LOCK(&temp->lines);
07020             AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
07021                if (strcasecmp(l->name, ltemp->name)) {
07022                   continue;
07023                }
07024                ast_mutex_lock(&ltemp->lock);
07025                l->instance = ltemp->instance;
07026                l->hookstate = ltemp->hookstate;
07027                if (!AST_LIST_EMPTY(&ltemp->sub)) {
07028                   ast_mutex_lock(&l->lock);
07029                   l->sub = ltemp->sub;
07030                   AST_LIST_TRAVERSE(&l->sub, sub, list) {
07031                      sub->parent = l;
07032                   }
07033                   ast_mutex_unlock(&l->lock);
07034                }
07035                ast_mutex_unlock(&ltemp->lock);
07036             }
07037             AST_LIST_UNLOCK(&temp->lines);
07038          }
07039          AST_LIST_UNLOCK(&d->lines);
07040          ast_mutex_unlock(&d->lock);
07041       }
07042       AST_LIST_UNLOCK(&devices);
07043    }
07044 
07045    ast_mutex_unlock(&d->lock);
07046 
07047    ast_verb(3, "%s config for device '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), d->name);
07048    
07049    return d;
07050 
07051  }

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

Definition at line 6906 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_strlen_zero(), ast_verb, config_parse_variables(), default_line, skinny_line::lock, LOG_NOTICE, mwi_event_cb(), skinny_line::mwi_event_sub, TYPE_LINE, and update().

Referenced by config_load().

06907  {
06908    struct skinny_line *l, *temp;
06909    int update = 0;
06910  
06911    ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);
06912 
06913    /* We find the old line and remove it just before the new
06914       line is created */
06915    AST_LIST_LOCK(&lines);
06916    AST_LIST_TRAVERSE(&lines, temp, all) {
06917       if (!strcasecmp(lname, temp->name) && temp->prune) {
06918          update = 1;
06919          break;
06920       }
06921    }
06922 
06923    if (!(l=ast_calloc(1, sizeof(*l)))) {
06924       ast_verb(1, "Unable to allocate memory for line %s.\n", lname);
06925       AST_LIST_UNLOCK(&lines);
06926       return NULL;
06927    }
06928 
06929    memcpy(l, default_line, sizeof(*default_line));
06930    ast_mutex_init(&l->lock);
06931    ast_copy_string(l->name, lname, sizeof(l->name));
06932    AST_LIST_INSERT_TAIL(&lines, l, all);
06933 
06934    ast_mutex_lock(&l->lock);
06935    AST_LIST_UNLOCK(&lines);
06936 
06937    config_parse_variables(TYPE_LINE, l, v);
06938          
06939    if (!ast_strlen_zero(l->mailbox)) {
06940       char *cfg_mailbox, *cfg_context;
06941       cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
06942       ast_verb(3, "Setting mailbox '%s' on line %s\n", cfg_mailbox, l->name);
06943       strsep(&cfg_context, "@");
06944       if (ast_strlen_zero(cfg_context))
06945           cfg_context = "default";
06946       l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, l,
06947          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
06948          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
06949          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
06950          AST_EVENT_IE_END);
06951    }
06952  
06953    ast_mutex_unlock(&l->lock);
06954    
06955    /* We do not want to unlink or free the line yet, it needs
06956       to be available to detect a device reconfig when we load the
06957       devices.  Old lines will be pruned after the reload completes */
06958 
06959    ast_verb(3, "%s config for line '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), l->name);
06960 
06961    return l;
06962  }

static int config_load ( void   )  [static]

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

07054  {
07055    int on = 1;
07056    struct ast_config *cfg;
07057    char *cat;
07058    struct skinny_device *d;
07059    struct skinny_line *l;
07060    int oldport = ntohs(bindaddr.sin_port);
07061    struct ast_flags config_flags = { 0 };
07062    
07063    ast_log(LOG_NOTICE, "Configuring skinny from %s\n", config);
07064   
07065    if (gethostname(ourhost, sizeof(ourhost))) {
07066       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled.\n");
07067       return 0;
07068    }
07069    cfg = ast_config_load(config, config_flags);
07070   
07071    /* We *must* have a config file otherwise stop immediately */
07072    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
07073       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled.\n", config);
07074       return -1;
07075    }
07076    memset(&bindaddr, 0, sizeof(bindaddr));
07077    memset(&default_prefs, 0, sizeof(default_prefs));
07078 
07079    /* Copy the default jb config over global_jbconf */
07080    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
07081 
07082    /* load the general section */
07083    cat = ast_category_browse(cfg, "general");
07084    config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));
07085 
07086    if (ntohl(bindaddr.sin_addr.s_addr)) {
07087       __ourip = bindaddr.sin_addr;
07088    } else {
07089       hp = ast_gethostbyname(ourhost, &ahp);
07090       if (!hp) {
07091          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
07092          ast_config_destroy(cfg);
07093          return 0;
07094       }
07095       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
07096    }
07097    if (!ntohs(bindaddr.sin_port)) {
07098       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
07099    }
07100    bindaddr.sin_family = AF_INET;
07101 
07102    /* load the lines sections */
07103    default_line->confcapability = default_capability;
07104    default_line->confprefs = default_prefs;
07105    config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
07106    cat = ast_category_browse(cfg, "lines");
07107    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
07108       l = config_line(cat, ast_variable_browse(cfg, cat));
07109       cat = ast_category_browse(cfg, cat);
07110    }
07111       
07112    /* load the devices sections */
07113    default_device->confcapability = default_capability;
07114    default_device->confprefs = default_prefs;
07115    config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
07116    cat = ast_category_browse(cfg, "devices");
07117    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
07118       d = config_device(cat, ast_variable_browse(cfg, cat));
07119       cat = ast_category_browse(cfg, cat);
07120    }
07121 
07122    ast_mutex_lock(&netlock);
07123    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
07124       close(skinnysock);
07125       skinnysock = -1;
07126    }
07127    if (skinnysock < 0) {
07128       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
07129       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
07130          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
07131          ast_config_destroy(cfg);
07132          ast_mutex_unlock(&netlock);
07133          return 0;
07134       }
07135       if (skinnysock < 0) {
07136          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
07137       } else {
07138          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
07139             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
07140                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07141                      strerror(errno));
07142             close(skinnysock);
07143             skinnysock = -1;
07144             ast_config_destroy(cfg);
07145             ast_mutex_unlock(&netlock);
07146             return 0;
07147          }
07148          if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
07149                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
07150                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07151                      strerror(errno));
07152                close(skinnysock);
07153                skinnysock = -1;
07154                ast_config_destroy(cfg);
07155                ast_mutex_unlock(&netlock);
07156                return 0;
07157          }
07158          ast_verb(2, "Skinny listening on %s:%d\n",
07159                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
07160          ast_netsock_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
07161          ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
07162       }
07163    }
07164    ast_mutex_unlock(&netlock);
07165    ast_config_destroy(cfg);
07166    return 1;
07167 }

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

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

06538  {
06539    struct ast_variable *v;
06540    int lineInstance = 1;
06541    int speeddialInstance = 1;
06542    
06543    while(vptr) {
06544       v = vptr;
06545       vptr = vptr->next;
06546  
06547       if (type & (TYPE_GENERAL)) {
06548          char newcontexts[AST_MAX_CONTEXT];
06549          char oldcontexts[AST_MAX_CONTEXT];
06550          char *stringp, *context, *oldregcontext;
06551          if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06552             v = v->next;
06553             continue;
06554          }
06555          if (!strcasecmp(v->name, "bindaddr")) {
06556             if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06557                ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06558             } else {
06559                memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
06560             }
06561             continue;
06562          } else if (!strcasecmp(v->name, "keepalive")) {
06563             keep_alive = atoi(v->value);
06564             continue;
06565          } else if (!strcasecmp(v->name, "regcontext")) {
06566             ast_copy_string(newcontexts, v->value, sizeof(newcontexts));
06567             stringp = newcontexts;
06568             /* Initialize copy of current global_regcontext for later use in removing stale contexts */
06569             ast_copy_string(oldcontexts, regcontext, sizeof(oldcontexts));
06570             oldregcontext = oldcontexts;
06571             /* Let's remove any contexts that are no longer defined in regcontext */
06572             cleanup_stale_contexts(stringp, oldregcontext);
06573             /* Create contexts if they don't exist already */
06574             while ((context = strsep(&stringp, "&"))) {
06575                ast_copy_string(used_context, context, sizeof(used_context));
06576                ast_context_find_or_create(NULL, NULL, context, "Skinny");
06577             }
06578             ast_copy_string(regcontext, v->value, sizeof(regcontext));
06579             continue;
06580          } else if (!strcasecmp(v->name, "dateformat")) {
06581             memcpy(date_format, v->value, sizeof(date_format));
06582             continue;
06583          } else if (!strcasecmp(v->name, "tos")) {
06584             if (ast_str2tos(v->value, &qos.tos))
06585                ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06586             continue;
06587          } else if (!strcasecmp(v->name, "tos_audio")) {
06588             if (ast_str2tos(v->value, &qos.tos_audio))
06589                ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06590             continue;
06591          } else if (!strcasecmp(v->name, "tos_video")) {
06592             if (ast_str2tos(v->value, &qos.tos_video))
06593                ast_log(LOG_WARNING, "Invalid tos_video value at line %d, refer to QoS documentation\n", v->lineno);
06594             continue;
06595          } else if (!strcasecmp(v->name, "cos")) {
06596             if (ast_str2cos(v->value, &qos.cos))
06597                ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06598             continue;
06599          } else if (!strcasecmp(v->name, "cos_audio")) {
06600             if (ast_str2cos(v->value, &qos.cos_audio))
06601                ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06602             continue;
06603          } else if (!strcasecmp(v->name, "cos_video")) {
06604             if (ast_str2cos(v->value, &qos.cos_video))
06605                ast_log(LOG_WARNING, "Invalid cos_video value at line %d, refer to QoS documentation\n", v->lineno);
06606             continue;
06607          } else if (!strcasecmp(v->name, "bindport")) {
06608             if (sscanf(v->value, "%5d", &ourport) == 1) {
06609                bindaddr.sin_port = htons(ourport);
06610             } else {
06611                ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
06612             }
06613             continue;
06614          } else if (!strcasecmp(v->name, "allow")) {
06615             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
06616             continue;
06617          } else if (!strcasecmp(v->name, "disallow")) {
06618             ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
06619             continue;
06620          } 
06621       }
06622  
06623       if (!strcasecmp(v->name, "transfer")) {
06624          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06625             CDEV_OPTS->transfer = ast_true(v->value);
06626             continue;
06627          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06628             CLINE_OPTS->transfer = ast_true(v->value);
06629             continue;
06630          }
06631       } else if (!strcasecmp(v->name, "callwaiting")) {
06632          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06633             CDEV_OPTS->callwaiting = ast_true(v->value);
06634             continue;
06635          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06636             CLINE_OPTS->callwaiting = ast_true(v->value);
06637             continue;
06638          }
06639       } else if (!strcasecmp(v->name, "directmedia") || !strcasecmp(v->name, "canreinvite")) {
06640          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06641             CLINE_OPTS->directmedia = ast_true(v->value);
06642             continue;
06643          }
06644       } else if (!strcasecmp(v->name, "nat")) {
06645          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06646             CLINE_OPTS->nat = ast_true(v->value);
06647             continue;
06648          }
06649       } else if (!strcasecmp(v->name, "context")) {
06650          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06651             ast_copy_string(CLINE_OPTS->context, v->value, sizeof(CLINE_OPTS->context));
06652             continue;
06653          }
06654       }else if (!strcasecmp(v->name, "vmexten")) {
06655          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06656             ast_copy_string(CDEV_OPTS->vmexten, v->value, sizeof(CDEV_OPTS->vmexten));
06657             continue;
06658          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06659             ast_copy_string(CLINE_OPTS->vmexten, v->value, sizeof(CLINE_OPTS->vmexten));
06660             continue;
06661          }
06662       } else if (!strcasecmp(v->name, "mwiblink")) {
06663          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06664             CDEV_OPTS->mwiblink = ast_true(v->value);
06665             continue;
06666          } else if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06667             CLINE_OPTS->mwiblink = ast_true(v->value);
06668             continue;
06669          }
06670       } else if (!strcasecmp(v->name, "linelabel")) {
06671          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06672             ast_copy_string(CLINE_OPTS->label, v->value, sizeof(CLINE_OPTS->label));
06673             continue;
06674          }
06675       } else if (!strcasecmp(v->name, "callerid")) {
06676          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06677             if (!strcasecmp(v->value, "asreceived")) {
06678                CLINE_OPTS->cid_num[0] = '\0';
06679                CLINE_OPTS->cid_name[0] = '\0';
06680             } else {
06681                ast_callerid_split(v->value, CLINE_OPTS->cid_name, sizeof(CLINE_OPTS->cid_name), CLINE_OPTS->cid_num, sizeof(CLINE_OPTS->cid_num));
06682             }
06683             continue;
06684          }
06685       } else if (!strcasecmp(v->name, "amaflags")) {
06686          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06687             int tempamaflags = ast_cdr_amaflags2int(v->value);
06688             if (tempamaflags < 0) {
06689                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
06690             } else {
06691                CLINE_OPTS->amaflags = tempamaflags;
06692             }
06693             continue;
06694          }
06695       } else if (!strcasecmp(v->name, "regexten")) {
06696          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06697             ast_copy_string(CLINE_OPTS->regexten, v->value, sizeof(CLINE_OPTS->regexten));
06698             continue;
06699          }
06700       } else if (!strcasecmp(v->name, "language")) {
06701          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06702             ast_copy_string(CLINE_OPTS->language, v->value, sizeof(CLINE_OPTS->language));
06703             continue;
06704          }
06705       } else if (!strcasecmp(v->name, "accountcode")) {
06706          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06707             ast_copy_string(CLINE_OPTS->accountcode, v->value, sizeof(CLINE_OPTS->accountcode));
06708             continue;
06709          }
06710       } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
06711          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06712             ast_copy_string(CLINE_OPTS->mohinterpret, v->value, sizeof(CLINE_OPTS->mohinterpret));
06713             continue;
06714          }
06715       } else if (!strcasecmp(v->name, "mohsuggest")) {
06716          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06717             ast_copy_string(CLINE_OPTS->mohsuggest, v->value, sizeof(CLINE_OPTS->mohsuggest));
06718             continue;
06719          }
06720       } else if (!strcasecmp(v->name, "callgroup")) {
06721          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06722             CLINE_OPTS->callgroup = ast_get_group(v->value);
06723             continue;
06724          }
06725       } else if (!strcasecmp(v->name, "pickupgroup")) {
06726          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06727             CLINE_OPTS->pickupgroup = ast_get_group(v->value);
06728             continue;
06729          }
06730       } else if (!strcasecmp(v->name, "immediate")) {
06731          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE | TYPE_DEF_LINE | TYPE_LINE)) {
06732             CLINE_OPTS->immediate = ast_true(v->value);
06733             continue;
06734          }
06735       } else if (!strcasecmp(v->name, "cancallforward")) {
06736          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06737             CLINE_OPTS->cancallforward = ast_true(v->value);
06738             continue;
06739          }
06740       } else if (!strcasecmp(v->name, "mailbox")) {
06741          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06742             ast_copy_string(CLINE_OPTS->mailbox, v->value, sizeof(CLINE_OPTS->mailbox));
06743             continue;
06744          }
06745       } else if ( !strcasecmp(v->name, "parkinglot")) {
06746          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06747             ast_copy_string(CLINE_OPTS->parkinglot, v->value, sizeof(CLINE_OPTS->parkinglot));
06748             continue;
06749          }
06750       } else if (!strcasecmp(v->name, "hasvoicemail")) {
06751          if (type & (TYPE_LINE)) {
06752             if (ast_true(v->value) && ast_strlen_zero(CLINE->mailbox)) {
06753                ast_copy_string(CLINE->mailbox, CLINE->name, sizeof(CLINE->mailbox));
06754             }
06755             continue;
06756          }
06757       } else if (!strcasecmp(v->name, "callreturn")) {
06758          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06759             CLINE_OPTS->callreturn = ast_true(v->value);
06760             continue;
06761          }
06762       } else if (!strcasecmp(v->name, "threewaycalling")) {
06763          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06764             CLINE_OPTS->threewaycalling = ast_true(v->value);
06765             continue;
06766          }
06767       } else if (!strcasecmp(v->name, "setvar")) {
06768          if (type & (TYPE_LINE)) {
06769             CLINE->chanvars = add_var(v->value, CLINE->chanvars);
06770             continue;
06771          }
06772       } else if (!strcasecmp(v->name, "earlyrtp")) {
06773          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06774             CDEV_OPTS->earlyrtp = ast_true(v->value);
06775             continue;
06776          }
06777       } else if (!strcasecmp(v->name, "host")) {
06778          if (type & (TYPE_DEVICE)) {
06779             if (ast_get_ip(&CDEV->addr, v->value)) {
06780                ast_log(LOG_WARNING, "Bad IP '%s' at line %d.\n", v->value, v->lineno);
06781             }
06782             continue;
06783          }
06784       } else if (!strcasecmp(v->name, "port")) {
06785          if (type & (TYPE_DEF_DEVICE)) {
06786             CDEV->addr.sin_port = htons(atoi(v->value));
06787             continue;
06788          }
06789       } else if (!strcasecmp(v->name, "device")) {
06790          if (type & (TYPE_DEVICE)) {
06791             ast_copy_string(CDEV_OPTS->id, v->value, sizeof(CDEV_OPTS->id));
06792             continue;
06793          }
06794       } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06795          if (type & (TYPE_DEVICE)) {
06796             CDEV->ha = ast_append_ha(v->name, v->value, CDEV->ha, NULL);
06797             continue;
06798          }
06799       } else if (!strcasecmp(v->name, "allow")) {
06800          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06801             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 1);
06802             continue;
06803          }
06804          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06805             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 1);
06806             continue;
06807          }
06808       } else if (!strcasecmp(v->name, "disallow")) {
06809          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06810             ast_parse_allow_disallow(&CDEV_OPTS->confprefs, &CDEV_OPTS->confcapability, v->value, 0);
06811             continue;
06812          }
06813          if (type & (TYPE_DEF_LINE | TYPE_LINE)) {
06814             ast_parse_allow_disallow(&CLINE_OPTS->confprefs, &CLINE_OPTS->confcapability, v->value, 0);
06815             continue;
06816          }
06817       } else if (!strcasecmp(v->name, "version")) {
06818          if (type & (TYPE_DEF_DEVICE | TYPE_DEVICE)) {
06819             ast_copy_string(CDEV_OPTS->version_id, v->value, sizeof(CDEV_OPTS->version_id));
06820             continue;
06821          }
06822       } else if (!strcasecmp(v->name, "line")) {
06823          if (type & (TYPE_DEVICE)) {
06824             struct skinny_line *l;
06825             AST_LIST_TRAVERSE(&lines, l, all) {
06826                if (!strcasecmp(v->value, l->name) && !l->prune) {
06827 
06828                   /* FIXME: temp solution about line conflicts */
06829                   struct skinny_device *d;
06830                   struct skinny_line *l2;
06831                   int lineinuse = 0;
06832                   AST_LIST_TRAVERSE(&devices, d, list) {
06833                      AST_LIST_TRAVERSE(&d->lines, l2, list) {
06834                         if (l2 == l && strcasecmp(d->id, CDEV->id)) {
06835                            ast_log(LOG_WARNING, "Line %s already used by %s. Not connecting to %s.\n", l->name, d->name, CDEV->name);
06836                            lineinuse++;
06837                         }
06838                      }
06839                   }
06840                   if (!lineinuse) {
06841                      if (!AST_LIST_FIRST(&CDEV->lines)) {
06842                         CDEV->activeline = l;
06843                      }
06844                      lineInstance++;
06845                      AST_LIST_INSERT_HEAD(&CDEV->lines, l, list);
06846                   }
06847                   break;
06848                }
06849             }
06850             continue;
06851          }
06852       } else if (!strcasecmp(v->name, "speeddial")) {
06853          if (type & (TYPE_DEVICE)) {
06854             struct skinny_speeddial *sd;
06855             if (!(sd = ast_calloc(1, sizeof(*sd)))) {
06856                ast_log(LOG_WARNING, "Unable to allocate memory for speeddial %s. Ignoring speeddial.\n", v->name);
06857                continue;
06858             } else {
06859                char buf[256];
06860                char *stringp = buf, *exten, *context, *label;
06861                   ast_copy_string(buf, v->value, sizeof(buf));
06862                exten = strsep(&stringp, ",");
06863                if ((context = strchr(exten, '@'))) {
06864                   *context++ = '\0';
06865                }
06866                label = stringp;
06867                ast_mutex_init(&sd->lock);
06868                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
06869                if (!ast_strlen_zero(context)) {
06870                   sd->isHint = 1;
06871                   sd->instance = lineInstance++;
06872                   ast_copy_string(sd->context, context, sizeof(sd->context));
06873                } else {
06874                   sd->isHint = 0;
06875                   sd->instance = speeddialInstance++;
06876                   sd->context[0] = '\0';
06877                }
06878                ast_copy_string(sd->label, S_OR(label, exten), sizeof(sd->label));
06879                sd->parent = CDEV;
06880                AST_LIST_INSERT_HEAD(&CDEV->speeddials, sd, list);
06881             }
06882             continue;
06883          }
06884       } else if (!strcasecmp(v->name, "addon")) {
06885          if (type & (TYPE_DEVICE)) {
06886             struct skinny_addon *a;
06887             if (!(a = ast_calloc(1, sizeof(*a)))) {
06888                ast_log(LOG_WARNING, "Unable to allocate memory for addon %s. Ignoring addon.\n", v->name);
06889                continue;
06890             } else {
06891                ast_mutex_init(&a->lock);
06892                ast_copy_string(a->type, v->value, sizeof(a->type));
06893                AST_LIST_INSERT_HEAD(&CDEV->addons, a, list);
06894             }
06895             continue;
06896          }
06897 
06898       } else {
06899          ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
06900          continue;
06901       }
06902       ast_log(LOG_WARNING, "Invalid category used: %s at line %d\n", v->name, v->lineno);
06903    }
06904  }

static char* control2str ( int  ind  )  [static]

Definition at line 4052 of file chan_skinny.c.

References AST_CONTROL_ANSWER, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OFFHOOK, AST_CONTROL_OPTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RADIO_KEY, AST_CONTROL_RADIO_UNKEY, AST_CONTROL_RING, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_TAKEOFFHOOK, AST_CONTROL_UNHOLD, AST_CONTROL_WINK, ast_threadstorage_get(), CONTROL2STR_BUFSIZE, and control2str_threadbuf.

Referenced by skinny_indicate().

04052                                   {
04053    char *tmp;
04054 
04055    switch (ind) {
04056    case AST_CONTROL_HANGUP:
04057       return "Other end has hungup";
04058    case AST_CONTROL_RING:
04059       return "Local ring";
04060    case AST_CONTROL_RINGING:
04061       return "Remote end is ringing";
04062    case AST_CONTROL_ANSWER:
04063       return "Remote end has answered";
04064    case AST_CONTROL_BUSY:
04065       return "Remote end is busy";
04066    case AST_CONTROL_TAKEOFFHOOK:
04067       return "Make it go off hook";
04068    case AST_CONTROL_OFFHOOK:
04069       return "Line is off hook";
04070    case AST_CONTROL_CONGESTION:
04071       return "Congestion (circuits busy)";
04072    case AST_CONTROL_FLASH:
04073       return "Flash hook";
04074    case AST_CONTROL_WINK:
04075       return "Wink";
04076    case AST_CONTROL_OPTION:
04077       return "Set a low-level option";
04078    case AST_CONTROL_RADIO_KEY:
04079       return "Key Radio";
04080    case AST_CONTROL_RADIO_UNKEY:
04081       return "Un-Key Radio";
04082    case AST_CONTROL_PROGRESS:
04083       return "Remote end is making Progress";
04084    case AST_CONTROL_PROCEEDING:
04085       return "Remote end is proceeding";
04086    case AST_CONTROL_HOLD:
04087       return "Hold";
04088    case AST_CONTROL_UNHOLD:
04089       return "Unhold";
04090    case AST_CONTROL_SRCUPDATE:
04091       return "Media Source Update";
04092    case -1:
04093       return "Stop tone";
04094    default:
04095       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
04096                         return "Unknown";
04097       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
04098       return tmp;
04099    }
04100 }

static void delete_devices ( void   )  [static]

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

07170 {
07171    struct skinny_device *d;
07172    struct skinny_line *l;
07173    struct skinny_speeddial *sd;
07174    struct skinny_addon *a;
07175 
07176    AST_LIST_LOCK(&devices);
07177    AST_LIST_LOCK(&lines);
07178 
07179    /* Delete all devices */
07180    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
07181       /* Delete all lines for this device */
07182       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07183          AST_LIST_REMOVE(&lines, l, all);
07184          free(l);
07185       }
07186       /* Delete all speeddials for this device */
07187       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07188          free(sd);
07189       }
07190       /* Delete all addons for this device */
07191       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07192          free(a);
07193       } 
07194       free(d);
07195    }
07196    AST_LIST_UNLOCK(&lines);
07197    AST_LIST_UNLOCK(&devices);
07198 }

static void destroy_session ( struct skinnysession s  )  [static]

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

06227 {
06228    struct skinnysession *cur;
06229    AST_LIST_LOCK(&sessions);
06230    AST_LIST_TRAVERSE_SAFE_BEGIN(&sessions, cur, list) {
06231       if (cur == s) {
06232          AST_LIST_REMOVE_CURRENT(list);
06233          if (s->fd > -1) 
06234             close(s->fd);
06235          
06236          ast_mutex_destroy(&s->lock);
06237          
06238          ast_free(s);
06239       } else {
06240          ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
06241       }
06242    }
06243    AST_LIST_TRAVERSE_SAFE_END
06244    AST_LIST_UNLOCK(&sessions);
06245 }

static char* device2str ( int  type  )  [static]

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

02839 {
02840    char *tmp;
02841 
02842    switch (type) {
02843    case SKINNY_DEVICE_NONE:
02844       return "No Device";
02845    case SKINNY_DEVICE_30SPPLUS:
02846       return "30SP Plus";
02847    case SKINNY_DEVICE_12SPPLUS:
02848       return "12SP Plus";
02849    case SKINNY_DEVICE_12SP:
02850       return "12SP";
02851    case SKINNY_DEVICE_12:
02852       return "12";
02853    case SKINNY_DEVICE_30VIP:
02854       return "30VIP";
02855    case SKINNY_DEVICE_7910:
02856       return "7910";
02857    case SKINNY_DEVICE_7960:
02858       return "7960";
02859    case SKINNY_DEVICE_7940:
02860       return "7940";
02861    case SKINNY_DEVICE_7935:
02862       return "7935";
02863    case SKINNY_DEVICE_ATA186:
02864       return "ATA186";
02865    case SKINNY_DEVICE_7941:
02866       return "7941";
02867    case SKINNY_DEVICE_7971:
02868       return "7971";
02869    case SKINNY_DEVICE_7914:
02870       return "7914";
02871    case SKINNY_DEVICE_7985:
02872       return "7985";
02873    case SKINNY_DEVICE_7911:
02874       return "7911";
02875    case SKINNY_DEVICE_7961GE:
02876       return "7961GE";
02877    case SKINNY_DEVICE_7941GE:
02878       return "7941GE";
02879    case SKINNY_DEVICE_7931:
02880       return "7931";
02881    case SKINNY_DEVICE_7921:
02882       return "7921";
02883    case SKINNY_DEVICE_7906:
02884       return "7906";
02885    case SKINNY_DEVICE_7962:
02886       return "7962";
02887    case SKINNY_DEVICE_7937:
02888       return "7937";
02889    case SKINNY_DEVICE_7942:
02890       return "7942";
02891    case SKINNY_DEVICE_7945:
02892       return "7945";
02893    case SKINNY_DEVICE_7965:
02894       return "7965";
02895    case SKINNY_DEVICE_7975:
02896       return "7975";
02897    case SKINNY_DEVICE_7905:
02898       return "7905";
02899    case SKINNY_DEVICE_7920:
02900       return "7920";
02901    case SKINNY_DEVICE_7970:
02902       return "7970";
02903    case SKINNY_DEVICE_7912:
02904       return "7912";
02905    case SKINNY_DEVICE_7902:
02906       return "7902";
02907    case SKINNY_DEVICE_CIPC:
02908       return "IP Communicator";
02909    case SKINNY_DEVICE_7961:
02910       return "7961";
02911    case SKINNY_DEVICE_7936:
02912       return "7936";
02913    case SKINNY_DEVICE_SCCPGATEWAY_AN:
02914       return "SCCPGATEWAY_AN";
02915    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
02916       return "SCCPGATEWAY_BRI";
02917    case SKINNY_DEVICE_UNKNOWN:
02918       return "Unknown";
02919    default:
02920       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
02921          return "Unknown";
02922       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
02923       return tmp;
02924    }
02925 }

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

Definition at line 6426 of file chan_skinny.c.

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

Referenced by restart_monitor().

06427 {
06428    int res;
06429 
06430    /* This thread monitors all the interfaces which are not yet in use
06431       (and thus do not have a separate thread) indefinitely */
06432    /* From here on out, we die whenever asked */
06433    for(;;) {
06434       pthread_testcancel();
06435       /* Wait for sched or io */
06436       res = ast_sched_wait(sched);
06437       if ((res < 0) || (res > 1000)) {
06438          res = 1000;
06439       }
06440       res = ast_io_wait(io, res);
06441       ast_mutex_lock(&monlock);
06442       if (res >= 0) {
06443          ast_sched_runq(sched);
06444       }
06445       ast_mutex_unlock(&monlock);
06446    }
06447    /* Never reached */
06448    return NULL;
06449 
06450 }

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

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

01509 {
01510    struct skinny_line *l;
01511 
01512    /*Dialing from on hook or on a 7920 uses instance 0 in requests
01513      but we need to start looking at instance 1 */
01514 
01515    if (!instance)
01516       instance = 1;
01517 
01518    AST_LIST_TRAVERSE(&d->lines, l, list){
01519       if (l->instance == instance)
01520          break;
01521    }
01522 
01523    if (!l) {
01524       ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
01525    }
01526    return l;
01527 }

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

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

01530 {
01531    struct skinny_line *l;
01532    struct skinny_line *tmpl = NULL;
01533    struct skinny_device *d;
01534    char line[256];
01535    char *at;
01536    char *device;
01537    int checkdevice = 0;
01538 
01539    ast_copy_string(line, dest, sizeof(line));
01540    at = strchr(line, '@');
01541    if (at)
01542       *at++ = '\0';
01543    device = at;
01544 
01545    if (!ast_strlen_zero(device))
01546       checkdevice = 1;
01547 
01548    AST_LIST_LOCK(&devices);
01549    AST_LIST_TRAVERSE(&devices, d, list){
01550       if (checkdevice && tmpl)
01551          break;
01552       else if (!checkdevice) {
01553          /* This is a match, since we're checking for line on every device. */
01554       } else if (!strcasecmp(d->name, device)) {
01555          if (skinnydebug)
01556             ast_verb(2, "Found device: %s\n", d->name);
01557       } else
01558          continue;
01559 
01560       /* Found the device (or we don't care which device) */
01561       AST_LIST_TRAVERSE(&d->lines, l, list){
01562          /* Search for the right line */
01563          if (!strcasecmp(l->name, line)) {
01564             if (tmpl) {
01565                ast_verb(2, "Ambiguous line name: %s\n", line);
01566                AST_LIST_UNLOCK(&devices);
01567                return NULL;
01568             } else
01569                tmpl = l;
01570          }
01571       }
01572    }
01573    AST_LIST_UNLOCK(&devices);
01574    return tmpl;
01575 }

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

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

01648 {
01649    struct skinny_speeddial *sd;
01650 
01651    AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01652       if (sd->isHint == isHint && sd->instance == instance)
01653          break;
01654    }
01655 
01656    if (!sd) {
01657       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01658    }
01659    return sd;
01660 }

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

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

01597 {
01598    struct skinny_line *l = find_line_by_instance(d, instance);
01599    struct skinny_subchannel *sub;
01600 
01601    if (!l) {
01602       return NULL;
01603    }
01604 
01605    /* 7920 phones set call reference to 0, so use the first
01606       sub-channel on the list.
01607            This MIGHT need more love to be right */
01608    if (!reference)
01609       sub = AST_LIST_FIRST(&l->sub);
01610    else {
01611       AST_LIST_TRAVERSE(&l->sub, sub, list) {
01612          if (sub->callid == reference)
01613             break;
01614       }
01615    }
01616    if (!sub) {
01617       ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
01618    }
01619    return sub;
01620 }

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

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

01624 {
01625    struct skinny_line *l;
01626    struct skinny_subchannel *sub = NULL;
01627 
01628    AST_LIST_TRAVERSE(&d->lines, l, list){
01629       AST_LIST_TRAVERSE(&l->sub, sub, list){
01630          if (sub->callid == reference)
01631             break;
01632       }
01633       if (sub)
01634          break;
01635    }
01636 
01637    if (!l) {
01638       ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
01639    } else {
01640       if (!sub) {
01641          ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
01642       }
01643    }
01644    return sub;
01645 }

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

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

01358 {
01359    struct skinny_device *d = s->device;
01360    struct skinny_addon *a;
01361    int i;
01362 
01363    switch (d->type) {
01364       case SKINNY_DEVICE_30SPPLUS:
01365       case SKINNY_DEVICE_30VIP:
01366          /* 13 rows, 2 columns */
01367          for (i = 0; i < 4; i++)
01368             (btn++)->buttonDefinition = BT_CUST_LINE;
01369          (btn++)->buttonDefinition = BT_REDIAL;
01370          (btn++)->buttonDefinition = BT_VOICEMAIL;
01371          (btn++)->buttonDefinition = BT_CALLPARK;
01372          (btn++)->buttonDefinition = BT_FORWARDALL;
01373          (btn++)->buttonDefinition = BT_CONFERENCE;
01374          for (i = 0; i < 4; i++)
01375             (btn++)->buttonDefinition = BT_NONE;
01376          for (i = 0; i < 13; i++)
01377             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01378          
01379          break;
01380       case SKINNY_DEVICE_12SPPLUS:
01381       case SKINNY_DEVICE_12SP:
01382       case SKINNY_DEVICE_12:
01383          /* 6 rows, 2 columns */
01384          for (i = 0; i < 2; i++)
01385             (btn++)->buttonDefinition = BT_CUST_LINE;
01386          for (i = 0; i < 4; i++)
01387             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01388          (btn++)->buttonDefinition = BT_HOLD;
01389          (btn++)->buttonDefinition = BT_REDIAL;
01390          (btn++)->buttonDefinition = BT_TRANSFER;
01391          (btn++)->buttonDefinition = BT_FORWARDALL;
01392          (btn++)->buttonDefinition = BT_CALLPARK;
01393          (btn++)->buttonDefinition = BT_VOICEMAIL;
01394          break;
01395       case SKINNY_DEVICE_7910:
01396          (btn++)->buttonDefinition = BT_LINE;
01397          (btn++)->buttonDefinition = BT_HOLD;
01398          (btn++)->buttonDefinition = BT_TRANSFER;
01399          (btn++)->buttonDefinition = BT_DISPLAY;
01400          (btn++)->buttonDefinition = BT_VOICEMAIL;
01401          (btn++)->buttonDefinition = BT_CONFERENCE;
01402          (btn++)->buttonDefinition = BT_FORWARDALL;
01403          for (i = 0; i < 2; i++)
01404             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01405          (btn++)->buttonDefinition = BT_REDIAL;
01406          break;
01407       case SKINNY_DEVICE_7960:
01408       case SKINNY_DEVICE_7961:
01409       case SKINNY_DEVICE_7961GE:
01410       case SKINNY_DEVICE_7962:
01411       case SKINNY_DEVICE_7965:
01412          for (i = 0; i < 6; i++)
01413             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01414          break;
01415       case SKINNY_DEVICE_7940:
01416       case SKINNY_DEVICE_7941:
01417       case SKINNY_DEVICE_7941GE:
01418       case SKINNY_DEVICE_7942:
01419       case SKINNY_DEVICE_7945:
01420          for (i = 0; i < 2; i++)
01421             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01422          break;
01423       case SKINNY_DEVICE_7935:
01424       case SKINNY_DEVICE_7936:
01425          for (i = 0; i < 2; i++)
01426             (btn++)->buttonDefinition = BT_LINE;
01427          break;
01428       case SKINNY_DEVICE_ATA186:
01429          (btn++)->buttonDefinition = BT_LINE;
01430          break;
01431       case SKINNY_DEVICE_7970:
01432       case SKINNY_DEVICE_7971:
01433       case SKINNY_DEVICE_7975:
01434       case SKINNY_DEVICE_CIPC:
01435          for (i = 0; i < 8; i++)
01436             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01437          break;
01438       case SKINNY_DEVICE_7985:
01439          /* XXX I have no idea what the buttons look like on these. */
01440          ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
01441          break;
01442       case SKINNY_DEVICE_7912:
01443       case SKINNY_DEVICE_7911:
01444       case SKINNY_DEVICE_7905:
01445          (btn++)->buttonDefinition = BT_LINE;
01446          (btn++)->buttonDefinition = BT_HOLD;
01447          break;
01448       case SKINNY_DEVICE_7920:
01449          /* XXX I don't know if this is right. */
01450          for (i = 0; i < 4; i++)
01451             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01452          break;
01453       case SKINNY_DEVICE_7921:
01454          for (i = 0; i < 6; i++)
01455             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01456          break;
01457       case SKINNY_DEVICE_7902:
01458          ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
01459          break;
01460       case SKINNY_DEVICE_7906:
01461          ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
01462          break;
01463       case SKINNY_DEVICE_7931:
01464          ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
01465          break;
01466       case SKINNY_DEVICE_7937:
01467          ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
01468          break;
01469       case SKINNY_DEVICE_7914:
01470          ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n", d->type);
01471          break;
01472       case SKINNY_DEVICE_SCCPGATEWAY_AN:
01473       case SKINNY_DEVICE_SCCPGATEWAY_BRI:
01474          ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
01475          break;
01476       default:
01477          ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
01478          break;
01479    }
01480 
01481    AST_LIST_LOCK(&d->addons);
01482    AST_LIST_TRAVERSE(&d->addons, a, list) {
01483       if (!strcasecmp(a->type, "7914")) {
01484          for (i = 0; i < 14; i++)
01485             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01486       } else {
01487          ast_log(LOG_WARNING, "Unknown addon type '%s' found.  Skipping.\n", a->type);
01488       }
01489    }
01490    AST_LIST_UNLOCK(&d->addons);
01491 
01492    return btn;
01493 }

static int get_devicestate ( struct skinny_line l  )  [static]

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

04024 {
04025    struct skinny_subchannel *sub;
04026    int res = AST_DEVICE_UNKNOWN;
04027 
04028    if (!l)
04029       res = AST_DEVICE_INVALID;
04030    else if (!l->device)
04031       res = AST_DEVICE_UNAVAILABLE;
04032    else if (l->dnd)
04033       res = AST_DEVICE_BUSY;
04034    else {
04035       if (l->hookstate == SKINNY_ONHOOK) {
04036          res = AST_DEVICE_NOT_INUSE;
04037       } else {
04038          res = AST_DEVICE_INUSE;
04039       }
04040 
04041       AST_LIST_TRAVERSE(&l->sub, sub, list) {
04042          if (sub->onhold) {
04043             res = AST_DEVICE_ONHOLD;
04044             break;
04045          }
04046       }
04047    }
04048 
04049    return res;
04050 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 6247 of file chan_skinny.c.

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

Referenced by skinny_session().

06248 {
06249    int res;
06250    int dlen = 0;
06251    int *bufaddr;
06252    struct pollfd fds[1];
06253 
06254    fds[0].fd = s->fd;
06255    fds[0].events = POLLIN;
06256    fds[0].revents = 0;
06257    res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
06258                    /* we add 10% to the keep_alive to deal */
06259                    /* with network delays, etc */
06260    if (res < 0) {
06261       if (errno != EINTR) {
06262          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
06263          return res;
06264       }
06265    } else if (res == 0) {
06266       if (skinnydebug)
06267          ast_verb(1, "Skinny Client was lost, unregistering\n");
06268       skinny_unregister(NULL, s);
06269       return -1;
06270    }
06271            
06272    if (fds[0].revents) {
06273       ast_mutex_lock(&s->lock);
06274       memset(s->inbuf, 0, sizeof(s->inbuf));
06275       res = read(s->fd, s->inbuf, 4);
06276       if (res < 0) {
06277          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06278 
06279          if (skinnydebug)
06280             ast_verb(1, "Skinny Client was lost, unregistering\n");
06281 
06282          skinny_unregister(NULL, s);
06283          ast_mutex_unlock(&s->lock);
06284          return res;
06285       } else if (res != 4) {
06286          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
06287          ast_mutex_unlock(&s->lock);
06288          
06289          if (res == 0) {
06290             if (skinnydebug)
06291                ast_verb(1, "Skinny Client was lost, unregistering\n");
06292             skinny_unregister(NULL, s);
06293          }
06294 
06295          return -1;
06296       }
06297 
06298       bufaddr = (int *)s->inbuf;
06299       dlen = letohl(*bufaddr);
06300       if (dlen < 4) {
06301          ast_debug(1, "Skinny Client sent invalid data.\n");
06302          ast_mutex_unlock(&s->lock);
06303          return -1;
06304       }
06305       if (dlen+8 > sizeof(s->inbuf)) {
06306          dlen = sizeof(s->inbuf) - 8;
06307       }
06308       *bufaddr = htolel(dlen);
06309 
06310       res = read(s->fd, s->inbuf+4, dlen+4);
06311       ast_mutex_unlock(&s->lock);
06312       if (res < 0) {
06313          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06314          return res;
06315       } else if (res != (dlen+4)) {
06316          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
06317          return -1;
06318       }
06319       return res;
06320    }
06321    return 0;
06322 }

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

Definition at line 5502 of file chan_skinny.c.

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

Referenced by handle_message().

05503 {
05504    /* no response necessary */
05505    if (skinnydebug)
05506       ast_verb(1, "Received Alarm Message: %s\n", req->data.alarm.displayMessage);
05507 
05508    return 1;
05509 }

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

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

05330 {
05331    struct skinny_device *d = s->device;
05332    struct skinny_line *l;
05333    int i;
05334 
05335    struct skinny_speeddial *sd;
05336    struct button_definition_template btn[42];
05337    int lineInstance = 1;
05338    int speeddialInstance = 1;
05339    int buttonCount = 0;
05340 
05341    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
05342       return -1;
05343 
05344    memset(&btn, 0, sizeof(btn));
05345 
05346    get_button_template(s, btn);
05347 
05348    for (i=0; i<42; i++) {
05349       int btnSet = 0;
05350       switch (btn[i].buttonDefinition) {
05351          case BT_CUST_LINE:
05352             /* assume failure */
05353             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05354             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05355 
05356             AST_LIST_TRAVERSE(&d->lines, l, list) {
05357                if (l->instance == lineInstance) {
05358                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05359                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05360                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05361                   lineInstance++;
05362                   buttonCount++;
05363                   btnSet = 1;
05364                   break;
05365                }
05366             }
05367 
05368             if (!btnSet) {
05369                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05370                   if (sd->isHint && sd->instance == lineInstance) {
05371                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05372                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05373                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05374                      lineInstance++;
05375                      buttonCount++;
05376                      btnSet = 1;
05377                      break;
05378                   }
05379                }
05380             }
05381             break;
05382          case BT_CUST_LINESPEEDDIAL:
05383             /* assume failure */
05384             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05385             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05386 
05387             AST_LIST_TRAVERSE(&d->lines, l, list) {
05388                if (l->instance == lineInstance) {
05389                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05390                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05391                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05392                   lineInstance++;
05393                   buttonCount++;
05394                   btnSet = 1;
05395                   break;
05396                }
05397             }
05398 
05399             if (!btnSet) {
05400                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05401                   if (sd->isHint && sd->instance == lineInstance) {
05402                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05403                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05404                      req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05405                      lineInstance++;
05406                      buttonCount++;
05407                      btnSet = 1;
05408                      break;
05409                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
05410                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05411                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05412                      req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
05413                      speeddialInstance++;
05414                      buttonCount++;
05415                      btnSet = 1;
05416                      break;
05417                   }
05418                }
05419             }
05420             break;
05421          case BT_LINE:
05422             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
05423             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05424 
05425             AST_LIST_TRAVERSE(&d->lines, l, list) {
05426                if (l->instance == lineInstance) {
05427                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05428                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05429                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
05430                   lineInstance++;
05431                   buttonCount++;
05432                   btnSet = 1;
05433                   break;
05434                }
05435             }
05436             break;
05437          case BT_SPEEDDIAL:
05438             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05439             req->data.buttontemplate.definition[i].instanceNumber = 0;
05440 
05441             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05442                if (!sd->isHint && sd->instance == speeddialInstance) {
05443                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05444                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05445                   req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance - 1);
05446                   speeddialInstance++;
05447                   buttonCount++;
05448                   btnSet = 1;
05449                   break;
05450                }
05451             }
05452             break;
05453          case BT_NONE:
05454             break;
05455          default:
05456             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
05457             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
05458             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05459             buttonCount++;
05460             btnSet = 1;
05461             break;
05462       }
05463    }
05464 
05465    req->data.buttontemplate.buttonOffset = htolel(0);
05466    req->data.buttontemplate.buttonCount = htolel(buttonCount);
05467    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
05468 
05469    if (skinnydebug)
05470       ast_verb(1, "Sending %d template to %s\n",
05471                d->type,
05472                d->name);
05473    transmit_response(d, req);
05474    return 1;
05475 }

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

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

04585 {
04586    struct skinny_line *l = sub->parent;
04587    struct skinny_device *d = l->device;
04588    struct ast_channel *c = sub->owner;
04589    pthread_t t;
04590 
04591    if (l->hookstate == SKINNY_ONHOOK) {
04592       l->hookstate = SKINNY_OFFHOOK;
04593       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04594       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04595    }
04596    if (skinnydebug)
04597       ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04598    transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04599 
04600    if (l->cfwdtype & cfwdtype) {
04601       set_callforwards(l, NULL, cfwdtype);
04602       ast_safe_sleep(c, 500);
04603       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04604       transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
04605       transmit_displaynotify(d, "CFwd disabled", 10);
04606       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04607          ast_indicate(c, -1);
04608          ast_hangup(c);
04609       }
04610       transmit_cfwdstate(d, l);
04611    } else {
04612       l->getforward = cfwdtype;
04613       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04614       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04615       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04616          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04617          ast_hangup(c);
04618       }
04619    }
04620    return 0;
04621 }

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

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

05210 {
05211    struct skinny_device *d = s->device;
05212    struct skinny_line *l;
05213    uint32_t count = 0;
05214    int codecs = 0;
05215    int i;
05216 
05217    count = letohl(req->data.caps.count);
05218    if (count > SKINNY_MAX_CAPABILITIES) {
05219       count = SKINNY_MAX_CAPABILITIES;
05220       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
05221    }
05222 
05223    for (i = 0; i < count; i++) {
05224       int acodec = 0;
05225       int scodec = 0;
05226       scodec = letohl(req->data.caps.caps[i].codec);
05227       acodec = codec_skinny2ast(scodec);
05228       if (skinnydebug)
05229          ast_verb(1, "Adding codec capability '%d (%d)'\n", acodec, scodec);
05230       codecs |= acodec;
05231    }
05232 
05233    d->capability = d->confcapability & codecs;
05234    ast_verb(0, "Device capability set to '%d'\n", d->capability);
05235    AST_LIST_TRAVERSE(&d->lines, l, list) {
05236       ast_mutex_lock(&l->lock);
05237       l->capability = l->confcapability & d->capability;
05238       ast_mutex_unlock(&l->lock);
05239    }
05240 
05241    return 1;
05242 }

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

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

05579 {
05580    struct skinny_device *d = s->device;
05581    struct skinny_line *l;
05582    struct skinny_subchannel *sub = NULL;
05583    struct ast_channel *c;
05584    pthread_t t;
05585 
05586    if (skinnydebug)
05587       ast_verb(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
05588 
05589    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05590 
05591    if (!sub) {
05592       l = find_line_by_instance(d, d->lastlineinstance);
05593       if (!l) {
05594          return 0;
05595       }
05596    } else {
05597       l = sub->parent;
05598    }
05599 
05600    c = skinny_new(l, AST_STATE_DOWN);
05601 
05602    if(!c) {
05603       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05604    } else {
05605       l->hookstate = SKINNY_OFFHOOK;
05606 
05607       sub = c->tech_pvt;
05608       l->activesub = sub;
05609       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05610       if (skinnydebug)
05611          ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05612       transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05613       transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05614 
05615       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
05616          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05617       }
05618       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
05619       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05620          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05621          ast_hangup(c);
05622       }
05623    }
05624    
05625    return 1;
05626 }

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

Definition at line 6041 of file chan_skinny.c.

Referenced by handle_message().

06042 {
06043    /* XXX umm...okay?  Why do I care? */
06044    return 1;
06045 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

04430 {
04431    if (!sub)
04432       return -1;
04433    if (sub->related) {
04434       skinny_hold(sub);
04435       skinny_unhold(sub->related);
04436       sub->parent->activesub = sub->related;
04437    } else {
04438       if (sub->onhold) {
04439          skinny_unhold(sub);
04440          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04441       } else {
04442          skinny_hold(sub);
04443          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04444       }
04445    }
04446    return 1;
04447 }

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

Definition at line 4622 of file chan_skinny.c.

Referenced by handle_message().

04623 {
04624    /* no response necessary */
04625    return 1;
04626 }

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

Definition at line 4510 of file chan_skinny.c.

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

Referenced by handle_message().

04511 {
04512    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04513       return -1;
04514 
04515    transmit_response(s->device, req);
04516    return 1;
04517 }

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

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

04629 {
04630    struct skinny_subchannel *sub = NULL;
04631    struct skinny_line *l;
04632    struct skinny_device *d = s->device;
04633    struct ast_frame f = { 0, };
04634    char dgt;
04635    int digit;
04636    int lineInstance;
04637    int callReference;
04638 
04639    digit = letohl(req->data.keypad.button);
04640    lineInstance = letohl(req->data.keypad.lineInstance);
04641    callReference = letohl(req->data.keypad.callReference);
04642 
04643    if (digit == 14) {
04644       dgt = '*';
04645    } else if (digit == 15) {
04646       dgt = '#';
04647    } else if (digit >= 0 && digit <= 9) {
04648       dgt = '0' + digit;
04649    } else {
04650       /* digit=10-13 (A,B,C,D ?), or
04651        * digit is bad value
04652        *
04653        * probably should not end up here, but set
04654        * value for backward compatibility, and log
04655        * a warning.
04656        */
04657       dgt = '0' + digit;
04658       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04659    }
04660 
04661    f.subclass = dgt;
04662 
04663    f.src = "skinny";
04664 
04665    if (lineInstance && callReference)
04666       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04667    else
04668       sub = d->activeline->activesub;
04669       //sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04670 
04671    if (!sub)
04672       return 0;
04673 
04674    l = sub->parent;
04675    if (sub->owner) {
04676       if (sub->owner->_state == 0) {
04677          f.frametype = AST_FRAME_DTMF_BEGIN;
04678          ast_queue_frame(sub->owner, &f);
04679       }
04680       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04681       f.frametype = AST_FRAME_DTMF_END;
04682       ast_queue_frame(sub->owner, &f);
04683       /* XXX This seriously needs to be fixed */
04684       if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
04685          if (sub->owner->_state == 0) {
04686             f.frametype = AST_FRAME_DTMF_BEGIN;
04687             ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04688          }
04689          f.frametype = AST_FRAME_DTMF_END;
04690          ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04691       }
04692    } else {
04693       if (skinnydebug)
04694          ast_verb(1, "No owner: %s\n", l->name);
04695    }
04696    return 1;
04697 }

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

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

05270 {
05271    struct skinny_device *d = s->device;
05272    struct skinny_line *l;
05273    struct skinny_speeddial *sd = NULL;
05274    int instance;
05275 
05276    instance = letohl(req->data.line.lineNumber);
05277 
05278    AST_LIST_LOCK(&devices);
05279 
05280    l = find_line_by_instance(d, instance);
05281 
05282    if (!l) {
05283       sd = find_speeddial_by_instance(d, instance, 1);
05284    }
05285 
05286    if (!l && !sd) {
05287       return 0;
05288    }
05289 
05290    AST_LIST_UNLOCK(&devices);
05291 
05292    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
05293       return -1;
05294 
05295    req->data.linestat.lineNumber = letohl(instance);
05296    if (!l) {
05297       memcpy(req->data.linestat.lineDirNumber, sd->label, sizeof(req->data.linestat.lineDirNumber));
05298       memcpy(req->data.linestat.lineDisplayName, sd->label, sizeof(req->data.linestat.lineDisplayName));
05299    } else {
05300       memcpy(req->data.linestat.lineDirNumber, l->name, sizeof(req->data.linestat.lineDirNumber));
05301       memcpy(req->data.linestat.lineDisplayName, l->label, sizeof(req->data.linestat.lineDisplayName));
05302    }
05303    transmit_response(d, req);
05304    return 1;
05305 }

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

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

06054 {
06055    int res = 0;
06056 
06057    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
06058       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
06059       ast_free(req);
06060       return 0;
06061    }
06062 
06063    SKINNY_DEVONLY(if (skinnydebug > 1) {
06064       ast_verb(4, "Received %s from %s\n", message2str(req->e), s->device->name);
06065    })
06066 
06067    switch(letohl(req->e)) {
06068    case KEEP_ALIVE_MESSAGE:
06069       res = handle_keep_alive_message(req, s);
06070       break;
06071    case REGISTER_MESSAGE:
06072       if (skinnydebug)
06073          ast_verb(1, "Device %s is attempting to register\n", req->data.reg.name);
06074 
06075       res = handle_register_message(req, s);
06076       break;
06077    case IP_PORT_MESSAGE:
06078       res = handle_ip_port_message(req, s);
06079       break;
06080    case KEYPAD_BUTTON_MESSAGE:
06081        {
06082       struct skinny_device *d = s->device;
06083       struct skinny_subchannel *sub;
06084       int lineInstance;
06085       int callReference;
06086 
06087       if (skinnydebug)
06088          ast_verb(1, "Collected digit: [%d]\n", letohl(req->data.keypad.button));
06089 
06090       lineInstance = letohl(req->data.keypad.lineInstance);
06091       callReference = letohl(req->data.keypad.callReference);
06092 
06093       if (lineInstance) {
06094          sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
06095       } else {
06096          sub = d->activeline->activesub;
06097       }
06098 
06099       if (sub && ((sub->owner && sub->owner->_state <  AST_STATE_UP) || sub->onhold)) {
06100          char dgt;
06101          int digit = letohl(req->data.keypad.button);
06102 
06103          if (digit == 14) {
06104             dgt = '*';
06105          } else if (digit == 15) {
06106             dgt = '#';
06107          } else if (digit >= 0 && digit <= 9) {
06108             dgt = '0' + digit;
06109          } else {
06110             /* digit=10-13 (A,B,C,D ?), or
06111             * digit is bad value
06112             *
06113             * probably should not end up here, but set
06114             * value for backward compatibility, and log
06115             * a warning.
06116             */
06117             dgt = '0' + digit;
06118             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
06119          }
06120 
06121          d->exten[strlen(d->exten)] = dgt;
06122          d->exten[strlen(d->exten)+1] = '\0';
06123       } else
06124          res = handle_keypad_button_message(req, s);
06125       }
06126       break;
06127    case ENBLOC_CALL_MESSAGE:
06128       res = handle_enbloc_call_message(req, s);
06129       break;
06130    case STIMULUS_MESSAGE:
06131       res = handle_stimulus_message(req, s);
06132       break;
06133    case OFFHOOK_MESSAGE:
06134       res = handle_offhook_message(req, s);
06135       break;
06136    case ONHOOK_MESSAGE:
06137       res = handle_onhook_message(req, s);
06138       break;
06139    case CAPABILITIES_RES_MESSAGE:
06140       if (skinnydebug)
06141          ast_verb(1, "Received CapabilitiesRes\n");
06142 
06143       res = handle_capabilities_res_message(req, s);
06144       break;
06145    case SPEED_DIAL_STAT_REQ_MESSAGE:
06146       if (skinnydebug)
06147          ast_verb(1, "Received SpeedDialStatRequest\n");
06148 
06149       res = handle_speed_dial_stat_req_message(req, s);
06150       break;
06151    case LINE_STATE_REQ_MESSAGE:
06152       if (skinnydebug)
06153          ast_verb(1, "Received LineStatRequest\n");
06154       res = handle_line_state_req_message(req, s);
06155       break;
06156    case TIME_DATE_REQ_MESSAGE:
06157       if (skinnydebug)
06158          ast_verb(1, "Received Time/Date Request\n");
06159 
06160       res = handle_time_date_req_message(req, s);
06161       break;
06162    case BUTTON_TEMPLATE_REQ_MESSAGE:
06163       if (skinnydebug)
06164          ast_verb(1, "Buttontemplate requested\n");
06165 
06166       res = handle_button_template_req_message(req, s);
06167       break;
06168    case VERSION_REQ_MESSAGE:
06169       if (skinnydebug)
06170          ast_verb(1, "Version Request\n");
06171 
06172       res = handle_version_req_message(req, s);
06173       break;
06174    case SERVER_REQUEST_MESSAGE:
06175       if (skinnydebug)
06176          ast_verb(1, "Received Server Request\n");
06177 
06178       res = handle_server_request_message(req, s);
06179       break;
06180    case ALARM_MESSAGE:
06181       res = handle_alarm_message(req, s);
06182       break;
06183    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
06184       if (skinnydebug)
06185          ast_verb(1, "Received Open Receive Channel Ack\n");
06186 
06187       res = handle_open_receive_channel_ack_message(req, s);
06188       break;
06189    case SOFT_KEY_SET_REQ_MESSAGE:
06190       if (skinnydebug)
06191          ast_verb(1, "Received SoftKeySetReq\n");
06192 
06193       res = handle_soft_key_set_req_message(req, s);
06194       break;
06195    case SOFT_KEY_EVENT_MESSAGE:
06196       res = handle_soft_key_event_message(req, s);
06197       break;
06198    case UNREGISTER_MESSAGE:
06199       if (skinnydebug)
06200          ast_verb(1, "Received Unregister Request\n");
06201 
06202       res = handle_unregister_message(req, s);
06203       break;
06204    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
06205       if (skinnydebug)
06206          ast_verb(1, "Received SoftKey Template Request\n");
06207 
06208       res = handle_soft_key_template_req_message(req, s);
06209       break;
06210    case HEADSET_STATUS_MESSAGE:
06211       res = handle_headset_status_message(req, s);
06212       break;
06213    case REGISTER_AVAILABLE_LINES_MESSAGE:
06214       res = handle_register_available_lines_message(req, s);
06215       break;
06216    default:
06217       if (skinnydebug)
06218          ast_verb(1, "RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
06219       break;
06220    }
06221    if (res >= 0 && req)
06222       ast_free(req);
06223    return res;
06224 }

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

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

05046 {
05047    struct skinny_device *d = s->device;
05048    struct skinny_line *l;
05049    struct skinny_subchannel *sub;
05050    struct ast_channel *c;
05051    struct skinny_line *tmp;
05052    pthread_t t;
05053    int instance;
05054    int reference;
05055 
05056    /* if any line on a device is offhook, than the device must be offhook, 
05057       unless we have shared lines CCM seems that it would never get here, 
05058       but asterisk does, so we may need to do more work.  Ugly, we should 
05059       probably move hookstate from line to device, afterall, it's actually
05060        a device that changes hookstates */
05061 
05062    AST_LIST_TRAVERSE(&d->lines, tmp, list) {
05063       if (tmp->hookstate == SKINNY_OFFHOOK) {
05064          ast_verbose(VERBOSE_PREFIX_3 "Got offhook message when device (%s@%s) already offhook\n", tmp->name, d->name);
05065          return 0;
05066       }
05067    }
05068 
05069    instance = letohl(req->data.offhook.instance);
05070    reference = letohl(req->data.offhook.reference);
05071 
05072    if (instance) {
05073       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05074       if (!sub) {
05075          l = find_line_by_instance(d, d->lastlineinstance);
05076          if (!l) {
05077             return 0;
05078          }
05079       } else {
05080          l = sub->parent;
05081       }
05082    } else {
05083       l = d->activeline;
05084       sub = l->activesub;
05085    }
05086 
05087    transmit_ringer_mode(d, SKINNY_RING_OFF);
05088    l->hookstate = SKINNY_OFFHOOK;
05089 
05090    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
05091 
05092    if (sub && sub->onhold) {
05093       return 1;
05094    }
05095 
05096    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05097 
05098    if (sub && sub->outgoing) {
05099       /* We're answering a ringing call */
05100       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05101       transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05102       transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05103       transmit_callstateonly(d, sub, SKINNY_CONNECTED);
05104       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05105       start_rtp(sub);
05106       ast_setstate(sub->owner, AST_STATE_UP);
05107    } else {
05108       if (sub && sub->owner) {
05109          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
05110       } else {
05111          c = skinny_new(l, AST_STATE_DOWN);
05112          if (c) {
05113             sub = c->tech_pvt;
05114             l->activesub = sub;
05115             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05116             if (skinnydebug)
05117                ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05118             transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05119             transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05120             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05121 
05122             /* start the switch thread */
05123             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05124                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05125                ast_hangup(c);
05126             }
05127          } else {
05128             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05129          }
05130       }
05131    }
05132    return 1;
05133 }

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

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

05136 {
05137    struct skinny_device *d = s->device;
05138    struct skinny_line *l;
05139    struct skinny_subchannel *sub;
05140    int instance;
05141    int reference;
05142    int onlysub = 0;
05143 
05144    instance = letohl(req->data.onhook.instance);
05145    reference = letohl(req->data.onhook.reference);
05146 
05147    if (instance && reference) {
05148       sub = find_subchannel_by_instance_reference(d, instance, reference);
05149       if (!sub) {
05150          return 0;
05151       }
05152       l = sub->parent;
05153    } else {
05154       l = d->activeline;
05155       sub = l->activesub;
05156       if (!sub) {
05157          return 0;
05158       }
05159    }
05160 
05161    if (l->hookstate == SKINNY_ONHOOK) {
05162       /* Something else already put us back on hook */
05163       return 0;
05164    }
05165 
05166    ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05167 
05168    if (sub->onhold) {
05169       return 0;
05170    }
05171 
05172    if (!AST_LIST_NEXT(sub, list)) {
05173       onlysub = 1;
05174    } else {
05175       AST_LIST_REMOVE(&l->sub, sub, list);
05176    }
05177 
05178    sub->cxmode = SKINNY_CX_RECVONLY;
05179    if (onlysub || sub->xferor){  /* is this the only call to this device? */
05180       l->hookstate = SKINNY_ONHOOK;
05181       if (skinnydebug)
05182          ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
05183    }
05184 
05185    transmit_callstate(d, l->instance, l->hookstate, sub->callid);
05186    if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05187       /* We're allowed to transfer, we have two active calls and
05188          we made at least one of the calls.  Let's try and transfer */
05189       handle_transfer_button(sub);
05190    } else {
05191       /* Hangup the current call */
05192       /* If there is another active call, skinny_hangup will ring the phone with the other call */
05193       if (sub->xferor && sub->related){
05194          sub->related->related = NULL;
05195          sub->related->blindxfer = 0;
05196       }
05197 
05198       if (sub->owner) {
05199          sub->alreadygone = 1;
05200          ast_queue_hangup(sub->owner);
05201       } else {
05202          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05203             l->name, d->name, sub->callid);
05204       }
05205    }
05206    return 1;
05207 }

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

Definition at line 5511 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_log(), ast_rtp_get_us(), ast_rtp_set_peer(), ast_verb, media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, 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().

05512 {
05513    struct skinny_device *d = s->device;
05514    struct skinny_line *l;
05515    struct skinny_subchannel *sub;
05516    struct ast_format_list fmt;
05517    struct sockaddr_in sin;
05518    struct sockaddr_in us;
05519    uint32_t addr;
05520    int port;
05521    int status;
05522    int passthruid;
05523 
05524    status = letohl(req->data.openreceivechannelack.status);
05525    if (status) {
05526       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
05527       return 0;
05528    }
05529    addr = letohl(req->data.openreceivechannelack.ipAddr);
05530    port = letohl(req->data.openreceivechannelack.port);
05531    passthruid = letohl(req->data.openreceivechannelack.passThruId);
05532 
05533    sin.sin_family = AF_INET;
05534    sin.sin_addr.s_addr = addr;
05535    sin.sin_port = htons(port);
05536 
05537    sub = find_subchannel_by_reference(d, passthruid);
05538 
05539    if (!sub)
05540       return 0;
05541 
05542    l = sub->parent;
05543 
05544    if (sub->rtp) {
05545       ast_rtp_set_peer(sub->rtp, &sin);
05546       ast_rtp_get_us(sub->rtp, &us);
05547    } else {
05548       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
05549       return 0;
05550    }
05551 
05552    if (skinnydebug)
05553       ast_verb(1, "ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
05554 
05555    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
05556       return -1;
05557 
05558    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
05559 
05560    if (skinnydebug)
05561       ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
05562 
05563    req->data.startmedia.conferenceId = htolel(sub->callid);
05564    req->data.startmedia.passThruPartyId = htolel(sub->callid);
05565    req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
05566    req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
05567    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
05568    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
05569    req->data.startmedia.qualifier.precedence = htolel(127);
05570    req->data.startmedia.qualifier.vad = htolel(0);
05571    req->data.startmedia.qualifier.packets = htolel(0);
05572    req->data.startmedia.qualifier.bitRate = htolel(0);
05573    transmit_response(d, req);
05574 
05575    return 1;
05576 }

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

Definition at line 6047 of file chan_skinny.c.

Referenced by handle_message().

06048 {
06049    /* XXX I have no clue what this is for, but my phone was sending it, so... */
06050    return 1;
06051 }

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

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

04520 {
04521    struct skinny_device *d = NULL;
04522    char name[16];
04523    int res;
04524 
04525    memcpy(&name, req->data.reg.name, sizeof(name));
04526 
04527    res = skinny_register(req, s);
04528    if (!res) {
04529       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
04530       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
04531          return -1;
04532 
04533       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
04534 
04535       /* transmit_respons in line as we don't have a valid d */
04536       ast_mutex_lock(&s->lock);
04537 
04538       if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
04539          ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
04540          ast_mutex_unlock(&s->lock);
04541          return -1;
04542       }
04543 
04544       memset(s->outbuf, 0, sizeof(s->outbuf));
04545       memcpy(s->outbuf, req, skinny_header_size);
04546       memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
04547 
04548       res = write(s->fd, s->outbuf, letohl(req->len)+8);
04549 
04550       if (res != letohl(req->len)+8) {
04551          ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
04552       }
04553    
04554       ast_mutex_unlock(&s->lock);
04555 
04556       return 0;
04557    }
04558    ast_verb(3, "Device '%s' successfully registered\n", name);
04559 
04560    d = s->device;
04561    
04562    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
04563       return -1;
04564 
04565    req->data.regack.res[0] = '0';
04566    req->data.regack.res[1] = '\0';
04567    req->data.regack.keepAlive = htolel(keep_alive);
04568    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
04569    req->data.regack.res2[0] = '0';
04570    req->data.regack.res2[1] = '\0';
04571    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
04572    transmit_response(d, req);
04573    if (skinnydebug)
04574       ast_verb(1, "Requesting capabilities\n");
04575 
04576    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
04577       return -1;
04578 
04579    transmit_response(d, req);
04580 
04581    return res;
04582 }

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

02729 {
02730    switch (cmd) {
02731    case CLI_INIT:
02732       e->command = "skinny reload";
02733       e->usage =
02734          "Usage: skinny reload\n"
02735          "       Reloads the chan_skinny configuration\n";
02736       return NULL;
02737    case CLI_GENERATE:
02738       return NULL;
02739    }
02740    
02741    if (a->argc != e->args)
02742       return CLI_SHOWUSAGE;
02743 
02744    skinny_reload();
02745    return CLI_SUCCESS;
02746 
02747 }

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

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

02794 {
02795    struct skinny_device *d;
02796    struct skinny_req *req;
02797 
02798    switch (cmd) {
02799    case CLI_INIT:
02800       e->command = "skinny reset";
02801       e->usage =
02802          "Usage: skinny reset <DeviceId|DeviceName|all> [restart]\n"
02803          "       Causes a Skinny device to reset itself, optionally with a full restart\n";
02804       return NULL;
02805    case CLI_GENERATE:
02806       return complete_skinny_reset(a->line, a->word, a->pos, a->n);
02807    }
02808 
02809    if (a->argc < 3 || a->argc > 4)
02810       return CLI_SHOWUSAGE;
02811 
02812    AST_LIST_LOCK(&devices);
02813    AST_LIST_TRAVERSE(&devices, d, list) {
02814       int fullrestart = 0;
02815       if (!strcasecmp(a->argv[2], d->id) || !strcasecmp(a->argv[2], d->name) || !strcasecmp(a->argv[2], "all")) {
02816          if (!(d->session))
02817             continue;
02818 
02819          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
02820             continue;
02821 
02822          if (a->argc == 4 && !strcasecmp(a->argv[3], "restart"))
02823             fullrestart = 1;
02824 
02825          if (fullrestart)
02826             req->data.reset.resetType = 2;
02827          else
02828             req->data.reset.resetType = 1;
02829 
02830          ast_verb(3, "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
02831          transmit_response(d, req);
02832       }
02833    }
02834    AST_LIST_UNLOCK(&devices);
02835    return CLI_SUCCESS;
02836 }

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

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

02687 {
02688    switch (cmd) {
02689    case CLI_INIT:
02690 #ifdef SKINNY_DEVMODE
02691       e->command = "skinny set debug {off|on|packet}";
02692       e->usage =
02693          "Usage: skinny set debug {off|on|packet}\n"
02694          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02695 #else
02696       e->command = "skinny set debug {off|on}";
02697       e->usage =
02698          "Usage: skinny set debug {off|on}\n"
02699          "       Enables/Disables dumping of Skinny packets for debugging purposes\n";
02700 #endif
02701       return NULL;
02702    case CLI_GENERATE:
02703       return NULL;
02704    }
02705    
02706    if (a->argc != e->args)
02707       return CLI_SHOWUSAGE;
02708 
02709    if (!strncasecmp(a->argv[e->args - 1], "on", 2)) {
02710       skinnydebug = 1;
02711       ast_cli(a->fd, "Skinny Debugging Enabled\n");
02712       return CLI_SUCCESS;
02713    } else if (!strncasecmp(a->argv[e->args - 1], "off", 3)) {
02714       skinnydebug = 0;
02715       ast_cli(a->fd, "Skinny Debugging Disabled\n");
02716       return CLI_SUCCESS;
02717 #ifdef SKINNY_DEVMODE
02718    } else if (!strncasecmp(a->argv[e->args - 1], "packet", 6)) {
02719       skinnydebug = 2;
02720       ast_cli(a->fd, "Skinny Debugging Enabled including Packets\n");
02721       return CLI_SUCCESS;
02722 #endif
02723    } else {
02724       return CLI_SHOWUSAGE;
02725    }
02726 }

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

03187 {
03188    switch (cmd) {
03189    case CLI_INIT:
03190       e->command = "skinny show device";
03191       e->usage =
03192          "Usage: skinny show device <DeviceId|DeviceName>\n"
03193          "       Lists all deviceinformation of a specific device known to the Skinny subsystem.\n";
03194       return NULL;
03195    case CLI_GENERATE:
03196       return complete_skinny_show_device(a->line, a->word, a->pos, a->n);
03197    }
03198 
03199    return _skinny_show_device(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03200 }

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

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

03047 {
03048 
03049    switch (cmd) {
03050    case CLI_INIT:
03051       e->command = "skinny show devices";
03052       e->usage =
03053          "Usage: skinny show devices\n"
03054          "       Lists all devices known to the Skinny subsystem.\n";
03055       return NULL;
03056    case CLI_GENERATE:
03057       return NULL;
03058    }
03059 
03060    return _skinny_show_devices(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03061 }

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

03497 {
03498    switch (cmd) {
03499    case CLI_INIT:
03500       e->command = "skinny show line";
03501       e->usage =
03502          "Usage: skinny show line <Line> [ on <DeviceID|DeviceName> ]\n"
03503          "       List all lineinformation of a specific line known to the Skinny subsystem.\n";
03504       return NULL;
03505    case CLI_GENERATE:
03506       return complete_skinny_show_line(a->line, a->word, a->pos, a->n);
03507    }
03508 
03509    return _skinny_show_line(0, a->fd, NULL, NULL, a->argc, (const char **) a->argv);
03510 }

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

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

03308 {
03309    int verbose = 0;
03310 
03311    switch (cmd) {
03312    case CLI_INIT:
03313       e->command = "skinny show lines [verbose]";
03314       e->usage =
03315          "Usage: skinny show lines\n"
03316          "       Lists all lines known to the Skinny subsystem.\n"
03317          "       If 'verbose' is specified, the output includes\n"
03318          "       information about subs for each line.\n";
03319       return NULL;
03320    case CLI_GENERATE:
03321       return NULL;
03322    }
03323 
03324    if (a->argc == e->args) {
03325       if (!strcasecmp(a->argv[e->args-1], "verbose")) {
03326          verbose = 1;
03327       } else {
03328          return CLI_SHOWUSAGE;
03329       }
03330    } else if (a->argc != e->args - 1) {
03331       return CLI_SHOWUSAGE;
03332    }
03333 
03334    return _skinny_show_lines(a->fd, NULL, NULL, NULL, a->argc, (const char **) a->argv);
03335 }

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

03514 {
03515    switch (cmd) {
03516    case CLI_INIT:
03517       e->command = "skinny show settings";
03518       e->usage =
03519          "Usage: skinny show settings\n"
03520          "       Lists all global configuration settings of the Skinny subsystem.\n";
03521       return NULL;
03522    case CLI_GENERATE:
03523       return NULL;
03524    }  
03525 
03526    if (a->argc != 3)
03527       return CLI_SHOWUSAGE;
03528 
03529    ast_cli(a->fd, "\nGlobal Settings:\n");
03530    ast_cli(a->fd, "  Skinny Port:            %d\n", ntohs(bindaddr.sin_port));
03531    ast_cli(a->fd, "  Bindaddress:            %s\n", ast_inet_ntoa(bindaddr.sin_addr));
03532    ast_cli(a->fd, "  KeepAlive:              %d\n", keep_alive);
03533    ast_cli(a->fd, "  Date Format:            %s\n", date_format);
03534    ast_cli(a->fd, "  Voice Mail Extension:   %s\n", S_OR(global_vmexten, "(not set)"));
03535    ast_cli(a->fd, "  Reg. context:           %s\n", S_OR(regcontext, "(not set)"));
03536    ast_cli(a->fd, "  Jitterbuffer enabled:   %s\n", (ast_test_flag(&global_jbconf, AST_JB_ENABLED) ? "Yes" : "No"));
03537    ast_cli(a->fd, "  Jitterbuffer forced:    %s\n", (ast_test_flag(&global_jbconf, AST_JB_FORCED) ? "Yes" : "No"));
03538    ast_cli(a->fd, "  Jitterbuffer max size:  %ld\n", global_jbconf.max_size);
03539    ast_cli(a->fd, "  Jitterbuffer resync:    %ld\n", global_jbconf.resync_threshold);
03540    ast_cli(a->fd, "  Jitterbuffer impl:      %s\n", global_jbconf.impl);
03541    ast_cli(a->fd, "  Jitterbuffer log:       %s\n", (ast_test_flag(&global_jbconf, AST_JB_LOG) ? "Yes" : "No"));
03542 
03543    return CLI_SUCCESS;
03544 }

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

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

05663 {
05664    struct skinny_device *d = s->device;
05665    struct skinny_line *l;
05666    struct skinny_subchannel *sub = NULL;
05667    struct ast_channel *c;
05668    pthread_t t;
05669    int event;
05670    int instance;
05671    int callreference;
05672 
05673    event = letohl(req->data.softkeyeventmessage.softKeyEvent);
05674    instance = letohl(req->data.softkeyeventmessage.instance);
05675    callreference = letohl(req->data.softkeyeventmessage.callreference);
05676 
05677    if (instance) {
05678       l = find_line_by_instance(d, instance);
05679       if (callreference) {
05680          sub = find_subchannel_by_instance_reference(d, instance, callreference);
05681       } else {
05682          sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
05683       }
05684    } else {
05685       l = find_line_by_instance(d, d->lastlineinstance);
05686    }
05687 
05688    if (!l) {
05689       if (skinnydebug)
05690          ast_verb(1, "Received Softkey Event: %d(%d/%d)\n", event, instance, callreference);
05691       return 0;
05692    }
05693 
05694    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
05695 
05696    switch(event) {
05697    case SOFTKEY_NONE:
05698       if (skinnydebug)
05699          ast_verb(1, "Received Softkey Event: None(%d/%d)\n", instance, callreference);
05700       break;
05701    case SOFTKEY_REDIAL:
05702       if (skinnydebug)
05703          ast_verb(1, "Received Softkey Event: Redial(%d/%d)\n", instance, callreference);
05704 
05705       if (ast_strlen_zero(l->lastnumberdialed)) {
05706          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
05707          l->hookstate = SKINNY_ONHOOK;
05708          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05709          transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
05710          break;
05711       }
05712 
05713       if (!sub || !sub->owner) {
05714          c = skinny_new(l, AST_STATE_DOWN);
05715       } else {
05716          c = sub->owner;
05717       }
05718 
05719       if (!c) {
05720          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05721       } else {
05722          sub = c->tech_pvt;
05723          l->activesub = sub;
05724          if (l->hookstate == SKINNY_ONHOOK) {
05725             l->hookstate = SKINNY_OFFHOOK;
05726             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05727             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05728          }
05729          if (skinnydebug)
05730             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05731          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05732          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05733          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
05734 
05735          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
05736             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05737          }
05738          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
05739          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05740             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05741             ast_hangup(c);
05742          }
05743       }
05744       break;
05745    case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
05746       if (skinnydebug)
05747          ast_verb(1, "Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
05748 
05749       /* New Call ALWAYS gets a new sub-channel */
05750       c = skinny_new(l, AST_STATE_DOWN);
05751       sub = c->tech_pvt;
05752    
05753       /* transmit_ringer_mode(d, SKINNY_RING_OFF);
05754       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON); */
05755 
05756       /* l->hookstate = SKINNY_OFFHOOK; */
05757 
05758       if (!c) {
05759          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05760       } else {
05761          sub = c->tech_pvt;
05762          l->activesub = sub;
05763          if (l->hookstate == SKINNY_ONHOOK) {
05764             l->hookstate = SKINNY_OFFHOOK;
05765             transmit_speaker_mode(d, SKINNY_SPEAKERON);
05766          }
05767          ast_verb(1, "Call-id: %d\n", sub->callid);
05768 
05769          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05770 
05771          if (skinnydebug)
05772             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05773          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05774          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05775          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05776 
05777          /* start the switch thread */
05778          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05779             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05780             ast_hangup(c);
05781          }
05782       }
05783       break;
05784    case SOFTKEY_HOLD:
05785       if (skinnydebug)
05786          ast_verb(1, "Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
05787       handle_hold_button(sub);   
05788       break;
05789    case SOFTKEY_TRNSFER:
05790       if (skinnydebug)
05791          ast_verb(1, "Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
05792       if (l->transfer)
05793          handle_transfer_button(sub);
05794       else
05795          transmit_displaynotify(d, "Transfer disabled", 10);
05796 
05797       break;
05798    case SOFTKEY_DND:
05799       if (skinnydebug)
05800          ast_verb(1, "Received Softkey Event: DND(%d/%d)\n", instance, callreference);
05801 
05802       /* Do not disturb */
05803       if (l->dnd != 0){
05804          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
05805          l->dnd = 0;
05806          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
05807          transmit_displaynotify(d, "DnD disabled", 10);
05808       } else {
05809          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
05810          l->dnd = 1;
05811          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
05812          transmit_displaynotify(d, "DnD enabled", 10);
05813       }
05814       break;
05815    case SOFTKEY_CFWDALL:
05816       if (skinnydebug)
05817          ast_verb(1, "Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
05818 
05819       if (!sub || !sub->owner) {
05820          c = skinny_new(l, AST_STATE_DOWN);
05821       } else {
05822          c = sub->owner;
05823       }
05824 
05825       if (!c) {
05826          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05827       } else {
05828          sub = c->tech_pvt;
05829          l->activesub = sub;
05830          handle_callforward_button(sub, SKINNY_CFWD_ALL);
05831       }
05832       break;
05833    case SOFTKEY_CFWDBUSY:
05834       if (skinnydebug)
05835          ast_verb(1, "Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
05836 
05837       if (!sub || !sub->owner) {
05838          c = skinny_new(l, AST_STATE_DOWN);
05839       } else {
05840          c = sub->owner;
05841       }
05842 
05843       if (!c) {
05844          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05845       } else {
05846          sub = c->tech_pvt;
05847          l->activesub = sub;
05848          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
05849       }
05850       break;
05851    case SOFTKEY_CFWDNOANSWER:
05852       if (skinnydebug)
05853          ast_verb(1, "Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
05854 
05855 #if 0 /* Not sure how to handle this yet */
05856       if (!sub || !sub->owner) {
05857          c = skinny_new(l, AST_STATE_DOWN);
05858       } else {
05859          c = sub->owner;
05860       }
05861 
05862       if (!c) {
05863          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05864       } else {
05865          sub = c->tech_pvt;
05866          l->activesub = sub;
05867          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
05868       }
05869 #endif
05870       break;
05871    case SOFTKEY_BKSPC:
05872       if (skinnydebug)
05873          ast_verb(1, "Received Softkey Event: Backspace(%d/%d)\n", instance, callreference);
05874       break;
05875    case SOFTKEY_ENDCALL:
05876       if (skinnydebug)
05877          ast_verb(1, "Received Softkey Event: End Call(%d/%d)\n", instance, callreference);
05878 
05879       if (l->hookstate == SKINNY_ONHOOK) {
05880          /* Something else already put us back on hook */
05881          break;
05882       }
05883       if (sub) {
05884          int onlysub = 0;
05885 
05886          if (!AST_LIST_NEXT(sub, list)) {
05887             onlysub = 1;
05888          } else {
05889             AST_LIST_REMOVE(&l->sub, sub, list);
05890          }
05891 
05892          sub->cxmode = SKINNY_CX_RECVONLY;
05893          if (onlysub || sub->xferor){    /*Are there other calls to this device */
05894             l->hookstate = SKINNY_ONHOOK;
05895             if (skinnydebug)
05896                ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, callreference);
05897          }
05898 
05899          transmit_callstate(d, l->instance, l->hookstate, sub->callid);
05900          ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05901          if (skinnydebug)
05902             ast_verb(1, "Skinny %s@%s went on hook\n", l->name, d->name);
05903          if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05904             /* We're allowed to transfer, we have two active calls and
05905                we made at least one of the calls.  Let's try and transfer */
05906             handle_transfer_button(sub);
05907          } else {
05908             /* Hangup the current call */
05909             /* If there is another active call, skinny_hangup will ring the phone with the other call */
05910             if (sub->xferor && sub->related){
05911                sub->related->related = NULL;
05912                sub->related->blindxfer = 0;
05913             }
05914 
05915             if (sub->owner) {
05916                sub->alreadygone = 1;
05917                ast_queue_hangup(sub->owner);
05918             } else {
05919                ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05920                   l->name, d->name, sub->callid);
05921             }
05922          }
05923          if ((l->hookstate == SKINNY_ONHOOK) && (AST_LIST_NEXT(sub, list) && !AST_LIST_NEXT(sub, list)->rtp)) {
05924             ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05925          }
05926       }
05927       break;
05928    case SOFTKEY_RESUME:
05929       if (skinnydebug)
05930          ast_verb(1, "Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
05931 
05932       if (sub) {
05933          if (sub->onhold) {
05934             skinny_unhold(sub);
05935             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05936          } else {
05937             skinny_hold(sub);
05938             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_ONHOLD);
05939          }
05940       }
05941 
05942       break;
05943    case SOFTKEY_ANSWER:
05944       if (skinnydebug)
05945          ast_verb(1, "Received Softkey Event: Answer(%d/%d)\n", instance, callreference);
05946 
05947       transmit_ringer_mode(d, SKINNY_RING_OFF);
05948       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05949       if (l->hookstate == SKINNY_ONHOOK) {
05950          transmit_speaker_mode(d, SKINNY_SPEAKERON);
05951          l->hookstate = SKINNY_OFFHOOK;
05952       }
05953 
05954       if (sub && sub->outgoing) {
05955          /* We're answering a ringing call */
05956          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05957          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05958          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05959          transmit_callstateonly(d, sub, SKINNY_CONNECTED);
05960          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05961          start_rtp(sub);
05962          ast_setstate(sub->owner, AST_STATE_UP);
05963       }
05964       break;
05965    case SOFTKEY_INFO:
05966       if (skinnydebug)
05967          ast_verb(1, "Received Softkey Event: Info(%d/%d)\n", instance, callreference);
05968       break;
05969    case SOFTKEY_CONFRN:
05970       if (skinnydebug)
05971          ast_verb(1, "Received Softkey Event: Conference(%d/%d)\n", instance, callreference);
05972       /* XXX determine the best way to pull off a conference.  Meetme? */
05973       break;
05974    case SOFTKEY_PARK:
05975       {
05976       int extout;
05977       char message[32];
05978 
05979       if (skinnydebug)
05980          ast_verb(1, "Received Softkey Event: Park Call(%d/%d)\n", instance, callreference);
05981 
05982       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
05983          c = sub->owner;
05984          if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
05985             snprintf(message, sizeof(message), "Call Parked at: %d", extout);
05986             transmit_displaynotify(d, message, 10);
05987          } else {
05988             transmit_displaynotify(d, "Call Park failed", 10);
05989          }
05990       } else {
05991          transmit_displaynotify(d, "Call Park not available", 10);
05992       }
05993       }
05994       break;
05995    case SOFTKEY_JOIN:
05996       if (skinnydebug)
05997          ast_verb(1, "Received Softkey Event: Join(%d/%d)\n", instance, callreference);
05998       break;
05999    case SOFTKEY_MEETME:
06000       /* XXX How is this different from CONFRN? */
06001       if (skinnydebug)
06002          ast_verb(1, "Received Softkey Event: Meetme(%d/%d)\n", instance, callreference);
06003       break;
06004    case SOFTKEY_PICKUP:
06005       if (skinnydebug)
06006          ast_verb(1, "Received Softkey Event: Pickup(%d/%d)\n", instance, callreference);
06007       break;
06008    case SOFTKEY_GPICKUP:
06009       if (skinnydebug)
06010          ast_verb(1, "Received Softkey Event: Group Pickup(%d/%d)\n", instance, callreference);
06011       break;
06012    default:
06013       if (skinnydebug)
06014          ast_verb(1, "Received unknown Softkey Event: %d(%d/%d)\n", event, instance, callreference);
06015       break;
06016    }
06017 
06018    return 1;
06019 }

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

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

05630 {
05631    int i;
05632    int x;
05633    int y;
05634    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
05635    struct skinny_device *d = s->device;
05636 
05637    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
05638       return -1;
05639 
05640    req->data.softkeysets.softKeySetOffset = htolel(0);
05641    req->data.softkeysets.softKeySetCount = htolel(11);
05642    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
05643    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
05644       const uint8_t *defaults = softkeymode->defaults;
05645       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
05646          This will have to do for now. */
05647       for (y = 0; y < softkeymode->count; y++) {
05648          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
05649             if (defaults[y] == i+1) {
05650                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
05651                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
05652             }
05653          }
05654       }
05655       softkeymode++;
05656    }
05657    transmit_response(d, req);
05658    transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05659    return 1;
05660 }

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

Definition at line 4699 of file chan_skinny.c.

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

Referenced by handle_message().

04700 {
04701    struct skinny_device *d = s->device;
04702    struct skinny_line *l;
04703    struct skinny_subchannel *sub;
04704    /*struct skinny_speeddial *sd;*/
04705    struct ast_channel *c;
04706    pthread_t t;
04707    int event;
04708    int instance;
04709    int callreference;
04710    /*int res = 0;*/
04711 
04712    event = letohl(req->data.stimulus.stimulus);
04713    instance = letohl(req->data.stimulus.stimulusInstance);
04714    callreference = letohl(req->data.stimulus.callreference); 
04715    if (skinnydebug)
04716       ast_verb(1, "callreference in handle_stimulus_message is '%d'\n", callreference);
04717 
04718    /*  Note that this call should be using the passed in instance and callreference */
04719    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04720 
04721    if (!sub) {
04722       l = find_line_by_instance(d, d->lastlineinstance);
04723       if (!l) {
04724          return 0;
04725       }
04726       sub = l->activesub;
04727    } else {
04728       l = sub->parent;
04729    }
04730 
04731    switch(event) {
04732    case STIMULUS_REDIAL:
04733       if (skinnydebug)
04734          ast_verb(1, "Received Stimulus: Redial(%d/%d)\n", instance, callreference);
04735 
04736       if (ast_strlen_zero(l->lastnumberdialed)) {
04737          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
04738          l->hookstate = SKINNY_ONHOOK;
04739          transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04740          transmit_callstate(d, l->instance, SKINNY_ONHOOK, instance);
04741          break;
04742       }
04743 
04744       c = skinny_new(l, AST_STATE_DOWN);
04745       if (!c) {
04746          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04747       } else {
04748          sub = c->tech_pvt;
04749          l = sub->parent;
04750          l->activesub = sub;
04751          if (l->hookstate == SKINNY_ONHOOK) {
04752             l->hookstate = SKINNY_OFFHOOK;
04753             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04754          }
04755          if (skinnydebug)
04756             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04757          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04758          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04759          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04760 
04761          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
04762             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04763          }
04764          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
04765          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04766             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04767             ast_hangup(c);
04768          }
04769       }
04770       break;
04771    case STIMULUS_SPEEDDIAL:
04772        {
04773       struct skinny_speeddial *sd;
04774 
04775       if (skinnydebug)
04776          ast_verb(1, "Received Stimulus: SpeedDial(%d/%d)\n", instance, callreference);
04777       if (!(sd = find_speeddial_by_instance(d, instance, 0))) {
04778          return 0;
04779       }
04780 
04781       if (!sub || !sub->owner)
04782          c = skinny_new(l, AST_STATE_DOWN);
04783       else
04784          c = sub->owner;
04785 
04786       if (!c) {
04787          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04788       } else {
04789          sub = c->tech_pvt;
04790          l = sub->parent;
04791          l->activesub = sub;
04792          if (l->hookstate == SKINNY_ONHOOK) {
04793             l->hookstate = SKINNY_OFFHOOK;
04794             transmit_speaker_mode(d, SKINNY_SPEAKERON);
04795             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04796          }
04797          if (skinnydebug)
04798             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04799          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04800          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04801          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04802 
04803          if (!ast_ignore_pattern(c->context, sd->exten)) {
04804             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04805          }
04806          if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
04807             ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
04808             ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
04809 
04810             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04811                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04812                ast_hangup(c);
04813             }
04814             break;
04815          }
04816       }
04817        }
04818       break;
04819    case STIMULUS_HOLD:
04820       if (skinnydebug)
04821          ast_verb(1, "Received Stimulus: Hold(%d/%d)\n", instance, callreference);
04822       handle_hold_button(sub);
04823       break;
04824    case STIMULUS_TRANSFER:
04825       if (skinnydebug)
04826          ast_verb(1, "Received Stimulus: Transfer(%d/%d)\n", instance, callreference);
04827       if (l->transfer)
04828          handle_transfer_button(sub);
04829       else
04830          transmit_displaynotify(d, "Transfer disabled", 10);
04831       break;
04832    case STIMULUS_CONFERENCE:
04833       if (skinnydebug)
04834          ast_verb(1, "Received Stimulus: Conference(%d/%d)\n", instance, callreference);
04835       /* XXX determine the best way to pull off a conference.  Meetme? */
04836       break;
04837    case STIMULUS_VOICEMAIL:
04838       if (skinnydebug)
04839          ast_verb(1, "Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
04840 
04841       if (!sub || !sub->owner) {
04842          c = skinny_new(l, AST_STATE_DOWN);
04843       } else {
04844          c = sub->owner;
04845       }
04846       if (!c) {
04847          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04848       } else {
04849          sub = c->tech_pvt;
04850          l = sub->parent;
04851          l->activesub = sub;
04852 
04853          if (ast_strlen_zero(l->vmexten))  /* Exit the call if no VM pilot */
04854             break;
04855 
04856          if (l->hookstate == SKINNY_ONHOOK){
04857             l->hookstate = SKINNY_OFFHOOK;
04858             transmit_speaker_mode(d, SKINNY_SPEAKERON);
04859             transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
04860          }
04861 
04862          if (skinnydebug)
04863             ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04864 
04865          transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
04866          transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04867          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04868 
04869          if (!ast_ignore_pattern(c->context, l->vmexten)) {
04870             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04871          }
04872 
04873          if (ast_exists_extension(c, c->context, l->vmexten, 1, l->cid_num)) {
04874             ast_copy_string(c->exten, l->vmexten, sizeof(c->exten));
04875             ast_copy_string(l->lastnumberdialed, l->vmexten, sizeof(l->lastnumberdialed));
04876             if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04877                ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04878                ast_hangup(c);
04879             }
04880             break;
04881          }
04882       }
04883       break;
04884    case STIMULUS_CALLPARK:
04885       {
04886       int extout;
04887       char message[32];
04888 
04889       if (skinnydebug)
04890          ast_verb(1, "Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
04891 
04892       if ((sub && sub->owner) && (sub->owner->_state ==  AST_STATE_UP)){
04893          c = sub->owner;
04894          if (!ast_masq_park_call(ast_bridged_channel(c), c, 0, &extout)) {
04895             snprintf(message, sizeof(message), "Call Parked at: %d", extout);
04896             transmit_displaynotify(d, message, 10);
04897          } else {
04898             transmit_displaynotify(d, "Call Park failed", 10);
04899          }
04900       } else {
04901          transmit_displaynotify(d, "Call Park not available", 10);
04902       }
04903       }
04904       break;
04905    case STIMULUS_DND:
04906       if (skinnydebug)
04907          ast_verb(1, "Received Stimulus: DND (%d/%d)\n", instance, callreference);
04908 
04909       /* Do not disturb */
04910       if (l->dnd != 0){
04911          ast_verb(3, "Disabling DND on %s@%s\n", l->name, d->name);
04912          l->dnd = 0;
04913          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_ON);
04914          transmit_displaynotify(d, "DnD disabled", 10);
04915       } else {
04916          ast_verb(3, "Enabling DND on %s@%s\n", l->name, d->name);
04917          l->dnd = 1;
04918          transmit_lamp_indication(d, STIMULUS_DND, 1, SKINNY_LAMP_OFF);
04919          transmit_displaynotify(d, "DnD enabled", 10);
04920       }
04921       break;
04922    case STIMULUS_FORWARDALL:
04923       if (skinnydebug)
04924          ast_verb(1, "Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
04925 
04926       if (!sub || !sub->owner) {
04927          c = skinny_new(l, AST_STATE_DOWN);
04928       } else {
04929          c = sub->owner;
04930       }
04931 
04932       if (!c) {
04933          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04934       } else {
04935          sub = c->tech_pvt;
04936          handle_callforward_button(sub, SKINNY_CFWD_ALL);
04937       }
04938       break;
04939    case STIMULUS_FORWARDBUSY:
04940       if (skinnydebug)
04941          ast_verb(1, "Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
04942 
04943       if (!sub || !sub->owner) {
04944          c = skinny_new(l, AST_STATE_DOWN);
04945       } else {
04946          c = sub->owner;
04947       }
04948 
04949       if (!c) {
04950          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04951       } else {
04952          sub = c->tech_pvt;
04953          handle_callforward_button(sub, SKINNY_CFWD_BUSY);
04954       }
04955       break;
04956    case STIMULUS_FORWARDNOANSWER:
04957       if (skinnydebug)
04958          ast_verb(1, "Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
04959 
04960 #if 0 /* Not sure how to handle this yet */
04961       if (!sub || !sub->owner) {
04962          c = skinny_new(l, AST_STATE_DOWN);
04963       } else {
04964          c = sub->owner;
04965       }
04966 
04967       if (!c) {
04968          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04969       } else {
04970          sub = c->tech_pvt;
04971          handle_callforward_button(sub, SKINNY_CFWD_NOANSWER);
04972       }
04973 #endif
04974       break;
04975    case STIMULUS_DISPLAY:
04976       /* Not sure what this is */
04977       if (skinnydebug)
04978          ast_verb(1, "Received Stimulus: Display(%d/%d)\n", instance, callreference);
04979       break;
04980    case STIMULUS_LINE:
04981       if (skinnydebug)
04982          ast_verb(1, "Received Stimulus: Line(%d/%d)\n", instance, callreference);
04983 
04984       l = find_line_by_instance(d, instance);
04985 
04986       if (!l) {
04987          return 0;
04988       }
04989 
04990       d->activeline = l;
04991 
04992       /* turn the speaker on */
04993       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04994       transmit_ringer_mode(d, SKINNY_RING_OFF);
04995       transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04996 
04997       l->hookstate = SKINNY_OFFHOOK;
04998 
04999       if (sub && sub->outgoing) {
05000          /* We're answering a ringing call */
05001          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05002          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05003          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
05004          transmit_callstateonly(d, sub, SKINNY_CONNECTED);
05005          transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
05006          transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05007          start_rtp(sub);
05008          ast_setstate(sub->owner, AST_STATE_UP);
05009       } else {
05010          if (sub && sub->owner) {
05011             ast_debug(1, "Current subchannel [%s] already has owner\n", sub->owner->name);
05012          } else {
05013             c = skinny_new(l, AST_STATE_DOWN);
05014             if (c) {
05015                sub = c->tech_pvt;
05016                l->activesub = sub;
05017                transmit_callstate(d, l->instance, SKINNY_OFFHOOK, sub->callid);
05018                if (skinnydebug)
05019                   ast_verb(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
05020                transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
05021                transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05022                transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05023 
05024                /* start the switch thread */
05025                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05026                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05027                   ast_hangup(c);
05028                }
05029             } else {
05030                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05031             }
05032          }
05033       }
05034       break;
05035    default:
05036       if (skinnydebug)
05037          ast_verb(1, "RECEIVED UNKNOWN STIMULUS:  %d(%d/%d)\n", event, instance, callreference);
05038       break;
05039    }
05040    ast_devstate_changed(AST_DEVICE_UNKNOWN, "Skinny/%s@%s", l->name, d->name);
05041 
05042    return 1;
05043 }

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

Definition at line 5307 of file chan_skinny.c.

References ast_localtime(), ast_tvnow(), skinny_req::data, definetimedate_message::day, definetimedate_message::dayofweek, skinny_data::definetimedate, DEFINETIMEDATE_MESSAGE, skinnysession::device, definetimedate_message::hour, htolel, definetimedate_message::milliseconds, definetimedate_message::minute, definetimedate_message::month, req_alloc(), definetimedate_message::seconds, definetimedate_message::timestamp, ast_tm::tm_hour, ast_tm::tm_mday, ast_tm::tm_min, ast_tm::tm_mon, ast_tm::tm_sec, ast_tm::tm_usec, ast_tm::tm_wday, ast_tm::tm_year, transmit_response(), and definetimedate_message::year.

Referenced by handle_message(), and transmit_displaymessage().

05308 {
05309    struct timeval now = ast_tvnow();
05310    struct ast_tm cmtime;
05311 
05312    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
05313       return -1;
05314 
05315    ast_localtime(&now, &cmtime, NULL);
05316    req->data.definetimedate.year = htolel(cmtime.tm_year+1900);
05317    req->data.definetimedate.month = htolel(cmtime.tm_mon+1);
05318    req->data.definetimedate.dayofweek = htolel(cmtime.tm_wday);
05319    req->data.definetimedate.day = htolel(cmtime.tm_mday);
05320    req->data.definetimedate.hour = htolel(cmtime.tm_hour);
05321    req->data.definetimedate.minute = htolel(cmtime.tm_min);
05322    req->data.definetimedate.seconds = htolel(cmtime.tm_sec);
05323    req->data.definetimedate.milliseconds = htolel(cmtime.tm_usec / 1000);
05324    req->data.definetimedate.timestamp = htolel(now.tv_sec);
05325    transmit_response(s->device, req);
05326    return 1;
05327 }

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4449 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_debug, ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verbose, skinny_subchannel::blindxfer, skinny_subchannel::callid, skinny_line::device, errno, KEYDEF_OFFHOOKWITHFEAT, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, skinny_subchannel::related, SKINNY_DIALTONE, skinny_hold(), skinny_new(), SKINNY_OFFHOOK, skinny_ss(), skinny_transfer(), ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_selectsoftkeys(), transmit_tone(), and skinny_subchannel::xferor.

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

04450 {
04451    struct skinny_line *l = sub->parent;
04452    struct skinny_device *d = l->device;
04453    struct skinny_subchannel *newsub;
04454    struct ast_channel *c;
04455    pthread_t t;
04456 
04457    if (!sub) {
04458       ast_verbose("Transfer: No subchannel to transfer\n");
04459       return -1;
04460    }
04461    if (!sub->related) {
04462       /* Another sub has not been created so this must be first XFER press */
04463       if (!sub->onhold) {
04464          skinny_hold(sub);
04465       }
04466       c = skinny_new(l, AST_STATE_DOWN);
04467       if (c) {
04468          newsub = c->tech_pvt;
04469          /* point the sub and newsub at each other so we know they are related */
04470          newsub->related = sub;
04471          sub->related = newsub;
04472          newsub->xferor = 1;
04473          l->activesub = newsub;
04474          transmit_callstate(d, l->instance, SKINNY_OFFHOOK, newsub->callid);
04475          if (skinnydebug)
04476             ast_debug(1, "Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04477          transmit_displaymessage(d, NULL, l->instance, newsub->callid); /* clear display */
04478          transmit_tone(d, SKINNY_DIALTONE, l->instance, newsub->callid);
04479          transmit_selectsoftkeys(d, l->instance, newsub->callid, KEYDEF_OFFHOOKWITHFEAT);
04480          /* start the switch thread */
04481          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04482             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04483             ast_hangup(c);
04484          }
04485       } else {
04486          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04487       }
04488    } else {
04489       /* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
04490       if (sub->blindxfer) {
04491          /* toggle blindxfer off */
04492          sub->blindxfer = 0;
04493          sub->related->blindxfer = 0;
04494          /* we really need some indications */
04495       } else {
04496          /* We were doing attended transfer */
04497          if (sub->owner->_state == AST_STATE_DOWN || sub->related->owner->_state == AST_STATE_DOWN) {
04498             /* one of the subs so we cant transfer yet, toggle blindxfer on */
04499             sub->blindxfer = 1;
04500             sub->related->blindxfer = 1;
04501          } else {
04502             /* big assumption we have two channels, lets transfer */
04503             skinny_transfer(sub);
04504          }
04505       }
04506    }
04507    return 0;
04508 }

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

Definition at line 6021 of file chan_skinny.c.

References skinny_unregister().

Referenced by handle_message().

06022 {
06023    return skinny_unregister(req, s);
06024 }

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

Definition at line 5477 of file chan_skinny.c.

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

Referenced by handle_message().

05478 {
05479    struct skinny_device *d = s->device;
05480    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
05481       return -1;
05482 
05483    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
05484    transmit_response(d, req);
05485    return 1;
05486 }

static int load_module ( void   )  [static]

Definition at line 7282 of file chan_skinny.c.

References ARRAY_LEN, ast_channel_register(), ast_cli_register_multiple(), ast_log(), ast_manager_register2(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_rtp_proto_register(), cli_skinny, config_load(), EVENT_FLAG_REPORTING, EVENT_FLAG_SYSTEM, htolel, io_context_create(), LOG_ERROR, LOG_WARNING, manager_skinny_show_device(), manager_skinny_show_devices(), manager_skinny_show_line(), manager_skinny_show_lines(), mandescr_show_device, mandescr_show_devices, mandescr_show_line, mandescr_show_lines, skinny_req::res, restart_monitor(), sched_context_create(), skinny_rtp, skinny_tech, and soft_key_template_definition::softKeyEvent.

07283 {
07284    int res = 0;
07285 
07286    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
07287       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
07288    }
07289    /* load and parse config */
07290    res = config_load();
07291    if (res == -1) {
07292       return AST_MODULE_LOAD_DECLINE;
07293    }
07294 
07295    /* Make sure we can register our skinny channel type */
07296    if (ast_channel_register(&skinny_tech)) {
07297       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
07298       return -1;
07299    }
07300 
07301    ast_rtp_proto_register(&skinny_rtp);
07302    ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07303 
07304    ast_manager_register2("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices,
07305          "List SKINNY devices (text format)", mandescr_show_devices);
07306    ast_manager_register2("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device,
07307          "Show SKINNY device (text format)", mandescr_show_device);
07308    ast_manager_register2("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines,
07309          "List SKINNY lines (text format)", mandescr_show_lines);
07310    ast_manager_register2("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line,
07311          "Show SKINNY line (text format)", mandescr_show_line);
07312 
07313    sched = sched_context_create();
07314    if (!sched) {
07315       ast_log(LOG_WARNING, "Unable to create schedule context\n");
07316    }
07317    io = io_context_create();
07318    if (!io) {
07319       ast_log(LOG_WARNING, "Unable to create I/O context\n");
07320    }
07321    /* And start the monitor for the first time */
07322    restart_monitor();
07323 
07324    return AST_MODULE_LOAD_SUCCESS;
07325 }

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

Definition at line 3165 of file chan_skinny.c.

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

Referenced by load_module().

03166 {
03167    const char *a[4];
03168    const char *device;
03169 
03170    device = astman_get_header(m, "Device");
03171    if (ast_strlen_zero(device)) {
03172       astman_send_error(s, m, "Device: <name> missing.");
03173       return 0;
03174    }
03175    a[0] = "skinny";
03176    a[1] = "show";
03177    a[2] = "device";
03178    a[3] = device;
03179 
03180    _skinny_show_device(1, -1, s, m, 4, a);
03181    astman_append(s, "\r\n\r\n" );
03182    return 0;
03183 }

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

Show SKINNY devices in the manager API.

Definition at line 3023 of file chan_skinny.c.

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

Referenced by load_module().

03024 {
03025    const char *id = astman_get_header(m, "ActionID");
03026    const char *a[] = {"skinny", "show", "devices"};
03027    char idtext[256] = "";
03028    int total = 0;
03029 
03030    if (!ast_strlen_zero(id))
03031       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03032 
03033    astman_send_listack(s, m, "Device status list will follow", "start");
03034    /* List the devices in separate manager events */
03035    _skinny_show_devices(-1, &total, s, m, 3, a);
03036    /* Send final confirmation */
03037    astman_append(s,
03038    "Event: DevicelistComplete\r\n"
03039    "EventList: Complete\r\n"
03040    "ListItems: %d\r\n"
03041    "%s"
03042    "\r\n", total, idtext);
03043    return 0;
03044 }

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

Definition at line 3475 of file chan_skinny.c.

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

Referenced by load_module().

03476 {
03477    const char *a[4];
03478    const char *line;
03479 
03480    line = astman_get_header(m, "Line");
03481    if (ast_strlen_zero(line)) {
03482       astman_send_error(s, m, "Line: <name> missing.");
03483       return 0;
03484    }
03485    a[0] = "skinny";
03486    a[1] = "show";
03487    a[2] = "line";
03488    a[3] = line;
03489 
03490    _skinny_show_line(1, -1, s, m, 4, a);
03491    astman_append(s, "\r\n\r\n" );
03492    return 0;
03493 }

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

Show Skinny lines in the manager API.

Definition at line 3284 of file chan_skinny.c.

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

Referenced by load_module().

03285 {
03286    const char *id = astman_get_header(m, "ActionID");
03287    const char *a[] = {"skinny", "show", "lines"};
03288    char idtext[256] = "";
03289    int total = 0;
03290 
03291    if (!ast_strlen_zero(id))
03292       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
03293 
03294    astman_send_listack(s, m, "Line status list will follow", "start");
03295    /* List the lines in separate manager events */
03296    _skinny_show_lines(-1, &total, s, m, 3, a);
03297    /* Send final confirmation */
03298    astman_append(s,
03299    "Event: LinelistComplete\r\n"
03300    "EventList: Complete\r\n"
03301    "ListItems: %d\r\n"
03302    "%s"
03303    "\r\n", total, idtext);
03304    return 0;
03305 }

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

Definition at line 2520 of file chan_skinny.c.

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

Referenced by config_line(), and skinny_register().

02521 {
02522    struct skinny_line *l = userdata;
02523    struct skinny_device *d = l->device;
02524    if (d) {
02525       struct skinnysession *s = d->session;
02526       struct skinny_line *l2;
02527       int new_msgs = 0;
02528       int dev_msgs = 0;
02529 
02530       if (s) {
02531          if (event) {
02532             l->newmsgs = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
02533          }
02534 
02535          if (l->newmsgs) {
02536             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02537          } else {
02538             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
02539          }
02540 
02541          /* find out wether the device lamp should be on or off */
02542          AST_LIST_TRAVERSE(&d->lines, l2, list) {
02543             if (l2->newmsgs) {
02544                dev_msgs++;
02545             }
02546          }
02547 
02548          if (dev_msgs) {
02549             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, d->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
02550          } else {
02551             transmit_lamp_indication(d, STIMULUS_VOICEMAIL, 0, SKINNY_LAMP_OFF);
02552          }
02553          ast_verb(3, "Skinny mwi_event_cb found %d new messages\n", new_msgs);
02554       }
02555    }
02556 }

static void print_codec_to_cli ( int  fd,
struct ast_codec_pref pref 
) [static]

Print codec list from preference to CLI/manager.

Definition at line 2928 of file chan_skinny.c.

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

Referenced by _skinny_show_line().

02929 {
02930    int x, codec;
02931 
02932    for(x = 0; x < 32 ; x++) {
02933       codec = ast_codec_pref_index(pref, x);
02934       if (!codec)
02935          break;
02936       ast_cli(fd, "%s", ast_getformatname(codec));
02937       ast_cli(fd, ":%d", pref->framing[x]);
02938       if (x < 31 && ast_codec_pref_index(pref, x + 1))
02939          ast_cli(fd, ",");
02940    }
02941    if (!x)
02942       ast_cli(fd, "none");
02943 }

static void register_exten ( struct skinny_line l  )  [static]

Definition at line 1764 of file chan_skinny.c.

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

Referenced by skinny_register().

01765 {
01766    char multi[256];
01767    char *stringp, *ext, *context;
01768 
01769    if (ast_strlen_zero(regcontext))
01770       return;
01771 
01772    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01773    stringp = multi;
01774    while ((ext = strsep(&stringp, "&"))) {
01775       if ((context = strchr(ext, '@'))) {
01776          *context++ = '\0'; /* split ext@context */
01777          if (!ast_context_find(context)) {
01778             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01779             continue;
01780          }
01781       } else {
01782          context = regcontext;
01783       }
01784       ast_add_extension(context, 1, ext, 1, NULL, NULL, "Noop",
01785           ast_strdup(l->name), ast_free_ptr, "Skinny");
01786    }
01787 }

static int reload ( void   )  [static]

Definition at line 7403 of file chan_skinny.c.

References skinny_reload().

07404 {
07405    skinny_reload();
07406    return 0;
07407 }

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

Definition at line 6452 of file chan_skinny.c.

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

Referenced by load_module(), and skinny_request().

06453 {
06454    /* If we're supposed to be stopped -- stay stopped */
06455    if (monitor_thread == AST_PTHREADT_STOP)
06456       return 0;
06457 
06458    ast_mutex_lock(&monlock);
06459    if (monitor_thread == pthread_self()) {
06460       ast_mutex_unlock(&monlock);
06461       ast_log(LOG_WARNING, "Cannot kill myself\n");
06462       return -1;
06463    }
06464    if (monitor_thread != AST_PTHREADT_NULL) {
06465       /* Wake up the thread */
06466       pthread_kill(monitor_thread, SIGURG);
06467    } else {
06468       /* Start a new monitor */
06469       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06470          ast_mutex_unlock(&monlock);
06471          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06472          return -1;
06473       }
06474    }
06475    ast_mutex_unlock(&monlock);
06476    return 0;
06477 }

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

Definition at line 1706 of file chan_skinny.c.

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

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

01707 {
01708    if (!l)
01709       return 0;
01710 
01711    if (!ast_strlen_zero(cfwd)) {
01712       if (cfwdtype & SKINNY_CFWD_ALL) {
01713          l->cfwdtype |= SKINNY_CFWD_ALL;
01714          ast_copy_string(l->call_forward_all, cfwd, sizeof(l->call_forward_all));
01715       }
01716       if (cfwdtype & SKINNY_CFWD_BUSY) {
01717          l->cfwdtype |= SKINNY_CFWD_BUSY;
01718          ast_copy_string(l->call_forward_busy, cfwd, sizeof(l->call_forward_busy));
01719       }
01720       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01721          l->cfwdtype |= SKINNY_CFWD_NOANSWER;
01722          ast_copy_string(l->call_forward_noanswer, cfwd, sizeof(l->call_forward_noanswer));
01723       }
01724    } else {
01725       if (cfwdtype & SKINNY_CFWD_ALL) {
01726          l->cfwdtype &= ~SKINNY_CFWD_ALL;
01727          memset(l->call_forward_all, 0, sizeof(l->call_forward_all));
01728       }
01729       if (cfwdtype & SKINNY_CFWD_BUSY) {
01730          l->cfwdtype &= ~SKINNY_CFWD_BUSY;
01731          memset(l->call_forward_busy, 0, sizeof(l->call_forward_busy));
01732       }
01733       if (cfwdtype & SKINNY_CFWD_NOANSWER) {
01734          l->cfwdtype &= ~SKINNY_CFWD_NOANSWER;
01735          memset(l->call_forward_noanswer, 0, sizeof(l->call_forward_noanswer));
01736       }
01737    }
01738    return l->cfwdtype;
01739 }

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 3867 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_debug, ast_setstate(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, skinny_subchannel::cxmode, skinny_line::device, KEYDEF_CONNECTED, ast_channel::name, skinny_subchannel::parent, skinny_subchannel::rtp, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_SILENCE, skinny_transfer(), start_rtp(), ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), and transmit_tone().

03868 {
03869    int res = 0;
03870    struct skinny_subchannel *sub = ast->tech_pvt;
03871    struct skinny_line *l = sub->parent;
03872    struct skinny_device *d = l->device;
03873 
03874    if (sub->blindxfer) {
03875       if (skinnydebug)
03876          ast_debug(1, "skinny_answer(%s) on %s@%s-%d with BlindXFER, transferring\n",
03877             ast->name, l->name, d->name, sub->callid);
03878       ast_setstate(ast, AST_STATE_UP);
03879       skinny_transfer(sub);
03880       return 0;
03881    }
03882 
03883    sub->cxmode = SKINNY_CX_SENDRECV;
03884    if (!sub->rtp) {
03885       start_rtp(sub);
03886    }
03887    if (skinnydebug)
03888       ast_verb(1, "skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, d->name, sub->callid);
03889    if (ast->_state != AST_STATE_UP) {
03890       ast_setstate(ast, AST_STATE_UP);
03891    }
03892 
03893    transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03894    /* order matters here...
03895       for some reason, transmit_callinfo must be before transmit_callstate,
03896       or you won't get keypad messages in some situations. */
03897    transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2);
03898    transmit_callstateonly(d, sub, SKINNY_CONNECTED);
03899    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
03900    transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
03901    transmit_displaypromptstatus(d, "Connected", 0, l->instance, sub->callid);
03902    l->activesub = sub;
03903    return res;
03904 }

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

Definition at line 3723 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, AST_CONTROL_BUSY, AST_CONTROL_RINGING, AST_LIST_NEXT, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_verb, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, skinny_line::device, KEYDEF_RINGIN, LOG_ERROR, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_subchannel::parent, SKINNY_ALERT, SKINNY_CALLWAITTONE, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, STIMULUS_LINE, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), and transmit_selectsoftkeys().

03724 {
03725    int res = 0;
03726    int tone = 0;
03727    struct skinny_subchannel *sub = ast->tech_pvt;
03728    struct skinny_line *l = sub->parent;
03729    struct skinny_device *d = l->device;
03730 
03731    if (!d->registered) {
03732       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03733       return -1;
03734    }
03735 
03736    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03737       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
03738       return -1;
03739    }
03740 
03741    if (skinnydebug)
03742       ast_verb(3, "skinny_call(%s)\n", ast->name);
03743 
03744    if (l->dnd) {
03745       ast_queue_control(ast, AST_CONTROL_BUSY);
03746       return -1;
03747    }
03748 
03749    if (AST_LIST_NEXT(sub,list) && !l->callwaiting) {
03750       ast_queue_control(ast, AST_CONTROL_BUSY);
03751       return -1;
03752    }
03753    
03754    switch (l->hookstate) {
03755    case SKINNY_OFFHOOK:
03756       tone = SKINNY_CALLWAITTONE;
03757       break;
03758    case SKINNY_ONHOOK:
03759       tone = SKINNY_ALERT;
03760       l->activesub = sub;
03761       break;
03762    default:
03763       ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
03764       break;
03765    }
03766 
03767    transmit_callstateonly(d, sub, SKINNY_RINGIN);
03768    transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGIN);
03769    transmit_displaypromptstatus(d, "Ring-In", 0, l->instance, sub->callid);
03770    transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
03771    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03772    transmit_ringer_mode(d, SKINNY_RING_INSIDE);
03773 
03774    ast_setstate(ast, AST_STATE_RINGING);
03775    ast_queue_control(ast, AST_CONTROL_RINGING);
03776    sub->outgoing = 1;
03777    return res;
03778 }

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6479 of file chan_skinny.c.

References find_line_by_name(), and get_devicestate().

06480 {
06481    struct skinny_line *l;
06482    char *tmp;
06483 
06484    tmp = ast_strdupa(data);
06485 
06486    l = find_line_by_name(tmp);
06487 
06488    return get_devicestate(l);
06489 }

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

Definition at line 2468 of file chan_skinny.c.

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

Referenced by skinny_register().

02469 {
02470    struct skinny_speeddial *sd = data;
02471    struct skinny_device *d = sd->parent;
02472    char hint[AST_MAX_EXTENSION];
02473    int callstate = SKINNY_CALLREMOTEMULTILINE;
02474    int lamp = SKINNY_LAMP_OFF;
02475 
02476    switch (state) {
02477    case AST_EXTENSION_DEACTIVATED: /* Retry after a while */
02478    case AST_EXTENSION_REMOVED:     /* Extension is gone */
02479       ast_verb(2, "Extension state: Watcher for hint %s %s. Notify Device %s\n", exten, state == AST_EXTENSION_DEACTIVATED ? "deactivated" : "removed", d->name);
02480       sd->stateid = -1;
02481       callstate = SKINNY_ONHOOK;
02482       lamp = SKINNY_LAMP_OFF;
02483       break;
02484    case AST_EXTENSION_RINGING:
02485    case AST_EXTENSION_UNAVAILABLE:
02486       callstate = SKINNY_RINGIN;
02487       lamp = SKINNY_LAMP_BLINK;
02488       break;
02489    case AST_EXTENSION_BUSY: /* callstate = SKINNY_BUSY wasn't wanting to work - I'll settle for this */
02490    case AST_EXTENSION_INUSE:
02491       callstate = SKINNY_CALLREMOTEMULTILINE;
02492       lamp = SKINNY_LAMP_ON;
02493       break;
02494    case AST_EXTENSION_ONHOLD:
02495       callstate = SKINNY_HOLD;
02496       lamp = SKINNY_LAMP_WINK;
02497       break;
02498    case AST_EXTENSION_NOT_INUSE:
02499    default:
02500       callstate = SKINNY_ONHOOK;
02501       lamp = SKINNY_LAMP_OFF;
02502       break;
02503    }
02504 
02505    if (ast_get_hint(hint, sizeof(hint), NULL, 0, NULL, sd->context, sd->exten)) {
02506       /* If they are not registered, we will override notification and show no availability */
02507       if (ast_device_state(hint) == AST_DEVICE_UNAVAILABLE) {
02508          callstate = SKINNY_ONHOOK;
02509          lamp = SKINNY_LAMP_FLASH;
02510       }
02511    }
02512 
02513    transmit_lamp_indication(d, STIMULUS_LINE, sd->instance, lamp);
02514    transmit_callstate(d, sd->instance, callstate, 0);
02515    sd->laststate = state;
02516 
02517    return 0;
02518 }

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

Definition at line 3992 of file chan_skinny.c.

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

03993 {
03994    struct skinny_subchannel *sub = newchan->tech_pvt;
03995    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
03996    if (sub->owner != oldchan) {
03997       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
03998       return -1;
03999    }
04000    sub->owner = newchan;
04001    return 0;
04002 }

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

Definition at line 2573 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, AST_RTP_TRY_PARTIAL, ast_verb, skinny_subchannel::lock, ast_channel::name, skinny_subchannel::parent, skinny_subchannel::rtp, and ast_channel::tech_pvt.

02574 {
02575    struct skinny_subchannel *sub = NULL;
02576    struct skinny_line *l;
02577    enum ast_rtp_get_result res = AST_RTP_TRY_NATIVE;
02578 
02579    if (skinnydebug)
02580       ast_verb(1, "skinny_get_rtp_peer() Channel = %s\n", c->name);
02581 
02582 
02583    if (!(sub = c->tech_pvt))
02584       return AST_RTP_GET_FAILED;
02585 
02586    ast_mutex_lock(&sub->lock);
02587 
02588    if (!(sub->rtp)){
02589       ast_mutex_unlock(&sub->lock);
02590       return AST_RTP_GET_FAILED;
02591    }
02592    
02593    *rtp = sub->rtp;
02594 
02595    l = sub->parent;
02596 
02597    if (!l->directmedia || l->nat){
02598       res = AST_RTP_TRY_PARTIAL;
02599       if (skinnydebug)
02600          ast_verb(1, "skinny_get_rtp_peer() Using AST_RTP_TRY_PARTIAL \n");
02601    }
02602 
02603    ast_mutex_unlock(&sub->lock);
02604 
02605    return res;
02606 
02607 }

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

Definition at line 2561 of file chan_skinny.c.

References AST_RTP_GET_FAILED, AST_RTP_TRY_NATIVE, ast_channel::tech_pvt, and skinny_subchannel::vrtp.

02562 {
02563    struct skinny_subchannel *sub = NULL;
02564 
02565    if (!(sub = c->tech_pvt) || !(sub->vrtp))
02566       return AST_RTP_GET_FAILED;
02567 
02568    *rtp = sub->vrtp;
02569 
02570    return AST_RTP_TRY_NATIVE;
02571 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3780 of file chan_skinny.c.

References skinny_device::activeline, skinny_line::activesub, skinny_subchannel::alreadygone, ast_debug, ast_free, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_NEXT, AST_LIST_REMOVE, ast_module_unref(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_verb, skinny_subchannel::callid, skinny_line::device, skinny_subchannel::lock, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, skinny_subchannel::related, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_closereceivechannel(), transmit_displaymessage(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

03781 {
03782    struct skinny_subchannel *sub = ast->tech_pvt;
03783    struct skinny_line *l;
03784    struct skinny_device *d;
03785    struct skinnysession *s;
03786 
03787    if (!sub) {
03788       ast_debug(1, "Asked to hangup channel not connected\n");
03789       return 0;
03790    }
03791 
03792    l = sub->parent;
03793    d = l->device;
03794    s = d->session;
03795 
03796    if (skinnydebug)
03797       ast_verb(3,"Hanging up %s/%d\n",d->name,sub->callid);
03798 
03799    AST_LIST_REMOVE(&l->sub, sub, list);
03800 
03801    if (d->registered) {
03802       /* Ignoring l->type, doesn't seem relevant and previous code 
03803          assigned rather than tested, ie always true */
03804       if (!AST_LIST_EMPTY(&l->sub)) {
03805          if (sub->related) {
03806             sub->related->related = NULL;
03807 
03808          }
03809          if (sub == l->activesub) {      /* we are killing the active sub, but there are other subs on the line*/
03810             ast_verb(4,"Killing active sub %d\n", sub->callid);
03811             if (sub->related) {
03812                l->activesub = sub->related;
03813             } else {
03814                if (AST_LIST_NEXT(sub, list)) {
03815                   l->activesub = AST_LIST_NEXT(sub, list);
03816                } else {
03817                   l->activesub = AST_LIST_FIRST(&l->sub);
03818                }
03819             }
03820             //transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
03821             transmit_activatecallplane(d, l);
03822             transmit_closereceivechannel(d, sub);
03823             transmit_stopmediatransmission(d, sub);
03824             transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03825             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03826          } else {    /* we are killing a background sub on the line with other subs*/
03827             ast_verb(4,"Killing inactive sub %d\n", sub->callid);
03828             if (AST_LIST_NEXT(sub, list)) {
03829                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03830             } else {
03831                transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03832             }
03833          }
03834       } else {                                                /* no more subs on line so make idle */
03835          ast_verb(4,"Killing only sub %d\n", sub->callid);
03836          l->hookstate = SKINNY_ONHOOK;
03837          transmit_callstate(d, l->instance, SKINNY_ONHOOK, sub->callid);
03838          l->activesub = NULL;
03839          transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
03840          if (sub->parent == d->activeline) {
03841             transmit_activatecallplane(d, l);
03842             transmit_closereceivechannel(d, sub);
03843             transmit_stopmediatransmission(d, sub);
03844             transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
03845             transmit_ringer_mode(d, SKINNY_RING_OFF);
03846             transmit_displaymessage(d, NULL, l->instance, sub->callid); /* clear display */
03847             transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03848             /* we should check to see if we can start the ringer if another line is ringing */
03849          }
03850       }
03851    }
03852    ast_mutex_lock(&sub->lock);
03853    sub->owner = NULL;
03854    ast->tech_pvt = NULL;
03855    sub->alreadygone = 0;
03856    sub->outgoing = 0;
03857    if (sub->rtp) {
03858       ast_rtp_destroy(sub->rtp);
03859       sub->rtp = NULL;
03860    }
03861    ast_mutex_unlock(&sub->lock);
03862    ast_free(sub);
03863    ast_module_unref(ast_module_info->self);
03864    return 0;
03865 }

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 4377 of file chan_skinny.c.

References AST_CONTROL_HOLD, ast_queue_control_data(), ast_strlen_zero(), ast_verb, skinny_line::device, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, S_OR, SKINNY_HOLD, SKINNY_LAMP_WINK, STIMULUS_LINE, transmit_activatecallplane(), transmit_callstateonly(), transmit_closereceivechannel(), transmit_lamp_indication(), and transmit_stopmediatransmission().

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

04378 {
04379    struct skinny_line *l = sub->parent;
04380    struct skinny_device *d = l->device;
04381 
04382    /* Don't try to hold a channel that doesn't exist */
04383    if (!sub || !sub->owner)
04384       return 0;
04385 
04386    /* Channel needs to be put on hold */
04387    if (skinnydebug)
04388       ast_verb(1, "Putting on Hold(%d)\n", l->instance);
04389 
04390    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
04391       S_OR(l->mohsuggest, NULL),
04392       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
04393 
04394    transmit_activatecallplane(d, l);
04395    transmit_closereceivechannel(d, sub);
04396    transmit_stopmediatransmission(d, sub);
04397 
04398    transmit_callstateonly(d, sub, SKINNY_HOLD);
04399    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
04400    sub->onhold = 1;
04401    return 1;
04402 }

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

Definition at line 4169 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_debug, ast_log(), ast_moh_start(), ast_moh_stop(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_verb, skinny_subchannel::blindxfer, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, control2str(), skinny_line::device, LOG_NOTICE, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_subchannel::parent, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, skinny_transfer(), ast_channel::tech_pvt, transmit_callinfo(), transmit_callstateonly(), transmit_dialednumber(), transmit_displaypromptstatus(), and transmit_tone().

04170 {
04171    struct skinny_subchannel *sub = ast->tech_pvt;
04172    struct skinny_line *l = sub->parent;
04173    struct skinny_device *d = l->device;
04174    struct skinnysession *s = d->session;
04175 
04176    if (!s) {
04177       ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
04178       return -1;
04179    }
04180 
04181    if (skinnydebug)
04182       ast_verb(3, "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
04183    switch(ind) {
04184    case AST_CONTROL_RINGING:
04185       if (sub->blindxfer) {
04186          if (skinnydebug)
04187             ast_debug(1, "Channel %s set up for Blind Xfer, so Xfer rather than ring device\n", ast->name);
04188          skinny_transfer(sub);
04189          break;
04190       }
04191       if (ast->_state != AST_STATE_UP) {
04192          if (!sub->progress) {
04193             if (!d->earlyrtp) {
04194                transmit_tone(d, SKINNY_ALERT, l->instance, sub->callid);
04195             }
04196             transmit_callstateonly(d, sub, SKINNY_RINGOUT);
04197             transmit_dialednumber(d, l->lastnumberdialed, l->instance, sub->callid);
04198             transmit_displaypromptstatus(d, "Ring Out", 0, l->instance, sub->callid);
04199             transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
04200             sub->ringing = 1;
04201             if (!d->earlyrtp) {
04202                break;
04203             }
04204          }
04205       }
04206       return -1; /* Tell asterisk to provide inband signalling */
04207    case AST_CONTROL_BUSY:
04208       if (ast->_state != AST_STATE_UP) {
04209          if (!d->earlyrtp) {
04210             transmit_tone(d, SKINNY_BUSYTONE, l->instance, sub->callid);
04211          }
04212          transmit_callstateonly(d, sub, SKINNY_BUSY);
04213          sub->alreadygone = 1;
04214          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
04215          if (!d->earlyrtp) {
04216             break;
04217          }
04218       }
04219       return -1; /* Tell asterisk to provide inband signalling */
04220    case AST_CONTROL_CONGESTION:
04221       if (ast->_state != AST_STATE_UP) {
04222          if (!d->earlyrtp) {
04223             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
04224          }
04225          transmit_callstateonly(d, sub, SKINNY_CONGESTION);
04226          sub->alreadygone = 1;
04227          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
04228          if (!d->earlyrtp) {
04229             break;
04230          }
04231       }
04232       return -1; /* Tell asterisk to provide inband signalling */
04233    case AST_CONTROL_PROGRESS:
04234       if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
04235          if (!d->earlyrtp) {
04236             transmit_tone(d, SKINNY_ALERT, l->instance, sub->callid);
04237          }
04238          transmit_callstateonly(d, sub, SKINNY_PROGRESS);
04239          transmit_displaypromptstatus(d, "Call Progress", 0, l->instance, sub->callid);
04240          transmit_callinfo(d, ast->cid.cid_name, ast->cid.cid_num, l->lastnumberdialed, l->lastnumberdialed, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
04241          sub->progress = 1;
04242          if (!d->earlyrtp) {
04243             break;
04244          }
04245       }
04246       return -1; /* Tell asterisk to provide inband signalling */
04247    case -1:  /* STOP_TONE */
04248       transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
04249       break;
04250    case AST_CONTROL_HOLD:
04251       ast_moh_start(ast, data, l->mohinterpret);
04252       break;
04253    case AST_CONTROL_UNHOLD:
04254       ast_moh_stop(ast);
04255       break;
04256    case AST_CONTROL_PROCEEDING:
04257       break;
04258    case AST_CONTROL_SRCUPDATE:
04259       ast_rtp_new_source(sub->rtp);
04260       break;
04261    default:
04262       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
04263       return -1; /* Tell asterisk to provide inband signalling */
04264    }
04265    return 0;
04266 }

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

Definition at line 4268 of file chan_skinny.c.

References accountcode, ast_channel::adsicpe, ast_channel::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), AST_DEVICE_NOT_INUSE, ast_hangup(), ast_jb_configure(), AST_LIST_INSERT_HEAD, ast_log(), ast_module_ref(), ast_mutex_init(), ast_pbx_start(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, skinny_subchannel::blindxfer, ast_channel::callgroup, skinny_subchannel::callid, skinny_line::chanvars, ast_channel::cid, ast_callerid::cid_ani, ast_channel::context, skinny_subchannel::cxmode, skinny_line::device, ast_channel::exten, get_devicestate(), global_jbconf, language, skinny_subchannel::lock, LOG_WARNING, ast_channel::name, ast_variable::name, skinny_subchannel::nat, ast_channel::nativeformats, ast_variable::next, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, parkinglot, pbx_builtin_setvar_helper(), ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, skinny_subchannel::related, ast_channel::rings, skinny_subchannel::rtp, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, skinny_tech, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, ast_variable::value, ast_channel::writeformat, and skinny_subchannel::xferor.

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

04269 {
04270    struct ast_channel *tmp;
04271    struct skinny_subchannel *sub;
04272    struct skinny_device *d = l->device;
04273    struct ast_variable *v = NULL;
04274    int fmt;
04275 
04276    if (!l->device) {
04277       ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
04278       return NULL;
04279    }
04280 
04281    tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
04282    if (!tmp) {
04283       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
04284       return NULL;
04285    } else {
04286       sub = ast_calloc(1, sizeof(*sub));
04287       if (!sub) {
04288          ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
04289          return NULL;
04290       } else {
04291          ast_mutex_init(&sub->lock);
04292 
04293          sub->owner = tmp;
04294          sub->callid = callnums++;
04295          d->lastlineinstance = l->instance;
04296          d->lastcallreference = sub->callid;
04297          sub->cxmode = SKINNY_CX_INACTIVE;
04298          sub->nat = l->nat;
04299          sub->parent = l;
04300          sub->onhold = 0;
04301          sub->blindxfer = 0;
04302          sub->xferor = 0;
04303          sub->related = NULL;
04304 
04305          AST_LIST_INSERT_HEAD(&l->sub, sub, list);
04306          //l->activesub = sub;
04307       }
04308       tmp->tech = &skinny_tech;
04309       tmp->tech_pvt = sub;
04310       tmp->nativeformats = l->capability;
04311       if (!tmp->nativeformats)
04312          // Should throw an error
04313          tmp->nativeformats = default_capability;
04314       fmt = ast_best_codec(tmp->nativeformats);
04315       if (skinnydebug)
04316          ast_verb(1, "skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
04317       if (sub->rtp) {
04318          ast_channel_set_fd(tmp, 0, ast_rtp_fd(sub->rtp));
04319       }
04320       if (state == AST_STATE_RING) {
04321          tmp->rings = 1;
04322       }
04323       tmp->writeformat = fmt;
04324       tmp->rawwriteformat = fmt;
04325       tmp->readformat = fmt;
04326       tmp->rawreadformat = fmt;
04327       if (!ast_strlen_zero(l->language))
04328          ast_string_field_set(tmp, language, l->language);
04329       if (!ast_strlen_zero(l->accountcode))
04330          ast_string_field_set(tmp, accountcode, l->accountcode);
04331       if (!ast_strlen_zero(l->parkinglot))
04332          ast_string_field_set(tmp, parkinglot, l->parkinglot);
04333       if (l->amaflags)
04334          tmp->amaflags = l->amaflags;
04335 
04336       ast_module_ref(ast_module_info->self);
04337       tmp->callgroup = l->callgroup;
04338       tmp->pickupgroup = l->pickupgroup;
04339 
04340       /* XXX Need to figure out how to handle CFwdNoAnswer */
04341       if (l->cfwdtype & SKINNY_CFWD_ALL) {
04342          ast_string_field_set(tmp, call_forward, l->call_forward_all);
04343       } else if (l->cfwdtype & SKINNY_CFWD_BUSY) {
04344          if (get_devicestate(l) != AST_DEVICE_NOT_INUSE) {
04345             ast_string_field_set(tmp, call_forward, l->call_forward_busy);
04346          }
04347       }
04348 
04349       ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
04350       ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
04351 
04352       /* Don't use ast_set_callerid() here because it will
04353        * generate a needless NewCallerID event */
04354       tmp->cid.cid_ani = ast_strdup(l->cid_num);
04355 
04356       tmp->priority = 1;
04357       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04358 
04359       if (sub->rtp)
04360          ast_jb_configure(tmp, &global_jbconf);
04361 
04362       /* Set channel variables for this call from configuration */
04363       for (v = l->chanvars ; v ; v = v->next)
04364          pbx_builtin_setvar_helper(tmp, v->name, v->value);
04365 
04366       if (state != AST_STATE_DOWN) {
04367          if (ast_pbx_start(tmp)) {
04368             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04369             ast_hangup(tmp);
04370             tmp = NULL;
04371          }
04372       }
04373    }
04374    return tmp;
04375 }

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

Definition at line 3594 of file chan_skinny.c.

References ast_copy_string(), ast_log(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_ani, skinny_line::device, ast_channel::exten, LOG_WARNING, skinny_subchannel::parent, skinny_subchannel::rtp, SKINNY_REORDER, start_rtp(), ast_channel::tech_pvt, and transmit_tone().

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

03595 {
03596    struct ast_channel *c = data;
03597    struct skinny_subchannel *sub = c->tech_pvt;
03598    struct skinny_line *l = sub->parent;
03599    struct skinny_device *d = l->device;
03600    int res = 0;
03601 
03602    ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
03603    ast_set_callerid(c,
03604       l->hidecallerid ? "" : l->cid_num,
03605       l->hidecallerid ? "" : l->cid_name,
03606       c->cid.cid_ani ? NULL : l->cid_num);
03607    ast_setstate(c, AST_STATE_RING);
03608    if (!sub->rtp) {
03609       start_rtp(sub);
03610    }
03611    res = ast_pbx_run(c);
03612    if (res) {
03613       ast_log(LOG_WARNING, "PBX exited non-zero\n");
03614       transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03615    }
03616    return NULL;
03617 }

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

Definition at line 3954 of file chan_skinny.c.

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

03955 {
03956    struct ast_frame *fr;
03957    struct skinny_subchannel *sub = ast->tech_pvt;
03958    ast_mutex_lock(&sub->lock);
03959    fr = skinny_rtp_read(sub);
03960    ast_mutex_unlock(&sub->lock);
03961    return fr;
03962 }

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

Definition at line 1813 of file chan_skinny.c.

References __ourip, ast_app_has_voicemail(), ast_apply_ha(), ast_copy_string(), AST_DEVICE_NOT_INUSE, ast_devstate_changed(), ast_extension_state_add(), AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_strlen_zero(), ast_verb, skinny_speeddial::context, skinny_req::data, skinny_line::device, skinnysession::device, skinny_speeddial::exten, skinnysession::fd, skinny_device::ha, letohl, skinny_device::lines, LOG_WARNING, mwi_event_cb(), register_message::name, skinny_line::newmsgs, skinny_device::ourip, skinny_data::reg, register_exten(), skinny_device::session, set_callforwards(), skinnysession::sin, skinny_extensionstate_cb(), skinny_device::speeddials, skinny_speeddial::stateid, and register_message::type.

Referenced by handle_register_message().

01814 {
01815    struct skinny_device *d;
01816    struct skinny_line *l;
01817    struct skinny_speeddial *sd;
01818    struct sockaddr_in sin;
01819    socklen_t slen;
01820    int instance;
01821 
01822    AST_LIST_LOCK(&devices);
01823    AST_LIST_TRAVERSE(&devices, d, list){
01824       if (!strcasecmp(req->data.reg.name, d->id)
01825             && ast_apply_ha(d->ha, &(s->sin))) {
01826          s->device = d;
01827          d->type = letohl(req->data.reg.type);
01828          if (ast_strlen_zero(d->version_id)) {
01829             ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
01830          }
01831          d->registered = 1;
01832          d->session = s;
01833 
01834          slen = sizeof(sin);
01835          if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
01836             ast_log(LOG_WARNING, "Cannot get socket name\n");
01837             sin.sin_addr = __ourip;
01838          }
01839          d->ourip = sin.sin_addr;
01840 
01841          AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01842             sd->stateid = ast_extension_state_add(sd->context, sd->exten, skinny_extensionstate_cb, sd);
01843          }
01844          instance = 0;
01845          AST_LIST_TRAVERSE(&d->lines, l, list) {
01846             instance++;
01847          }
01848          AST_LIST_TRAVERSE(&d->lines, l, list) {
01849             /* FIXME: All sorts of issues will occur if this line is already connected to a device */
01850             if (l->device) {
01851                ast_verb(1, "Line %s already connected to %s. Not connecting to %s.\n", l->name, l->device->name, d->name);
01852             } else {
01853                l->device = d;
01854                l->capability = l->confcapability & d->capability;
01855                l->prefs = l->confprefs;
01856                if (!l->prefs.order[0]) {
01857                   l->prefs = d->confprefs;
01858                }
01859                /* l->capability = d->capability;
01860                l->prefs = d->prefs; */
01861                l->instance = instance;
01862                l->newmsgs = ast_app_has_voicemail(l->mailbox, NULL);
01863                set_callforwards(l, NULL, 0);
01864                register_exten(l);
01865                /* initialize MWI on line and device */
01866                mwi_event_cb(0, l);
01867                ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
01868             }
01869             --instance;
01870          }
01871          break;
01872       }
01873    }
01874    AST_LIST_UNLOCK(&devices);
01875    if (!d) {
01876       return 0;
01877    }
01878    return 1;
01879 }

int skinny_reload ( void   )  [static]

Definition at line 7200 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_REMOVE_CURRENT, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_verb, config_load(), skinny_req::data, free, skinny_device::lines, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, skinny_device::session, skinny_device::speeddials, and transmit_response().

Referenced by handle_skinny_reload(), and reload().

07201 {
07202    struct skinny_device *d;
07203    struct skinny_line *l;
07204    struct skinny_speeddial *sd;
07205    struct skinny_addon *a;
07206    struct skinny_req *req;
07207 
07208    if (skinnyreload) {
07209       ast_verb(3, "Chan_skinny is already reloading.\n");
07210       return 0;
07211    }
07212 
07213    skinnyreload = 1;
07214 
07215    /* Mark all devices and lines as candidates to be pruned */
07216    AST_LIST_LOCK(&devices);
07217    AST_LIST_TRAVERSE(&devices, d, list) {
07218       d->prune = 1;
07219    }
07220    AST_LIST_UNLOCK(&devices);
07221 
07222    AST_LIST_LOCK(&lines);
07223    AST_LIST_TRAVERSE(&lines, l, all) {
07224       l->prune = 1;
07225    }
07226    AST_LIST_UNLOCK(&lines);
07227 
07228         config_load();
07229 
07230    /* Remove any devices that no longer exist in the config */
07231    AST_LIST_LOCK(&devices);
07232    AST_LIST_TRAVERSE_SAFE_BEGIN(&devices, d, list) {
07233       if (!d->prune) {
07234          continue;
07235       }
07236       ast_verb(3, "Removing device '%s'\n", d->name);
07237       /* Delete all lines for this device. 
07238          We do not want to free the line here, that
07239          will happen below. */
07240       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07241       }
07242       /* Delete all speeddials for this device */
07243       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07244          free(sd);
07245       }
07246       /* Delete all addons for this device */
07247       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07248          free(a);
07249       }
07250       AST_LIST_REMOVE_CURRENT(list);
07251       free(d);
07252    }
07253    AST_LIST_TRAVERSE_SAFE_END;
07254    AST_LIST_UNLOCK(&devices);
07255 
07256    AST_LIST_LOCK(&lines);  
07257    AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) {
07258       if (l->prune) {
07259          AST_LIST_REMOVE_CURRENT(all);
07260          free(l);
07261       }
07262    }
07263    AST_LIST_TRAVERSE_SAFE_END;
07264    AST_LIST_UNLOCK(&lines);  
07265 
07266    AST_LIST_TRAVERSE(&devices, d, list) {
07267       /* Do a soft reset to re-register the devices after
07268          cleaning up the removed devices and lines */
07269       if (d->session) {
07270          ast_verb(3, "Restarting device '%s'\n", d->name);
07271          if ((req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE))) {
07272             req->data.reset.resetType = 2;
07273             transmit_response(d, req);
07274          }
07275       }
07276    }
07277    
07278    skinnyreload = 0;
07279         return 0;
07280 }

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

Definition at line 6324 of file chan_skinny.c.

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

Referenced by skinny_session().

06325 {
06326    struct skinny_req *req;
06327    int *bufaddr;
06328 
06329    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
06330       return NULL;
06331 
06332    ast_mutex_lock(&s->lock);
06333    memcpy(req, s->inbuf, skinny_header_size);
06334    bufaddr = (int *)(s->inbuf);
06335    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
06336 
06337    ast_mutex_unlock(&s->lock);
06338 
06339    if (letohl(req->e) < 0) {
06340       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
06341       ast_free(req);
06342       return NULL;
06343    }
06344 
06345    return req;
06346 }

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

Definition at line 6491 of file chan_skinny.c.

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

06492 {
06493    int oldformat;
06494    
06495    struct skinny_line *l;
06496    struct ast_channel *tmpc = NULL;
06497    char tmp[256];
06498    char *dest = data;
06499 
06500    oldformat = format;
06501    
06502    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
06503       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
06504       return NULL;
06505    }
06506 
06507    ast_copy_string(tmp, dest, sizeof(tmp));
06508    if (ast_strlen_zero(tmp)) {
06509       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
06510       return NULL;
06511    }
06512    l = find_line_by_name(tmp);
06513    if (!l) {
06514       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
06515       return NULL;
06516    }
06517    ast_verb(3, "skinny_request(%s)\n", tmp);
06518    tmpc = skinny_new(l, AST_STATE_DOWN);
06519    if (!tmpc) {
06520       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
06521    }
06522    restart_monitor();
06523    return tmpc;
06524 }

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

Definition at line 3907 of file chan_skinny.c.

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

Referenced by skinny_read().

03908 {
03909    struct ast_channel *ast = sub->owner;
03910    struct ast_frame *f;
03911 
03912    if (!sub->rtp) {
03913       /* We have no RTP allocated for this channel */
03914       return &ast_null_frame;
03915    }
03916 
03917    switch(ast->fdno) {
03918    case 0:
03919       f = ast_rtp_read(sub->rtp); /* RTP Audio */
03920       break;
03921    case 1:
03922       f = ast_rtcp_read(sub->rtp); /* RTCP Control Channel */
03923       break;
03924    case 2:
03925       f = ast_rtp_read(sub->vrtp); /* RTP Video */
03926       break;
03927    case 3:
03928       f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
03929       break;
03930 #if 0
03931    case 5:
03932       /* Not yet supported */
03933       f = ast_udptl_read(sub->udptl); /* UDPTL for T.38 */
03934       break;
03935 #endif
03936    default:
03937       f = &ast_null_frame;
03938    }
03939 
03940    if (ast) {
03941       /* We already hold the channel lock */
03942       if (f->frametype == AST_FRAME_VOICE) {
03943          if (f->subclass != ast->nativeformats) {
03944             ast_debug(1, "Oooh, format changed to %d\n", f->subclass);
03945             ast->nativeformats = f->subclass;
03946             ast_set_read_format(ast, ast->readformat);
03947             ast_set_write_format(ast, ast->writeformat);
03948          }
03949       }
03950    }
03951    return f;
03952 }

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

Definition at line 4004 of file chan_skinny.c.

04005 {
04006    return -1; /* Start inband indications */
04007 }

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

Definition at line 4009 of file chan_skinny.c.

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

04010 {
04011 #if 0
04012    struct skinny_subchannel *sub = ast->tech_pvt;
04013    struct skinny_line *l = sub->parent;
04014    struct skinny_device *d = l->device;
04015    int tmp;
04016    /* not right */
04017    sprintf(tmp, "%d", digit);
04018    transmit_tone(d, digit, l->instance, sub->callid);
04019 #endif
04020    return -1; /* Stop inband indications */
04021 }

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

Definition at line 6348 of file chan_skinny.c.

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

Referenced by accept_thread().

06349 {
06350    int res;
06351    struct skinny_req *req;
06352    struct skinnysession *s = data;
06353 
06354    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
06355 
06356    for (;;) {
06357       res = get_input(s);
06358       if (res < 0) {
06359          break;
06360       }
06361 
06362       if (res > 0)
06363       {
06364          if (!(req = skinny_req_parse(s))) {
06365             destroy_session(s);
06366             return NULL;
06367          }
06368 
06369          res = handle_message(req, s);
06370          if (res < 0) {
06371             destroy_session(s);
06372             return NULL;
06373          }
06374       }
06375    }
06376    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06377 
06378    if (s) 
06379       destroy_session(s);
06380    
06381    return 0;
06382 }

static int skinny_set_rtp_peer ( struct ast_channel c,
struct ast_rtp rtp,
struct ast_rtp vrtp,
struct ast_rtp trtp,
int  codecs,
int  nat_active 
) [static]

Definition at line 2609 of file chan_skinny.c.

References ast_channel::_state, ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_rtp_get_peer(), ast_rtp_get_us(), AST_STATE_UP, ast_verb, media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, codec_ast2skinny(), start_media_transmission_message::conferenceId, stop_media_transmission_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, skinny_line::device, htolel, skinny_device::ourip, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_subchannel::parent, start_media_transmission_message::passThruPartyId, stop_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, media_qualifier::precedence, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), s, skinny_device::session, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, ast_channel::tech_pvt, transmit_response(), and media_qualifier::vad.

02610 {
02611    struct skinny_subchannel *sub;
02612    struct skinny_line *l;
02613    struct skinny_device *d;
02614    struct skinnysession *s;
02615    struct ast_format_list fmt;
02616    struct sockaddr_in us;
02617    struct sockaddr_in them;
02618    struct skinny_req *req;
02619    
02620    sub = c->tech_pvt;
02621 
02622    if (c->_state != AST_STATE_UP)
02623       return 0;
02624 
02625    if (!sub) {
02626       return -1;
02627    }
02628 
02629    l = sub->parent;
02630    d = l->device;
02631    s = d->session;
02632 
02633    if (rtp){
02634       ast_rtp_get_peer(rtp, &them);
02635 
02636       /* Shutdown any early-media or previous media on re-invite */
02637       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02638          return -1;
02639 
02640       req->data.stopmedia.conferenceId = htolel(sub->callid);
02641       req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02642       transmit_response(d, req);
02643 
02644       if (skinnydebug)
02645          ast_verb(1, "Peerip = %s:%d\n", ast_inet_ntoa(them.sin_addr), ntohs(them.sin_port));
02646 
02647       if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
02648          return -1;
02649 
02650       fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
02651 
02652       if (skinnydebug)
02653          ast_verb(1, "Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
02654 
02655       req->data.startmedia.conferenceId = htolel(sub->callid);
02656       req->data.startmedia.passThruPartyId = htolel(sub->callid);
02657       if (!(l->directmedia) || (l->nat)){
02658          ast_rtp_get_us(rtp, &us);
02659          req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
02660          req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
02661       } else {
02662          req->data.startmedia.remoteIp = htolel(them.sin_addr.s_addr);
02663          req->data.startmedia.remotePort = htolel(ntohs(them.sin_port));
02664       }
02665       req->data.startmedia.packetSize = htolel(fmt.cur_ms);
02666       req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
02667       req->data.startmedia.qualifier.precedence = htolel(127);
02668       req->data.startmedia.qualifier.vad = htolel(0);
02669       req->data.startmedia.qualifier.packets = htolel(0);
02670       req->data.startmedia.qualifier.bitRate = htolel(0);
02671       transmit_response(d, req);
02672 
02673       return 0;
02674    }
02675    /* Need a return here to break the bridge */
02676    return 0;
02677 }

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

Definition at line 3619 of file chan_skinny.c.

References ast_channel::_state, ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_safe_sleep(), AST_STATE_UP, ast_strlen_zero(), ast_verb, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_num, ast_channel::context, skinny_line::device, ast_channel::exten, len(), LOG_WARNING, ast_channel::name, skinny_subchannel::owner, skinny_subchannel::parent, set_callforwards(), SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_newcall(), SKINNY_OFFHOOK, SKINNY_REORDER, SKINNY_SILENCE, STIMULUS_FORWARDALL, ast_channel::tech_pvt, transmit_cfwdstate(), transmit_displaynotify(), transmit_lamp_indication(), and transmit_tone().

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

03620 {
03621    struct ast_channel *c = data;
03622    struct skinny_subchannel *sub = c->tech_pvt;
03623    struct skinny_line *l = sub->parent;
03624    struct skinny_device *d = l->device;
03625    int len = 0;
03626    int timeout = firstdigittimeout;
03627    int res = 0;
03628    int loop_pause = 100;
03629 
03630    ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
03631 
03632    len = strlen(d->exten);
03633 
03634    while (len < AST_MAX_EXTENSION-1) {
03635       res = 1;  /* Assume that we will get a digit */
03636       while (strlen(d->exten) == len){
03637          ast_safe_sleep(c, loop_pause);
03638          timeout -= loop_pause;
03639          if ( (timeout -= loop_pause) <= 0){
03640              res = 0;
03641              break;
03642          }
03643       res = 1;
03644       }
03645 
03646       timeout = 0;
03647       len = strlen(d->exten);
03648 
03649       if (!ast_ignore_pattern(c->context, d->exten)) {
03650          transmit_tone(d, SKINNY_SILENCE, l->instance, sub->callid);
03651       }
03652       if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
03653          if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
03654             if (l->getforward) {
03655                /* Record this as the forwarding extension */
03656                set_callforwards(l, d->exten, l->getforward);
03657                ast_verb(3, "Setting call forward (%d) to '%s' on channel %s\n",
03658                      l->cfwdtype, d->exten, c->name);
03659                transmit_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
03660                transmit_lamp_indication(d, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
03661                transmit_displaynotify(d, "CFwd enabled", 10);
03662                transmit_cfwdstate(d, l);
03663                ast_safe_sleep(c, 500);
03664                ast_indicate(c, -1);
03665                ast_safe_sleep(c, 1000);
03666                memset(d->exten, 0, sizeof(d->exten));
03667                len = 0;
03668                l->getforward = 0;
03669                if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03670                   ast_indicate(c, -1);
03671                   ast_hangup(c);
03672                }
03673                return NULL;
03674             } else {
03675                ast_copy_string(c->exten, d->exten, sizeof(c->exten));
03676                ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
03677                memset(d->exten, 0, sizeof(d->exten));
03678                skinny_newcall(c);
03679                return NULL;
03680             }
03681          } else {
03682             /* It's a match, but they just typed a digit, and there is an ambiguous match,
03683                so just set the timeout to matchdigittimeout and wait some more */
03684             timeout = matchdigittimeout;
03685          }
03686       } else if (res == 0) {
03687          ast_debug(1, "Not enough digits (%s) (and no ambiguous match)...\n", d->exten);
03688          memset(d->exten, 0, sizeof(d->exten));
03689          if (l->hookstate == SKINNY_OFFHOOK) {
03690             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03691          }
03692          if (sub->owner && sub->owner->_state != AST_STATE_UP) {
03693             ast_indicate(c, -1);
03694             ast_hangup(c);
03695          }
03696          return NULL;
03697       } else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
03698             ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
03699          ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
03700          memset(d->exten, 0, sizeof(d->exten));
03701          if (l->hookstate == SKINNY_OFFHOOK) {
03702             transmit_tone(d, SKINNY_REORDER, l->instance, sub->callid);
03703             /* hang out for 3 seconds to let congestion play */
03704             ast_safe_sleep(c, 3000);
03705          }
03706          break;
03707       }
03708       if (!timeout) {
03709          timeout = gendigittimeout;
03710       }
03711       if (len && !ast_ignore_pattern(c->context, d->exten)) {
03712          ast_indicate(c, -1);
03713       }
03714    }
03715    if (c)
03716       ast_hangup(c);
03717    memset(d->exten, 0, sizeof(d->exten));
03718    return NULL;
03719 }

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

Definition at line 4102 of file chan_skinny.c.

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

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

04103 {
04104    struct skinny_subchannel *xferor; /* the sub doing the transferring */
04105    struct skinny_subchannel *xferee; /* the sub being transferred */
04106    struct ast_tone_zone_sound *ts = NULL;
04107       
04108    if (ast_bridged_channel(sub->owner) || ast_bridged_channel(sub->related->owner)) {
04109       if (sub->xferor) {
04110          xferor = sub;
04111          xferee = sub->related;
04112       } else {
04113          xferor = sub;
04114          xferee = sub->related;
04115       }
04116       
04117       if (skinnydebug) {
04118          ast_debug(1, "Transferee channels (local/remote): %s and %s\n",
04119             xferee->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
04120          ast_debug(1, "Transferor channels (local/remote): %s and %s\n",
04121             xferor->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
04122       }
04123       if (ast_bridged_channel(xferor->owner)) {
04124          if (ast_bridged_channel(xferee->owner)) {
04125             ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
04126          }
04127          if (xferor->owner->_state == AST_STATE_RING) {
04128             /* play ringing inband */
04129             if ((ts = ast_get_indication_tone(xferor->owner->zone, "ring"))) {
04130                ast_playtones_start(xferor->owner, 0, ts->data, 1);
04131                ts = ast_tone_zone_sound_unref(ts);
04132             }
04133          }
04134          if (skinnydebug)
04135             ast_debug(1, "Transfer Masquerading %s to %s\n",
04136                xferee->owner->name, ast_bridged_channel(xferor->owner)?ast_bridged_channel(xferor->owner)->name:"");
04137          if (ast_channel_masquerade(xferee->owner, ast_bridged_channel(xferor->owner))) {
04138             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04139                ast_bridged_channel(xferor->owner)->name, xferee->owner->name);
04140             return -1;
04141          }
04142       } else if (ast_bridged_channel(xferee->owner)) {
04143          ast_queue_control(xferee->owner, AST_CONTROL_UNHOLD);
04144          if (xferor->owner->_state == AST_STATE_RING) {
04145             /* play ringing inband */
04146             if ((ts = ast_get_indication_tone(xferor->owner->zone, "ring"))) {
04147                ast_playtones_start(xferor->owner, 0, ts->data, 1);
04148                ts = ast_tone_zone_sound_unref(ts);
04149             }
04150          }
04151          if (skinnydebug)
04152             ast_debug(1, "Transfer Masquerading %s to %s\n",
04153                xferor->owner->name, ast_bridged_channel(xferee->owner)?ast_bridged_channel(xferee->owner)->name:"");
04154          if (ast_channel_masquerade(xferor->owner, ast_bridged_channel(xferee->owner))) {
04155             ast_log(LOG_WARNING, "Unable to masquerade %s as %s\n",
04156                ast_bridged_channel(xferee->owner)->name, xferor->owner->name);
04157             return -1;
04158          }
04159          return 0;
04160       } else {
04161          if (option_debug)
04162             ast_log(LOG_DEBUG, "Neither %s nor %s are in a bridge, nothing to transfer\n",
04163                xferor->owner->name, xferee->owner->name);
04164       }
04165    }
04166    return 0;
04167 }

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 4404 of file chan_skinny.c.

References AST_CONTROL_UNHOLD, ast_queue_control(), ast_verb, skinny_line::device, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, SKINNY_CONNECTED, SKINNY_LAMP_ON, SKINNY_OFFHOOK, STIMULUS_LINE, transmit_activatecallplane(), transmit_callstateonly(), transmit_connect(), and transmit_lamp_indication().

Referenced by handle_hold_button(), and handle_soft_key_event_message().

04405 {
04406    struct skinny_line *l = sub->parent;
04407    struct skinny_device *d = l->device;
04408 
04409    /* Don't try to unhold a channel that doesn't exist */
04410    if (!sub || !sub->owner)
04411       return 0;
04412 
04413    /* Channel is on hold, so we will unhold */
04414    if (skinnydebug)
04415       ast_verb(1, "Taking off Hold(%d)\n", l->instance);
04416 
04417    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
04418 
04419    transmit_activatecallplane(d, l);
04420 
04421    transmit_connect(d, sub);
04422    transmit_callstateonly(d, sub, SKINNY_CONNECTED);
04423    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04424    l->hookstate = SKINNY_OFFHOOK;
04425    sub->onhold = 0;
04426    return 1;
04427 }

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

Definition at line 1881 of file chan_skinny.c.

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

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

01882 {
01883    struct skinny_device *d;
01884    struct skinny_line *l;
01885    struct skinny_speeddial *sd;
01886 
01887    d = s->device;
01888 
01889    if (d) {
01890       d->session = NULL;
01891       d->registered = 0;
01892 
01893       AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
01894          if (sd->stateid > -1)
01895             ast_extension_state_del(sd->stateid, NULL);
01896       }
01897       AST_LIST_TRAVERSE(&d->lines, l, list) {
01898          if (l->device == d) {
01899             l->device = NULL;
01900             l->capability = 0;
01901             ast_parse_allow_disallow(&l->prefs, &l->capability, "all", 0);       
01902             l->instance = 0;
01903             unregister_exten(l);
01904             ast_devstate_changed(AST_DEVICE_UNAVAILABLE, "Skinny/%s@%s", l->name, d->name);
01905          }
01906       }
01907    }
01908 
01909    return -1; /* main loop will destroy the session */
01910 }

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

Definition at line 3964 of file chan_skinny.c.

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

03965 {
03966    struct skinny_subchannel *sub = ast->tech_pvt;
03967    int res = 0;
03968    if (frame->frametype != AST_FRAME_VOICE) {
03969       if (frame->frametype == AST_FRAME_IMAGE) {
03970          return 0;
03971       } else {
03972          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
03973          return 0;
03974       }
03975    } else {
03976       if (!(frame->subclass & ast->nativeformats)) {
03977          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
03978             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
03979          return -1;
03980       }
03981    }
03982    if (sub) {
03983       ast_mutex_lock(&sub->lock);
03984       if (sub->rtp) {
03985          res = ast_rtp_write(sub->rtp, frame);
03986       }
03987       ast_mutex_unlock(&sub->lock);
03988    }
03989    return res;
03990 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3557 of file chan_skinny.c.

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

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

03558 {
03559    struct skinny_line *l = sub->parent;
03560    struct skinny_device *d = l->device;
03561    int hasvideo = 0;
03562 
03563    ast_mutex_lock(&sub->lock);
03564    /* Allocate the RTP */
03565    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03566    if (hasvideo)
03567       sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
03568    
03569    if (sub->rtp && sub->owner) {
03570       ast_channel_set_fd(sub->owner, 0, ast_rtp_fd(sub->rtp));
03571       ast_channel_set_fd(sub->owner, 1, ast_rtcp_fd(sub->rtp));
03572    }
03573    if (hasvideo && sub->vrtp && sub->owner) {
03574       ast_channel_set_fd(sub->owner, 2, ast_rtp_fd(sub->vrtp));
03575       ast_channel_set_fd(sub->owner, 3, ast_rtcp_fd(sub->vrtp));
03576    }
03577    if (sub->rtp) {
03578       ast_rtp_setqos(sub->rtp, qos.tos_audio, qos.cos_audio, "Skinny RTP");
03579       ast_rtp_setnat(sub->rtp, l->nat);
03580    }
03581    if (sub->vrtp) {
03582       ast_rtp_setqos(sub->vrtp, qos.tos_video, qos.cos_video, "Skinny VRTP");
03583       ast_rtp_setnat(sub->vrtp, l->nat);
03584    }
03585    /* Set Frame packetization */
03586    if (sub->rtp)
03587       ast_rtp_codec_setpref(sub->rtp, &l->prefs);
03588 
03589    /* Create the RTP connection */
03590    transmit_connect(d, sub);
03591    ast_mutex_unlock(&sub->lock);
03592 }

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

Definition at line 2354 of file chan_skinny.c.

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

Referenced by skinny_hangup(), skinny_hold(), and skinny_unhold().

02355 {
02356    struct skinny_req *req;
02357 
02358    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02359       return;
02360 
02361    req->data.activatecallplane.lineInstance = htolel(l->instance);
02362    transmit_response(d, req);
02363 }

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

Definition at line 2107 of file chan_skinny.c.

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

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

02108 {
02109    struct skinny_req *req;
02110 
02111    /* We should not be able to get here without a device */
02112    if (!d)
02113       return;
02114 
02115    if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
02116       return;
02117 
02118    if (skinnydebug)
02119          ast_verb(1, "Setting Callinfo to %s(%s) from %s(%s) on %s(%d)\n", fromname, fromnum, toname, tonum, d->name, instance);
02120 
02121    if (fromname) {
02122       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
02123    }
02124    if (fromnum) {
02125       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
02126    }
02127    if (toname) {
02128       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
02129    }
02130    if (tonum) {
02131       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
02132    }
02133    req->data.callinfo.instance = htolel(instance);
02134    req->data.callinfo.reference = htolel(callid);
02135    req->data.callinfo.type = htolel(calltype);
02136    transmit_response(d, req);
02137 }

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

Definition at line 2378 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, CALL_STATE_MESSAGE, call_state_message::callReference, call_state_message::callState, skinny_data::callstate, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, stop_media_transmission_message::conferenceId, close_receive_channel_message::conferenceId, skinny_req::data, htolel, KEYDEF_ONHOOK, activate_call_plane_message::lineInstance, call_state_message::lineInstance, close_receive_channel_message::partyId, stop_media_transmission_message::passThruPartyId, req_alloc(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, transmit_displaypromptstatus(), transmit_response(), transmit_selectsoftkeys(), and transmit_speaker_mode().

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

02379 {
02380    struct skinny_req *req;
02381 
02382    if (state == SKINNY_ONHOOK) {
02383       if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02384          return;
02385 
02386       req->data.closereceivechannel.conferenceId = htolel(callid);
02387       req->data.closereceivechannel.partyId = htolel(callid);
02388       transmit_response(d, req);
02389 
02390       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02391          return;
02392 
02393       req->data.stopmedia.conferenceId = htolel(callid);
02394       req->data.stopmedia.passThruPartyId = htolel(callid);
02395       transmit_response(d, req);
02396 
02397       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
02398 
02399       transmit_displaypromptstatus(d, NULL, 0, instance, callid);
02400    }
02401 
02402    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02403       return;
02404 
02405    req->data.callstate.callState = htolel(state);
02406    req->data.callstate.lineInstance = htolel(instance);
02407    req->data.callstate.callReference = htolel(callid);
02408    transmit_response(d, req);
02409 
02410    if (state == SKINNY_ONHOOK) {
02411       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
02412    }
02413 
02414    if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
02415       if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02416          return;
02417 
02418       req->data.activatecallplane.lineInstance = htolel(instance);
02419       transmit_response(d, req);
02420    }
02421 }

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

Definition at line 2424 of file chan_skinny.c.

References forward_stat_message::activeforward, ast_copy_string(), ast_strlen_zero(), skinny_req::data, FORWARD_STAT_MESSAGE, skinny_data::forwardstat, forward_stat_message::fwdall, forward_stat_message::fwdallnum, forward_stat_message::fwdbusy, forward_stat_message::fwdbusynum, forward_stat_message::fwdnoanswer, forward_stat_message::fwdnoanswernum, htolel, forward_stat_message::lineNumber, req_alloc(), SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CFWD_NOANSWER, and transmit_response().

Referenced by handle_callforward_button(), and skinny_ss().

02425 {
02426    struct skinny_req *req;
02427    int anyon = 0;
02428 
02429    if (!(req = req_alloc(sizeof(struct forward_stat_message), FORWARD_STAT_MESSAGE)))
02430       return;
02431 
02432    if (l->cfwdtype & SKINNY_CFWD_ALL) {
02433       if (!ast_strlen_zero(l->call_forward_all)) {
02434          ast_copy_string(req->data.forwardstat.fwdallnum, l->call_forward_all, sizeof(req->data.forwardstat.fwdallnum));
02435          req->data.forwardstat.fwdall = htolel(1);
02436          anyon++;
02437       } else {
02438          req->data.forwardstat.fwdall = htolel(0);
02439       }
02440    }
02441    if (l->cfwdtype & SKINNY_CFWD_BUSY) {
02442       if (!ast_strlen_zero(l->call_forward_busy)) {
02443          ast_copy_string(req->data.forwardstat.fwdbusynum, l->call_forward_busy, sizeof(req->data.forwardstat.fwdbusynum));
02444          req->data.forwardstat.fwdbusy = htolel(1);
02445          anyon++;
02446       } else {
02447          req->data.forwardstat.fwdbusy = htolel(0);
02448       }
02449    }
02450    if (l->cfwdtype & SKINNY_CFWD_NOANSWER) {
02451       if (!ast_strlen_zero(l->call_forward_noanswer)) {
02452          ast_copy_string(req->data.forwardstat.fwdnoanswernum, l->call_forward_noanswer, sizeof(req->data.forwardstat.fwdnoanswernum));
02453          req->data.forwardstat.fwdnoanswer = htolel(1);
02454          anyon++;
02455       } else {
02456          req->data.forwardstat.fwdnoanswer = htolel(0);
02457       }
02458    }
02459    req->data.forwardstat.lineNumber = htolel(l->instance);
02460    if (anyon)
02461       req->data.forwardstat.activeforward = htolel(7);
02462    else
02463       req->data.forwardstat.activeforward = htolel(0);
02464 
02465    transmit_response(d, req);
02466 }

static void transmit_closereceivechannel ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_connect ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_dialednumber ( struct skinny_device d,
const char *  text,
int  instance,
int  callid 
) [static]
static void transmit_displaymessage ( struct skinny_device d,
const char *  text,
int  instance,
int  reference 
) [static]

Definition at line 2241 of file chan_skinny.c.

References ast_copy_string(), ast_verb, CLEAR_DISPLAY_MESSAGE, skinny_req::data, skinny_data::displaytext, DISPLAYTEXT_MESSAGE, handle_time_date_req_message(), req_alloc(), skinny_device::session, displaytext_message::text, and transmit_response().

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

02242 {
02243    struct skinny_req *req;
02244 
02245    if (text == 0) {
02246       if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
02247          return;
02248 
02249       //what do we want hear CLEAR_DISPLAY_MESSAGE or CLEAR_PROMPT_STATUS???
02250       //if we are clearing the display, it appears there is no instance and refernece info (size 0)
02251       //req->data.clearpromptstatus.lineInstance = instance;
02252       //req->data.clearpromptstatus.callReference = reference;
02253 
02254       /* send datetime message. We have to do it here because it will clear the display on the phone if we do it elsewhere */
02255       handle_time_date_req_message(NULL, d->session);
02256 
02257       if (skinnydebug)
02258          ast_verb(1, "Clearing Display\n");
02259    } else {
02260       if (!(req = req_alloc(sizeof(struct displaytext_message), DISPLAYTEXT_MESSAGE)))
02261          return;
02262 
02263       ast_copy_string(req->data.displaytext.text, text, sizeof(req->data.displaytext.text));
02264       if (skinnydebug)
02265          ast_verb(1, "Displaying message '%s'\n", req->data.displaytext.text);
02266    }
02267 
02268    transmit_response(d, req);
02269 }

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

Definition at line 2287 of file chan_skinny.c.

References ast_copy_string(), ast_verb, display_prompt_status_message::callReference, clear_prompt_message::callReference, CLEAR_PROMPT_MESSAGE, skinny_data::clearpromptstatus, skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_data::displaypromptstatus, htolel, display_prompt_status_message::lineInstance, clear_prompt_message::lineInstance, display_prompt_status_message::messageTimeout, display_prompt_status_message::promptMessage, req_alloc(), and transmit_response().

Referenced by handle_stimulus_message(), skinny_answer(), skinny_call(), skinny_indicate(), and transmit_callstate().

02288 {
02289    struct skinny_req *req;
02290 
02291    if (text == 0) {
02292       if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
02293          return;
02294 
02295       req->data.clearpromptstatus.lineInstance = htolel(instance);
02296       req->data.clearpromptstatus.callReference = htolel(callid);
02297 
02298       if (skinnydebug)
02299          ast_verb(1, "Clearing Prompt\n");
02300    } else {
02301       if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
02302          return;
02303 
02304       ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
02305       req->data.displaypromptstatus.messageTimeout = htolel(t);
02306       req->data.displaypromptstatus.lineInstance = htolel(instance);
02307       req->data.displaypromptstatus.callReference = htolel(callid);
02308 
02309       if (skinnydebug)
02310          ast_verb(1, "Displaying Prompt Status '%s'\n", text);
02311    }
02312 
02313    transmit_response(d, req);
02314 }

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

Definition at line 2043 of file chan_skinny.c.

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

Referenced by handle_button_template_req_message(), handle_keep_alive_message(), handle_line_state_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_server_request_message(), handle_skinny_reset(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), handle_version_req_message(), skinny_reload(), skinny_set_rtp_peer(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_callstateonly(), transmit_cfwdstate(), transmit_closereceivechannel(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and transmit_tone().

02044 {
02045    struct skinnysession *s = d->session;
02046    int res = 0;
02047 
02048    if (!s) {
02049       ast_log(LOG_WARNING, "Asked to transmit to a non-existent session!\n");
02050       return -1;
02051    }
02052 
02053    ast_mutex_lock(&s->lock);
02054 
02055    SKINNY_DEVONLY(if (skinnydebug>1) ast_verb(4, "Transmitting %s to %s\n", message2str(req->e), d->name);)
02056 
02057    if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
02058       ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
02059       ast_mutex_unlock(&s->lock);
02060       return -1;
02061    }
02062 
02063    memset(s->outbuf, 0, sizeof(s->outbuf));
02064    memcpy(s->outbuf, req, skinny_header_size);
02065    memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
02066 
02067    res = write(s->fd, s->outbuf, letohl(req->len)+8);
02068    
02069    if (res != letohl(req->len)+8) {
02070       ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
02071       if (res == -1) {
02072          if (skinnydebug)
02073             ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
02074          skinny_unregister(NULL, s);
02075       }
02076       
02077    }
02078    
02079    ast_free(req);
02080    ast_mutex_unlock(&s->lock);
02081    return 1;
02082 }

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

Definition at line 2216 of file chan_skinny.c.

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

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

02217 {
02218    struct skinny_req *req;
02219 
02220    if (skinnydebug)
02221       ast_verb(1, "Setting ringer mode to '%d'.\n", mode);
02222 
02223    if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
02224       return;
02225 
02226    req->data.setringer.ringerMode = htolel(mode);
02227    /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
02228       Note: The phone will always show as ringing on the display.
02229 
02230       1: phone will audibly ring over and over
02231       2: phone will audibly ring only once
02232       any other value, will NOT cause the phone to audibly ring
02233    */
02234    req->data.setringer.unknown1 = htolel(1);
02235    /* XXX the value here doesn't seem to change anything.  Must be higher than 0.
02236       Perhaps a packet capture can shed some light on this. */
02237    req->data.setringer.unknown2 = htolel(1);
02238    transmit_response(d, req);
02239 }

static void transmit_selectsoftkeys ( struct skinny_device d,
int  instance,
int  callid,
int  softkey 
) [static]
static void transmit_speaker_mode ( struct skinny_device d,
int  mode 
) [static]
static void transmit_stopmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]
static void transmit_tone ( struct skinny_device d,
int  tone,
int  instance,
int  reference 
) [static]

Definition at line 2159 of file chan_skinny.c.

References skinny_req::data, htolel, stop_tone_message::instance, start_tone_message::instance, stop_tone_message::reference, start_tone_message::reference, req_alloc(), SKINNY_NOTONE, START_TONE_MESSAGE, skinny_data::starttone, STOP_TONE_MESSAGE, skinny_data::stoptone, start_tone_message::tone, and transmit_response().

Referenced by handle_callforward_button(), handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), handle_transfer_button(), skinny_answer(), skinny_hangup(), skinny_indicate(), skinny_newcall(), skinny_senddigit_end(), and skinny_ss().

02160 {
02161    struct skinny_req *req;
02162 
02163    if (tone == SKINNY_NOTONE) {
02164       /* This is bad, mmm'kay? */
02165       return;
02166    }
02167 
02168    if (tone > 0) {
02169       if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
02170          return;
02171       req->data.starttone.tone = htolel(tone);
02172       req->data.starttone.instance = htolel(instance);
02173       req->data.starttone.reference = htolel(reference);
02174    } else {
02175       if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
02176          return;
02177       req->data.stoptone.instance = htolel(instance);
02178       req->data.stoptone.reference = htolel(reference);
02179    }
02180 
02181    //Bad, tone is already set so this is redundant and a change to the if above
02182    //may lead to issues where we try to set a tone to a stop_tone_message
02183    //if (tone > 0) {
02184    // req->data.starttone.tone = htolel(tone);
02185    //}
02186    transmit_response(d, req);
02187 }

static int unload_module ( void   )  [static]

Definition at line 7327 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ARRAY_LEN, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_context_destroy(), ast_context_find(), ast_event_unsubscribe(), AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_manager_unregister(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_skinny, delete_devices(), skinnysession::device, skinnysession::fd, free, skinny_device::lines, skinny_subchannel::lock, skinny_line::lock, monlock, skinny_line::mwi_event_sub, netlock, skinny_subchannel::owner, s, sched_context_destroy(), skinny_rtp, skinny_tech, skinny_line::sub, skinnysession::t, and unregister_exten().

07328 {
07329    struct skinnysession *s;
07330    struct skinny_device *d;
07331    struct skinny_line *l;
07332    struct skinny_subchannel *sub;
07333    struct ast_context *con;
07334 
07335    ast_rtp_proto_unregister(&skinny_rtp);
07336    ast_channel_unregister(&skinny_tech);
07337    ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07338 
07339    ast_manager_unregister("SKINNYdevices");
07340    ast_manager_unregister("SKINNYshowdevice");
07341    ast_manager_unregister("SKINNYlines");
07342    ast_manager_unregister("SKINNYshowline");
07343    
07344    AST_LIST_LOCK(&sessions);
07345    /* Destroy all the interfaces and free their memory */
07346    while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
07347       d = s->device;
07348       AST_LIST_TRAVERSE(&d->lines, l, list){
07349          ast_mutex_lock(&l->lock);
07350          AST_LIST_TRAVERSE(&l->sub, sub, list) {
07351             ast_mutex_lock(&sub->lock);
07352             if (sub->owner) {
07353                sub->alreadygone = 1;
07354                ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
07355             }
07356             ast_mutex_unlock(&sub->lock);
07357          }
07358          if (l->mwi_event_sub)
07359             ast_event_unsubscribe(l->mwi_event_sub);
07360          ast_mutex_unlock(&l->lock);
07361          unregister_exten(l);
07362       }
07363       if (s->fd > -1)
07364          close(s->fd);
07365       pthread_cancel(s->t);
07366       pthread_kill(s->t, SIGURG);
07367       pthread_join(s->t, NULL);
07368       free(s);
07369    }
07370    AST_LIST_UNLOCK(&sessions);
07371 
07372    delete_devices();
07373 
07374    ast_mutex_lock(&monlock);
07375    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
07376       pthread_cancel(monitor_thread);
07377       pthread_kill(monitor_thread, SIGURG);
07378       pthread_join(monitor_thread, NULL);
07379    }
07380    monitor_thread = AST_PTHREADT_STOP;
07381    ast_mutex_unlock(&monlock);
07382 
07383    ast_mutex_lock(&netlock);
07384    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
07385       pthread_cancel(accept_t);
07386       pthread_kill(accept_t, SIGURG);
07387       pthread_join(accept_t, NULL);
07388    }
07389    accept_t = AST_PTHREADT_STOP;
07390    ast_mutex_unlock(&netlock);
07391 
07392    close(skinnysock);
07393    if (sched)
07394       sched_context_destroy(sched);
07395 
07396    con = ast_context_find(used_context);
07397    if (con)
07398       ast_context_destroy(con, "Skinny");
07399    
07400    return 0;
07401 }

static void unregister_exten ( struct skinny_line l  )  [static]

Definition at line 1789 of file chan_skinny.c.

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

Referenced by skinny_unregister(), and unload_module().

01790 {
01791    char multi[256];
01792    char *stringp, *ext, *context;
01793 
01794    if (ast_strlen_zero(regcontext))
01795       return;
01796 
01797    ast_copy_string(multi, S_OR(l->regexten, l->name), sizeof(multi));
01798    stringp = multi;
01799    while ((ext = strsep(&stringp, "&"))) {
01800       if ((context = strchr(ext, '@'))) {
01801          *context++ = '\0'; /* split ext@context */
01802          if (!ast_context_find(context)) {
01803             ast_log(LOG_WARNING, "Context %s must exist in regcontext= in skinny.conf!\n", context);
01804             continue;
01805          }
01806       } else {
01807          context = regcontext;
01808       }
01809       ast_context_remove_extension(context, ext, 1, NULL);
01810    }
01811 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, .reload = reload, } [static]

Definition at line 7413 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 980 of file chan_skinny.c.

Referenced by config_load(), and skinny_register().

pthread_t accept_t [static]

Definition at line 984 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 981 of file chan_skinny.c.

Referenced by __init_manager(), config_load(), config_parse_variables(), and rpt_exec().

Definition at line 7413 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]
int callnums = 1 [static]

Definition at line 985 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 3546 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

Definition at line 85 of file chan_skinny.c.

struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_control2str_threadbuf , .custom_init = NULL , } [static]

Definition at line 179 of file chan_skinny.c.

Referenced by control2str().

unsigned int cos

Definition at line 108 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 109 of file chan_skinny.c.

unsigned int cos_video

Definition at line 110 of file chan_skinny.c.

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

Definition at line 117 of file chan_skinny.c.

int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 87 of file chan_skinny.c.

Definition at line 1294 of file chan_skinny.c.

Referenced by config_device(), and config_load().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 161 of file chan_skinny.c.

Definition at line 1221 of file chan_skinny.c.

Referenced by config_line(), and config_load().

struct ast_codec_pref default_prefs [static]

Definition at line 88 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

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

Definition at line 176 of file chan_skinny.c.

Referenced by device2str().

int firstdigittimeout = 16000 [static]

Definition at line 1104 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1107 of file chan_skinny.c.

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

Definition at line 114 of file chan_skinny.c.

struct hostent* hp
struct io_context* io [static]

Definition at line 1091 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 113 of file chan_skinny.c.

char mandescr_show_device[] [static]
Initial value:
"Description: Show one SKINNY device with details on current status.\n"
"Variables: \n"
"  Device: <name>           The device name you want to check.\n"
"  ActionID: <id>   Optional action ID for this AMI transaction.\n"

Definition at line 3159 of file chan_skinny.c.

Referenced by load_module().

char mandescr_show_devices[] [static]

Definition at line 3014 of file chan_skinny.c.

Referenced by load_module().

char mandescr_show_line[] [static]
Initial value:
"Description: Show one SKINNY line with details on current status.\n"
"Variables: \n"
"  Line: <name>           The line name you want to check.\n"
"  ActionID: <id>   Optional action ID for this AMI transaction.\n"

Definition at line 3469 of file chan_skinny.c.

Referenced by load_module().

char mandescr_show_lines[] [static]

Definition at line 3275 of file chan_skinny.c.

Referenced by load_module().

int matchdigittimeout = 3000 [static]

Definition at line 1110 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1101 of file chan_skinny.c.

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

Definition at line 1095 of file chan_skinny.c.

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

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

Definition at line 1097 of file chan_skinny.c.

Referenced by config_load(), and unload_module().

char ourhost[256] [static]

Definition at line 978 of file chan_skinny.c.

int ourport [static]

Definition at line 979 of file chan_skinny.c.

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

Definition at line 116 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 1090 of file chan_skinny.c.

Definition at line 967 of file chan_skinny.c.

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 2679 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1335 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 973 of file chan_skinny.c.

int skinnyreload = 0 [static]

Definition at line 974 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 983 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 762 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]
Initial value:

Definition at line 806 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 792 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]
Initial value:

Definition at line 801 of file chan_skinny.c.

Definition at line 825 of file chan_skinny.c.

const uint8_t soft_key_default_offhook[] [static]

Definition at line 784 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]
Initial value:

Definition at line 815 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 771 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 752 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]
Initial value:

Definition at line 778 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]
Initial value:

Definition at line 810 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]
Initial value:

Definition at line 821 of file chan_skinny.c.

Definition at line 589 of file chan_skinny.c.

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

Definition at line 84 of file chan_skinny.c.

unsigned int tos

Definition at line 105 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 106 of file chan_skinny.c.

unsigned int tos_video

Definition at line 107 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 115 of file chan_skinny.c.

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

Definition at line 118 of file chan_skinny.c.


Generated by  doxygen 1.6.2