Wed Apr 6 11:30:01 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_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 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 = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static ast_mutex_t netlock = { { { NULL }, { 0 }, 0, { NULL }, { 0 }, {{{ 0 }}}, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP } , 1, PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP }
static char ourhost [256]
static int ourport
struct {
   unsigned int   cos
   unsigned int   cos_audio
   unsigned int   cos_video
   unsigned int   tos
   unsigned int   tos_audio
   unsigned int   tos_video
qos
static char regcontext [AST_MAX_CONTEXT]
static struct sched_contextsched = NULL
static int skinny_header_size = 12
static struct ast_rtp_glue skinny_rtp_glue
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
static int skinnyreload = 0
static int skinnysock = -1
static const uint8_t soft_key_default_connected []
static const uint8_t soft_key_default_connwithconf []
static const uint8_t soft_key_default_connwithtrans []
static const uint8_t soft_key_default_dadfd []
static struct soft_key_definitions soft_key_default_definitions []
static const uint8_t soft_key_default_offhook []
static const uint8_t soft_key_default_offhookwithfeat []
static const uint8_t soft_key_default_onhold []
static const uint8_t soft_key_default_onhook []
static const uint8_t soft_key_default_ringin []
static const uint8_t soft_key_default_ringout []
static const uint8_t soft_key_default_unknown []
static struct soft_key_template_definition soft_key_template_default []
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static char used_context [AST_MAX_EXTENSION]
static char version_id [16] = "P002F202"


Detailed Description

Implementation of the Skinny protocol.

Author:
Jeremy McNamara & Florian Overkamp & North Antara

Definition in file chan_skinny.c.


Define Documentation

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116

Definition at line 955 of file chan_skinny.c.

Referenced by transmit_activatecallplane().

#define ALARM_MESSAGE   0x0020

Definition at line 322 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 529 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 532 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 533 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 531 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_LINE   0xB1

Definition at line 540 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 539 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 526 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_DND   STIMULUS_DND

Definition at line 530 of file chan_skinny.c.

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 523 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 524 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 525 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 521 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 527 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 534 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 519 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 520 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 522 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 528 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 318 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 489 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 427 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 926 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 562 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 290 of file chan_skinny.c.

Referenced by handle_message().

#define CDEV   ((struct skinny_device *)item)

Definition at line 6624 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CDEV_OPTS   ((struct skinny_device_options *)item)

Definition at line 6623 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 560 of file chan_skinny.c.

Referenced by transmit_clear_display_message().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 559 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 943 of file chan_skinny.c.

Referenced by transmit_clearpromptmessage().

#define CLINE   ((struct skinny_line *)item)

Definition at line 6622 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLINE_OPTS   ((struct skinny_line_options *)item)

Definition at line 6621 of file chan_skinny.c.

Referenced by config_parse_variables().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 598 of file chan_skinny.c.

Referenced by transmit_closereceivechannel().

#define CONTROL2STR_BUFSIZE   100

Definition at line 237 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 158 of file chan_skinny.c.

Referenced by config_load().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 157 of file chan_skinny.c.

Referenced by config_device(), and config_load().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 476 of file chan_skinny.c.

Referenced by transmit_definetimedate().

#define DEVICE2STR_BUFSIZE   15

Definition at line 234 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 960 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 949 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 934 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 554 of file chan_skinny.c.

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 266 of file chan_skinny.c.

Referenced by handle_message().

#define FORWARD_STAT_MESSAGE   0x0090

Definition at line 449 of file chan_skinny.c.

Referenced by transmit_cfwdstate().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 349 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     bswap_32(x)

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

Referenced by transmit_softkeysetres().

#define IP_PORT_MESSAGE   0x0002

Definition at line 256 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 585 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 243 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

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

#define KEYDEF_CONNWITHTRANS   5

Definition at line 617 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 618 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

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

Referenced by handle_transfer_button().

#define KEYDEF_ONHOLD   2

Definition at line 614 of file chan_skinny.c.

Referenced by handle_hold_button(), and handle_soft_key_event_message().

#define KEYDEF_ONHOOK   0

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

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

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

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 258 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     bswap_32(x)

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

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 468 of file chan_skinny.c.

Referenced by transmit_linestatres().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 312 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 278 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 284 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 330 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 587 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 352 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 350 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 246 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 564 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 580 of file chan_skinny.c.

Referenced by handle_skinny_reset(), and skinny_reload().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 918 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 320 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 569 of file chan_skinny.c.

Referenced by transmit_serverres().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 383 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 396 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 375 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 390 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 1107 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 1094 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 1106 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLREMOTEMULTILINE   13

Definition at line 1101 of file chan_skinny.c.

Referenced by skinny_extensionstate_cb().

#define SKINNY_CALLWAIT   9

Definition at line 1097 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 1109 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CFWD_ALL   (1 << 0)

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

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

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

#define SKINNY_CX_CONFERENCE   3

Definition at line 1132 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 1134 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 1133 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 1129 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 1128 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 1130 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 1049 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 1048 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 1047 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 1046 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 1050 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 1076 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 1072 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 1065 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 1051 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 1060 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 1075 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 1058 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 1073 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 1064 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 1063 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 1054 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 1079 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 1067 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 1053 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 1056 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 1062 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 1068 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 1069 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 1052 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 1078 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 1061 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 1066 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 1070 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 1074 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 1057 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 1071 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 1059 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 1055 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 1077 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 1045 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_OPTIONS

Definition at line 1303 of file chan_skinny.c.

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 1080 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 1081 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_INVALID   14

Definition at line 1102 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

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

Referenced by skinny_extensionstate_cb().

#define SKINNY_LAMP_OFF   1

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

Referenced by skinny_extensionstate_cb(), and skinny_hold().

#define SKINNY_LINE_OPTIONS

Definition at line 1193 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

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

#define SKINNY_MICON   1

Definition at line 1086 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 1110 of file chan_skinny.c.

#define SKINNY_OFFHOOK   1

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

#define SKINNY_PROGRESS   12

Definition at line 1100 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_REORDER   0x25

Definition at line 1108 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 1121 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 1119 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

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

#define SKINNY_RINGIN   4

Definition at line 1092 of file chan_skinny.c.

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

#define SKINNY_RINGOUT   3

Definition at line 1091 of file chan_skinny.c.

Referenced by skinny_indicate(), and update_connectedline().

#define SKINNY_SILENCE   0x00

Definition at line 1104 of file chan_skinny.c.

#define SKINNY_SPEAKEROFF   2

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

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 340 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 338 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 903 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 348 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 605 of file chan_skinny.c.

Referenced by transmit_softkeytemplateres().

#define SOFTKEY_ANSWER   0x0B

Definition at line 635 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 632 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 629 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 630 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 631 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 637 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_DND   0x13

Definition at line 643 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 642 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 627 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_IDIVERT   0x14

Definition at line 644 of file chan_skinny.c.

#define SOFTKEY_INFO   0x0C

Definition at line 636 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 639 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 640 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 626 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 624 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 641 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 625 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 634 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 628 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 307 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 461 of file chan_skinny.c.

Referenced by transmit_speeddialstatres().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 401 of file chan_skinny.c.

Referenced by transmit_startmediatransmission().

#define START_TONE_MESSAGE   0x0082

Definition at line 361 of file chan_skinny.c.

Referenced by transmit_start_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 511 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 514 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 515 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 513 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 508 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DND   0x3F

Definition at line 512 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 505 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and skinny_ss().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 506 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 507 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 503 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

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

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 516 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 501 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 502 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 504 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 510 of file chan_skinny.c.

Referenced by handle_stimulus_message(), and mwi_event_cb().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 420 of file chan_skinny.c.

Referenced by transmit_stopmediatransmission().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 369 of file chan_skinny.c.

Referenced by transmit_stop_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 317 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_DEF_DEVICE   2

Definition at line 6616 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEF_LINE   4

Definition at line 6617 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_DEVICE   8

Definition at line 6618 of file chan_skinny.c.

Referenced by config_device(), and config_parse_variables().

#define TYPE_GENERAL   1

Definition at line 6615 of file chan_skinny.c.

Referenced by config_load(), and config_parse_variables().

#define TYPE_LINE   16

Definition at line 6619 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 347 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 319 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

00247 {

static void __init_device2str_threadbuf ( void   )  [static]

Definition at line 233 of file chan_skinny.c.

00247 {

static void __reg_module ( void   )  [static]

Definition at line 7504 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 6473 of file chan_skinny.c.

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

Referenced by config_load().

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

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

implement the setvar config line

Definition at line 1636 of file chan_skinny.c.

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

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

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

Definition at line 1797 of file chan_skinny.c.

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

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

static int codec_ast2skinny ( format_t  astcodec  )  [static]

Definition at line 1740 of file chan_skinny.c.

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

Referenced by transmit_connect(), and transmit_startmediatransmission().

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

static format_t codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

Definition at line 1718 of file chan_skinny.c.

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

Referenced by handle_capabilities_res_message().

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

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

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

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

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

Definition at line 2958 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_reset().

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

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

Definition at line 2953 of file chan_skinny.c.

References ast_strdup, and complete_skinny_devices().

Referenced by handle_skinny_show_device().

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

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

Definition at line 2963 of file chan_skinny.c.

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

Referenced by handle_skinny_show_line().

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

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

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

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

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

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

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

static int config_load ( void   )  [static]

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

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

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

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

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

static char* control2str ( int  ind  )  [static]

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

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

static void delete_devices ( void   )  [static]

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

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

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 6315 of file chan_skinny.c.

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

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

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

static char* device2str ( int  type  )  [static]

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

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

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

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

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

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

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

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

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

Definition at line 1585 of file chan_skinny.c.

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

Referenced by skinny_devicestate(), and skinny_request().

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

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

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

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

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

Definition at line 1652 of file chan_skinny.c.

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

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

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

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

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

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

Definition at line 1413 of file chan_skinny.c.

References skinny_device::addons, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_UNLOCK, ast_log(), BT_CALLPARK, BT_CONFERENCE, BT_CUST_LINE, BT_CUST_LINESPEEDDIAL, BT_DISPLAY, BT_FORWARDALL, BT_HOLD, BT_LINE, BT_NONE, BT_REDIAL, BT_SPEEDDIAL, BT_TRANSFER, BT_VOICEMAIL, skinnysession::device, 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().

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

static int get_devicestate ( struct skinny_line l  )  [static]

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

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

static int get_input ( struct skinnysession s  )  [static]

Definition at line 6336 of file chan_skinny.c.

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

Referenced by do_message(), and skinny_session().

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

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

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

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

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

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

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

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

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

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

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

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

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

static int handle_hold_button ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 4857 of file chan_skinny.c.

Referenced by handle_message().

04858 {
04859    /* no response necessary */
04860    return 1;
04861 }

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

Definition at line 4740 of file chan_skinny.c.

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

Referenced by handle_message().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4749 of file chan_skinny.c.

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

Referenced by handle_message().

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static int handle_transfer_button ( struct skinny_subchannel sub  )  [static]

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

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

static int load_module ( void   )  [static]

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

07376 {
07377    int res = 0;
07378 
07379    for (; res < ARRAY_LEN(soft_key_template_default); res++) {
07380       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
07381    }
07382    /* load and parse config */
07383    res = config_load();
07384    if (res == -1) {
07385       return AST_MODULE_LOAD_DECLINE;
07386    }
07387 
07388    /* Make sure we can register our skinny channel type */
07389    if (ast_channel_register(&skinny_tech)) {
07390       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
07391       return -1;
07392    }
07393 
07394    ast_rtp_glue_register(&skinny_rtp_glue);
07395    ast_cli_register_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07396 
07397    ast_manager_register_xml("SKINNYdevices", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_devices);
07398    ast_manager_register_xml("SKINNYshowdevice", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_device);
07399    ast_manager_register_xml("SKINNYlines", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_lines);
07400    ast_manager_register_xml("SKINNYshowline", EVENT_FLAG_SYSTEM | EVENT_FLAG_REPORTING, manager_skinny_show_line);
07401 
07402    sched = sched_context_create();
07403    if (!sched) {
07404       ast_log(LOG_WARNING, "Unable to create schedule context\n");
07405    }
07406    io = io_context_create();
07407    if (!io) {
07408       ast_log(LOG_WARNING, "Unable to create I/O context\n");
07409    }
07410    /* And start the monitor for the first time */
07411    restart_monitor();
07412 
07413    return AST_MODULE_LOAD_SUCCESS;
07414 }

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

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

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

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

Show SKINNY devices in the manager API.

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

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

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

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

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

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

Show Skinny lines in the manager API.

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

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

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

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

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

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

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

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

static void register_exten ( struct skinny_line l  )  [static]

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

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

static int reload ( void   )  [static]

Definition at line 7493 of file chan_skinny.c.

References skinny_reload().

07494 {
07495    skinny_reload();
07496    return 0;
07497 }

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

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

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

static int restart_monitor ( void   )  [static]

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

06542 {
06543    /* If we're supposed to be stopped -- stay stopped */
06544    if (monitor_thread == AST_PTHREADT_STOP)
06545       return 0;
06546 
06547    ast_mutex_lock(&monlock);
06548    if (monitor_thread == pthread_self()) {
06549       ast_mutex_unlock(&monlock);
06550       ast_log(LOG_WARNING, "Cannot kill myself\n");
06551       return -1;
06552    }
06553    if (monitor_thread != AST_PTHREADT_NULL) {
06554       /* Wake up the thread */
06555       pthread_kill(monitor_thread, SIGURG);
06556    } else {
06557       /* Start a new monitor */
06558       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
06559          ast_mutex_unlock(&monlock);
06560          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
06561          return -1;
06562       }
06563    }
06564    ast_mutex_unlock(&monlock);
06565    return 0;
06566 }

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

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

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

static int skinny_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

static int skinny_devicestate ( void *  data  )  [static]

Definition at line 6568 of file chan_skinny.c.

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

06569 {
06570    struct skinny_line *l;
06571    char *tmp;
06572 
06573    tmp = ast_strdupa(data);
06574 
06575    l = find_line_by_name(tmp);
06576 
06577    return get_devicestate(l);
06578 }

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

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

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

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

Definition at line 4192 of file chan_skinny.c.

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

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

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

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

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

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

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

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

static int skinny_hangup ( struct ast_channel ast  )  [static]

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

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4150 of file chan_skinny.c.

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

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

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

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

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

int skinny_reload ( void   )  [static]

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

07294 {
07295    struct skinny_device *d;
07296    struct skinny_line *l;
07297    struct skinny_speeddial *sd;
07298    struct skinny_addon *a;
07299    struct skinny_req *req;
07300 
07301    if (skinnyreload) {
07302       ast_verb(3, "Chan_skinny is already reloading.\n");
07303       return 0;
07304    }
07305 
07306    skinnyreload = 1;
07307 
07308    /* Mark all devices and lines as candidates to be pruned */
07309    AST_LIST_LOCK(&devices);
07310    AST_LIST_TRAVERSE(&devices, d, list) {
07311       d->prune = 1;
07312    }
07313    AST_LIST_UNLOCK(&devices);
07314 
07315    AST_LIST_LOCK(&lines);
07316    AST_LIST_TRAVERSE(&lines, l, all) {
07317       l->prune = 1;
07318    }
07319    AST_LIST_UNLOCK(&lines);
07320 
07321         config_load();
07322 
07323    /* Remove any devices that no longer exist in the config */
07324    AST_LIST_LOCK(&devices);
07325    AST_LIST_TRAVERSE_SAFE_BEGIN(&devices, d, list) {
07326       if (!d->prune) {
07327          continue;
07328       }
07329       ast_verb(3, "Removing device '%s'\n", d->name);
07330       /* Delete all lines for this device. 
07331          We do not want to free the line here, that
07332          will happen below. */
07333       while ((l = AST_LIST_REMOVE_HEAD(&d->lines, list))) {
07334       }
07335       /* Delete all speeddials for this device */
07336       while ((sd = AST_LIST_REMOVE_HEAD(&d->speeddials, list))) {
07337          free(sd);
07338       }
07339       /* Delete all addons for this device */
07340       while ((a = AST_LIST_REMOVE_HEAD(&d->addons, list))) {
07341          free(a);
07342       }
07343       AST_LIST_REMOVE_CURRENT(list);
07344       free(d);
07345    }
07346    AST_LIST_TRAVERSE_SAFE_END;
07347    AST_LIST_UNLOCK(&devices);
07348 
07349    AST_LIST_LOCK(&lines);  
07350    AST_LIST_TRAVERSE_SAFE_BEGIN(&lines, l, all) {
07351       if (l->prune) {
07352          AST_LIST_REMOVE_CURRENT(all);
07353          free(l);
07354       }
07355    }
07356    AST_LIST_TRAVERSE_SAFE_END;
07357    AST_LIST_UNLOCK(&lines);  
07358 
07359    AST_LIST_TRAVERSE(&devices, d, list) {
07360       /* Do a soft reset to re-register the devices after
07361          cleaning up the removed devices and lines */
07362       if (d->session) {
07363          ast_verb(3, "Restarting device '%s'\n", d->name);
07364          if ((req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE))) {
07365             req->data.reset.resetType = 2;
07366             transmit_response(d, req);
07367          }
07368       }
07369    }
07370    
07371    skinnyreload = 0;
07372         return 0;
07373 }

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

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

06414 {
06415    struct skinny_req *req;
06416    int *bufaddr;
06417 
06418    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
06419       return NULL;
06420 
06421    ast_mutex_lock(&s->lock);
06422    memcpy(req, s->inbuf, skinny_header_size);
06423    bufaddr = (int *)(s->inbuf);
06424    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
06425 
06426    ast_mutex_unlock(&s->lock);
06427 
06428    if (letohl(req->e) < 0) {
06429       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
06430       ast_free(req);
06431       return NULL;
06432    }
06433 
06434    return req;
06435 }

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

06581 {
06582    format_t oldformat;
06583    
06584    struct skinny_line *l;
06585    struct ast_channel *tmpc = NULL;
06586    char tmp[256];
06587    char *dest = data;
06588 
06589    oldformat = format;
06590    
06591    if (!(format &= AST_FORMAT_AUDIO_MASK)) {
06592       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%s'\n", ast_getformatname_multiple(tmp, sizeof(tmp), format));
06593       return NULL;
06594    }
06595 
06596    ast_copy_string(tmp, dest, sizeof(tmp));
06597    if (ast_strlen_zero(tmp)) {
06598       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
06599       return NULL;
06600    }
06601    l = find_line_by_name(tmp);
06602    if (!l) {
06603       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
06604       return NULL;
06605    }
06606    ast_verb(3, "skinny_request(%s)\n", tmp);
06607    tmpc = skinny_new(l, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
06608    if (!tmpc) {
06609       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
06610    }
06611    restart_monitor();
06612    return tmpc;
06613 }

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

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

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

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

Definition at line 4204 of file chan_skinny.c.

04205 {
04206    return -1; /* Start inband indications */
04207 }

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

Definition at line 4209 of file chan_skinny.c.

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

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

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

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

06438 {
06439    int res;
06440    struct skinny_req *req;
06441    struct skinnysession *s = data;
06442 
06443    ast_verb(3, "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
06444 
06445    for (;;) {
06446       res = get_input(s);
06447       if (res < 0) {
06448          break;
06449       }
06450 
06451       if (res > 0)
06452       {
06453          if (!(req = skinny_req_parse(s))) {
06454             destroy_session(s);
06455             return NULL;
06456          }
06457 
06458          res = handle_message(req, s);
06459          if (res < 0) {
06460             destroy_session(s);
06461             return NULL;
06462          }
06463       }
06464    }
06465    ast_debug(3, "Skinny Session returned: %s\n", strerror(errno));
06466 
06467    if (s) 
06468       destroy_session(s);
06469    
06470    return 0;
06471 }

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

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

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

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

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

static int skinny_transfer ( struct skinny_subchannel sub  )  [static]

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

static void start_rtp ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void transmit_definetimedate ( struct skinny_device d  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void transmit_serverres ( struct skinny_device d  )  [static]

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

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

static void transmit_softkeysetres ( struct skinny_device d  )  [static]

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

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

static void transmit_softkeytemplateres ( struct skinny_device d  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

static void transmit_versionres ( struct skinny_device d  )  [static]

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

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

static int unload_module ( void   )  [static]

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

07417 {
07418    struct skinnysession *s;
07419    struct skinny_device *d;
07420    struct skinny_line *l;
07421    struct skinny_subchannel *sub;
07422    struct ast_context *con;
07423 
07424    ast_rtp_glue_unregister(&skinny_rtp_glue);
07425    ast_channel_unregister(&skinny_tech);
07426    ast_cli_unregister_multiple(cli_skinny, ARRAY_LEN(cli_skinny));
07427 
07428    ast_manager_unregister("SKINNYdevices");
07429    ast_manager_unregister("SKINNYshowdevice");
07430    ast_manager_unregister("SKINNYlines");
07431    ast_manager_unregister("SKINNYshowline");
07432    
07433    AST_LIST_LOCK(&sessions);
07434    /* Destroy all the interfaces and free their memory */
07435    while((s = AST_LIST_REMOVE_HEAD(&sessions, list))) {
07436       d = s->device;
07437       AST_LIST_TRAVERSE(&d->lines, l, list){
07438          ast_mutex_lock(&l->lock);
07439          AST_LIST_TRAVERSE(&l->sub, sub, list) {
07440             ast_mutex_lock(&sub->lock);
07441             if (sub->owner) {
07442                sub->alreadygone = 1;
07443                ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
07444             }
07445             ast_mutex_unlock(&sub->lock);
07446          }
07447          if (l->mwi_event_sub)
07448             ast_event_unsubscribe(l->mwi_event_sub);
07449          ast_mutex_unlock(&l->lock);
07450          manager_event(EVENT_FLAG_SYSTEM, "PeerStatus", "ChannelType: Skinny\r\nPeer: Skinny/%s@%s\r\nPeerStatus: Unregistered\r\n", l->name, d->name);
07451          unregister_exten(l);
07452       }
07453       if (s->fd > -1)
07454          close(s->fd);
07455       pthread_cancel(s->t);
07456       pthread_kill(s->t, SIGURG);
07457       pthread_join(s->t, NULL);
07458       free(s);
07459    }
07460    AST_LIST_UNLOCK(&sessions);
07461 
07462    delete_devices();
07463 
07464    ast_mutex_lock(&monlock);
07465    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
07466       pthread_cancel(monitor_thread);
07467       pthread_kill(monitor_thread, SIGURG);
07468       pthread_join(monitor_thread, NULL);
07469    }
07470    monitor_thread = AST_PTHREADT_STOP;
07471    ast_mutex_unlock(&monlock);
07472 
07473    ast_mutex_lock(&netlock);
07474    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
07475       pthread_cancel(accept_t);
07476       pthread_kill(accept_t, SIGURG);
07477       pthread_join(accept_t, NULL);
07478    }
07479    accept_t = AST_PTHREADT_STOP;
07480    ast_mutex_unlock(&netlock);
07481 
07482    close(skinnysock);
07483    if (sched)
07484       sched_context_destroy(sched);
07485 
07486    con = ast_context_find(used_context);
07487    if (con)
07488       ast_context_destroy(con, "Skinny");
07489    
07490    return 0;
07491 }

static void unregister_exten ( struct skinny_line l  )  [static]

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

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

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

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

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


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

struct in_addr __ourip [static]

Definition at line 1037 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 1041 of file chan_skinny.c.

struct ast_hostent ahp [static]

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

struct sockaddr_in bindaddr [static]

Definition at line 1034 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 1042 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

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

Referenced by control2str().

unsigned int cos

Definition at line 165 of file chan_skinny.c.

unsigned int cos_audio

Definition at line 166 of file chan_skinny.c.

unsigned int cos_video

Definition at line 167 of file chan_skinny.c.

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

Definition at line 174 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 1351 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 218 of file chan_skinny.c.

struct skinny_line_options* default_line = &default_line_struct [static]

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

Referenced by device2str().

int firstdigittimeout = 16000 [static]

Definition at line 1161 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 1164 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 226 of file chan_skinny.c.

char global_vmexten[AST_MAX_EXTENSION] [static]

Definition at line 171 of file chan_skinny.c.

struct hostent* hp [static]

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

int keep_alive = 120 [static]

Definition at line 170 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 1167 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 1158 of file chan_skinny.c.

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

Definition at line 1152 of file chan_skinny.c.

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

Definition at line 1154 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 1035 of file chan_skinny.c.

int ourport [static]

Definition at line 1036 of file chan_skinny.c.

struct { ... } qos [static]

char regcontext[AST_MAX_CONTEXT] [static]

Definition at line 173 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 1147 of file chan_skinny.c.

int skinny_header_size = 12 [static]

Definition at line 1024 of file chan_skinny.c.

struct ast_rtp_glue skinny_rtp_glue [static]

Definition at line 2869 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1391 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 1030 of file chan_skinny.c.

int skinnyreload = 0 [static]

Definition at line 1031 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 1040 of file chan_skinny.c.

const uint8_t soft_key_default_connected[] [static]

Definition at line 819 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 863 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 849 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 858 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 882 of file chan_skinny.c.

Referenced by transmit_softkeysetres().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 841 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 872 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 828 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 809 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 835 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 867 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 878 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[] [static]

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

unsigned int tos_audio

Definition at line 163 of file chan_skinny.c.

unsigned int tos_video

Definition at line 164 of file chan_skinny.c.

char used_context[AST_MAX_EXTENSION] [static]

Definition at line 172 of file chan_skinny.c.

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

Definition at line 175 of file chan_skinny.c.


Generated on Wed Apr 6 11:30:01 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7