Mon Mar 19 11:30:44 2012

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

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

Go to the source code of this file.

Data Structures

struct  activate_call_plane_message
struct  alarm_message
struct  button_definition
struct  button_definition_template
struct  button_template_res_message
struct  call_info_message
struct  call_state_message
struct  capabilities_res_message
struct  clear_prompt_message
struct  close_receive_channel_message
struct  definetimedate_message
struct  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_AUTH_LIMIT   50
#define DEFAULT_AUTH_TIMEOUT   30
#define DEFAULT_SKINNY_BACKLOG   2
#define DEFAULT_SKINNY_PORT   2000
#define DEFINETIMEDATE_MESSAGE   0x0094
#define DEVICE2STR_BUFSIZE   15
#define DIALED_NUMBER_MESSAGE   0x011D
#define DISPLAY_NOTIFY_MESSAGE   0x0114
#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112
#define DISPLAYTEXT_MESSAGE   0x0099
#define ENBLOC_CALL_MESSAGE   0x0004
#define FORWARD_STAT_MESSAGE   0x0090
#define HEADSET_STATUS_MESSAGE   0x002B
#define htolel(x)   bswap_32(x)
#define htoles(x)   bswap_16(x)
#define IP_PORT_MESSAGE   0x0002
#define KEEP_ALIVE_ACK_MESSAGE   0x0100
#define KEEP_ALIVE_MESSAGE   0x0000
#define KEYDEF_CONNECTED   1
#define KEYDEF_CONNWITHCONF   7
#define KEYDEF_CONNWITHTRANS   5
#define KEYDEF_DADFD   6
#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 (format_t astcodec)
static format_t codec_skinny2ast (enum skinny_codecs skinnycodec)
static char * complete_skinny_devices (const char *word, int state)
static char * complete_skinny_reset (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_device (const char *line, const char *word, int pos, int state)
static char * complete_skinny_show_line (const char *line, const char *word, int pos, int state)
static struct skinny_deviceconfig_device (const char *dname, struct ast_variable *v)
static struct skinny_lineconfig_line (const char *lname, struct ast_variable *v)
static int config_load (void)
static void config_parse_variables (int type, void *item, struct ast_variable *vptr)
static char * control2str (int ind)
static void delete_devices (void)
static void destroy_session (struct skinnysession *s)
static char * device2str (int type)
static void * do_monitor (void *data)
static struct skinny_linefind_line_by_instance (struct skinny_device *d, int instance)
static struct skinny_linefind_line_by_name (const char *dest)
static struct skinny_speeddialfind_speeddial_by_instance (struct skinny_device *d, int instance, int isHint)
static struct skinny_subchannelfind_subchannel_by_instance_reference (struct skinny_device *d, int instance, int reference)
static struct skinny_subchannelfind_subchannel_by_reference (struct skinny_device *d, int reference)
static void * get_button_template (struct skinnysession *s, struct button_definition_template *btn)
static int get_devicestate (struct skinny_line *l)
static int get_input (struct skinnysession *s)
static int handle_button_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_callforward_button (struct skinny_subchannel *sub, int cfwdtype)
static int handle_capabilities_res_message (struct skinny_req *req, struct skinnysession *s)
static int handle_enbloc_call_message (struct skinny_req *req, struct skinnysession *s)
static int handle_hold_button (struct skinny_subchannel *sub)
static int handle_ip_port_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keep_alive_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_message (struct skinny_req *req, struct skinnysession *s)
static int handle_message (struct skinny_req *req, struct skinnysession *s)
static int handle_offhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_onhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_open_receive_channel_ack_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_message (struct skinny_req *req, struct skinnysession *s)
static char * handle_skinny_reload (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_reset (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_set_debug (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_device (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 Show device information.
static char * handle_skinny_show_devices (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_line (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List line information.
static char * handle_skinny_show_lines (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static char * handle_skinny_show_settings (struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
 List global settings for the Skinny subsystem.
static int handle_soft_key_event_message (struct skinny_req *req, struct skinnysession *s)
static int handle_stimulus_message (struct skinny_req *req, struct skinnysession *s)
static int handle_transfer_button (struct skinny_subchannel *sub)
static int load_module (void)
static int manager_skinny_show_device (struct mansession *s, const struct message *m)
static int manager_skinny_show_devices (struct mansession *s, const struct message *m)
 Show SKINNY devices in the manager API.
static int manager_skinny_show_line (struct mansession *s, const struct message *m)
static int manager_skinny_show_lines (struct mansession *s, const struct message *m)
 Show Skinny lines in the manager API.
static void mwi_event_cb (const struct ast_event *event, void *userdata)
static void print_codec_to_cli (int fd, struct ast_codec_pref *pref)
 Print codec list from preference to CLI/manager.
static void register_exten (struct skinny_line *l)
static int reload (void)
static struct skinny_reqreq_alloc (size_t size, int response_message)
static int restart_monitor (void)
static int set_callforwards (struct skinny_line *l, const char *cfwd, int cfwdtype)
static int skinny_answer (struct ast_channel *ast)
static int skinny_call (struct ast_channel *ast, char *dest, int timeout)
static int skinny_devicestate (void *data)
static int skinny_extensionstate_cb (char *context, char *exten, int state, void *data)
static int skinny_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_glue_result skinny_get_rtp_peer (struct ast_channel *c, struct ast_rtp_instance **instance)
static enum ast_rtp_glue_result skinny_get_vrtp_peer (struct ast_channel *c, struct ast_rtp_instance **instance)
static int skinny_hangup (struct ast_channel *ast)
static int skinny_hold (struct skinny_subchannel *sub)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelskinny_new (struct skinny_line *l, int state, const char *linkedid)
static void * skinny_newcall (void *data)
static struct ast_frameskinny_read (struct ast_channel *ast)
static int skinny_register (struct skinny_req *req, struct skinnysession *s)
static int skinny_reload (void)
static struct skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_senddigit_begin (struct ast_channel *ast, char digit)
static int skinny_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void * skinny_session (void *data)
static int skinny_set_rtp_peer (struct ast_channel *c, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
static void * skinny_ss (void *data)
static int skinny_transfer (struct skinny_subchannel *sub)
static int skinny_unhold (struct skinny_subchannel *sub)
static int skinny_unregister (struct skinny_req *req, struct skinnysession *s)
static int skinny_write (struct ast_channel *ast, struct ast_frame *frame)
static void start_rtp (struct skinny_subchannel *sub)
static void transmit_activatecallplane (struct skinny_device *d, struct skinny_line *l)
static void transmit_callinfo (struct skinny_device *d, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinny_device *d, int buttonInstance, unsigned callid, int state)
static void transmit_cfwdstate (struct skinny_device *d, struct skinny_line *l)
static void transmit_clear_display_message (struct skinny_device *d, int instance, int reference)
static void transmit_clearpromptmessage (struct skinny_device *d, int instance, int callid)
static void transmit_closereceivechannel (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_connect (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_definetimedate (struct skinny_device *d)
static void transmit_dialednumber (struct skinny_device *d, const char *text, int instance, int callid)
static void transmit_displaynotify (struct skinny_device *d, const char *text, int t)
static void transmit_displaypromptstatus (struct skinny_device *d, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinny_device *d, int stimulus, int instance, int indication)
static void transmit_linestatres (struct skinny_device *d, struct skinny_line *l)
static int transmit_response (struct skinny_device *d, struct skinny_req *req)
static void transmit_ringer_mode (struct skinny_device *d, int mode)
static void transmit_selectsoftkeys (struct skinny_device *d, int instance, int callid, int softkey)
static void transmit_serverres (struct skinny_device *d)
static void transmit_softkeysetres (struct skinny_device *d)
static void transmit_softkeytemplateres (struct skinny_device *d)
static void transmit_speaker_mode (struct skinny_device *d, int mode)
static void transmit_speeddialstatres (struct skinny_device *d, struct skinny_speeddial *sd)
static void transmit_start_tone (struct skinny_device *d, int tone, int instance, int reference)
static void transmit_startmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub, struct sockaddr_in dest, struct ast_format_list fmt)
static void transmit_stop_tone (struct skinny_device *d, int instance, int reference)
static void transmit_stopmediatransmission (struct skinny_device *d, struct skinny_subchannel *sub)
static void transmit_versionres (struct skinny_device *d)
static int unload_module (void)
static void unregister_exten (struct skinny_line *l)
static void update_connectedline (struct skinny_subchannel *sub, const void *data, size_t datalen)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Skinny Client Control Protocol (Skinny)" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "88eaa8f5c1bd988bedd71113385e0886" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, }
static struct in_addr __ourip
static pthread_t accept_t
static struct ast_hostent ahp
static struct ast_module_infoast_module_info = &__mod_info
static int auth_limit = DEFAULT_AUTH_LIMIT
static int auth_timeout = DEFAULT_AUTH_TIMEOUT
static struct sockaddr_in bindaddr
static int callnums = 1
static struct ast_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 format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW
static struct skinny_device_optionsdefault_device = &default_device_struct
static struct skinny_device_options default_device_struct
static struct ast_jb_conf default_jbconf
static struct skinny_line_optionsdefault_line = &default_line_struct
static struct skinny_line_options default_line_struct
static struct ast_codec_pref default_prefs
static struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = __init_device2str_threadbuf , .custom_init = NULL , }
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
static char global_vmexten [AST_MAX_EXTENSION]
static struct hostent * hp
static struct io_contextio
static int keep_alive = 120
static int matchdigittimeout = 3000
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static ast_mutex_t netlock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 }
static char ourhost [256]
static int ourport
struct {
   unsigned int   cos
   unsigned int   cos_audio
   unsigned int   cos_video
   unsigned int   tos
   unsigned int   tos_audio
   unsigned int   tos_video
qos
static char regcontext [AST_MAX_CONTEXT]
static struct sched_contextsched = NULL
static int skinny_header_size = 12
static struct ast_rtp_glue skinny_rtp_glue
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
static int skinnyreload = 0
static int skinnysock = -1
static const uint8_t soft_key_default_connected []
static const uint8_t soft_key_default_connwithconf []
static const uint8_t soft_key_default_connwithtrans []
static const uint8_t soft_key_default_dadfd []
static struct soft_key_definitions soft_key_default_definitions []
static const uint8_t soft_key_default_offhook []
static const uint8_t soft_key_default_offhookwithfeat []
static const uint8_t soft_key_default_onhold []
static const uint8_t soft_key_default_onhook []
static const uint8_t soft_key_default_ringin []
static const uint8_t soft_key_default_ringout []
static const uint8_t soft_key_default_unknown []
static struct soft_key_template_definition soft_key_template_default []
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static int unauth_sessions = 0
static char used_context [AST_MAX_EXTENSION]
static char version_id [16] = "P002F202"


Detailed Description

Implementation of the Skinny protocol.

Author:
Jeremy McNamara & Florian Overkamp & North Antara

Definition in file chan_skinny.c.


Define Documentation

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116

Definition at line 964 of file chan_skinny.c.

Referenced by transmit_activatecallplane().

#define ALARM_MESSAGE   0x0020

Definition at line 331 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 538 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 541 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 542 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 540 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 549 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 548 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 535 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 539 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 532 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 533 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 534 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 530 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 536 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 543 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 528 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 529 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 531 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 537 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 327 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 498 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 436 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 935 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 571 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 299 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6663 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6662 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 569 of file chan_skinny.c.

Referenced by transmit_clear_display_message().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 568 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 952 of file chan_skinny.c.

Referenced by transmit_clearpromptmessage().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6661 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6660 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 607 of file chan_skinny.c.

Referenced by transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 246 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_AUTH_LIMIT   50

Definition at line 164 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_AUTH_TIMEOUT   30

Definition at line 163 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 161 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 160 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 485 of file chan_skinny.c.

Referenced by transmit_definetimedate().

#define DEVICE2STR_BUFSIZE   15

Definition at line 243 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 969 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 958 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 943 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 563 of file chan_skinny.c.

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 275 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 458 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 358 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)

Definition at line 195 of file chan_skinny.c.

Referenced by get_input(), handle_register_message(), load_module(), req_alloc(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), and transmit_stopmediatransmission().

#define htoles (  )     bswap_16(x)

Definition at line 196 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define IP_PORT_MESSAGE   0x0002

Definition at line 265 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 594 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 252 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

Definition at line 622 of file chan_skinny.c.

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

#define KEYDEF_CONNWITHCONF   7

Definition at line 628 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 626 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 627 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

Definition at line 625 of file chan_skinny.c.

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

#define KEYDEF_OFFHOOKWITHFEAT   9

Definition at line 630 of file chan_skinny.c.

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 623 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

Definition at line 621 of file chan_skinny.c.

Referenced by handle_callforward_button(), handle_message(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), and skinny_hangup().

#define KEYDEF_RINGIN   3

Definition at line 624 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

Definition at line 629 of file chan_skinny.c.

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

#define KEYDEF_UNKNOWN   10

Definition at line 631 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 267 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)

Definition at line 193 of file chan_skinny.c.

Referenced by get_input(), handle_capabilities_res_message(), handle_keypad_button_message(), handle_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_register(), skinny_req_parse(), transmit_linestatres(), and transmit_response().

#define letohs (  )     bswap_16(x)

Definition at line 194 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 477 of file chan_skinny.c.

Referenced by transmit_linestatres().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 321 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 287 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 293 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 339 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 596 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 361 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 359 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 573 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 589 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 927 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 329 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 578 of file chan_skinny.c.

Referenced by transmit_serverres().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 392 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 405 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 384 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 399 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1116 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1103 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1115 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1110 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1106 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1118 of file chan_skinny.c.

#define SKINNY_CFWD_ALL   (1 << 0)

Definition at line 1132 of file chan_skinny.c.

Referenced by _skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), skinny_new(), and transmit_cfwdstate().

#define SKINNY_CFWD_BUSY   (1 << 1)

Definition at line 1133 of file chan_skinny.c.

Referenced by _skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), skinny_new(), and transmit_cfwdstate().

#define SKINNY_CFWD_NOANSWER   (1 << 2)

Definition at line 1134 of file chan_skinny.c.

Referenced by _skinny_show_line(), handle_soft_key_event_message(), handle_stimulus_message(), set_callforwards(), and transmit_cfwdstate().

#define SKINNY_CONGESTION   7

Definition at line 1104 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

Definition at line 1102 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_unhold(), and update_connectedline().

#define SKINNY_CX_CONF   3

Definition at line 1140 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 1141 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1143 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1142 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1138 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1137 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1139 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1058 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1057 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1056 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1055 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1059 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1085 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1081 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1074 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1060 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1069 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1084 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1067 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1082 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1073 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1072 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1063 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1088 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1076 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1062 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1065 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1071 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1077 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1078 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1061 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1087 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1070 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1075 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1079 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1083 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1066 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1080 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1068 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1064 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1086 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1054 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1312 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1089 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1090 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 1053 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVONLY ( code   ) 

Definition at line 138 of file chan_skinny.c.

Referenced by handle_message(), and transmit_response().

#define SKINNY_DIALTONE   0x21

Definition at line 1114 of file chan_skinny.c.

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

#define SKINNY_HOLD   8

Definition at line 1105 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1111 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 1125 of file chan_skinny.c.

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

#define SKINNY_LAMP_FLASH   4

Definition at line 1124 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

Definition at line 1121 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), handle_stimulus_message(), mwi_event_cb(), skinny_extensionstate_cb(), and skinny_hangup().

#define SKINNY_LAMP_ON   2

Definition at line 1122 of file chan_skinny.c.

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), mwi_event_cb(), skinny_extensionstate_cb(), skinny_hangup(), skinny_ss(), and skinny_unhold().

#define SKINNY_LAMP_WINK   3

Definition at line 1123 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1202 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 309 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 162 of file chan_skinny.c.

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

#define SKINNY_MICOFF   2

Definition at line 1096 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1095 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1119 of file chan_skinny.c.

#define SKINNY_OFFHOOK   1

Definition at line 1098 of file chan_skinny.c.

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_call(), skinny_ss(), and skinny_unhold().

#define SKINNY_ONHOOK   2

Definition at line 1099 of file chan_skinny.c.

Referenced by get_devicestate(), handle_callforward_button(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_extensionstate_cb(), and skinny_hangup().

#define SKINNY_PARK   11

Definition at line 1108 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1109 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_REORDER   0x25

Definition at line 1117 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1130 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1128 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

Definition at line 1127 of file chan_skinny.c.

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

#define SKINNY_RING_OUTSIDE   3

Definition at line 1129 of file chan_skinny.c.

#define SKINNY_RINGIN   4

Definition at line 1101 of file chan_skinny.c.

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

#define SKINNY_RINGOUT   3

Definition at line 1100 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_SILENCE   0x00

Definition at line 1113 of file chan_skinny.c.

#define SKINNY_SPEAKEROFF   2

Definition at line 1093 of file chan_skinny.c.

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

#define SKINNY_SPEAKERON   1

Definition at line 1092 of file chan_skinny.c.

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

#define SKINNY_TRANSFER   10

Definition at line 1107 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 349 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 347 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 912 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 357 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 614 of file chan_skinny.c.

Referenced by transmit_softkeytemplateres().

#define SOFTKEY_ANSWER   0x0B

Definition at line 644 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 641 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 639 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 640 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 646 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 652 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 642 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 651 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 636 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 653 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 645 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 648 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 649 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 635 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 647 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 650 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 634 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 643 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 637 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 316 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 470 of file chan_skinny.c.

Referenced by transmit_speeddialstatres().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 410 of file chan_skinny.c.

Referenced by transmit_startmediatransmission().

#define START_TONE_MESSAGE   0x0082

Definition at line 370 of file chan_skinny.c.

Referenced by transmit_start_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 520 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 523 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 524 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 522 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 517 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 521 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 514 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 515 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 516 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 512 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

Definition at line 518 of file chan_skinny.c.

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

#define STIMULUS_MESSAGE   0x0005

Definition at line 280 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 525 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 510 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 511 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 513 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 519 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 429 of file chan_skinny.c.

Referenced by transmit_stopmediatransmission().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 378 of file chan_skinny.c.

Referenced by transmit_stop_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 326 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6655 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6656 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6657 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6654 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6658 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 356 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 328 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 558 of file chan_skinny.c.

Referenced by transmit_versionres().


Enumeration Type Documentation

enum skinny_codecs

Enumerator:
SKINNY_CODEC_ALAW 
SKINNY_CODEC_ULAW 
SKINNY_CODEC_G723_1 
SKINNY_CODEC_G729A 
SKINNY_CODEC_G726_32 
SKINNY_CODEC_H261 
SKINNY_CODEC_H263 

Definition at line 150 of file chan_skinny.c.

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


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 245 of file chan_skinny.c.

00256 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 242 of file chan_skinny.c.

00256 {

static void __reg_module ( void   )  [static]

Definition at line 7562 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 7562 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 3247 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, skinny_subchannel::list, 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().

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

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 3136 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_subchannel::list, skinny_device::session, and skinnysession::sin.

Referenced by handle_skinny_show_devices(), and manager_skinny_show_devices().

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

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 3504 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, skinny_subchannel::list, 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().

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

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 3380 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, skinny_subchannel::list, ast_channel::name, skinny_subchannel::owner, and skinny_line::sub.

Referenced by handle_skinny_show_lines(), and manager_skinny_show_lines().

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

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

Definition at line 6499 of file chan_skinny.c.

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

Referenced by config_load().

06500 {
06501    int as;
06502    struct sockaddr_in sin;
06503    socklen_t sinlen;
06504    struct skinnysession *s;
06505    struct protoent *p;
06506    int arg = 1;
06507 
06508    for (;;) {
06509       sinlen = sizeof(sin);
06510       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
06511       if (as < 0) {
06512          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
06513          continue;
06514       }
06515 
06516       if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) {
06517          close(as);
06518          ast_atomic_fetchadd_int(&unauth_sessions, -1);
06519          continue;
06520       }
06521 
06522       p = getprotobyname("tcp");
06523       if(p) {
06524          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
06525             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
06526          }
06527       }
06528       if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
06529          close(as);
06530          ast_atomic_fetchadd_int(&unauth_sessions, -1);
06531          continue;
06532       }
06533 
06534       memcpy(&s->sin, &sin, sizeof(sin));
06535       ast_mutex_init(&s->lock);
06536       s->fd = as;
06537 
06538       if(time(&s->start) == -1) {
06539          ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
06540          destroy_session(s);
06541          continue;
06542       }
06543 
06544       AST_LIST_LOCK(&sessions);
06545       AST_LIST_INSERT_HEAD(&sessions, s, list);
06546       AST_LIST_UNLOCK(&sessions);
06547 
06548       if (ast_pthread_create(&s->t, NULL, skinny_session, s)) {
06549          destroy_session(s);
06550       }
06551    }
06552    if (skinnydebug)
06553       ast_verb(1, "killing accept thread\n");
06554    close(as);
06555    return 0;
06556 }

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

implement the setvar config line

Definition at line 1637 of file chan_skinny.c.

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

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

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

Definition at line 1798 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( format_t  astcodec  )  [static]

Definition at line 1741 of file chan_skinny.c.

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

Referenced by transmit_connect(), and transmit_startmediatransmission().

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

static format_t codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

Definition at line 1719 of file chan_skinny.c.

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

Referenced by handle_capabilities_res_message().

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

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

Definition at line 2940 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, and skinny_subchannel::list.

Referenced by complete_skinny_reset(), and complete_skinny_show_device().

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

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

Definition at line 2959 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

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

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

Definition at line 2954 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

02955 {
02956    return (pos == 3 ? ast_strdup(complete_skinny_devices(word, state)) : NULL);
02957 }

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

Definition at line 2964 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_strdup, skinny_device::lines, and skinny_subchannel::list.

Referenced by handle_skinny_show_line().

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

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

Definition at line 7117 of file chan_skinny.c.

References 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_subchannel::list, skinny_line::lock, LOG_ERROR, LOG_NOTICE, skinny_subchannel::parent, skinny_device::session, skinny_line::sub, TYPE_DEVICE, and update().

Referenced by config_load().

07118  {
07119    struct skinny_device *d, *temp;
07120    struct skinny_line *l, *ltemp;
07121    struct skinny_subchannel *sub;
07122    int update = 0;
07123  
07124    ast_log(LOG_NOTICE, "Configuring skinny device %s.\n", dname);
07125 
07126    AST_LIST_LOCK(&devices);
07127    AST_LIST_TRAVERSE(&devices, temp, list) {
07128       if (!strcasecmp(dname, temp->name) && temp->prune) {
07129          update = 1;
07130          break;
07131       }
07132    }
07133 
07134    if (!(d = ast_calloc(1, sizeof(*d)))) {
07135       ast_verb(1, "Unable to allocate memory for device %s.\n", dname);
07136       AST_LIST_UNLOCK(&devices);
07137       return NULL;
07138    }
07139    memcpy(d, default_device, sizeof(*default_device));
07140    ast_mutex_init(&d->lock);
07141    ast_copy_string(d->name, dname, sizeof(d->name));
07142    AST_LIST_INSERT_TAIL(&devices, d, list);
07143 
07144    ast_mutex_lock(&d->lock);
07145    AST_LIST_UNLOCK(&devices);
07146  
07147    config_parse_variables(TYPE_DEVICE, d, v);
07148  
07149    if (!AST_LIST_FIRST(&d->lines)) {
07150       ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
07151       ast_mutex_unlock(&d->lock);
07152       return NULL;
07153    }
07154    if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
07155       d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
07156    }
07157  
07158    if (skinnyreload){
07159       AST_LIST_LOCK(&devices);
07160       AST_LIST_TRAVERSE(&devices, temp, list) {
07161          if (strcasecmp(d->id, temp->id) || !temp->prune || !temp->session) {
07162             continue;
07163          }
07164          ast_mutex_lock(&d->lock);
07165          d->session = temp->session;
07166          d->session->device = d;
07167 
07168          AST_LIST_LOCK(&d->lines);
07169          AST_LIST_TRAVERSE(&d->lines, l, list){
07170             l->device = d; 
07171 
07172             AST_LIST_LOCK(&temp->lines);
07173             AST_LIST_TRAVERSE(&temp->lines, ltemp, list) {
07174                if (strcasecmp(l->name, ltemp->name)) {
07175                   continue;
07176                }
07177                ast_mutex_lock(&ltemp->lock);
07178                l->instance = ltemp->instance;
07179                l->hookstate = ltemp->hookstate;
07180                if (!AST_LIST_EMPTY(&ltemp->sub)) {
07181                   ast_mutex_lock(&l->lock);
07182                   l->sub = ltemp->sub;
07183                   AST_LIST_TRAVERSE(&l->sub, sub, list) {
07184                      sub->parent = l;
07185                   }
07186                   ast_mutex_unlock(&l->lock);
07187                }
07188                ast_mutex_unlock(&ltemp->lock);
07189             }
07190             AST_LIST_UNLOCK(&temp->lines);
07191          }
07192          AST_LIST_UNLOCK(&d->lines);
07193          ast_mutex_unlock(&d->lock);
07194       }
07195       AST_LIST_UNLOCK(&devices);
07196    }
07197 
07198    ast_mutex_unlock(&d->lock);
07199 
07200    ast_verb(3, "%s config for device '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), d->name);
07201    
07202    return d;
07203 
07204  }

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

Definition at line 7059 of file chan_skinny.c.

References skinny_line::all, ast_calloc, ast_copy_string(), AST_EVENT_IE_CONTEXT, AST_EVENT_IE_END, AST_EVENT_IE_MAILBOX, AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS, AST_EVENT_IE_PLTYPE_STR, AST_EVENT_MWI, ast_event_subscribe(), AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), ast_mutex_init, ast_mutex_lock, ast_mutex_unlock, ast_strdupa, ast_strlen_zero(), ast_verb, config_parse_variables(), default_line, LOG_NOTICE, mwi_event_cb(), strsep(), TYPE_LINE, and update().

Referenced by config_load().

07060  {
07061    struct skinny_line *l, *temp;
07062    int update = 0;
07063  
07064    ast_log(LOG_NOTICE, "Configuring skinny line %s.\n", lname);
07065 
07066    /* We find the old line and remove it just before the new
07067       line is created */
07068    AST_LIST_LOCK(&lines);
07069    AST_LIST_TRAVERSE(&lines, temp, all) {
07070       if (!strcasecmp(lname, temp->name) && temp->prune) {
07071          update = 1;
07072          break;
07073       }
07074    }
07075 
07076    if (!(l=ast_calloc(1, sizeof(*l)))) {
07077       ast_verb(1, "Unable to allocate memory for line %s.\n", lname);
07078       AST_LIST_UNLOCK(&lines);
07079       return NULL;
07080    }
07081 
07082    memcpy(l, default_line, sizeof(*default_line));
07083    ast_mutex_init(&l->lock);
07084    ast_copy_string(l->name, lname, sizeof(l->name));
07085    AST_LIST_INSERT_TAIL(&lines, l, all);
07086 
07087    ast_mutex_lock(&l->lock);
07088    AST_LIST_UNLOCK(&lines);
07089 
07090    config_parse_variables(TYPE_LINE, l, v);
07091          
07092    if (!ast_strlen_zero(l->mailbox)) {
07093       char *cfg_mailbox, *cfg_context;
07094       cfg_context = cfg_mailbox = ast_strdupa(l->mailbox);
07095       ast_verb(3, "Setting mailbox '%s' on line %s\n", cfg_mailbox, l->name);
07096       strsep(&cfg_context, "@");
07097       if (ast_strlen_zero(cfg_context))
07098           cfg_context = "default";
07099       l->mwi_event_sub = ast_event_subscribe(AST_EVENT_MWI, mwi_event_cb, "skinny MWI subsciption", l,
07100          AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, cfg_mailbox,
07101          AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, cfg_context,
07102          AST_EVENT_IE_NEWMSGS, AST_EVENT_IE_PLTYPE_EXISTS,
07103          AST_EVENT_IE_END);
07104    }
07105  
07106    ast_mutex_unlock(&l->lock);
07107    
07108    /* We do not want to unlink or free the line yet, it needs
07109       to be available to detect a device reconfig when we load the
07110       devices.  Old lines will be pruned after the reload completes */
07111 
07112    ast_verb(3, "%s config for line '%s'\n", update ? "Updated" : (skinnyreload ? "Reloaded" : "Created"), l->name);
07113 
07114    return l;
07115  }

static int config_load ( void   )  [static]

Definition at line 7206 of file chan_skinny.c.

References 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, config_device(), config_flags, config_line(), config_parse_variables(), CONFIG_STATUS_FILEINVALID, default_device, default_jbconf, 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().

07207  {
07208    int on = 1;
07209    struct ast_config *cfg;
07210    char *cat;
07211    int oldport = ntohs(bindaddr.sin_port);
07212    struct ast_flags config_flags = { 0 };
07213    
07214    ast_log(LOG_NOTICE, "Configuring skinny from %s\n", config);
07215   
07216    if (gethostname(ourhost, sizeof(ourhost))) {
07217       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled.\n");
07218       return 0;
07219    }
07220    cfg = ast_config_load(config, config_flags);
07221   
07222    /* We *must* have a config file otherwise stop immediately */
07223    if (!cfg || cfg == CONFIG_STATUS_FILEINVALID) {
07224       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled.\n", config);
07225       return -1;
07226    }
07227    memset(&bindaddr, 0, sizeof(bindaddr));
07228    memset(&default_prefs, 0, sizeof(default_prefs));
07229 
07230    /* Copy the default jb config over global_jbconf */
07231    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
07232 
07233    /* load the general section */
07234    cat = ast_category_browse(cfg, "general");
07235    config_parse_variables(TYPE_GENERAL, NULL, ast_variable_browse(cfg, "general"));
07236 
07237    if (ntohl(bindaddr.sin_addr.s_addr)) {
07238       __ourip = bindaddr.sin_addr;
07239    } else {
07240       hp = ast_gethostbyname(ourhost, &ahp);
07241       if (!hp) {
07242          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
07243          ast_config_destroy(cfg);
07244          return 0;
07245       }
07246       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
07247    }
07248    if (!ntohs(bindaddr.sin_port)) {
07249       bindaddr.sin_port = htons(DEFAULT_SKINNY_PORT);
07250    }
07251    bindaddr.sin_family = AF_INET;
07252 
07253    /* load the lines sections */
07254    default_line->confcapability = default_capability;
07255    default_line->confprefs = default_prefs;
07256    config_parse_variables(TYPE_DEF_LINE, default_line, ast_variable_browse(cfg, "lines"));
07257    cat = ast_category_browse(cfg, "lines");
07258    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "devices")) {
07259       config_line(cat, ast_variable_browse(cfg, cat));
07260       cat = ast_category_browse(cfg, cat);
07261    }
07262       
07263    /* load the devices sections */
07264    default_device->confcapability = default_capability;
07265    default_device->confprefs = default_prefs;
07266    config_parse_variables(TYPE_DEF_DEVICE, default_device, ast_variable_browse(cfg, "devices"));
07267    cat = ast_category_browse(cfg, "devices");
07268    while (cat && strcasecmp(cat, "general") && strcasecmp(cat, "lines")) {
07269       config_device(cat, ast_variable_browse(cfg, cat));
07270       cat = ast_category_browse(cfg, cat);
07271    }
07272 
07273    ast_mutex_lock(&netlock);
07274    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
07275       close(skinnysock);
07276       skinnysock = -1;
07277    }
07278    if (skinnysock < 0) {
07279       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
07280       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
07281          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
07282          ast_config_destroy(cfg);
07283          ast_mutex_unlock(&netlock);
07284          return 0;
07285       }
07286       if (skinnysock < 0) {
07287          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
07288       } else {
07289          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
07290             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
07291                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07292                      strerror(errno));
07293             close(skinnysock);
07294             skinnysock = -1;
07295             ast_config_destroy(cfg);
07296             ast_mutex_unlock(&netlock);
07297             return 0;
07298          }
07299          if (listen(skinnysock, DEFAULT_SKINNY_BACKLOG)) {
07300                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
07301                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
07302                      strerror(errno));
07303                close(skinnysock);
07304                skinnysock = -1;
07305                ast_config_destroy(cfg);
07306                ast_mutex_unlock(&netlock);
07307                return 0;
07308          }
07309          ast_verb(2, "Skinny listening on %s:%d\n",
07310                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
07311          ast_netsock_set_qos(skinnysock, qos.tos, qos.cos, "Skinny");
07312          ast_pthread_create_background(&accept_t, NULL, accept_thread, NULL);
07313       }
07314    }
07315    ast_mutex_unlock(&netlock);
07316    ast_config_destroy(cfg);
07317    return 1;
07318 }

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

Definition at line 6665 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_sockaddr_to_sin, ast_str2cos(), ast_str2tos(), ast_strlen_zero(), ast_true(), CDEV, CDEV_OPTS, cleanup_stale_contexts(), CLINE, CLINE_OPTS, context, DEFAULT_AUTH_LIMIT, DEFAULT_AUTH_TIMEOUT, default_prefs, exten, global_jbconf, skinny_speeddial::label, ast_variable::lineno, skinny_device::lines, skinny_subchannel::list, LOG_WARNING, ast_variable::name, ast_variable::next, qos, S_OR, ast_sockaddr::ss, strsep(), 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().

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

static char* control2str ( int  ind  )  [static]

Definition at line 4249 of file chan_skinny.c.

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

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

static void delete_devices ( void   )  [static]

Definition at line 7320 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, skinny_subchannel::list, and skinny_device::speeddials.

Referenced by unload_module().

07321 {
07322    struct skinny_device *d;
07323    struct skinny_line *l;
07324    struct skinny_speeddial *sd;
07325    struct skinny_addon *a;
07326 
07327    AST_LIST_LOCK(&devices);
07328    AST_LIST_LOCK(&lines);
07329 
07330    /* Delete all devices */
07331    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
07332       /* Delete all lines for this device */
07333       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07334          AST_LIST_REMOVE(&lines, l, all);
07335          free(l);
07336       }
07337       /* Delete all speeddials for this device */
07338       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07339          free(sd);
07340       }
07341       /* Delete all addons for this device */
07342       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07343          free(a);
07344       } 
07345       free(d);
07346    }
07347    AST_LIST_UNLOCK(&lines);
07348    AST_LIST_UNLOCK(&devices);
07349 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 6316 of file chan_skinny.c.

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

Referenced by accept_thread(), fax_session_new(), fax_session_reserve(), and skinny_session().

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

static char* device2str ( int  type  )  [static]

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

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

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

Definition at line 6558 of file chan_skinny.c.

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

06559 {
06560    int res;
06561 
06562    /* This thread monitors all the interfaces which are not yet in use
06563       (and thus do not have a separate thread) indefinitely */
06564    /* From here on out, we die whenever asked */
06565    for(;;) {
06566       pthread_testcancel();
06567       /* Wait for sched or io */
06568       res = ast_sched_wait(sched);
06569       if ((res < 0) || (res > 1000)) {
06570          res = 1000;
06571       }
06572       res = ast_io_wait(io, res);
06573       ast_mutex_lock(&monlock);
06574       if (res >= 0) {
06575          ast_sched_runq(sched);
06576       }
06577       ast_mutex_unlock(&monlock);
06578    }
06579    /* Never reached */
06580    return NULL;
06581 
06582 }

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

Definition at line 1565 of file chan_skinny.c.

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

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

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

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

Definition at line 1586 of file chan_skinny.c.

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

Referenced by skinny_devicestate(), and skinny_request().

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

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

Definition at line 1704 of file chan_skinny.c.

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

Referenced by handle_message(), and handle_stimulus_message().

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

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

Definition at line 1653 of file chan_skinny.c.

References AST_LIST_FIRST, AST_LIST_TRAVERSE, ast_log(), skinny_subchannel::callid, find_line_by_instance(), skinny_subchannel::list, 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().

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

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

Definition at line 1680 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message().

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

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

Definition at line 1414 of file chan_skinny.c.

References 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, skinny_subchannel::list, LOG_WARNING, SKINNY_DEVICE_12, SKINNY_DEVICE_12SP, SKINNY_DEVICE_12SPPLUS, SKINNY_DEVICE_30SPPLUS, SKINNY_DEVICE_30VIP, SKINNY_DEVICE_7902, SKINNY_DEVICE_7905, SKINNY_DEVICE_7906, SKINNY_DEVICE_7910, SKINNY_DEVICE_7911, SKINNY_DEVICE_7912, SKINNY_DEVICE_7914, SKINNY_DEVICE_7920, SKINNY_DEVICE_7921, SKINNY_DEVICE_7931, SKINNY_DEVICE_7935, SKINNY_DEVICE_7936, SKINNY_DEVICE_7937, SKINNY_DEVICE_7940, SKINNY_DEVICE_7941, SKINNY_DEVICE_7941GE, SKINNY_DEVICE_7942, SKINNY_DEVICE_7945, SKINNY_DEVICE_7960, SKINNY_DEVICE_7961, SKINNY_DEVICE_7961GE, SKINNY_DEVICE_7962, SKINNY_DEVICE_7965, SKINNY_DEVICE_7970, SKINNY_DEVICE_7971, SKINNY_DEVICE_7975, SKINNY_DEVICE_7985, SKINNY_DEVICE_ATA186, SKINNY_DEVICE_CIPC, SKINNY_DEVICE_SCCPGATEWAY_AN, SKINNY_DEVICE_SCCPGATEWAY_BRI, and skinny_addon::type.

Referenced by handle_button_template_req_message().

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

static int get_devicestate ( struct skinny_line l  )  [static]

Definition at line 4220 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::list, skinny_subchannel::onhold, SKINNY_ONHOOK, and skinny_line::sub.

Referenced by skinny_devicestate(), and skinny_new().

04221 {
04222    struct skinny_subchannel *sub;
04223    int res = AST_DEVICE_UNKNOWN;
04224 
04225    if (!l)
04226       res = AST_DEVICE_INVALID;
04227    else if (!l->device)
04228       res = AST_DEVICE_UNAVAILABLE;
04229    else if (l->dnd)
04230       res = AST_DEVICE_BUSY;
04231    else {
04232       if (l->hookstate == SKINNY_ONHOOK) {
04233          res = AST_DEVICE_NOT_INUSE;
04234       } else {
04235          res = AST_DEVICE_INUSE;
04236       }
04237 
04238       AST_LIST_TRAVERSE(&l->sub, sub, list) {
04239          if (sub->onhold) {
04240             res = AST_DEVICE_ONHOLD;
04241             break;
04242          }
04243       }
04244    }
04245 
04246    return res;
04247 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 6340 of file chan_skinny.c.

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

Referenced by do_message(), and skinny_session().

06341 {
06342    int res;
06343    int dlen = 0;
06344    int timeout = keep_alive * 1100;
06345    time_t now;
06346    int *bufaddr;
06347    struct pollfd fds[1];
06348 
06349    if (!s->device) {
06350       if(time(&now) == -1) {
06351          ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
06352          return -1;
06353       }
06354 
06355       timeout = (auth_timeout - (now - s->start)) * 1000;
06356       if (timeout < 0) {
06357          /* we have timed out */
06358          if (skinnydebug)
06359             ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
06360          return -1;
06361       }
06362    }
06363 
06364    fds[0].fd = s->fd;
06365    fds[0].events = POLLIN;
06366    fds[0].revents = 0;
06367    res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */
06368                    /* we add 10% to the keep_alive to deal */
06369                    /* with network delays, etc */
06370    if (res < 0) {
06371       if (errno != EINTR) {
06372          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
06373          return res;
06374       }
06375    } else if (res == 0) {
06376       if (skinnydebug) {
06377          if (s->device) {
06378             ast_verb(1, "Skinny Client was lost, unregistering\n");
06379          } else {
06380             ast_verb(1, "Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
06381          }
06382       }
06383       skinny_unregister(NULL, s);
06384       return -1;
06385    }
06386            
06387    if (fds[0].revents) {
06388       ast_mutex_lock(&s->lock);
06389       memset(s->inbuf, 0, sizeof(s->inbuf));
06390       res = read(s->fd, s->inbuf, 4);
06391       if (res < 0) {
06392          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06393 
06394          if (skinnydebug)
06395             ast_verb(1, "Skinny Client was lost, unregistering\n");
06396 
06397          skinny_unregister(NULL, s);
06398          ast_mutex_unlock(&s->lock);
06399          return res;
06400       } else if (res != 4) {
06401          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
06402          ast_mutex_unlock(&s->lock);
06403          
06404          if (res == 0) {
06405             if (skinnydebug)
06406                ast_verb(1, "Skinny Client was lost, unregistering\n");
06407             skinny_unregister(NULL, s);
06408          }
06409 
06410          return -1;
06411       }
06412 
06413       bufaddr = (int *)s->inbuf;
06414       dlen = letohl(*bufaddr);
06415       if (dlen < 4) {
06416          ast_debug(1, "Skinny Client sent invalid data.\n");
06417          ast_mutex_unlock(&s->lock);
06418          return -1;
06419       }
06420       if (dlen+8 > sizeof(s->inbuf)) {
06421          dlen = sizeof(s->inbuf) - 8;
06422       }
06423       *bufaddr = htolel(dlen);
06424 
06425       res = read(s->fd, s->inbuf+4, dlen+4);
06426       ast_mutex_unlock(&s->lock);
06427       if (res < 0) {
06428          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
06429          return res;
06430       } else if (res != (dlen+4)) {
06431          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
06432          return -1;
06433       }
06434       return res;
06435    }
06436    return 0;
06437 }

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

Definition at line 5506 of file chan_skinny.c.

References AST_LIST_TRAVERSE, ast_verb, BT_CUST_LINE, BT_LINE, BT_NONE, BUTTON_TEMPLATE_RES_MESSAGE, button_definition::buttonDefinition, button_definition_template::buttonDefinition, skinny_data::buttontemplate, skinny_req::data, button_template_res_message::definition, skinnysession::device, get_button_template(), skinny_speeddial::instance, button_definition::instanceNumber, skinny_speeddial::isHint, skinny_device::lines, skinny_subchannel::list, req_alloc(), and skinny_device::speeddials.

Referenced by handle_message().

05507 {
05508    struct skinny_device *d = s->device;
05509    struct skinny_line *l;
05510    int i;
05511 
05512    struct skinny_speeddial *sd;
05513    struct button_definition_template btn[42];
05514    int lineInstance = 1;
05515    int speeddialInstance = 1;
05516    int buttonCount = 0;
05517 
05518    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
05519       return -1;
05520 
05521    memset(&btn, 0, sizeof(btn));
05522 
05523    get_button_template(s, btn);
05524 
05525    for (i=0; i<42; i++) {
05526       int btnSet = 0;
05527       switch (btn[i].buttonDefinition) {
05528          case BT_CUST_LINE:
05529             /* assume failure */
05530             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05531             req->data.buttontemplate.definition[i].instanceNumber = 0;
05532 
05533             AST_LIST_TRAVERSE(&d->lines, l, list) {
05534                if (l->instance == lineInstance) {
05535                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05536                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05537                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05538                   lineInstance++;
05539                   buttonCount++;
05540                   btnSet = 1;
05541                   break;
05542                }
05543             }
05544 
05545             if (!btnSet) {
05546                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05547                   if (sd->isHint && sd->instance == lineInstance) {
05548                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05549                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05550                      req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05551                      lineInstance++;
05552                      buttonCount++;
05553                      btnSet = 1;
05554                      break;
05555                   }
05556                }
05557             }
05558             break;
05559          case BT_CUST_LINESPEEDDIAL:
05560             /* assume failure */
05561             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05562             req->data.buttontemplate.definition[i].instanceNumber = 0;
05563 
05564             AST_LIST_TRAVERSE(&d->lines, l, list) {
05565                if (l->instance == lineInstance) {
05566                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05567                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05568                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05569                   lineInstance++;
05570                   buttonCount++;
05571                   btnSet = 1;
05572                   break;
05573                }
05574             }
05575 
05576             if (!btnSet) {
05577                AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05578                   if (sd->isHint && sd->instance == lineInstance) {
05579                      ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05580                      req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05581                      req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05582                      lineInstance++;
05583                      buttonCount++;
05584                      btnSet = 1;
05585                      break;
05586                   } else if (!sd->isHint && sd->instance == speeddialInstance) {
05587                      ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05588                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05589                      req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance;
05590                      speeddialInstance++;
05591                      buttonCount++;
05592                      btnSet = 1;
05593                      break;
05594                   }
05595                }
05596             }
05597             break;
05598          case BT_LINE:
05599             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
05600             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
05601 
05602             AST_LIST_TRAVERSE(&d->lines, l, list) {
05603                if (l->instance == lineInstance) {
05604                   ast_verb(0, "Adding button: %d, %d\n", BT_LINE, lineInstance);
05605                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
05606                   req->data.buttontemplate.definition[i].instanceNumber = lineInstance;
05607                   lineInstance++;
05608                   buttonCount++;
05609                   btnSet = 1;
05610                   break;
05611                }
05612             }
05613             break;
05614          case BT_SPEEDDIAL:
05615             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
05616             req->data.buttontemplate.definition[i].instanceNumber = 0;
05617 
05618             AST_LIST_TRAVERSE(&d->speeddials, sd, list) {
05619                if (!sd->isHint && sd->instance == speeddialInstance) {
05620                   ast_verb(0, "Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
05621                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
05622                   req->data.buttontemplate.definition[i].instanceNumber = speeddialInstance - 1;
05623                   speeddialInstance++;
05624                   buttonCount++;
05625                   btnSet = 1;
05626                   break;
05627                }
05628             }
05629             break;
05630          case BT_NONE:
05631             break;
05632          default:
05633             ast_verb(0, "Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
05634             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
05635             req->data.buttontemplate.definition[i].instanceNumber = 0;
05636             buttonCount++;
05637             btnSet = 1;
05638             break;
05639       }
05640    }
05641 
05642    req->data.buttontemplate.buttonOffset = 0;
05643    req->data.buttontemplate.buttonCount = htolel(buttonCount);
05644    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
05645 
05646    if (skinnydebug)
05647       ast_verb(1, "Sending %d template to %s\n",
05648                d->type,
05649                d->name);
05650    transmit_response(d, req);
05651    return 1;
05652 }

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

Definition at line 4817 of file chan_skinny.c.

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

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

04818 {
04819    struct skinny_line *l = sub->parent;
04820    struct skinny_device *d = l->device;
04821    struct ast_channel *c = sub->owner;
04822    pthread_t t;
04823 
04824    if (l->hookstate == SKINNY_ONHOOK) {
04825       l->hookstate = SKINNY_OFFHOOK;
04826       transmit_speaker_mode(d, SKINNY_SPEAKERON);
04827       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
04828       transmit_activatecallplane(d, l);
04829    }
04830    transmit_clear_display_message(d, l->instance, sub->callid);
04831 
04832    if (l->cfwdtype & cfwdtype) {
04833       set_callforwards(l, NULL, cfwdtype);
04834       ast_safe_sleep(c, 500);
04835       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04836       transmit_closereceivechannel(d, sub);
04837       transmit_stopmediatransmission(d, sub);
04838       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
04839       transmit_clearpromptmessage(d, l->instance, sub->callid);
04840       transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
04841       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
04842       transmit_activatecallplane(d, l);
04843       transmit_displaynotify(d, "CFwd disabled", 10);
04844       if (sub->owner && sub->owner->_state != AST_STATE_UP) {
04845          ast_indicate(c, -1);
04846          ast_hangup(c);
04847       }
04848       transmit_cfwdstate(d, l);
04849    } else {
04850       l->getforward = cfwdtype;
04851       transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
04852       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_RINGOUT);
04853       if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04854          ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04855          ast_hangup(c);
04856       }
04857    }
04858    return 0;
04859 }

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

Definition at line 5470 of file chan_skinny.c.

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

Referenced by handle_message().

05471 {
05472    struct skinny_device *d = s->device;
05473    struct skinny_line *l;
05474    uint32_t count = 0;
05475    format_t codecs = 0;
05476    int i;
05477    char buf[256];
05478 
05479    count = letohl(req->data.caps.count);
05480    if (count > SKINNY_MAX_CAPABILITIES) {
05481       count = SKINNY_MAX_CAPABILITIES;
05482       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
05483    }
05484 
05485    for (i = 0; i < count; i++) {
05486       format_t acodec = 0;
05487       int scodec = 0;
05488       scodec = letohl(req->data.caps.caps[i].codec);
05489       acodec = codec_skinny2ast(scodec);
05490       if (skinnydebug)
05491          ast_verb(1, "Adding codec capability '%" PRId64 " (%d)'\n", acodec, scodec);
05492       codecs |= acodec;
05493    }
05494 
05495    d->capability = d->confcapability & codecs;
05496    ast_verb(0, "Device capability set to '%s'\n", ast_getformatname_multiple(buf, sizeof(buf), d->capability));
05497    AST_LIST_TRAVERSE(&d->lines, l, list) {
05498       ast_mutex_lock(&l->lock);
05499       l->capability = l->confcapability & d->capability;
05500       ast_mutex_unlock(&l->lock);
05501    }
05502 
05503    return 1;
05504 }

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

Definition at line 5715 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, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_start_tone(), and transmit_stop_tone().

Referenced by handle_message().

05716 {
05717    struct skinny_device *d = s->device;
05718    struct skinny_line *l;
05719    struct skinny_subchannel *sub = NULL;
05720    struct ast_channel *c;
05721    pthread_t t;
05722 
05723    if (skinnydebug)
05724       ast_verb(1, "Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
05725 
05726    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05727 
05728    if (!sub) {
05729       l = find_line_by_instance(d, d->lastlineinstance);
05730       if (!l) {
05731          return 0;
05732       }
05733    } else {
05734       l = sub->parent;
05735    }
05736 
05737    c = skinny_new(l, AST_STATE_DOWN, NULL);
05738 
05739    if(!c) {
05740       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05741    } else {
05742       l->hookstate = SKINNY_OFFHOOK;
05743 
05744       sub = c->tech_pvt;
05745       l->activesub = sub;
05746       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05747       transmit_activatecallplane(d, l);
05748       transmit_clear_display_message(d, l->instance, sub->callid);
05749       transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05750 
05751       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
05752          transmit_stop_tone(d, l->instance, sub->callid);
05753       }
05754       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
05755       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
05756          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
05757          ast_hangup(c);
05758       }
05759    }
05760    
05761    return 1;
05762 }

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

04658 {
04659    if (!sub)
04660       return -1;
04661    if (sub->related) {
04662       skinny_hold(sub);
04663       skinny_unhold(sub->related);
04664       sub->parent->activesub = sub->related;
04665    } else {
04666       if (sub->onhold) {
04667          skinny_unhold(sub);
04668          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_CONNECTED);
04669       } else {
04670          skinny_hold(sub);
04671          transmit_selectsoftkeys(sub->parent->device, sub->parent->instance, sub->callid, KEYDEF_ONHOLD);
04672       }
04673    }
04674    return 1;
04675 }

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

Definition at line 4860 of file chan_skinny.c.

Referenced by handle_message().

04861 {
04862    /* no response necessary */
04863    return 1;
04864 }

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

Definition at line 4741 of file chan_skinny.c.

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

Referenced by handle_message().

04742 {
04743    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04744       return -1;
04745 
04746    transmit_response(s->device, req);
04747    return 1;
04748 }

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

Definition at line 4866 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, f, find_subchannel_by_instance_reference(), skinny_data::keypad, letohl, keypad_button_message::lineInstance, skinny_subchannel::list, LOG_WARNING, skinny_subchannel::owner, and skinny_subchannel::parent.

Referenced by handle_message().

04867 {
04868    struct skinny_subchannel *sub = NULL;
04869    struct skinny_line *l;
04870    struct skinny_device *d = s->device;
04871    struct ast_frame f = { 0, };
04872    char dgt;
04873    int digit;
04874    int lineInstance;
04875    int callReference;
04876 
04877    digit = letohl(req->data.keypad.button);
04878    lineInstance = letohl(req->data.keypad.lineInstance);
04879    callReference = letohl(req->data.keypad.callReference);
04880 
04881    if (digit == 14) {
04882       dgt = '*';
04883    } else if (digit == 15) {
04884       dgt = '#';
04885    } else if (digit >= 0 && digit <= 9) {
04886       dgt = '0' + digit;
04887    } else {
04888       /* digit=10-13 (A,B,C,D ?), or
04889        * digit is bad value
04890        *
04891        * probably should not end up here, but set
04892        * value for backward compatibility, and log
04893        * a warning.
04894        */
04895       dgt = '0' + digit;
04896       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04897    }
04898 
04899    f.subclass.integer = dgt;
04900 
04901    f.src = "skinny";
04902 
04903    if (lineInstance && callReference)
04904       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04905    else
04906       sub = d->activeline->activesub;
04907       //sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
04908 
04909    if (!sub)
04910       return 0;
04911 
04912    l = sub->parent;
04913    if (sub->owner) {
04914       if (sub->owner->_state == 0) {
04915          f.frametype = AST_FRAME_DTMF_BEGIN;
04916          ast_queue_frame(sub->owner, &f);
04917       }
04918       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
04919       f.frametype = AST_FRAME_DTMF_END;
04920       ast_queue_frame(sub->owner, &f);
04921       /* XXX This seriously needs to be fixed */
04922       if (AST_LIST_NEXT(sub, list) && AST_LIST_NEXT(sub, list)->owner) {
04923          if (sub->owner->_state == 0) {
04924             f.frametype = AST_FRAME_DTMF_BEGIN;
04925             ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04926          }
04927          f.frametype = AST_FRAME_DTMF_END;
04928          ast_queue_frame(AST_LIST_NEXT(sub, list)->owner, &f);
04929       }
04930    } else {
04931       if (skinnydebug)
04932          ast_verb(1, "No owner: %s\n", l->name);
04933    }
04934    return 1;
04935 }

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

Definition at line 6138 of file chan_skinny.c.

References ast_channel::_state, skinny_device::activeline, skinny_line::activesub, skinny_data::alarm, ALARM_MESSAGE, ast_free, ast_log(), AST_STATE_UP, ast_verb, keypad_button_message::button, BUTTON_TEMPLATE_REQ_MESSAGE, keypad_button_message::callReference, CAPABILITIES_RES_MESSAGE, skinny_req::data, skinnysession::device, alarm_message::displayMessage, skinny_req::e, ENBLOC_CALL_MESSAGE, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), handle_button_template_req_message(), handle_capabilities_res_message(), handle_enbloc_call_message(), handle_ip_port_message(), handle_keep_alive_message(), handle_keypad_button_message(), handle_offhook_message(), handle_onhook_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_soft_key_event_message(), handle_stimulus_message(), HEADSET_STATUS_MESSAGE, IP_PORT_MESSAGE, KEEP_ALIVE_MESSAGE, KEYDEF_ONHOOK, skinny_data::keypad, KEYPAD_BUTTON_MESSAGE, letohl, skinny_data::line, LINE_STATE_REQ_MESSAGE, keypad_button_message::lineInstance, line_state_req_message::lineNumber, LOG_WARNING, register_message::name, OFFHOOK_MESSAGE, skinny_subchannel::onhold, ONHOOK_MESSAGE, OPEN_RECEIVE_CHANNEL_ACK_MESSAGE, skinny_subchannel::owner, skinny_data::reg, REGISTER_AVAILABLE_LINES_MESSAGE, REGISTER_MESSAGE, SERVER_REQUEST_MESSAGE, SKINNY_DEVONLY, skinny_unregister(), SOFT_KEY_EVENT_MESSAGE, SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SPEED_DIAL_STAT_REQ_MESSAGE, speed_dial_stat_req_message::speedDialNumber, skinny_data::speeddialreq, STIMULUS_MESSAGE, TIME_DATE_REQ_MESSAGE, transmit_definetimedate(), transmit_linestatres(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speeddialstatres(), transmit_versionres(), UNREGISTER_MESSAGE, and VERSION_REQ_MESSAGE.

Referenced by skinny_session().

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

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

Definition at line 5289 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_verbose, 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, skinny_subchannel::list, LOG_WARNING, skinny_data::offhook, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, skinny_ss(), start_rtp(), STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_definetimedate(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_start_tone(), transmit_stop_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

05290 {
05291    struct skinny_device *d = s->device;
05292    struct skinny_line *l;
05293    struct skinny_subchannel *sub;
05294    struct ast_channel *c;
05295    struct skinny_line *tmp;
05296    pthread_t t;
05297    int instance;
05298 
05299    /* if any line on a device is offhook, than the device must be offhook, 
05300       unless we have shared lines CCM seems that it would never get here, 
05301       but asterisk does, so we may need to do more work.  Ugly, we should 
05302       probably move hookstate from line to device, afterall, it's actually
05303        a device that changes hookstates */
05304 
05305    AST_LIST_TRAVERSE(&d->lines, tmp, list) {
05306       if (tmp->hookstate == SKINNY_OFFHOOK) {
05307          ast_verbose(VERBOSE_PREFIX_3 "Got offhook message when device (%s@%s) already offhook\n", tmp->name, d->name);
05308          return 0;
05309       }
05310    }
05311 
05312    instance = letohl(req->data.offhook.instance);
05313 
05314    if (instance) {
05315       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
05316       if (!sub) {
05317          l = find_line_by_instance(d, d->lastlineinstance);
05318          if (!l) {
05319             return 0;
05320          }
05321       } else {
05322          l = sub->parent;
05323       }
05324    } else {
05325       l = d->activeline;
05326       sub = l->activesub;
05327    }
05328 
05329    /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
05330    transmit_definetimedate(d);
05331    
05332    transmit_ringer_mode(d, SKINNY_RING_OFF);
05333    l->hookstate = SKINNY_OFFHOOK;
05334 
05335    ast_devstate_changed(AST_DEVICE_INUSE, "Skinny/%s@%s", l->name, d->name);
05336 
05337    if (sub && sub->onhold) {
05338       return 1;
05339    }
05340 
05341    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
05342 
05343    if (sub && sub->outgoing) {
05344       /* We're answering a ringing call */
05345       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
05346       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05347       transmit_activatecallplane(d, l);
05348       transmit_stop_tone(d, l->instance, sub->callid);
05349       transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
05350       transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_CONNECTED);
05351       start_rtp(sub);
05352       ast_setstate(sub->owner, AST_STATE_UP);
05353    } else {
05354       if (sub && sub->owner) {
05355          ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
05356       } else {
05357          c = skinny_new(l, AST_STATE_DOWN, NULL);
05358          if (c) {
05359             sub = c->tech_pvt;
05360             l->activesub = sub;
05361             transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05362             transmit_activatecallplane(d, l);
05363             transmit_clear_display_message(d, l->instance, sub->callid);
05364             transmit_start_tone(d, SKINNY_DIALTONE, l->instance, sub->callid);
05365             transmit_selectsoftkeys(d, l->instance, sub->callid, KEYDEF_OFFHOOK);
05366 
05367             /* start the switch thread */
05368             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
05369                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
05370                ast_hangup(c);
05371             }
05372          } else {
05373             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
05374          }
05375       }
05376    }
05377    return 1;
05378 }

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

Definition at line 5380 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, KEYDEF_ONHOOK, letohl, skinny_subchannel::list, LOG_WARNING, skinny_subchannel::onhold, skinny_data::onhook, skinny_subchannel::owner, skinny_subchannel::parent, onhook_message::reference, skinny_subchannel::related, SKINNY_CX_RECVONLY, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, skinny_line::sub, transmit_activatecallplane(), transmit_callstate(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_definetimedate(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stopmediatransmission(), and skinny_subchannel::xferor.

Referenced by handle_message().

05381 {
05382    struct skinny_device *d = s->device;
05383    struct skinny_line *l;
05384    struct skinny_subchannel *sub;
05385    int instance;
05386    int reference;
05387    int onlysub = 0;
05388 
05389    instance = letohl(req->data.onhook.instance);
05390    reference = letohl(req->data.onhook.reference);
05391 
05392    if (instance && reference) {
05393       sub = find_subchannel_by_instance_reference(d, instance, reference);
05394       if (!sub) {
05395          return 0;
05396       }
05397       l = sub->parent;
05398    } else {
05399       l = d->activeline;
05400       sub = l->activesub;
05401       if (!sub) {
05402          return 0;
05403       }
05404    }
05405 
05406    if (l->hookstate == SKINNY_ONHOOK) {
05407       /* Something else already put us back on hook */
05408       return 0;
05409    }
05410 
05411    ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Skinny/%s@%s", l->name, d->name);
05412 
05413    if (sub->onhold) {
05414       return 0;
05415    }
05416 
05417    if (!AST_LIST_NEXT(sub, list)) {
05418       onlysub = 1;
05419    } else {
05420       AST_LIST_REMOVE(&l->sub, sub, list);
05421    }
05422 
05423    sub->cxmode = SKINNY_CX_RECVONLY;
05424    if (onlysub || sub->xferor){  /* is this the only call to this device? */
05425       l->hookstate = SKINNY_ONHOOK;
05426       if (skinnydebug)
05427          ast_debug(1, "Skinny %s@%s-%d went on hook\n", l->name, d->name, reference);
05428    }
05429 
05430    if (l->hookstate == SKINNY_ONHOOK) {
05431       transmit_closereceivechannel(d, sub);
05432       transmit_stopmediatransmission(d, sub);
05433       transmit_speaker_mode(d, SKINNY_SPEAKEROFF);
05434       transmit_clearpromptmessage(d, instance, sub->callid);
05435       transmit_callstate(d, l->instance, sub->callid, SKINNY_ONHOOK);
05436       transmit_selectsoftkeys(d, 0, 0, KEYDEF_ONHOOK);
05437       transmit_activatecallplane(d, l);
05438    } else if (l->hookstate == SKINNY_OFFHOOK) {
05439       transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
05440       transmit_activatecallplane(d, l);
05441    } else {
05442       transmit_callstate(d, l->instance, sub->callid, l->hookstate);
05443    }
05444 
05445    if (l->transfer && sub->xferor && sub->owner->_state >= AST_STATE_RING) {
05446       /* We're allowed to transfer, we have two active calls and
05447          we made at least one of the calls.  Let's try and transfer */
05448       handle_transfer_button(sub);
05449    } else {
05450       /* Hangup the current call */
05451       /* If there is another active call, skinny_hangup will ring the phone with the other call */
05452       if (sub->xferor && sub->related){
05453          sub->related->related = NULL;
05454          sub->related->blindxfer = 0;
05455       }
05456 
05457       if (sub->owner) {
05458          sub->alreadygone = 1;
05459          ast_queue_hangup(sub->owner);
05460       } else {
05461          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
05462             l->name, d->name, sub->callid);
05463       }
05464       /* Not ideal, but let's send updated time at onhook and offhook, as it clears the display */
05465       transmit_definetimedate(d);
05466    }
05467    return 1;
05468 }

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

Definition at line 5654 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_getformatname(), ast_inet_ntoa(), ast_log(), ast_rtp_instance_get_local_address(), ast_rtp_instance_set_remote_address(), ast_sockaddr_from_sin, ast_sockaddr_to_sin, ast_verb, ast_format_list::bits, ast_format_list::cur_ms, skinny_req::data, skinnysession::device, find_subchannel_by_reference(), open_receive_channel_ack_message::ipAddr, letohl, LOG_ERROR, skinny_data::openreceivechannelack, skinny_device::ourip, skinny_subchannel::parent, open_receive_channel_ack_message::passThruId, open_receive_channel_ack_message::port, skinny_subchannel::rtp, open_receive_channel_ack_message::status, status, and transmit_startmediatransmission().

Referenced by handle_message().

05655 {
05656    struct skinny_device *d = s->device;
05657    struct skinny_line *l;
05658    struct skinny_subchannel *sub;
05659    struct ast_format_list fmt;
05660    struct sockaddr_in sin = { 0, };
05661    struct sockaddr_in us = { 0, };
05662    struct ast_sockaddr sin_tmp;
05663    struct ast_sockaddr us_tmp;
05664    uint32_t addr;
05665    int port;
05666    int status;
05667    int passthruid;
05668 
05669    status = letohl(req->data.openreceivechannelack.status);
05670    if (status) {
05671       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
05672       return 0;
05673    }
05674    addr = req->data.openreceivechannelack.ipAddr;
05675    port = letohl(req->data.openreceivechannelack.port);
05676    passthruid = letohl(req->data.openreceivechannelack.passThruId);
05677 
05678    sin.sin_family = AF_INET;
05679    sin.sin_addr.s_addr = addr;
05680    sin.sin_port = htons(port);
05681 
05682    sub = find_subchannel_by_reference(d, passthruid);
05683 
05684    if (!sub)
05685       return 0;
05686 
05687    l = sub->parent;
05688 
05689    if (sub->rtp) {
05690       ast_sockaddr_from_sin(&sin_tmp, &sin);
05691       ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
05692       ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
05693       ast_sockaddr_to_sin(&us_tmp, &us);
05694       us.sin_addr.s_addr = us.sin_addr.s_addr ? us.sin_addr.s_addr : d->ourip.s_addr;
05695    } else {
05696       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
05697       return 0;
05698    }
05699 
05700    if (skinnydebug) {
05701       ast_verb(1, "device ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
05702       ast_verb(1, "asterisk ipaddr = %s:%d\n", ast_inet_ntoa(us.sin_addr), ntohs(us.sin_port));
05703    }
05704 
05705    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
05706 
05707    if (skinnydebug)
05708       ast_verb(1, "Setting payloadType to '%s' (%d ms)\n", ast_getformatname(fmt.bits), fmt.cur_ms);
05709 
05710    transmit_startmediatransmission(d, sub, us, fmt);
05711 
05712    return 1;
05713 }

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

Definition at line 4750 of file chan_skinny.c.

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

Referenced by handle_message().

04751 {
04752    struct skinny_device *d = NULL;
04753    char name[16];
04754    int res;
04755 
04756    memcpy(&name, req->data.reg.name, sizeof(name));
04757 
04758    res = skinny_register(req, s);
04759    if (!res) {
04760       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
04761       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
04762          return -1;
04763 
04764       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
04765 
04766       /* transmit_respons in line as we don't have a valid d */
04767       ast_mutex_lock(&s->lock);
04768 
04769       if (letohl(req->len) > SKINNY_MAX_PACKET || letohl(req->len) < 0) {
04770          ast_log(LOG_WARNING, "transmit_response: the length (%d) of the request is out of bounds (%d) \n",  letohl(req->len), SKINNY_MAX_PACKET);
04771          ast_mutex_unlock(&s->lock);
04772          return -1;
04773       }
04774 
04775       memset(s->outbuf, 0, sizeof(s->outbuf));
04776       memcpy(s->outbuf, req, skinny_header_size);
04777       memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
04778 
04779       res = write(s->fd, s->outbuf, letohl(req->len)+8);
04780 
04781       if (res != letohl(req->len)+8) {
04782          ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
04783       }
04784    
04785       ast_mutex_unlock(&s->lock);
04786 
04787       return 0;
04788    }
04789    ast_atomic_fetchadd_int(&unauth_sessions, -1);
04790 
04791    ast_verb(3, "Device '%s' successfully registered\n", name);
04792 
04793    d = s->device;
04794    
04795    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
04796       return -1;
04797 
04798    req->data.regack.res[0] = '0';
04799    req->data.regack.res[1] = '\0';
04800    req->data.regack.keepAlive = htolel(keep_alive);
04801    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
04802    req->data.regack.res2[0] = '0';
04803    req->data.regack.res2[1] = '\0';
04804    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
04805    transmit_response(d, req);
04806    if (skinnydebug)
04807       ast_verb(1, "Requesting capabilities\n");
04808 
04809    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
04810       return -1;
04811 
04812    transmit_response(d, req);
04813 
04814    return res;
04815 }

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

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

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

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

Definition at line 2984 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, complete_skinny_reset(), skinny_req::data, skinny_req::e, ast_cli_args::line, skinny_subchannel::list, ast_cli_args::n, ast_cli_args::pos, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, skinny_device::session, transmit_response(), and ast_cli_args::word.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 5765 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_ONHOOK, KEYDEF_RINGOUT, letohl, skinny_subchannel::list, LOG_WARNING, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, 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_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_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), transmit_stop_tone(), transmit_stopmediatransmission(), and skinny_subchannel::xferor.

Referenced by handle_message().

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

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

Definition at line 4937 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_ONHOOK, 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_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), start_rtp(), stimulus_message::stimulus, skinny_data::stimulus, STIMULUS_CALLPARK, STIMULUS_CONFERENCE, STIMULUS_DISPLAY, STIMULUS_DND, STIMULUS_FORWARDALL, STIMULUS_FORWARDBUSY, STIMULUS_FORWARDNOANSWER, STIMULUS_HOLD, STIMULUS_LINE, STIMULUS_REDIAL, STIMULUS_SPEEDDIAL, STIMULUS_TRANSFER, STIMULUS_VOICEMAIL, stimulus_message::stimulusInstance, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_start_tone(), transmit_stop_tone(), and transmit_stopmediatransmission().

Referenced by handle_message().

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

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

Definition at line 4677 of file chan_skinny.c.

References ast_channel::_state, skinny_line::activesub, ast_hangup(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verbose, skinny_subchannel::blindxfer, skinny_subchannel::callid, 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_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_selectsoftkeys(), transmit_start_tone(), and skinny_subchannel::xferor.

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

04678 {
04679    struct skinny_line *l;
04680    struct skinny_device *d;
04681    struct skinny_subchannel *newsub;
04682    struct ast_channel *c;
04683    pthread_t t;
04684 
04685    if (!sub) {
04686       ast_verbose("Transfer: No subchannel to transfer\n");
04687       return -1;
04688    }
04689 
04690    l = sub->parent;
04691    d = l->device;
04692 
04693    if (!sub->related) {
04694       /* Another sub has not been created so this must be first XFER press */
04695       if (!sub->onhold) {
04696          skinny_hold(sub);
04697       }
04698       c = skinny_new(l, AST_STATE_DOWN, NULL);
04699       if (c) {
04700          newsub = c->tech_pvt;
04701          /* point the sub and newsub at each other so we know they are related */
04702          newsub->related = sub;
04703          sub->related = newsub;
04704          newsub->xferor = 1;
04705          l->activesub = newsub;
04706          transmit_callstate(d, l->instance, sub->callid, SKINNY_OFFHOOK);
04707          transmit_activatecallplane(d, l);
04708          transmit_clear_display_message(d, l->instance, newsub->callid);
04709          transmit_start_tone(d, SKINNY_DIALTONE, l->instance, newsub->callid);
04710          transmit_selectsoftkeys(d, l->instance, newsub->callid, KEYDEF_OFFHOOKWITHFEAT);
04711          /* start the switch thread */
04712          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04713             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04714             ast_hangup(c);
04715          }
04716       } else {
04717          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04718       }
04719    } else {
04720       /* We already have a related sub so we can either complete XFER or go into BLINDXFER (or cancel BLINDXFER */
04721       if (sub->blindxfer) {
04722          /* toggle blindxfer off */
04723          sub->blindxfer = 0;
04724          sub->related->blindxfer = 0;
04725          /* we really need some indications */
04726       } else {
04727          /* We were doing attended transfer */
04728          if (sub->owner->_state == AST_STATE_DOWN || sub->related->owner->_state == AST_STATE_DOWN) {
04729             /* one of the subs so we cant transfer yet, toggle blindxfer on */
04730             sub->blindxfer = 1;
04731             sub->related->blindxfer = 1;
04732          } else {
04733             /* big assumption we have two channels, lets transfer */
04734             skinny_transfer(sub);
04735          }
04736       }
04737    }
04738    return 0;
04739 }

static int load_module ( void   )  [static]

Definition at line 7433 of file chan_skinny.c.

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

07434 {
07435    int res = 0;
07436 
07437    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
07438       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
07439    }
07440    /* load and parse config */
07441    res = config_load();
07442    if (res == -1) {
07443       return AST_MODULE_LOAD_DECLINE;
07444    }
07445 
07446    /* Make sure we can register our skinny channel type */
07447    if (ast_channel_register(&skinny_tech)) {
07448       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
07449       return -1;
07450    }
07451 
07452    ast_rtp_glue_register(&skinny_rtp_glue);
07453    ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07454 
07455    ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
07456    ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
07457    ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
07458    ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
07459 
07460    sched = sched_context_create();
07461    if (!sched) {
07462       ast_log(LOG_WARNING, "Unable to create schedule context\n");
07463    }
07464    io = io_context_create();
07465    if (!io) {
07466       ast_log(LOG_WARNING, "Unable to create I/O context\n");
07467    }
07468    /* And start the monitor for the first time */
07469    restart_monitor();
07470 
07471    return AST_MODULE_LOAD_SUCCESS;
07472 }

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

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

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

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

Show SKINNY devices in the manager API.

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

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

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

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

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

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

Show Skinny lines in the manager API.

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

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

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

Definition at line 2726 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_subchannel::list, skinny_line::newmsgs, skinny_device::session, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, STIMULUS_VOICEMAIL, and transmit_lamp_indication().

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

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

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

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

static void register_exten ( struct skinny_line l  )  [static]

Definition at line 1821 of file chan_skinny.c.

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

Referenced by skinny_register().

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

static int reload ( void   )  [static]

Definition at line 7551 of file chan_skinny.c.

References skinny_reload().

07552 {
07553    skinny_reload();
07554    return 0;
07555 }

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

Definition at line 1552 of file chan_skinny.c.

References ast_calloc, skinny_req::e, htolel, and skinny_req::len.

Referenced by handle_button_template_req_message(), handle_keep_alive_message(), handle_register_message(), handle_skinny_reset(), skinny_reload(), transmit_activatecallplane(), transmit_callinfo(), transmit_callstate(), transmit_cfwdstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_connect(), transmit_definetimedate(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_linestatres(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_serverres(), transmit_softkeysetres(), transmit_softkeytemplateres(), transmit_speaker_mode(), transmit_speeddialstatres(), transmit_start_tone(), transmit_startmediatransmission(), transmit_stop_tone(), transmit_stopmediatransmission(), and transmit_versionres().

01553 {
01554    struct skinny_req *req;
01555 
01556    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01557       return NULL;
01558 
01559    req->len = htolel(size+4);
01560    req->e = htolel(response_message);
01561 
01562    return req;
01563 }

static int restart_monitor ( void   )  [static]

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

06585 {
06586    /* If we're supposed to be stopped -- stay stopped */
06587    if (monitor_thread == AST_PTHREADT_STOP)
06588       return 0;
06589 
06590    ast_mutex_lock(&monlock);
06591    if (monitor_thread == pthread_self()) {
06592       ast_mutex_unlock(&monlock);
06593       ast_log(LOG_WARNING, "Cannot kill myself\n");
06594       return -1;
06595    }
06596    if (monitor_thread != AST_PTHREADT_NULL) {
06597       /* Wake up the thread */
06598       pthread_kill(monitor_thread, SIGURG);
06599    } else {
06600       /* Start a new monitor */
06601       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06602          ast_mutex_unlock(&monlock);
06603          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06604          return -1;
06605       }
06606    }
06607    ast_mutex_unlock(&monlock);
06608    return 0;
06609 }

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

Definition at line 1763 of file chan_skinny.c.

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

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

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

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 4057 of file chan_skinny.c.

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

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

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

Definition at line 3909 of file chan_skinny.c.

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

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

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6611 of file chan_skinny.c.

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

06612 {
06613    struct skinny_line *l;
06614    char *tmp;
06615 
06616    tmp = ast_strdupa(data);
06617 
06618    l = find_line_by_name(tmp);
06619 
06620    return get_devicestate(l);
06621 }

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

Definition at line 2626 of file chan_skinny.c.

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

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

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

Definition at line 4189 of file chan_skinny.c.

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

04190 {
04191    struct skinny_subchannel *sub = newchan->tech_pvt;
04192    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
04193    if (sub->owner != oldchan) {
04194       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
04195       return -1;
04196    }
04197    sub->owner = newchan;
04198    return 0;
04199 }

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

Definition at line 2780 of file chan_skinny.c.

References ao2_ref, ast_mutex_lock, ast_mutex_unlock, AST_RTP_GLUE_RESULT_FORBID, AST_RTP_GLUE_RESULT_LOCAL, AST_RTP_GLUE_RESULT_REMOTE, ast_verb, ast_channel::name, skinny_line::sub, and ast_channel::tech_pvt.

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

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

Definition at line 2767 of file chan_skinny.c.

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

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

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3966 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_instance_destroy(), ast_verb, skinny_subchannel::callid, skinny_line::device, KEYDEF_ONHOOK, skinny_subchannel::list, skinny_subchannel::lock, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, skinny_subchannel::related, skinny_subchannel::rtp, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SPEAKEROFF, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_activatecallplane(), transmit_callstate(), transmit_clear_display_message(), transmit_clearpromptmessage(), transmit_closereceivechannel(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_stop_tone(), and transmit_stopmediatransmission().

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 4605 of file chan_skinny.c.

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

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

04606 {
04607    struct skinny_line *l = sub->parent;
04608    struct skinny_device *d = l->device;
04609 
04610    /* Don't try to hold a channel that doesn't exist */
04611    if (!sub || !sub->owner)
04612       return 0;
04613 
04614    /* Channel needs to be put on hold */
04615    if (skinnydebug)
04616       ast_verb(1, "Putting on Hold(%d)\n", l->instance);
04617 
04618    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
04619       S_OR(l->mohsuggest, NULL),
04620       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
04621 
04622    transmit_activatecallplane(d, l);
04623    transmit_closereceivechannel(d, sub);
04624    transmit_stopmediatransmission(d, sub);
04625 
04626    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_HOLD);
04627    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_WINK);
04628    sub->onhold = 1;
04629    return 1;
04630 }

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

Definition at line 4372 of file chan_skinny.c.

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

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

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

Definition at line 4489 of file chan_skinny.c.

References accountcode, ast_channel::adsicpe, ast_channel::amaflags, ast_party_caller::ani, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc, ast_channel_set_fd(), ast_copy_string(), AST_DEVICE_NOT_INUSE, ast_getformatname(), ast_getformatname_multiple(), ast_hangup(), ast_jb_configure(), AST_LIST_INSERT_HEAD, ast_log(), ast_module_ref(), ast_mutex_init, ast_pbx_start(), ast_rtp_instance_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verb, ast_channel::caller, ast_channel::callgroup, skinny_line::chanvars, ast_channel::context, skinny_line::device, ast_channel::exten, get_devicestate(), global_jbconf, language, skinny_subchannel::list, LOG_WARNING, ast_variable::name, ast_channel::nativeformats, ast_variable::next, ast_party_id::number, parkinglot, pbx_builtin_setvar_helper(), ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, SKINNY_CFWD_ALL, SKINNY_CFWD_BUSY, SKINNY_CX_INACTIVE, skinny_tech, ast_party_number::str, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, ast_party_number::valid, ast_variable::value, and ast_channel::writeformat.

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

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

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

Definition at line 3769 of file chan_skinny.c.

References ast_party_caller::ani, ast_copy_string(), ast_log(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_channel::caller, skinny_subchannel::callid, ast_channel::connected, skinny_line::device, ast_channel::exten, ast_party_connected_line::id, LOG_WARNING, ast_party_id::name, ast_party_id::number, skinny_subchannel::rtp, SKINNY_REORDER, start_rtp(), ast_party_number::str, skinny_line::sub, ast_channel::tech_pvt, transmit_start_tone(), and ast_party_number::valid.

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

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

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

Definition at line 4147 of file chan_skinny.c.

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

04148 {
04149    struct ast_frame *fr;
04150    struct skinny_subchannel *sub = ast->tech_pvt;
04151    ast_mutex_lock(&sub->lock);
04152    fr = skinny_rtp_read(sub);
04153    ast_mutex_unlock(&sub->lock);
04154    return fr;
04155 }

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

Definition at line 1870 of file chan_skinny.c.

References 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_sockaddr_from_sin, ast_strlen_zero(), ast_verb, skinny_speeddial::context, skinny_req::data, skinny_line::device, skinnysession::device, EVENT_FLAG_SYSTEM, skinny_speeddial::exten, skinnysession::fd, skinny_device::ha, letohl, skinny_device::lines, skinny_subchannel::list, LOG_WARNING, manager_event, 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().

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

int skinny_reload ( void   )  [static]

Definition at line 7351 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, skinny_subchannel::list, 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().

07352 {
07353    struct skinny_device *d;
07354    struct skinny_line *l;
07355    struct skinny_speeddial *sd;
07356    struct skinny_addon *a;
07357    struct skinny_req *req;
07358 
07359    if (skinnyreload) {
07360       ast_verb(3, "Chan_skinny is already reloading.\n");
07361       return 0;
07362    }
07363 
07364    skinnyreload = 1;
07365 
07366    /* Mark all devices and lines as candidates to be pruned */
07367    AST_LIST_LOCK(&devices);
07368    AST_LIST_TRAVERSE(&devices, d, list) {
07369       d->prune = 1;
07370    }
07371    AST_LIST_UNLOCK(&devices);
07372 
07373    AST_LIST_LOCK(&lines);
07374    AST_LIST_TRAVERSE(&lines, l, all) {
07375       l->prune = 1;
07376    }
07377    AST_LIST_UNLOCK(&lines);
07378 
07379         config_load();
07380 
07381    /* Remove any devices that no longer exist in the config */
07382    AST_LIST_LOCK(&devices);
07383    AST_LIST_TRAVERSE_SAFE_BEGIN(&devices, d, list) {
07384       if (!d->prune) {
07385          continue;
07386       }
07387       ast_verb(3, "Removing device '%s'\n", d->name);
07388       /* Delete all lines for this device. 
07389          We do not want to free the line here, that
07390          will happen below. */
07391       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07392       }
07393       /* Delete all speeddials for this device */
07394       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07395          free(sd);
07396       }
07397       /* Delete all addons for this device */
07398       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07399          free(a);
07400       }
07401       AST_LIST_REMOVE_CURRENT(list);
07402       free(d);
07403    }
07404    AST_LIST_TRAVERSE_SAFE_END;
07405    AST_LIST_UNLOCK(&devices);
07406 
07407    AST_LIST_LOCK(&lines);  
07408    AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) {
07409       if (l->prune) {
07410          AST_LIST_REMOVE_CURRENT(all);
07411          free(l);
07412       }
07413    }
07414    AST_LIST_TRAVERSE_SAFE_END;
07415    AST_LIST_UNLOCK(&lines);  
07416 
07417    AST_LIST_TRAVERSE(&devices, d, list) {
07418       /* Do a soft reset to re-register the devices after
07419          cleaning up the removed devices and lines */
07420       if (d->session) {
07421          ast_verb(3, "Restarting device '%s'\n", d->name);
07422          if ((req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE))) {
07423             req->data.reset.resetType = 2;
07424             transmit_response(d, req);
07425          }
07426       }
07427    }
07428    
07429    skinnyreload = 0;
07430         return 0;
07431 }

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

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

06440 {
06441    struct skinny_req *req;
06442    int *bufaddr;
06443 
06444    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
06445       return NULL;
06446 
06447    ast_mutex_lock(&s->lock);
06448    memcpy(req, s->inbuf, skinny_header_size);
06449    bufaddr = (int *)(s->inbuf);
06450    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
06451 
06452    ast_mutex_unlock(&s->lock);
06453 
06454    if (letohl(req->e) < 0) {
06455       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
06456       ast_free(req);
06457       return NULL;
06458    }
06459 
06460    return req;
06461 }

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

Definition at line 6623 of file chan_skinny.c.

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

06624 {
06625    struct skinny_line *l;
06626    struct ast_channel *tmpc = NULL;
06627    char tmp[256];
06628    char *dest = data;
06629 
06630    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
06631       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
06632       return NULL;
06633    }
06634 
06635    ast_copy_string(tmp, dest, sizeof(tmp));
06636    if (ast_strlen_zero(tmp)) {
06637       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
06638       return NULL;
06639    }
06640    l = find_line_by_name(tmp);
06641    if (!l) {
06642       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
06643       return NULL;
06644    }
06645    ast_verb(3, "skinny_request(%s)\n", tmp);
06646    tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
06647    if (!tmpc) {
06648       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
06649    }
06650    restart_monitor();
06651    return tmpc;
06652 }

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

Definition at line 4100 of file chan_skinny.c.

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

Referenced by skinny_read().

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

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

Definition at line 4201 of file chan_skinny.c.

04202 {
04203    return -1; /* Start inband indications */
04204 }

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

Definition at line 4206 of file chan_skinny.c.

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

04207 {
04208 #if 0
04209    struct skinny_subchannel *sub = ast->tech_pvt;
04210    struct skinny_line *l = sub->parent;
04211    struct skinny_device *d = l->device;
04212    int tmp;
04213    /* not right */
04214    sprintf(tmp, "%d", digit);
04215    //transmit_tone(d, digit, l->instance, sub->callid);
04216 #endif
04217    return -1; /* Stop inband indications */
04218 }

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

Definition at line 6463 of file chan_skinny.c.

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

Referenced by accept_thread().

06464 {
06465    int res;
06466    struct skinny_req *req;
06467    struct skinnysession *s = data;
06468 
06469    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
06470 
06471    for (;;) {
06472       res = get_input(s);
06473       if (res < 0) {
06474          break;
06475       }
06476 
06477       if (res > 0)
06478       {
06479          if (!(req = skinny_req_parse(s))) {
06480             destroy_session(s);
06481             return NULL;
06482          }
06483 
06484          res = handle_message(req, s);
06485          if (res < 0) {
06486             destroy_session(s);
06487             return NULL;
06488          }
06489       }
06490    }
06491    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06492 
06493    if (s) 
06494       destroy_session(s);
06495    
06496    return 0;
06497 }

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

Definition at line 2817 of file chan_skinny.c.

References ast_channel::_state, ast_best_codec(), ast_codec_pref_getsize(), ast_getformatname(), ast_inet_ntoa(), ast_rtp_instance_get_local_address(), ast_rtp_instance_get_remote_address(), ast_sockaddr_to_sin, AST_STATE_UP, ast_verb, ast_format_list::bits, ast_format_list::cur_ms, skinny_line::device, skinny_device::ourip, skinny_subchannel::rtp, ast_channel::tech_pvt, transmit_startmediatransmission(), and transmit_stopmediatransmission().

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

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

Definition at line 3802 of file chan_skinny.c.

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

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

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

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

Definition at line 4305 of file chan_skinny.c.

References 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, and skinny_subchannel::xferor.

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 4632 of file chan_skinny.c.

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

Referenced by handle_hold_button(), and handle_soft_key_event_message().

04633 {
04634    struct skinny_line *l = sub->parent;
04635    struct skinny_device *d = l->device;
04636 
04637    /* Don't try to unhold a channel that doesn't exist */
04638    if (!sub || !sub->owner)
04639       return 0;
04640 
04641    /* Channel is on hold, so we will unhold */
04642    if (skinnydebug)
04643       ast_verb(1, "Taking off Hold(%d)\n", l->instance);
04644 
04645    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
04646 
04647    transmit_activatecallplane(d, l);
04648 
04649    transmit_connect(d, sub);
04650    transmit_callstate(d, sub->parent->instance, sub->callid, SKINNY_CONNECTED);
04651    transmit_lamp_indication(d, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04652    l->hookstate = SKINNY_OFFHOOK;
04653    sub->onhold = 0;
04654    return 1;
04655 }

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

Definition at line 1942 of file chan_skinny.c.

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

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

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

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

Definition at line 4157 of file chan_skinny.c.

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

04158 {
04159    struct skinny_subchannel *sub = ast->tech_pvt;
04160    int res = 0;
04161    if (frame->frametype != AST_FRAME_VOICE) {
04162       if (frame->frametype == AST_FRAME_IMAGE) {
04163          return 0;
04164       } else {
04165          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
04166          return 0;
04167       }
04168    } else {
04169       if (!(frame->subclass.codec & ast->nativeformats)) {
04170          char buf[256];
04171          ast_log(LOG_WARNING, "Asked to transmit frame type %s, while native formats is %s (read/write = %s/%s)\n",
04172             ast_getformatname(frame->subclass.codec),
04173             ast_getformatname_multiple(buf, sizeof(buf), ast->nativeformats),
04174             ast_getformatname(ast->readformat),
04175             ast_getformatname(ast->writeformat));
04176          return -1;
04177       }
04178    }
04179    if (sub) {
04180       ast_mutex_lock(&sub->lock);
04181       if (sub->rtp) {
04182          res = ast_rtp_instance_write(sub->rtp, frame);
04183       }
04184       ast_mutex_unlock(&sub->lock);
04185    }
04186    return res;
04187 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3723 of file chan_skinny.c.

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

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

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

Definition at line 2437 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 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_hangup(), skinny_hold(), and skinny_unhold().

02438 {
02439    struct skinny_req *req;
02440 
02441    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02442       return;
02443 
02444    req->data.activatecallplane.lineInstance = htolel(l->instance);
02445    transmit_response(d, req);
02446 }

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

Definition at line 2169 of file chan_skinny.c.

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

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

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

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

Definition at line 2448 of file chan_skinny.c.

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

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_answer(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), skinny_hold(), skinny_indicate(), skinny_unhold(), and update_connectedline().

02449 {
02450    struct skinny_req *req;
02451 
02452    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02453       return;
02454 
02455    req->data.callstate.callState = htolel(state);
02456    req->data.callstate.lineInstance = htolel(buttonInstance);
02457    req->data.callstate.callReference = htolel(callid);
02458    transmit_response(d, req);
02459 }

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

Definition at line 2461 of file chan_skinny.c.

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

Referenced by handle_callforward_button(), and skinny_ss().

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

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

Definition at line 2294 of file chan_skinny.c.

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

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

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

static void transmit_clearpromptmessage ( struct skinny_device d,
int  instance,
int  callid 
) [static]

Definition at line 2363 of file chan_skinny.c.

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

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

02364 {
02365    struct skinny_req *req;
02366 
02367    if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
02368       return;
02369 
02370    req->data.clearpromptstatus.lineInstance = htolel(instance);
02371    req->data.clearpromptstatus.callReference = htolel(callid);
02372 
02373    if (skinnydebug)
02374       ast_verb(1, "Clearing Prompt\n");
02375 
02376    transmit_response(d, req);
02377 }

static void transmit_closereceivechannel ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 2393 of file chan_skinny.c.

References skinny_subchannel::callid, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, close_receive_channel_message::conferenceId, skinny_req::data, htolel, close_receive_channel_message::partyId, req_alloc(), and transmit_response().

Referenced by handle_callforward_button(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_hangup(), and skinny_hold().

02394 {
02395    struct skinny_req *req;
02396 
02397    if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02398       return;
02399 
02400    req->data.closereceivechannel.conferenceId = htolel(0);
02401    req->data.closereceivechannel.partyId = htolel(sub->callid);
02402    transmit_response(d, req);
02403 }

static void transmit_connect ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 2201 of file chan_skinny.c.

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

02202 {
02203    struct skinny_req *req;
02204    struct skinny_line *l = sub->parent;
02205    struct ast_format_list fmt;
02206 
02207    if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
02208       return;
02209 
02210    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
02211 
02212    req->data.openreceivechannel.conferenceId = htolel(sub->callid);
02213    req->data.openreceivechannel.partyId = htolel(sub->callid);
02214    req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
02215    req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits));
02216    req->data.openreceivechannel.echo = htolel(0);
02217    req->data.openreceivechannel.bitrate = htolel(0);
02218    transmit_response(d, req);
02219 }

static void transmit_definetimedate ( struct skinny_device d  )  [static]

Definition at line 2532 of file chan_skinny.c.

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

Referenced by handle_message(), handle_offhook_message(), and handle_onhook_message().

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

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

Definition at line 2379 of file chan_skinny.c.

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

Referenced by skinny_answer(), and skinny_indicate().

02380 {
02381    struct skinny_req *req;
02382 
02383    if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
02384       return;
02385 
02386    ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
02387    req->data.dialednumber.lineInstance = htolel(instance);
02388    req->data.dialednumber.callReference = htolel(callid);
02389 
02390    transmit_response(d, req);
02391 }

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

Definition at line 2329 of file chan_skinny.c.

References ast_copy_string(), ast_verb, skinny_req::data, DISPLAY_NOTIFY_MESSAGE, display_notify_message::displayMessage, skinny_data::displaynotify, display_notify_message::displayTimeout, htolel, req_alloc(), and transmit_response().

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

02330 {
02331    struct skinny_req *req;
02332 
02333    if (!(req = req_alloc(sizeof(struct display_notify_message), DISPLAY_NOTIFY_MESSAGE)))
02334       return;
02335 
02336    ast_copy_string(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage));
02337    req->data.displaynotify.displayTimeout = htolel(t);
02338 
02339    if (skinnydebug)
02340       ast_verb(1, "Displaying notify '%s'\n", text);
02341 
02342    transmit_response(d, req);
02343 }

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

Definition at line 2345 of file chan_skinny.c.

References ast_copy_string(), ast_verb, display_prompt_status_message::callReference, skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_data::displaypromptstatus, htolel, display_prompt_status_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 update_connectedline().

02346 {
02347    struct skinny_req *req;
02348 
02349    if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
02350       return;
02351 
02352    ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
02353    req->data.displaypromptstatus.messageTimeout = htolel(t);
02354    req->data.displaypromptstatus.lineInstance = htolel(instance);
02355    req->data.displaypromptstatus.callReference = htolel(callid);
02356 
02357    if (skinnydebug)
02358       ast_verb(1, "Displaying Prompt Status '%s'\n", text);
02359 
02360    transmit_response(d, req);
02361 }

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

Definition at line 2256 of file chan_skinny.c.

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

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), mwi_event_cb(), skinny_call(), skinny_extensionstate_cb(), skinny_hangup(), skinny_hold(), skinny_ss(), and skinny_unhold().

02257 {
02258    struct skinny_req *req;
02259 
02260    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
02261       return;
02262 
02263    req->data.setlamp.stimulus = htolel(stimulus);
02264    req->data.setlamp.stimulusInstance = htolel(instance);
02265    req->data.setlamp.deviceStimulus = htolel(indication);
02266    transmit_response(d, req);
02267 }

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

Definition at line 2519 of file chan_skinny.c.

References skinny_req::data, letohl, LINE_STAT_RES_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::lineNumber, skinny_data::linestat, req_alloc(), and transmit_response().

Referenced by handle_message().

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

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

Definition at line 2105 of file chan_skinny.c.

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

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

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

Definition at line 2269 of file chan_skinny.c.

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

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

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

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

Definition at line 2242 of file chan_skinny.c.

References skinny_req::data, htolel, select_soft_keys_message::instance, select_soft_keys_message::reference, req_alloc(), SELECT_SOFT_KEYS_MESSAGE, skinny_data::selectsoftkey, select_soft_keys_message::softKeySetIndex, transmit_response(), and select_soft_keys_message::validKeyMask.

Referenced by handle_callforward_button(), handle_hold_button(), handle_message(), handle_offhook_message(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), handle_transfer_button(), skinny_answer(), skinny_call(), and skinny_hangup().

02243 {
02244    struct skinny_req *req;
02245 
02246    if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
02247       return;
02248 
02249    req->data.selectsoftkey.instance = htolel(instance);
02250    req->data.selectsoftkey.reference = htolel(callid);
02251    req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
02252    req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
02253    transmit_response(d, req);
02254 }

static void transmit_serverres ( struct skinny_device d  )  [static]

Definition at line 2564 of file chan_skinny.c.

References skinny_req::data, htolel, skinny_device::ourip, req_alloc(), server_res_message::server, SERVER_RES_MESSAGE, server_res_message::serverIpAddr, server_res_message::serverListenPort, server_identifier::serverName, skinny_data::serverres, and transmit_response().

Referenced by handle_message().

02565 {
02566    struct skinny_req *req;
02567    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
02568       return;
02569 
02570    memcpy(req->data.serverres.server[0].serverName, ourhost,
02571          sizeof(req->data.serverres.server[0].serverName));
02572    req->data.serverres.serverListenPort[0] = htolel(ourport);
02573    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
02574    transmit_response(d, req);
02575 }

static void transmit_softkeysetres ( struct skinny_device d  )  [static]

Definition at line 2577 of file chan_skinny.c.

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

Referenced by handle_message().

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

static void transmit_softkeytemplateres ( struct skinny_device d  )  [static]

Definition at line 2610 of file chan_skinny.c.

References skinny_req::data, htolel, req_alloc(), soft_key_template_default, SOFT_KEY_TEMPLATE_RES_MESSAGE, soft_key_template_res_message::softKeyCount, soft_key_template_res_message::softKeyOffset, skinny_data::softkeytemplate, soft_key_template_res_message::softKeyTemplateDefinition, soft_key_template_res_message::totalSoftKeyCount, and transmit_response().

Referenced by handle_message().

02611 {
02612    struct skinny_req *req;
02613    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
02614       return;
02615 
02616    req->data.softkeytemplate.softKeyOffset = htolel(0);
02617    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
02618    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
02619    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
02620       soft_key_template_default,
02621       sizeof(soft_key_template_default));
02622    transmit_response(d, req);
02623 }

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

Definition at line 2146 of file chan_skinny.c.

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

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

02147 {
02148    struct skinny_req *req;
02149 
02150    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
02151       return;
02152 
02153    req->data.setspeaker.mode = htolel(mode);
02154    transmit_response(d, req);
02155 }

static void transmit_speeddialstatres ( struct skinny_device d,
struct skinny_speeddial sd 
) [static]

Definition at line 2505 of file chan_skinny.c.

References ast_copy_string(), skinny_req::data, skinny_speeddial::exten, htolel, skinny_speeddial::instance, skinny_speeddial::label, req_alloc(), SPEED_DIAL_STAT_RES_MESSAGE, skinny_data::speeddial, speed_dial_stat_res_message::speedDialDirNumber, speed_dial_stat_res_message::speedDialDisplayName, speed_dial_stat_req_message::speedDialNumber, skinny_data::speeddialreq, and transmit_response().

Referenced by handle_message().

02506 {
02507    struct skinny_req *req;
02508 
02509    if (!(req = req_alloc(sizeof(struct speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
02510       return;
02511 
02512    req->data.speeddialreq.speedDialNumber = htolel(sd->instance);
02513    ast_copy_string(req->data.speeddial.speedDialDirNumber, sd->exten, sizeof(req->data.speeddial.speedDialDirNumber));
02514    ast_copy_string(req->data.speeddial.speedDialDisplayName, sd->label, sizeof(req->data.speeddial.speedDialDisplayName));
02515 
02516    transmit_response(d, req);
02517 }

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

Definition at line 2221 of file chan_skinny.c.

References skinny_req::data, htolel, start_tone_message::instance, start_tone_message::reference, req_alloc(), START_TONE_MESSAGE, skinny_data::starttone, 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_indicate(), skinny_newcall(), and skinny_ss().

02222 {
02223    struct skinny_req *req;
02224    if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
02225       return;
02226    req->data.starttone.tone = htolel(tone);
02227    req->data.starttone.instance = htolel(instance);
02228    req->data.starttone.reference = htolel(reference);
02229    transmit_response(d, req);
02230 }

static void transmit_startmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub,
struct sockaddr_in  dest,
struct ast_format_list  fmt 
) [static]

Definition at line 2417 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message(), and skinny_set_rtp_peer().

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

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

Definition at line 2232 of file chan_skinny.c.

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

Referenced by handle_enbloc_call_message(), handle_offhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_answer(), skinny_hangup(), skinny_indicate(), and skinny_ss().

02233 {
02234    struct skinny_req *req;
02235    if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
02236       return;
02237    req->data.stoptone.instance = htolel(instance);
02238    req->data.stoptone.reference = htolel(reference);
02239    transmit_response(d, req);
02240 }

static void transmit_stopmediatransmission ( struct skinny_device d,
struct skinny_subchannel sub 
) [static]

Definition at line 2405 of file chan_skinny.c.

References skinny_subchannel::callid, stop_media_transmission_message::conferenceId, skinny_req::data, htolel, stop_media_transmission_message::passThruPartyId, req_alloc(), STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, and transmit_response().

Referenced by handle_callforward_button(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_hangup(), skinny_hold(), and skinny_set_rtp_peer().

02406 {
02407    struct skinny_req *req;
02408 
02409    if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02410       return;
02411 
02412    req->data.stopmedia.conferenceId = htolel(0);
02413    req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02414    transmit_response(d, req);
02415 }

static void transmit_versionres ( struct skinny_device d  )  [static]

Definition at line 2554 of file chan_skinny.c.

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

Referenced by handle_message().

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

static int unload_module ( void   )  [static]

Definition at line 7474 of file chan_skinny.c.

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

07475 {
07476    struct skinnysession *s;
07477    struct skinny_device *d;
07478    struct skinny_line *l;
07479    struct skinny_subchannel *sub;
07480    struct ast_context *con;
07481 
07482    ast_rtp_glue_unregister(&skinny_rtp_glue);
07483    ast_channel_unregister(&skinny_tech);
07484    ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07485 
07486    ast_manager_unregister("SKINNYdevices");
07487    ast_manager_unregister("SKINNYshowdevice");
07488    ast_manager_unregister("SKINNYlines");
07489    ast_manager_unregister("SKINNYshowline");
07490    
07491    AST_LIST_LOCK(&sessions);
07492    /* Destroy all the interfaces and free their memory */
07493    while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
07494       d = s->device;
07495       AST_LIST_TRAVERSE(&d->lines, l, list){
07496          ast_mutex_lock(&l->lock);
07497          AST_LIST_TRAVERSE(&l->sub, sub, list) {
07498             ast_mutex_lock(&sub->lock);
07499             if (sub->owner) {
07500                sub->alreadygone = 1;
07501                ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
07502             }
07503             ast_mutex_unlock(&sub->lock);
07504          }
07505          if (l->mwi_event_sub)
07506             ast_event_unsubscribe(l->mwi_event_sub);
07507          ast_mutex_unlock(&l->lock);
07508          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
07509          unregister_exten(l);
07510       }
07511       if (s->fd > -1)
07512          close(s->fd);
07513       pthread_cancel(s->t);
07514       pthread_kill(s->t, SIGURG);
07515       pthread_join(s->t, NULL);
07516       free(s);
07517    }
07518    AST_LIST_UNLOCK(&sessions);
07519 
07520    delete_devices();
07521 
07522    ast_mutex_lock(&monlock);
07523    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
07524       pthread_cancel(monitor_thread);
07525       pthread_kill(monitor_thread, SIGURG);
07526       pthread_join(monitor_thread, NULL);
07527    }
07528    monitor_thread = AST_PTHREADT_STOP;
07529    ast_mutex_unlock(&monlock);
07530 
07531    ast_mutex_lock(&netlock);
07532    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
07533       pthread_cancel(accept_t);
07534       pthread_kill(accept_t, SIGURG);
07535       pthread_join(accept_t, NULL);
07536    }
07537    accept_t = AST_PTHREADT_STOP;
07538    ast_mutex_unlock(&netlock);
07539 
07540    close(skinnysock);
07541    if (sched)
07542       sched_context_destroy(sched);
07543 
07544    con = ast_context_find(used_context);
07545    if (con)
07546       ast_context_destroy(con, "Skinny");
07547    
07548    return 0;
07549 }

static void unregister_exten ( struct skinny_line l  )  [static]

Definition at line 1846 of file chan_skinny.c.

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

Referenced by skinny_unregister(), and unload_module().

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

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

Definition at line 2674 of file chan_skinny.c.

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

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


Variable Documentation

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

Definition at line 7562 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 1046 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 1050 of file chan_skinny.c.

struct ast_hostent ahp [static]

Definition at line 1047 of file chan_skinny.c.

Referenced by __ast_http_load(), ast_parse_arg(), config_load(), config_parse_variables(), create_addr(), festival_exec(), gtalk_load_config(), gtalk_update_stun(), jingle_load_config(), jingle_update_stun(), launch_netscript(), process_sdp(), realtime_peer(), realtime_user(), reload_config(), and rpt_exec().

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 7562 of file chan_skinny.c.

int auth_limit = DEFAULT_AUTH_LIMIT [static]

Definition at line 177 of file chan_skinny.c.

int auth_timeout = DEFAULT_AUTH_TIMEOUT [static]

Definition at line 176 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 1043 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 1051 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 3712 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

Definition at line 145 of file chan_skinny.c.

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

Definition at line 245 of file chan_skinny.c.

Referenced by control2str().

unsigned int cos

Definition at line 170 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 171 of file chan_skinny.c.

unsigned int cos_video

Definition at line 172 of file chan_skinny.c.

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

Definition at line 182 of file chan_skinny.c.

format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 147 of file chan_skinny.c.

struct skinny_device_options* default_device = &default_device_struct [static]

Definition at line 1360 of file chan_skinny.c.

Referenced by config_device(), and config_load().

struct skinny_device_options default_device_struct [static]

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

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

Definition at line 227 of file chan_skinny.c.

struct skinny_line_options* default_line = &default_line_struct [static]

Definition at line 1287 of file chan_skinny.c.

Referenced by config_line(), and config_load().

struct skinny_line_options default_line_struct [static]

struct ast_codec_pref default_prefs [static]

Definition at line 148 of file chan_skinny.c.

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

Definition at line 242 of file chan_skinny.c.

Referenced by device2str().

int firstdigittimeout = 16000 [static]

Definition at line 1170 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1173 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 235 of file chan_skinny.c.

char global_vmexten[AST_MAX_EXTENSION] [static]

Definition at line 179 of file chan_skinny.c.

struct hostent* hp [static]

Definition at line 1048 of file chan_skinny.c.

Referenced by __ast_http_load(), ast_gethostbyname(), ast_parse_arg(), build_peer(), connect_sphinx(), create_addr(), gtalk_load_config(), gtalk_update_stun(), iax_template_parse(), jingle_load_config(), jingle_update_stun(), launch_netscript(), process_sdp(), realtime_peer(), realtime_user(), reload_config(), rpt_exec(), and set_config().

struct io_context* io [static]

Definition at line 1157 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 175 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1176 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1167 of file chan_skinny.c.

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

Definition at line 1161 of file chan_skinny.c.

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

Definition at line 1163 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 1044 of file chan_skinny.c.

int ourport [static]

Definition at line 1045 of file chan_skinny.c.

struct { ... } qos [static]

char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 181 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 1156 of file chan_skinny.c.

int skinny_header_size = 12 [static]

Definition at line 1033 of file chan_skinny.c.

struct ast_rtp_glue skinny_rtp_glue [static]

Definition at line 2870 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1392 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 1039 of file chan_skinny.c.

int skinnyreload = 0 [static]

Definition at line 1040 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 1049 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 828 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 872 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 858 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 867 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 891 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 850 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 881 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 837 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 818 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 844 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 876 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 887 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[] [static]

Definition at line 655 of file chan_skinny.c.

Referenced by load_module(), transmit_softkeysetres(), and transmit_softkeytemplateres().

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

Definition at line 144 of file chan_skinny.c.

unsigned int tos

Definition at line 167 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 168 of file chan_skinny.c.

unsigned int tos_video

Definition at line 169 of file chan_skinny.c.

int unauth_sessions = 0 [static]

Definition at line 178 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 180 of file chan_skinny.c.

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

Definition at line 183 of file chan_skinny.c.


Generated on Mon Mar 19 11:30:44 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7