Mon Jun 27 16:51:10 2011

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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .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 960 of file chan_skinny.c.

Referenced by transmit_activatecallplane().

#define ALARM_MESSAGE   0x0020

Definition at line 327 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 534 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 537 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 538 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 536 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 545 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 544 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 531 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 535 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 528 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 529 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 530 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 526 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 532 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 539 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 524 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 525 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 527 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 533 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 323 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 494 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 432 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 931 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 567 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 295 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6674 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6673 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 565 of file chan_skinny.c.

Referenced by transmit_clear_display_message().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 564 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 948 of file chan_skinny.c.

Referenced by transmit_clearpromptmessage().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6672 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6671 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 603 of file chan_skinny.c.

Referenced by transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 242 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_AUTH_LIMIT   50

Definition at line 161 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_AUTH_TIMEOUT   30

Definition at line 160 of file chan_skinny.c.

Referenced by config_parse_variables().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 158 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 157 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 481 of file chan_skinny.c.

Referenced by transmit_definetimedate().

#define DEVICE2STR_BUFSIZE   15

Definition at line 239 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 965 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 954 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 939 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 559 of file chan_skinny.c.

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 271 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 454 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 354 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)

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

Referenced by transmit_softkeysetres().

#define IP_PORT_MESSAGE   0x0002

Definition at line 261 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 590 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 248 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

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

#define KEYDEF_CONNWITHTRANS   5

Definition at line 622 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 623 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

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

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 619 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

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

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

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

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 263 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)

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

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 473 of file chan_skinny.c.

Referenced by transmit_linestatres().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 317 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 283 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 289 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 335 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 592 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 357 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 355 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 251 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 569 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 585 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 923 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 325 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 574 of file chan_skinny.c.

Referenced by transmit_serverres().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 388 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 401 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 380 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 395 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1112 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1099 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1111 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1106 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1102 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1114 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

Definition at line 1128 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 1129 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 1130 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 1100 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

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

#define SKINNY_CX_CONFERENCE   3

Definition at line 1137 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1139 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1138 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1134 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1133 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1135 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1054 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1053 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1052 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1051 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1055 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1081 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1077 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1070 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1056 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1065 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1080 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1063 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1078 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1069 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1068 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1059 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1084 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1072 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1058 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1061 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1067 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1073 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1074 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1057 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1083 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1066 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1071 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1075 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1079 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1062 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1076 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1064 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1060 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1082 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1050 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1308 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1085 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1086 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 1049 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVONLY ( code   ) 

Definition at line 135 of file chan_skinny.c.

Referenced by handle_message(), and transmit_response().

#define SKINNY_DIALTONE   0x21

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1107 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

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

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

Definition at line 1117 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 1118 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 1119 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1198 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 305 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 159 of file chan_skinny.c.

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

#define SKINNY_MICOFF   2

Definition at line 1092 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 1091 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1115 of file chan_skinny.c.

#define SKINNY_OFFHOOK   1

Definition at line 1094 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 1095 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 1104 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 1105 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_REORDER   0x25

Definition at line 1113 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1126 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1124 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

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

#define SKINNY_RINGIN   4

Definition at line 1097 of file chan_skinny.c.

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

#define SKINNY_RINGOUT   3

Definition at line 1096 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_SILENCE   0x00

Definition at line 1109 of file chan_skinny.c.

#define SKINNY_SPEAKEROFF   2

Definition at line 1089 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 1088 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 1103 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 345 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 343 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 908 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 353 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 610 of file chan_skinny.c.

Referenced by transmit_softkeytemplateres().

#define SOFTKEY_ANSWER   0x0B

Definition at line 640 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 637 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 634 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 635 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 636 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 642 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 648 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 647 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 632 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 649 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 641 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 644 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 645 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 631 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 629 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 643 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 646 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 630 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 639 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 312 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 466 of file chan_skinny.c.

Referenced by transmit_speeddialstatres().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 406 of file chan_skinny.c.

Referenced by transmit_startmediatransmission().

#define START_TONE_MESSAGE   0x0082

Definition at line 366 of file chan_skinny.c.

Referenced by transmit_start_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 516 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 519 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 520 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 518 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 513 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 517 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 510 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 511 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 512 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 508 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

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

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 521 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 506 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 507 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 509 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 515 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 425 of file chan_skinny.c.

Referenced by transmit_stopmediatransmission().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 374 of file chan_skinny.c.

Referenced by transmit_stop_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 322 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6666 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6667 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6668 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6665 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6669 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 352 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 324 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

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


Function Documentation

static void __init_control2str_threadbuf ( void   )  [static]

Definition at line 241 of file chan_skinny.c.

00252 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 238 of file chan_skinny.c.

00252 {

static void __reg_module ( void   )  [static]

Definition at line 7574 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

implement the setvar config line

Definition at line 1642 of file chan_skinny.c.

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

01643 {
01644    struct ast_variable *tmpvar = NULL;
01645    char *varname = ast_strdupa(buf), *varval = NULL;
01646 
01647    if ((varval = strchr(varname,'='))) {
01648       *varval++ = '\0';
01649       if ((tmpvar = ast_variable_new(varname, varval, ""))) {
01650          tmpvar->next = list;
01651          list = tmpvar;
01652       }
01653    }
01654    return list;
01655 }

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

Definition at line 1803 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( format_t  astcodec  )  [static]

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

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

static format_t codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

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

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

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

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

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

Definition at line 2964 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

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

static char* complete_skinny_show_device ( 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_show_device().

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

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

Definition at line 2969 of file chan_skinny.c.

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

Referenced by handle_skinny_show_line().

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

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

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

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

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

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

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

static int config_load ( void   )  [static]

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

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

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

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

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

static char* control2str ( int  ind  )  [static]

Definition at line 4258 of file chan_skinny.c.

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

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

static void delete_devices ( void   )  [static]

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

07333 {
07334    struct skinny_device *d;
07335    struct skinny_line *l;
07336    struct skinny_speeddial *sd;
07337    struct skinny_addon *a;
07338 
07339    AST_LIST_LOCK(&devices);
07340    AST_LIST_LOCK(&lines);
07341 
07342    /* Delete all devices */
07343    while ((d = AST_LIST_REMOVE_HEAD(&devices, list))) {
07344       /* Delete all lines for this device */
07345       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07346          AST_LIST_REMOVE(&lines, l, all);
07347          free(l);
07348       }
07349       /* Delete all speeddials for this device */
07350       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07351          free(sd);
07352       }
07353       /* Delete all addons for this device */
07354       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07355          free(a);
07356       } 
07357       free(d);
07358    }
07359    AST_LIST_UNLOCK(&lines);
07360    AST_LIST_UNLOCK(&devices);
07361 }

static void destroy_session ( struct skinnysession s  )  [static]

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

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

static char* device2str ( int  type  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int get_devicestate ( struct skinny_line l  )  [static]

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

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

static int get_input ( struct skinnysession s  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 4865 of file chan_skinny.c.

Referenced by handle_message().

04866 {
04867    /* no response necessary */
04868    return 1;
04869 }

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

Definition at line 4746 of file chan_skinny.c.

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

Referenced by handle_message().

04747 {
04748    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
04749       return -1;
04750 
04751    transmit_response(s->device, req);
04752    return 1;
04753 }

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

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

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

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

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

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

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

Definition at line 5294 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, offhook_message::reference, 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().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

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

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

static int load_module ( void   )  [static]

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

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

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

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

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

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

Show SKINNY devices in the manager API.

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

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

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

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

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

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

Show Skinny lines in the manager API.

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

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

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

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

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

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

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

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

static void register_exten ( struct skinny_line l  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 7563 of file chan_skinny.c.

References skinny_reload().

07564 {
07565    skinny_reload();
07566    return 0;
07567 }

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

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

01558 {
01559    struct skinny_req *req;
01560 
01561    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01562       return NULL;
01563 
01564    req->len = htolel(size+4);
01565    req->e = htolel(response_message);
01566 
01567    return req;
01568 }

static int restart_monitor ( void   )  [static]

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

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

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

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

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

static int skinny_answer ( struct ast_channel ast  )  [static]

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

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

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

Definition at line 3913 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_ALERT, SKINNY_CALLWAITTONE, 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.

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

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6618 of file chan_skinny.c.

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

06619 {
06620    struct skinny_line *l;
06621    char *tmp;
06622 
06623    tmp = ast_strdupa(data);
06624 
06625    l = find_line_by_name(tmp);
06626 
06627    return get_devicestate(l);
06628 }

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

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

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

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

Definition at line 4198 of file chan_skinny.c.

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

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

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

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

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

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

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

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

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 3973 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_device::session, 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().

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 3773 of file chan_skinny.c.

References ast_party_caller::ani, ast_copy_string(), ast_log(), ast_party_name_free(), ast_party_name_init(), ast_party_number_free(), ast_party_number_init(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strdup, ast_channel::caller, skinny_subchannel::callid, ast_channel::connected, 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().

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

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

Definition at line 4156 of file chan_skinny.c.

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

04157 {
04158    struct ast_frame *fr;
04159    struct skinny_subchannel *sub = ast->tech_pvt;
04160    ast_mutex_lock(&sub->lock);
04161    fr = skinny_rtp_read(sub);
04162    ast_mutex_unlock(&sub->lock);
04163    return fr;
04164 }

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

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

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

int skinny_reload ( void   )  [static]

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4210 of file chan_skinny.c.

04211 {
04212    return -1; /* Start inband indications */
04213 }

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

Definition at line 4215 of file chan_skinny.c.

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

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

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

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

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

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

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

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

Definition at line 3806 of file chan_skinny.c.

References ast_channel::_state, ast_canmatch_extension(), ast_copy_string(), ast_debug, ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_safe_sleep(), AST_STATE_UP, ast_strlen_zero(), ast_verb, ast_channel::caller, skinny_subchannel::callid, ast_channel::context, 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().

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

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 3727 of file chan_skinny.c.

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

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

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

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

02443 {
02444    struct skinny_req *req;
02445 
02446    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02447       return;
02448 
02449    req->data.activatecallplane.lineInstance = htolel(l->instance);
02450    transmit_response(d, req);
02451 }

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

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

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

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

02454 {
02455    struct skinny_req *req;
02456 
02457    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
02458       return;
02459 
02460    req->data.callstate.callState = htolel(state);
02461    req->data.callstate.lineInstance = htolel(buttonInstance);
02462    req->data.callstate.callReference = htolel(callid);
02463    transmit_response(d, req);
02464 }

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

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

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

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

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

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

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

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

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

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

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

02399 {
02400    struct skinny_req *req;
02401 
02402    if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02403       return;
02404 
02405    req->data.closereceivechannel.conferenceId = htolel(0);
02406    req->data.closereceivechannel.partyId = htolel(sub->callid);
02407    transmit_response(d, req);
02408 }

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

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

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

static void transmit_definetimedate ( struct skinny_device d  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

02262 {
02263    struct skinny_req *req;
02264 
02265    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
02266       return;
02267 
02268    req->data.setlamp.stimulus = htolel(stimulus);
02269    req->data.setlamp.stimulusInstance = htolel(instance);
02270    req->data.setlamp.deviceStimulus = htolel(indication);
02271    transmit_response(d, req);
02272 }

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

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

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

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

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

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

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

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

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

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

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

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

static void transmit_serverres ( struct skinny_device d  )  [static]

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

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

static void transmit_softkeysetres ( struct skinny_device d  )  [static]

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

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

static void transmit_softkeytemplateres ( struct skinny_device d  )  [static]

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

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

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

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

02152 {
02153    struct skinny_req *req;
02154 
02155    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
02156       return;
02157 
02158    req->data.setspeaker.mode = htolel(mode);
02159    transmit_response(d, req);
02160 }

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

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

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

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

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

02227 {
02228    struct skinny_req *req;
02229    if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
02230       return;
02231    req->data.starttone.tone = htolel(tone);
02232    req->data.starttone.instance = htolel(instance);
02233    req->data.starttone.reference = htolel(reference);
02234    transmit_response(d, req);
02235 }

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

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

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

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

02238 {
02239    struct skinny_req *req;
02240    if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
02241       return;
02242    req->data.stoptone.instance = htolel(instance);
02243    req->data.stoptone.reference = htolel(reference);
02244    transmit_response(d, req);
02245 }

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

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

02411 {
02412    struct skinny_req *req;
02413 
02414    if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
02415       return;
02416 
02417    req->data.stopmedia.conferenceId = htolel(0);
02418    req->data.stopmedia.passThruPartyId = htolel(sub->callid);
02419    transmit_response(d, req);
02420 }

static void transmit_versionres ( struct skinny_device d  )  [static]

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

02560 {
02561    struct skinny_req *req;
02562    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
02563       return;
02564 
02565    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
02566    transmit_response(d, req);
02567 }

static int unload_module ( void   )  [static]

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

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

static void unregister_exten ( struct skinny_line l  )  [static]

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

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

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

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

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


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 = "8586c2a7d357cb591cc3a6607a8f62d1" , .load = load_module, .unload = unload_module, .reload = reload, .load_pri = AST_MODPRI_CHANNEL_DRIVER, } [static]

Definition at line 7574 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 1042 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 1046 of file chan_skinny.c.

struct ast_hostent ahp [static]

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

int auth_limit = DEFAULT_AUTH_LIMIT [static]

Definition at line 174 of file chan_skinny.c.

int auth_timeout = DEFAULT_AUTH_TIMEOUT [static]

Definition at line 173 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 1039 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 1047 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 3716 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

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

Referenced by control2str().

unsigned int cos

Definition at line 167 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 168 of file chan_skinny.c.

unsigned int cos_video

Definition at line 169 of file chan_skinny.c.

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

Definition at line 179 of file chan_skinny.c.

format_t default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 144 of file chan_skinny.c.

struct skinny_device_options* default_device = &default_device_struct [static]

Definition at line 1356 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

Definition at line 223 of file chan_skinny.c.

struct skinny_line_options* default_line = &default_line_struct [static]

Definition at line 1283 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 145 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 238 of file chan_skinny.c.

Referenced by device2str().

int firstdigittimeout = 16000 [static]

Definition at line 1166 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1169 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 231 of file chan_skinny.c.

char global_vmexten[AST_MAX_EXTENSION] [static]

Definition at line 176 of file chan_skinny.c.

struct hostent* hp [static]

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

int keep_alive = 120 [static]

Definition at line 172 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1172 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1163 of file chan_skinny.c.

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

Definition at line 1157 of file chan_skinny.c.

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

Definition at line 1159 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 1040 of file chan_skinny.c.

int ourport [static]

Definition at line 1041 of file chan_skinny.c.

struct { ... } qos [static]

char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 178 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 1152 of file chan_skinny.c.

int skinny_header_size = 12 [static]

Definition at line 1029 of file chan_skinny.c.

struct ast_rtp_glue skinny_rtp_glue [static]

Definition at line 2875 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1397 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 1035 of file chan_skinny.c.

int skinnyreload = 0 [static]

Definition at line 1036 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 1045 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 824 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 868 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 854 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 863 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 887 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 846 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 877 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 833 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 814 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 840 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 872 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 883 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[] [static]

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

unsigned int tos

Definition at line 164 of file chan_skinny.c.

unsigned int tos_audio

Definition at line 165 of file chan_skinny.c.

unsigned int tos_video

Definition at line 166 of file chan_skinny.c.

int unauth_sessions = 0 [static]

Definition at line 175 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 177 of file chan_skinny.c.

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

Definition at line 180 of file chan_skinny.c.


Generated on Mon Jun 27 16:51:10 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7