Sat Aug 6 00:39:52 2011

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

#include "asterisk.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.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/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.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/astobj.h"
#include "asterisk/abstract_jb.h"
#include "asterisk/threadstorage.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  dialed_number_message
struct  display_notify_message
struct  display_prompt_status_message
struct  displaytext_message
struct  enbloc_call_message
struct  keypad_button_message
struct  line_stat_res_message
struct  line_state_req_message
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  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_line
struct  skinny_paging_device
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_HINT   0xB1
#define BT_CUST_LINESPEEDDIAL   0xB0
#define BT_DISPLAY   STIMULUS_DISPLAY
#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 CLEAR_DISPLAY_MESSAGE   0x009A
#define CLEAR_NOTIFY_MESSAGE   0x0115
#define CLEAR_PROMPT_MESSAGE   0x0113
#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106
#define CONTROL2STR_BUFSIZE   100
#define DEFAULT_AUTH_LIMIT   50
#define DEFAULT_AUTH_TIMEOUT   30
#define DEFAULT_SKINNY_BACKLOG   2
#define DEFAULT_SKINNY_PORT   2000
#define DEFINETIMEDATE_MESSAGE   0x0094
#define DEVICE2STR_BUFSIZE   15
#define DIALED_NUMBER_MESSAGE   0x011D
#define DISPLAY_NOTIFY_MESSAGE   0x0114
#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112
#define DISPLAYTEXT_MESSAGE   0x0099
#define ENBLOC_CALL_MESSAGE   0x0004
#define HEADSET_STATUS_MESSAGE   0x002B
#define htolel(x)   (x)
#define htoles(x)   (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)   (x)
#define letohs(x)   (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_CALLWAIT   9
#define SKINNY_CALLWAITTONE   0x2D
#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_SCCPGATEWAY_AN   30027
#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028
#define SKINNY_DEVICE_UNKNOWN   -1
#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_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_ENDCALL   0x09
#define SOFTKEY_GPICKUP   0x12
#define SOFTKEY_HOLD   0x03
#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_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_LINE   2
#define TYPE_TRUNK   1
#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 __reg_module (void)
static void __unreg_module (void)
static void * accept_thread (void *ignore)
static struct skinny_devicebuild_device (const char *cat, struct ast_variable *v)
static int codec_ast2skinny (int astcodec)
static int codec_skinny2ast (enum skinny_codecs skinnycodec)
static char * complete_skinny_reset (const char *line, const char *word, int pos, int state)
static char * control2str (int ind)
static void control2str_threadbuf_init (void)
static void delete_devices (void)
static void destroy_session (struct skinnysession *s)
static char * device2str (int type)
static void device2str_threadbuf_init (void)
static void do_housekeeping (struct skinnysession *s)
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)
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_input (struct skinnysession *s)
static int handle_alarm_message (struct skinny_req *req, struct skinnysession *s)
static int handle_button_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_capabilities_res_message (struct skinny_req *req, struct skinnysession *s)
static int handle_enbloc_call_message (struct skinny_req *req, struct skinnysession *s)
static int handle_headset_status_message (struct skinny_req *req, struct skinnysession *s)
static int handle_ip_port_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keep_alive_message (struct skinny_req *req, struct skinnysession *s)
static int handle_keypad_button_message (struct skinny_req *req, struct skinnysession *s)
static int handle_line_state_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_message (struct skinny_req *req, struct skinnysession *s)
static int handle_offhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_onhook_message (struct skinny_req *req, struct skinnysession *s)
static int handle_open_receive_channel_ack_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_available_lines_message (struct skinny_req *req, struct skinnysession *s)
static int handle_register_message (struct skinny_req *req, struct skinnysession *s)
static int handle_server_request_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_event_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_set_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_soft_key_template_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_speed_dial_stat_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_stimulus_message (struct skinny_req *req, struct skinnysession *s)
static int handle_time_date_req_message (struct skinny_req *req, struct skinnysession *s)
static int handle_unregister_message (struct skinny_req *req, struct skinnysession *s)
static int handle_version_req_message (struct skinny_req *req, struct skinnysession *s)
static int load_module (void)
static int reload_config (void)
static struct skinny_reqreq_alloc (size_t size, int response_message)
static int restart_monitor (void)
static int skinny_answer (struct ast_channel *ast)
static int skinny_call (struct ast_channel *ast, char *dest, int timeout)
static int skinny_do_debug (int fd, int argc, char *argv[])
static int skinny_fixup (struct ast_channel *oldchan, struct ast_channel *newchan)
static enum ast_rtp_get_result skinny_get_rtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static enum ast_rtp_get_result skinny_get_vrtp_peer (struct ast_channel *c, struct ast_rtp **rtp)
static int skinny_hangup (struct ast_channel *ast)
static int skinny_hold (struct skinny_subchannel *sub)
static int skinny_indicate (struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct ast_channelskinny_new (struct skinny_line *l, int state)
static void * skinny_newcall (void *data)
static int skinny_no_debug (int fd, int argc, char *argv[])
static struct ast_frameskinny_read (struct ast_channel *ast)
static int skinny_register (struct skinny_req *req, struct skinnysession *s)
static struct skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, int format, void *data, int *cause)
static int skinny_reset_device (int fd, int argc, char *argv[])
static struct ast_frameskinny_rtp_read (struct skinny_subchannel *sub)
static int skinny_senddigit_begin (struct ast_channel *ast, char digit)
static int skinny_senddigit_end (struct ast_channel *ast, char digit, unsigned int duration)
static void * skinny_session (void *data)
static int skinny_set_rtp_peer (struct ast_channel *c, struct ast_rtp *rtp, struct ast_rtp *vrtp, int codecs, int nat_active)
static int skinny_show_devices (int fd, int argc, char *argv[])
static int skinny_show_lines (int fd, int argc, char *argv[])
static void * skinny_ss (void *data)
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_callinfo (struct skinnysession *s, const char *fromname, const char *fromnum, const char *toname, const char *tonum, int instance, int callid, int calltype)
static void transmit_callstate (struct skinnysession *s, int instance, int state, unsigned callid)
static void transmit_connect (struct skinnysession *s, struct skinny_subchannel *sub)
static void transmit_dialednumber (struct skinnysession *s, const char *text, int instance, int callid)
static void transmit_displaymessage (struct skinnysession *s, const char *text, int instance, int reference)
static void transmit_displaynotify (struct skinnysession *s, const char *text, int t)
static void transmit_displaypromptstatus (struct skinnysession *s, const char *text, int t, int instance, int callid)
static void transmit_lamp_indication (struct skinnysession *s, int stimulus, int instance, int indication)
static int transmit_response (struct skinnysession *s, struct skinny_req *req)
static void transmit_ringer_mode (struct skinnysession *s, int mode)
static void transmit_selectsoftkeys (struct skinnysession *s, int instance, int callid, int softkey)
static void transmit_speaker_mode (struct skinnysession *s, int mode)
static void transmit_tone (struct skinnysession *s, int tone, int instance, int reference)
static int unload_module (void)

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, }
static struct in_addr __ourip
static pthread_t accept_t
static char accountcode [AST_MAX_ACCOUNT_CODE] = ""
ast_hostent ahp
static int amaflags = 0
static const struct ast_module_infoast_module_info = &__mod_info
static int auth_limit = DEFAULT_AUTH_LIMIT
static int auth_timeout = DEFAULT_AUTH_TIMEOUT
static struct sockaddr_in bindaddr
static int callnums = 1
static int callreturn = 0
static int callwaiting = 0
static int cancallforward = 0
static char cid_name [AST_MAX_EXTENSION] = ""
static char cid_num [AST_MAX_EXTENSION] = ""
static struct ast_cli_entry cli_skinny []
static const char config [] = "skinny.conf"
static char context [AST_MAX_CONTEXT] = "default"
static struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = control2str_threadbuf_init , }
static ast_group_t cur_callergroup = 0
static ast_group_t cur_pickupgroup = 0
static char date_format [6] = "D-M-Y"
static char debug_usage []
static int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW
static struct ast_jb_conf default_jbconf
static struct ast_codec_pref default_prefs
static struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = device2str_threadbuf_init , }
static ast_mutex_t devicelock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct skinny_devicedevices
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
static struct ast_jb_conf global_jbconf
hostent * hp
static int immediate = 0
static struct io_contextio
static int keep_alive = 120
static char language [MAX_LANGUAGE] = ""
static char linelabel [AST_MAX_EXTENSION] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static char mohinterpret [MAX_MUSICCLASS] = "default"
static char mohsuggest [MAX_MUSICCLASS] = ""
static pthread_t monitor_thread = AST_PTHREADT_NULL
static ast_mutex_t monlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static int mwiblink = 0
static int nat = 0
static ast_mutex_t netlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static char no_debug_usage []
static char ourhost [256]
static int ourport
static char reset_usage []
static struct sched_contextsched = NULL
static ast_mutex_t sessionlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER )
static struct skinnysessionsessions
static char show_devices_usage []
static char show_lines_usage []
int skinny_header_size = 12
static struct ast_rtp_protocol skinny_rtp
static struct ast_channel_tech skinny_tech
static int skinnydebug = 0
static int 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 []
soft_key_template_definition soft_key_template_default []
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static int threewaycalling = 0
static int transfer = 0
static int unauth_sessions = 0
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 710 of file chan_skinny.c.

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

#define ALARM_MESSAGE   0x0020

Definition at line 232 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 426 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 428 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 429 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 427 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_HINT   0xB1

Definition at line 436 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 435 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 423 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 420 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 421 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 422 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 418 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 424 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 430 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 416 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 417 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 419 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 425 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 228 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 387 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 337 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 682 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 458 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 200 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 456 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 455 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 698 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 494 of file chan_skinny.c.

Referenced by skinny_hold(), and transmit_callstate().

#define CONTROL2STR_BUFSIZE   100

Definition at line 147 of file chan_skinny.c.

Referenced by control2str().

#define DEFAULT_AUTH_LIMIT   50

Definition at line 100 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_AUTH_TIMEOUT   30

Definition at line 99 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_SKINNY_BACKLOG   2

Definition at line 97 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_SKINNY_PORT   2000

Definition at line 96 of file chan_skinny.c.

Referenced by build_device(), and reload_config().

#define DEFINETIMEDATE_MESSAGE   0x0094

Definition at line 374 of file chan_skinny.c.

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 144 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 715 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 704 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 690 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 450 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 176 of file chan_skinny.c.

Referenced by handle_message().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 259 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     (x)

Definition at line 112 of file chan_skinny.c.

Referenced by get_input(), handle_button_template_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_server_request_message(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), load_module(), req_alloc(), skinny_hold(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_dialednumber(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

#define htoles (  )     (x)

Definition at line 113 of file chan_skinny.c.

#define IP_PORT_MESSAGE   0x0002

Definition at line 166 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 481 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 153 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

Definition at line 509 of file chan_skinny.c.

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

#define KEYDEF_CONNWITHCONF   7

Definition at line 515 of file chan_skinny.c.

#define KEYDEF_CONNWITHTRANS   5

Definition at line 513 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 514 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

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

#define KEYDEF_ONHOLD   2

Definition at line 510 of file chan_skinny.c.

#define KEYDEF_ONHOOK   0

Definition at line 508 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 511 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

Definition at line 516 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define KEYDEF_UNKNOWN   10

Definition at line 518 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 168 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     (x)

Definition at line 110 of file chan_skinny.c.

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

#define letohs (  )     (x)

Definition at line 111 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 366 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 222 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 188 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 194 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 240 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 483 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 262 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 260 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 156 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 460 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 476 of file chan_skinny.c.

Referenced by skinny_reset_device().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 674 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 230 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 465 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 293 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 306 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 285 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 300 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 881 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 869 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 880 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLWAIT   9

Definition at line 872 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 883 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CONGESTION   7

Definition at line 870 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

Definition at line 868 of file chan_skinny.c.

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

#define SKINNY_CX_CONF   3

Definition at line 904 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3

Definition at line 905 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 907 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 906 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 902 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 901 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 903 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 824 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 823 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 822 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 821 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 825 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 851 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 847 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 840 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 826 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 835 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 850 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 833 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 848 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 839 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 838 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 829 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 854 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 842 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 828 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 831 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 837 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 843 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 844 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 827 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 853 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 836 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 841 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 845 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 849 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 832 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 846 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 834 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 830 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 852 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 820 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 855 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 856 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 819 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DIALTONE   0x21

Definition at line 879 of file chan_skinny.c.

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

#define SKINNY_HOLD   8

Definition at line 871 of file chan_skinny.c.

#define SKINNY_INVALID   14

Definition at line 876 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 890 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_hold().

#define SKINNY_LAMP_FLASH   4

Definition at line 889 of file chan_skinny.c.

#define SKINNY_LAMP_OFF   1

Definition at line 886 of file chan_skinny.c.

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

#define SKINNY_LAMP_ON   2

Definition at line 887 of file chan_skinny.c.

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

#define SKINNY_LAMP_WINK   3

Definition at line 888 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

Definition at line 210 of file chan_skinny.c.

Referenced by handle_capabilities_res_message().

#define SKINNY_MAX_PACKET   1000

Definition at line 98 of file chan_skinny.c.

Referenced by skinny_req_parse(), and transmit_response().

#define SKINNY_MICOFF   2

Definition at line 862 of file chan_skinny.c.

#define SKINNY_MICON   1

Definition at line 861 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 884 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

Definition at line 864 of file chan_skinny.c.

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

#define SKINNY_ONHOOK   2

Definition at line 865 of file chan_skinny.c.

Referenced by build_device(), handle_onhook_message(), handle_soft_key_event_message(), handle_stimulus_message(), skinny_call(), skinny_hangup(), and transmit_callstate().

#define SKINNY_PARK   11

Definition at line 874 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 875 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 882 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 895 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 893 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

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

#define SKINNY_RINGIN   4

Definition at line 867 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RINGOUT   3

Definition at line 866 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00

Definition at line 878 of file chan_skinny.c.

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

#define SKINNY_SPEAKEROFF   2

Definition at line 859 of file chan_skinny.c.

Referenced by handle_stimulus_message(), skinny_hangup(), and transmit_callstate().

#define SKINNY_SPEAKERON   1

Definition at line 858 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define SKINNY_TRANSFER   10

Definition at line 873 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 250 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 248 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 659 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 258 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 501 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 531 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 528 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 525 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 526 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 527 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 533 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 529 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 538 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 523 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_INFO   0x0C

Definition at line 532 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 535 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 536 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 522 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 520 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 534 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 537 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 521 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 530 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 524 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 217 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 359 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 311 of file chan_skinny.c.

Referenced by handle_open_receive_channel_ack_message().

#define START_TONE_MESSAGE   0x0082

Definition at line 271 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 409 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 411 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 412 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 410 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 406 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 403 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 404 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 405 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 401 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

Definition at line 407 of file chan_skinny.c.

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

#define STIMULUS_MESSAGE   0x0005

Definition at line 181 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 413 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 399 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 400 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 402 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 408 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 330 of file chan_skinny.c.

Referenced by skinny_hold(), and transmit_callstate().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 279 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 227 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE   2

Definition at line 898 of file chan_skinny.c.

#define TYPE_TRUNK   1

Definition at line 897 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 257 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 229 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

Definition at line 445 of file chan_skinny.c.

Referenced by handle_version_req_message().


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

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


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 5090 of file chan_skinny.c.

static void __unreg_module ( void   )  [static]

Definition at line 5090 of file chan_skinny.c.

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

Definition at line 4608 of file chan_skinny.c.

References ast_atomic_fetchadd_int(), ast_calloc, ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_verbose(), auth_limit, destroy_session(), errno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, s, sessionlock, skinny_session(), skinnydebug, skinnysock, and unauth_sessions.

04609 {
04610    int as;
04611    struct sockaddr_in sin;
04612    socklen_t sinlen;
04613    struct skinnysession *s;
04614    struct protoent *p;
04615    int arg = 1;
04616    pthread_attr_t attr;
04617    pthread_t tcp_thread;
04618 
04619    pthread_attr_init(&attr);
04620    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04621 
04622    for (;;) {
04623       sinlen = sizeof(sin);
04624       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
04625       if (as < 0) {
04626          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
04627          continue;
04628       }
04629 
04630       if (ast_atomic_fetchadd_int(&unauth_sessions, +1) >= auth_limit) {
04631          close(as);
04632          ast_atomic_fetchadd_int(&unauth_sessions, -1);
04633          continue;
04634       }
04635 
04636       p = getprotobyname("tcp");
04637       if(p) {
04638          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
04639             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
04640          }
04641       }
04642       if (!(s = ast_calloc(1, sizeof(struct skinnysession)))) {
04643          close(as);
04644          ast_atomic_fetchadd_int(&unauth_sessions, -1);
04645          continue;
04646       }
04647 
04648       memcpy(&s->sin, &sin, sizeof(sin));
04649       ast_mutex_init(&s->lock);
04650       s->fd = as;
04651 
04652       if(time(&s->start) == -1) {
04653          ast_log(LOG_ERROR, "error executing time(): %s; disconnecting client\n", strerror(errno));
04654          destroy_session(s);
04655          continue;
04656       }
04657 
04658       ast_mutex_lock(&sessionlock);
04659       s->next = sessions;
04660       sessions = s;
04661       ast_mutex_unlock(&sessionlock);
04662 
04663       if (ast_pthread_create(&tcp_thread, &attr, skinny_session, s)) {
04664          destroy_session(s);
04665       }
04666    }
04667    if (skinnydebug)
04668       ast_verbose("killing accept thread\n");
04669    close(as);
04670    pthread_attr_destroy(&attr);
04671    return 0;
04672 }

static struct skinny_device* build_device ( const char *  cat,
struct ast_variable v 
) [static]

Definition at line 2138 of file chan_skinny.c.

References __ourip, accountcode, skinny_device::addons, skinny_device::addr, amaflags, ast_append_ha(), ast_callerid_split(), ast_calloc, ast_cdr_amaflags2int(), ast_copy_string(), ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_init(), ast_ouraddrfor(), ast_parse_allow_disallow(), ast_strlen_zero(), ast_true(), ast_verbose(), skinny_line::callgroup, skinny_line::callreturn, callreturn, skinny_line::callwaiting, callwaiting, skinny_line::cancallforward, cancallforward, skinny_line::capability, skinny_device::capability, skinny_line::cid_name, cid_name, skinny_line::cid_num, cid_num, skinny_line::context, context, cur_callergroup, cur_pickupgroup, default_capability, default_prefs, DEFAULT_SKINNY_PORT, skinny_device::earlyrtp, skinny_speeddial::exten, exten, free, skinny_device::ha, skinny_line::hookstate, skinny_device::id, skinny_line::immediate, immediate, skinny_line::instance, skinny_speeddial::instance, skinny_line::label, skinny_speeddial::label, skinny_line::language, language, skinny_device::lastlineinstance, linelabel, ast_variable::lineno, skinny_device::lines, skinny_line::lock, skinny_addon::lock, skinny_speeddial::lock, LOG_ERROR, LOG_WARNING, skinny_line::mailbox, mailbox, skinny_line::mohinterpret, mohinterpret, skinny_line::mohsuggest, mohsuggest, skinny_line::msgstate, skinny_line::mwiblink, mwiblink, skinny_line::name, ast_variable::name, skinny_device::name, skinny_line::nat, nat, ast_variable::next, skinny_line::next, skinny_addon::next, skinny_speeddial::next, skinny_line::onhooktime, option_verbose, skinny_device::ourip, skinny_line::parent, skinny_speeddial::parent, skinny_line::pickupgroup, skinny_line::prefs, skinny_device::prefs, SKINNY_ONHOOK, skinny_device::speeddials, skinny_line::threewaycalling, threewaycalling, skinny_line::transfer, transfer, skinny_line::type, skinny_addon::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, VERBOSE_PREFIX_3, and skinny_device::version_id.

Referenced by reload_config().

02139 {
02140    struct skinny_device *d;
02141    struct skinny_line *l;
02142    struct skinny_speeddial *sd;
02143    struct skinny_addon *a;
02144    int lineInstance = 1;
02145    int speeddialInstance = 1;
02146    int y = 0;
02147 
02148    if (!(d = ast_calloc(1, sizeof(struct skinny_device)))) {
02149       return NULL;
02150    } else {
02151       ast_copy_string(d->name, cat, sizeof(d->name));
02152       d->lastlineinstance = 1;
02153       d->capability = default_capability;
02154       d->prefs = default_prefs;
02155       d->earlyrtp = 1;
02156       while(v) {
02157          if (!strcasecmp(v->name, "host")) {
02158             if (ast_get_ip(&d->addr, v->value)) {
02159                free(d);
02160                return NULL;
02161             }
02162          } else if (!strcasecmp(v->name, "port")) {
02163             d->addr.sin_port = htons(atoi(v->value));
02164          } else if (!strcasecmp(v->name, "device")) {
02165             ast_copy_string(d->id, v->value, sizeof(d->id));
02166          } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
02167             d->ha = ast_append_ha(v->name, v->value, d->ha);
02168          } else if (!strcasecmp(v->name, "context")) {
02169             ast_copy_string(context, v->value, sizeof(context));
02170          } else if (!strcasecmp(v->name, "allow")) {
02171             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 1);
02172          } else if (!strcasecmp(v->name, "disallow")) {
02173             ast_parse_allow_disallow(&d->prefs, &d->capability, v->value, 0);
02174          } else if (!strcasecmp(v->name, "version")) {
02175             ast_copy_string(d->version_id, v->value, sizeof(d->version_id));
02176          } else if (!strcasecmp(v->name, "earlyrtp")) {
02177             d->earlyrtp = ast_true(v->value);
02178          } else if (!strcasecmp(v->name, "nat")) {
02179             nat = ast_true(v->value);
02180          } else if (!strcasecmp(v->name, "callerid")) {
02181             if (!strcasecmp(v->value, "asreceived")) {
02182                cid_num[0] = '\0';
02183                cid_name[0] = '\0';
02184             } else {
02185                ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
02186             }
02187          } else if (!strcasecmp(v->name, "language")) {
02188             ast_copy_string(language, v->value, sizeof(language));
02189          } else if (!strcasecmp(v->name, "accountcode")) {
02190             ast_copy_string(accountcode, v->value, sizeof(accountcode));
02191          } else if (!strcasecmp(v->name, "amaflags")) {
02192             y = ast_cdr_amaflags2int(v->value);
02193             if (y < 0) {
02194                ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
02195             } else {
02196                amaflags = y;
02197             }
02198          } else if (!strcasecmp(v->name, "mohinterpret") || !strcasecmp(v->name, "musiconhold")) {
02199             ast_copy_string(mohinterpret, v->value, sizeof(mohinterpret));
02200          } else if (!strcasecmp(v->name, "mohsuggest")) {
02201             ast_copy_string(mohsuggest, v->value, sizeof(mohsuggest));
02202          } else if (!strcasecmp(v->name, "callgroup")) {
02203             cur_callergroup = ast_get_group(v->value);
02204          } else if (!strcasecmp(v->name, "pickupgroup")) {
02205             cur_pickupgroup = ast_get_group(v->value);
02206          } else if (!strcasecmp(v->name, "immediate")) {
02207             immediate = ast_true(v->value);
02208          } else if (!strcasecmp(v->name, "cancallforward")) {
02209             cancallforward = ast_true(v->value);
02210          } else if (!strcasecmp(v->name, "mailbox")) {
02211             ast_copy_string(mailbox, v->value, sizeof(mailbox));
02212          } else if (!strcasecmp(v->name, "hasvoicemail")) {
02213             if (ast_true(v->value) && ast_strlen_zero(mailbox)) {
02214                ast_copy_string(mailbox, cat, sizeof(mailbox));
02215             }
02216          } else if (!strcasecmp(v->name, "callreturn")) {
02217             callreturn = ast_true(v->value);
02218          } else if (!strcasecmp(v->name, "callwaiting")) {
02219             callwaiting = ast_true(v->value);
02220          } else if (!strcasecmp(v->name, "transfer")) {
02221             transfer = ast_true(v->value);
02222          } else if (!strcasecmp(v->name, "threewaycalling")) {
02223             threewaycalling = ast_true(v->value);
02224          } else if (!strcasecmp(v->name, "mwiblink")) {
02225             mwiblink = ast_true(v->value);
02226          } else if (!strcasecmp(v->name, "linelabel")) {
02227             ast_copy_string(linelabel, v->value, sizeof(linelabel));
02228          } else if (!strcasecmp(v->name, "speeddial")) {
02229             if (!(sd = ast_calloc(1, sizeof(struct skinny_speeddial)))) {
02230                return NULL;
02231             } else {
02232                char *stringp, *exten, *label;
02233                stringp = v->value;
02234                exten = strsep(&stringp, ",");
02235                label = strsep(&stringp, ",");
02236                ast_mutex_init(&sd->lock);
02237                ast_copy_string(sd->exten, exten, sizeof(sd->exten));
02238                if (label)
02239                   ast_copy_string(sd->label, label, sizeof(sd->label));
02240                else
02241                   ast_copy_string(sd->label, exten, sizeof(sd->label));
02242                sd->instance = speeddialInstance++;
02243 
02244                sd->parent = d;
02245 
02246                sd->next = d->speeddials;
02247                d->speeddials = sd;
02248             }
02249          } else if (!strcasecmp(v->name, "addon")) {
02250             if (!(a = ast_calloc(1, sizeof(struct skinny_addon)))) {
02251                return NULL;
02252             } else {
02253                ast_mutex_init(&a->lock);
02254                ast_copy_string(a->type, v->value, sizeof(a->type));
02255 
02256                a->next = d->addons;
02257                d->addons = a;
02258             }
02259          } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
02260             if (!(l = ast_calloc(1, sizeof(struct skinny_line)))) {
02261                return NULL;
02262             } else {
02263                ast_mutex_init(&l->lock);
02264                ast_copy_string(l->name, v->value, sizeof(l->name));
02265 
02266                /* XXX Should we check for uniqueness?? XXX */
02267                ast_copy_string(l->context, context, sizeof(l->context));
02268                ast_copy_string(l->cid_num, cid_num, sizeof(l->cid_num));
02269                ast_copy_string(l->cid_name, cid_name, sizeof(l->cid_name));
02270                ast_copy_string(l->label, linelabel, sizeof(l->label));
02271                ast_copy_string(l->language, language, sizeof(l->language));
02272                ast_copy_string(l->mohinterpret, mohinterpret, sizeof(l->mohinterpret));
02273                ast_copy_string(l->mohsuggest, mohsuggest, sizeof(l->mohsuggest));
02274                ast_copy_string(l->mailbox, mailbox, sizeof(l->mailbox));
02275                if (!ast_strlen_zero(mailbox)) {
02276                   if (option_verbose > 2)
02277                      ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, d->name, l->name);
02278                }
02279                l->msgstate = -1;
02280                l->capability = d->capability;
02281                l->prefs = d->prefs;
02282                l->parent = d;
02283                if (!strcasecmp(v->name, "trunk")) {
02284                   l->type = TYPE_TRUNK;
02285                } else {
02286                   l->type = TYPE_LINE;
02287                }
02288                l->immediate = immediate;
02289                l->callgroup = cur_callergroup;
02290                l->pickupgroup = cur_pickupgroup;
02291                l->callreturn = callreturn;
02292                l->cancallforward = cancallforward;
02293                l->callwaiting = callwaiting;
02294                l->transfer = transfer;
02295                l->threewaycalling = threewaycalling;
02296                l->mwiblink = mwiblink;
02297                l->onhooktime = time(NULL);
02298                l->instance = lineInstance++;
02299                /* ASSUME we're onhook at this point */
02300                l->hookstate = SKINNY_ONHOOK;
02301                l->nat = nat;
02302 
02303                l->next = d->lines;
02304                d->lines = l;
02305             }
02306          } else {
02307             ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
02308          }
02309          v = v->next;
02310       }
02311 
02312       if (!d->lines) {
02313          ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
02314          return NULL;
02315       }
02316       if (/*d->addr.sin_addr.s_addr && */!ntohs(d->addr.sin_port)) {
02317          d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
02318       }
02319 #if 0
02320       /* I don't think we need this anymore at all, since d->ourip is set in skinny_register now */
02321       if (d->addr.sin_addr.s_addr) {
02322          /* XXX See note above, in 'host' option. */
02323          if (ast_ouraddrfor(&d->addr.sin_addr, &d->ourip)) {
02324             d->ourip = __ourip;
02325          }
02326       } else {
02327          d->ourip = __ourip;
02328       }
02329 #endif
02330    }
02331    return d;
02332 }

static int codec_ast2skinny ( int  astcodec  )  [static]

Definition at line 1398 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message(), and transmit_connect().

01399 {
01400    switch (astcodec) {
01401    case AST_FORMAT_ALAW:
01402       return SKINNY_CODEC_ALAW;
01403    case AST_FORMAT_ULAW:
01404       return SKINNY_CODEC_ULAW;
01405    case AST_FORMAT_G723_1:
01406       return SKINNY_CODEC_G723_1;
01407    case AST_FORMAT_G729A:
01408       return SKINNY_CODEC_G729A;
01409    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01410       return SKINNY_CODEC_G726_32;
01411    case AST_FORMAT_H261:
01412       return SKINNY_CODEC_H261;
01413    case AST_FORMAT_H263:
01414       return SKINNY_CODEC_H263;
01415    default:
01416       return 0;
01417    }
01418 }

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

01377 {
01378    switch (skinnycodec) {
01379    case SKINNY_CODEC_ALAW:
01380       return AST_FORMAT_ALAW;
01381    case SKINNY_CODEC_ULAW:
01382       return AST_FORMAT_ULAW;
01383    case SKINNY_CODEC_G723_1:
01384       return AST_FORMAT_G723_1;
01385    case SKINNY_CODEC_G729A:
01386       return AST_FORMAT_G729A;
01387    case SKINNY_CODEC_G726_32:
01388       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01389    case SKINNY_CODEC_H261:
01390       return AST_FORMAT_H261;
01391    case SKINNY_CODEC_H263:
01392       return AST_FORMAT_H263;
01393    default:
01394       return 0;
01395    }
01396 }

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

Definition at line 1889 of file chan_skinny.c.

References ast_strdup, devices, skinny_device::id, and skinny_device::next.

01890 {
01891    struct skinny_device *d;
01892 
01893    char *result = NULL;
01894    int wordlen = strlen(word);
01895    int which = 0;
01896 
01897    if (pos == 2) {
01898       for (d = devices; d && !result; d = d->next) {
01899          if (!strncasecmp(word, d->id, wordlen) && ++which > state)
01900             result = ast_strdup(d->id);
01901       }
01902    }
01903 
01904    return result;
01905 }

static char* control2str ( int  ind  )  [static]

Definition at line 2741 of file chan_skinny.c.

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

02741                                   {
02742    char *tmp;
02743 
02744    switch (ind) {
02745    case AST_CONTROL_HANGUP:
02746       return "Other end has hungup";
02747    case AST_CONTROL_RING:
02748       return "Local ring";
02749    case AST_CONTROL_RINGING:
02750       return "Remote end is ringing";
02751    case AST_CONTROL_ANSWER:
02752       return "Remote end has answered";
02753    case AST_CONTROL_BUSY:
02754       return "Remote end is busy";
02755    case AST_CONTROL_TAKEOFFHOOK:
02756       return "Make it go off hook";
02757    case AST_CONTROL_OFFHOOK:
02758       return "Line is off hook";
02759    case AST_CONTROL_CONGESTION:
02760       return "Congestion (circuits busy)";
02761    case AST_CONTROL_FLASH:
02762       return "Flash hook";
02763    case AST_CONTROL_WINK:
02764       return "Wink";
02765    case AST_CONTROL_OPTION:
02766       return "Set a low-level option";
02767    case AST_CONTROL_RADIO_KEY:
02768       return "Key Radio";
02769    case AST_CONTROL_RADIO_UNKEY:
02770       return "Un-Key Radio";
02771    case AST_CONTROL_PROGRESS:
02772       return "Remote end is making Progress";
02773    case AST_CONTROL_PROCEEDING:
02774       return "Remote end is proceeding";
02775    case AST_CONTROL_HOLD:
02776       return "Hold";
02777    case AST_CONTROL_UNHOLD:
02778       return "Unhold";
02779    case -1:
02780       return "Stop tone";
02781    default:
02782       if (!(tmp = ast_threadstorage_get(&control2str_threadbuf, CONTROL2STR_BUFSIZE)))
02783                         return "Unknown";
02784       snprintf(tmp, CONTROL2STR_BUFSIZE, "UNKNOWN-%d", ind);
02785       return tmp;
02786    }
02787 }

static void control2str_threadbuf_init ( void   )  [static]

Definition at line 146 of file chan_skinny.c.

00157 {

static void delete_devices ( void   )  [static]

Definition at line 4932 of file chan_skinny.c.

References ast_mutex_destroy(), ast_mutex_lock(), devicelock, devices, free, skinny_device::lines, skinny_speeddial::lock, skinny_line::lock, skinny_speeddial::next, skinny_line::next, and skinny_device::speeddials.

Referenced by unload_module().

04933 {
04934    struct skinny_device *d, *dlast;
04935    struct skinny_line *l, *llast;
04936    struct skinny_speeddial *sd, *sdlast;
04937    struct skinny_addon *a, *alast;
04938 
04939    ast_mutex_lock(&devicelock);
04940 
04941    /* Delete all devices */
04942    for (d=devices;d;) {
04943       /* Delete all lines for this device */
04944       for (l=d->lines;l;) {
04945          llast = l;
04946          l = l->next;
04947          ast_mutex_destroy(&llast->lock);
04948          free(llast);
04949       }
04950       /* Delete all speeddials for this device */
04951       for (sd=d->speeddials;sd;) {
04952          sdlast = sd;
04953          sd = sd->next;
04954          ast_mutex_destroy(&sdlast->lock);
04955          free(sdlast);
04956       }
04957       /* Delete all addons for this device */
04958       for (a=d->addons;a;) {
04959          alast = a;
04960          a = a->next;
04961          ast_mutex_destroy(&alast->lock);
04962          free(alast);
04963       }
04964       dlast = d;
04965       d = d->next;
04966       free(dlast);
04967    }
04968    devices=NULL;
04969    ast_mutex_unlock(&devicelock);
04970 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 4416 of file chan_skinny.c.

References ast_atomic_fetchadd_int(), ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), free, LOG_WARNING, skinnysession::next, s, sessionlock, and unauth_sessions.

04417 {
04418    struct skinnysession *cur, *prev = NULL;
04419    ast_mutex_lock(&sessionlock);
04420    cur = sessions;
04421    while(cur) {
04422       if (cur == s) {
04423          break;
04424       }
04425       prev = cur;
04426       cur = cur->next;
04427    }
04428    if (cur) {
04429       if (prev) {
04430          prev->next = cur->next;
04431       } else {
04432          sessions = cur->next;
04433       }
04434       if (s->fd > -1) {
04435          close(s->fd);
04436       }
04437       if (!s->device) {
04438          ast_atomic_fetchadd_int(&unauth_sessions, -1);
04439       }
04440       ast_mutex_destroy(&s->lock);
04441       free(s);
04442    } else {
04443       ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
04444    }
04445    ast_mutex_unlock(&sessionlock);
04446 }

static char* device2str ( int  type  )  [static]

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

01944 {
01945    char *tmp;
01946 
01947    switch (type) {
01948    case SKINNY_DEVICE_NONE:
01949       return "No Device";
01950    case SKINNY_DEVICE_30SPPLUS:
01951       return "30SP Plus";
01952    case SKINNY_DEVICE_12SPPLUS:
01953       return "12SP Plus";
01954    case SKINNY_DEVICE_12SP:
01955       return "12SP";
01956    case SKINNY_DEVICE_12:
01957       return "12";
01958    case SKINNY_DEVICE_30VIP:
01959       return "30VIP";
01960    case SKINNY_DEVICE_7910:
01961       return "7910";
01962    case SKINNY_DEVICE_7960:
01963       return "7960";
01964    case SKINNY_DEVICE_7940:
01965       return "7940";
01966    case SKINNY_DEVICE_7935:
01967       return "7935";
01968    case SKINNY_DEVICE_ATA186:
01969       return "ATA186";
01970    case SKINNY_DEVICE_7941:
01971       return "7941";
01972    case SKINNY_DEVICE_7971:
01973       return "7971";
01974    case SKINNY_DEVICE_7914:
01975       return "7914";
01976    case SKINNY_DEVICE_7985:
01977       return "7985";
01978    case SKINNY_DEVICE_7911:
01979       return "7911";
01980    case SKINNY_DEVICE_7961GE:
01981       return "7961GE";
01982    case SKINNY_DEVICE_7941GE:
01983       return "7941GE";
01984    case SKINNY_DEVICE_7931:
01985       return "7931";
01986    case SKINNY_DEVICE_7921:
01987       return "7921";
01988    case SKINNY_DEVICE_7906:
01989       return "7906";
01990    case SKINNY_DEVICE_7962:
01991       return "7962";
01992    case SKINNY_DEVICE_7937:
01993       return "7937";
01994    case SKINNY_DEVICE_7942:
01995       return "7942";
01996    case SKINNY_DEVICE_7945:
01997       return "7945";
01998    case SKINNY_DEVICE_7965:
01999       return "7965";
02000    case SKINNY_DEVICE_7975:
02001       return "7975";
02002    case SKINNY_DEVICE_7905:
02003       return "7905";
02004    case SKINNY_DEVICE_7920:
02005       return "7920";
02006    case SKINNY_DEVICE_7970:
02007       return "7970";
02008    case SKINNY_DEVICE_7912:
02009       return "7912";
02010    case SKINNY_DEVICE_7902:
02011       return "7902";
02012    case SKINNY_DEVICE_CIPC:
02013       return "IP Communicator";
02014    case SKINNY_DEVICE_7961:
02015       return "7961";
02016    case SKINNY_DEVICE_7936:
02017       return "7936";
02018    case SKINNY_DEVICE_SCCPGATEWAY_AN:
02019       return "SCCPGATEWAY_AN";
02020    case SKINNY_DEVICE_SCCPGATEWAY_BRI:
02021       return "SCCPGATEWAY_BRI";
02022    case SKINNY_DEVICE_UNKNOWN:
02023       return "Unknown";
02024    default:
02025       if (!(tmp = ast_threadstorage_get(&device2str_threadbuf, DEVICE2STR_BUFSIZE)))
02026          return "Unknown";
02027       snprintf(tmp, DEVICE2STR_BUFSIZE, "UNKNOWN-%d", type);
02028       return tmp;
02029    }
02030 }

static void device2str_threadbuf_init ( void   )  [static]

Definition at line 143 of file chan_skinny.c.

00157 {

static void do_housekeeping ( struct skinnysession s  )  [static]

Definition at line 1796 of file chan_skinny.c.

References handle_time_date_req_message(), and s.

Referenced by handle_keep_alive_message(), handle_onhook_message(), handle_soft_key_event_message(), and skinny_hangup().

01797 {
01798 /*
01799    int new;
01800    int old;
01801    struct skinny_device *d = s->device;
01802    struct skinny_line *l;
01803 */
01804 
01805    /* Update time on device */
01806    handle_time_date_req_message(NULL, s);
01807 
01808 /*
01809    for (l = d->lines; l; l = l->next) {
01810       if (has_voicemail(l)) {
01811          if (skinnydebug)
01812             ast_verbose("Checking for voicemail Skinny %s@%s\n", l->name, d->name);
01813          ast_app_inboxcount(l->mailbox, &new, &old);
01814          if (skinnydebug)
01815             ast_verbose("Skinny %s@%s has voicemail!\n", l->name, d->name);
01816          transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
01817       } else {
01818          transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
01819       }
01820    }
01821 */
01822 }

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

Definition at line 4674 of file chan_skinny.c.

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

04675 {
04676    int res;
04677 
04678    /* This thread monitors all the interfaces which are not yet in use
04679       (and thus do not have a separate thread) indefinitely */
04680    /* From here on out, we die whenever asked */
04681    for(;;) {
04682       pthread_testcancel();
04683       /* Wait for sched or io */
04684       res = ast_sched_wait(sched);
04685       if ((res < 0) || (res > 1000)) {
04686          res = 1000;
04687       }
04688       res = ast_io_wait(io, res);
04689       ast_mutex_lock(&monlock);
04690       if (res >= 0) {
04691          ast_sched_runq(sched);
04692       }
04693       ast_mutex_unlock(&monlock);
04694    }
04695    /* Never reached */
04696    return NULL;
04697 
04698 }

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

Definition at line 1257 of file chan_skinny.c.

References ast_log(), skinny_line::instance, skinny_device::lines, LOG_WARNING, skinny_device::name, and skinny_line::next.

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

01258 {
01259    struct skinny_line *l;
01260 
01261    if (!instance)
01262       instance = 1;
01263 
01264    for (l = d->lines; l; l = l->next) {
01265       if (l->instance == instance)
01266          break;
01267    }
01268 
01269    if (!l) {
01270       ast_log(LOG_WARNING, "Could not find line with instance '%d' on device '%s'\n", instance, d->name);
01271    }
01272    return l;
01273 }

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

Definition at line 1275 of file chan_skinny.c.

References ast_copy_string(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), devicelock, devices, skinny_device::lines, LOG_NOTICE, skinny_line::name, skinny_device::name, skinny_line::next, and skinny_device::next.

Referenced by skinny_request().

01276 {
01277    struct skinny_line *l;
01278    struct skinny_device *d;
01279    char line[256];
01280    char *at;
01281    char *device;
01282 
01283    ast_copy_string(line, dest, sizeof(line));
01284    at = strchr(line, '@');
01285    if (!at) {
01286       ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
01287       return NULL;
01288    }
01289    *at++ = '\0';
01290    device = at;
01291    ast_mutex_lock(&devicelock);
01292    for (d = devices; d; d = d->next) {
01293       if (!strcasecmp(d->name, device)) {
01294          if (skinnydebug)
01295             ast_verbose("Found device: %s\n", d->name);
01296          /* Found the device */
01297          for (l = d->lines; l; l = l->next) {
01298             /* Search for the right line */
01299             if (!strcasecmp(l->name, line)) {
01300                ast_mutex_unlock(&devicelock);
01301                return l;
01302             }
01303          }
01304       }
01305    }
01306    /* Device not found */
01307    ast_mutex_unlock(&devicelock);
01308    return NULL;
01309 }

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

Definition at line 1361 of file chan_skinny.c.

References ast_log(), skinny_speeddial::instance, LOG_WARNING, skinny_device::name, skinny_speeddial::next, and skinny_device::speeddials.

Referenced by handle_speed_dial_stat_req_message(), and handle_stimulus_message().

01362 {
01363    struct skinny_speeddial *sd;
01364 
01365    for (sd = d->speeddials; sd; sd = sd->next) {
01366       if (sd->instance == instance)
01367          break;
01368    }
01369 
01370    if (!sd) {
01371       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01372    }
01373    return sd;
01374 }

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

Definition at line 1312 of file chan_skinny.c.

References ast_log(), skinny_subchannel::callid, find_line_by_instance(), LOG_WARNING, skinny_device::name, skinny_subchannel::next, 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().

01313 {
01314    struct skinny_line *l = find_line_by_instance(d, instance);
01315    struct skinny_subchannel *sub;
01316 
01317    if (!l) {
01318       return NULL;
01319    }
01320 
01321    if (!reference)
01322       sub = l->sub;
01323    else {
01324       for (sub = l->sub; sub; sub = sub->next) {
01325          if (sub->callid == reference)
01326             break;
01327       }
01328    }
01329 
01330    if (!sub) {
01331       ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s'\n", reference, d->name);
01332    }
01333    return sub;
01334 }

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

Definition at line 1337 of file chan_skinny.c.

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

Referenced by handle_open_receive_channel_ack_message().

01338 {
01339    struct skinny_line *l;
01340    struct skinny_subchannel *sub = NULL;
01341 
01342    for (l = d->lines; l; l = l->next) {
01343       for (sub = l->sub; sub; sub = sub->next) {
01344          if (sub->callid == reference)
01345             break;
01346       }
01347       if (sub)
01348          break;
01349    }
01350 
01351    if (!l) {
01352       ast_log(LOG_WARNING, "Could not find any lines that contained a subchannel with reference '%d' on device '%s'\n", reference, d->name);
01353    } else {
01354       if (!sub) {
01355          ast_log(LOG_WARNING, "Could not find subchannel with reference '%d' on '%s@%s'\n", reference, l->name, d->name);
01356       }
01357    }
01358    return sub;
01359 }

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

Definition at line 1107 of file chan_skinny.c.

References skinny_device::addons, ast_log(), BT_CALLPARK, BT_CONFERENCE, BT_CUST_LINESPEEDDIAL, BT_DISPLAY, BT_FORWARDALL, BT_HOLD, BT_LINE, BT_NONE, BT_REDIAL, BT_SPEEDDIAL, BT_TRANSFER, BT_VOICEMAIL, LOG_WARNING, skinny_addon::next, s, 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, skinny_addon::type, and skinny_device::type.

Referenced by handle_button_template_req_message().

01108 {
01109    struct skinny_device *d = s->device;
01110    struct skinny_addon *a = d->addons;
01111    int i;
01112 
01113    switch (d->type) {
01114       case SKINNY_DEVICE_30SPPLUS:
01115       case SKINNY_DEVICE_30VIP:
01116          /* 13 rows, 2 columns */
01117          for (i = 0; i < 4; i++)
01118             (btn++)->buttonDefinition = BT_LINE;
01119          (btn++)->buttonDefinition = BT_REDIAL;
01120          (btn++)->buttonDefinition = BT_VOICEMAIL;
01121          (btn++)->buttonDefinition = BT_CALLPARK;
01122          (btn++)->buttonDefinition = BT_FORWARDALL;
01123          (btn++)->buttonDefinition = BT_CONFERENCE;
01124          for (i = 0; i < 4; i++)
01125             (btn++)->buttonDefinition = BT_NONE;
01126          for (i = 0; i < 13; i++)
01127             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01128          
01129          break;
01130       case SKINNY_DEVICE_12SPPLUS:
01131       case SKINNY_DEVICE_12SP:
01132       case SKINNY_DEVICE_12:
01133          /* 6 rows, 2 columns */
01134          for (i = 0; i < 2; i++)
01135             (btn++)->buttonDefinition = BT_LINE;
01136          (btn++)->buttonDefinition = BT_REDIAL;
01137          for (i = 0; i < 3; i++)
01138             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01139          (btn++)->buttonDefinition = BT_HOLD;
01140          (btn++)->buttonDefinition = BT_TRANSFER;
01141          (btn++)->buttonDefinition = BT_FORWARDALL;
01142          (btn++)->buttonDefinition = BT_CALLPARK;
01143          (btn++)->buttonDefinition = BT_VOICEMAIL;
01144          (btn++)->buttonDefinition = BT_CONFERENCE;
01145          break;
01146       case SKINNY_DEVICE_7910:
01147          (btn++)->buttonDefinition = BT_LINE;
01148          (btn++)->buttonDefinition = BT_HOLD;
01149          (btn++)->buttonDefinition = BT_TRANSFER;
01150          (btn++)->buttonDefinition = BT_DISPLAY;
01151          (btn++)->buttonDefinition = BT_VOICEMAIL;
01152          (btn++)->buttonDefinition = BT_CONFERENCE;
01153          (btn++)->buttonDefinition = BT_FORWARDALL;
01154          for (i = 0; i < 2; i++)
01155             (btn++)->buttonDefinition = BT_SPEEDDIAL;
01156          (btn++)->buttonDefinition = BT_REDIAL;
01157          break;
01158       case SKINNY_DEVICE_7960:
01159       case SKINNY_DEVICE_7961:
01160       case SKINNY_DEVICE_7961GE:
01161       case SKINNY_DEVICE_7962:
01162       case SKINNY_DEVICE_7965:
01163          for (i = 0; i < 6; i++)
01164             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01165          break;
01166       case SKINNY_DEVICE_7940:
01167       case SKINNY_DEVICE_7941:
01168       case SKINNY_DEVICE_7941GE:
01169       case SKINNY_DEVICE_7942:
01170       case SKINNY_DEVICE_7945:
01171          for (i = 0; i < 2; i++)
01172             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01173          break;
01174       case SKINNY_DEVICE_7935:
01175       case SKINNY_DEVICE_7936:
01176          for (i = 0; i < 2; i++)
01177             (btn++)->buttonDefinition = BT_LINE;
01178          break;
01179       case SKINNY_DEVICE_ATA186:
01180          (btn++)->buttonDefinition = BT_LINE;
01181          break;
01182       case SKINNY_DEVICE_7970:
01183       case SKINNY_DEVICE_7971:
01184       case SKINNY_DEVICE_7975:
01185       case SKINNY_DEVICE_CIPC:
01186          for (i = 0; i < 8; i++)
01187             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01188          break;
01189       case SKINNY_DEVICE_7985:
01190          /* XXX I have no idea what the buttons look like on these. */
01191          ast_log(LOG_WARNING, "Unsupported device type '%d (7985)' found.\n", d->type);
01192          break;
01193       case SKINNY_DEVICE_7912:
01194       case SKINNY_DEVICE_7911:
01195       case SKINNY_DEVICE_7905:
01196          (btn++)->buttonDefinition = BT_LINE;
01197          (btn++)->buttonDefinition = BT_HOLD;
01198          break;
01199       case SKINNY_DEVICE_7920:
01200          /* XXX I don't know if this is right. */
01201          for (i = 0; i < 4; i++)
01202             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01203          break;
01204       case SKINNY_DEVICE_7921:
01205          for (i = 0; i < 6; i++)
01206             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01207          break;
01208       case SKINNY_DEVICE_7902:
01209          ast_log(LOG_WARNING, "Unsupported device type '%d (7902)' found.\n", d->type);
01210          break;
01211       case SKINNY_DEVICE_7906:
01212          ast_log(LOG_WARNING, "Unsupported device type '%d (7906)' found.\n", d->type);
01213          break;
01214       case SKINNY_DEVICE_7931:
01215          ast_log(LOG_WARNING, "Unsupported device type '%d (7931)' found.\n", d->type);
01216          break;
01217       case SKINNY_DEVICE_7937:
01218          ast_log(LOG_WARNING, "Unsupported device type '%d (7937)' found.\n", d->type);
01219          break;
01220       case SKINNY_DEVICE_7914:
01221          ast_log(LOG_WARNING, "Unsupported device type '%d (7914)' found.  Expansion module registered by itself?\n", d->type);
01222          break;
01223       case SKINNY_DEVICE_SCCPGATEWAY_AN:
01224       case SKINNY_DEVICE_SCCPGATEWAY_BRI:
01225          ast_log(LOG_WARNING, "Unsupported device type '%d (SCCP gateway)' found.\n", d->type);
01226          break;
01227       default:
01228          ast_log(LOG_WARNING, "Unknown device type '%d' found.\n", d->type);
01229          break;
01230    }
01231 
01232    for (a = d->addons; a; a = a->next) {
01233       if (!strcasecmp(a->type, "7914")) {
01234          for (i = 0; i < 14; i++)
01235             (btn++)->buttonDefinition = BT_CUST_LINESPEEDDIAL;
01236       } else {
01237          ast_log(LOG_WARNING, "Unknown addon type '%s' found.  Skipping.\n", a->type);
01238       }
01239    }
01240 
01241    return btn;
01242 }

static int get_input ( struct skinnysession s  )  [static]

Definition at line 4448 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_poll, ast_verbose(), auth_timeout, errno, htolel, keep_alive, letohl, LOG_ERROR, LOG_WARNING, s, skinny_unregister(), and skinnydebug.

04449 {
04450    int res;
04451    int dlen = 0;
04452    int timeout = keep_alive * 1100;
04453    time_t now;
04454    int *bufaddr;
04455    struct pollfd fds[1];
04456 
04457    if (!s->device) {
04458       if(time(&now) == -1) {
04459          ast_log(LOG_ERROR, "error executing time(): %s\n", strerror(errno));
04460          return -1;
04461       }
04462 
04463       timeout = (auth_timeout - (now - s->start)) * 1000;
04464       if (timeout < 0) {
04465          /* we have timed out */
04466          if (skinnydebug)
04467             ast_verbose("Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
04468          return -1;
04469       }
04470    }
04471 
04472    fds[0].fd = s->fd;
04473    fds[0].events = POLLIN;
04474    fds[0].revents = 0;
04475    res = ast_poll(fds, 1, timeout); /* If nothing has happen, client is dead */
04476                    /* we add 10% to the keep_alive to deal */
04477                    /* with network delays, etc */
04478    if (res < 0) {
04479       if (errno != EINTR) {
04480          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
04481          return res;
04482       }
04483    } else if (res == 0) {
04484       if (skinnydebug) {
04485          if (s->device) {
04486             ast_verbose("Skinny Client was lost, unregistering\n");
04487          } else {
04488             ast_verbose("Skinny Client failed to authenticate in %d seconds\n", auth_timeout);
04489          }
04490       }
04491       skinny_unregister(NULL, s);
04492       return -1;
04493    }
04494            
04495    if (fds[0].revents) {
04496       ast_mutex_lock(&s->lock);
04497       memset(s->inbuf,0,sizeof(s->inbuf));
04498       res = read(s->fd, s->inbuf, 4);
04499       if (res < 0) {
04500          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
04501 
04502          if (skinnydebug)
04503             ast_verbose("Skinny Client was lost, unregistering\n");
04504          
04505          skinny_unregister(NULL,s);
04506          ast_mutex_unlock(&s->lock);
04507          return res;
04508       } else if (res != 4) {
04509          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
04510          ast_mutex_unlock(&s->lock);
04511          
04512          if (res == 0) {
04513             if (skinnydebug)
04514                ast_verbose("Skinny Client was lost, unregistering\n");
04515             skinny_unregister(NULL, s);
04516          }
04517            
04518          return -1;
04519       }
04520       
04521       bufaddr = (int *)s->inbuf;
04522       dlen = letohl(*bufaddr);
04523       if (dlen < 4) {
04524          ast_log(LOG_WARNING, "Skinny Client sent invalid data.\n");
04525          ast_mutex_unlock(&s->lock);
04526          return -1;
04527       }
04528       if (dlen+8 > sizeof(s->inbuf)) {
04529          dlen = sizeof(s->inbuf) - 8;
04530       }
04531       *bufaddr = htolel(dlen);
04532 
04533       res = read(s->fd, s->inbuf+4, dlen+4);
04534       ast_mutex_unlock(&s->lock);
04535       if (res < 0) {
04536          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
04537          return res;
04538       } else if (res != (dlen+4)) {
04539          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
04540          return -1;
04541       }
04542       return res;
04543    }
04544    return 0;
04545 }

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

Definition at line 3796 of file chan_skinny.c.

References skinny_data::alarm, ast_verbose(), skinny_req::data, alarm_message::displayMessage, and skinnydebug.

Referenced by handle_message().

03797 {
03798    /* no response necessary */
03799    if (skinnydebug)
03800       ast_verbose("Received Alarm Message: %s\n", req->data.alarm.displayMessage);
03801 
03802    return 1;
03803 }

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

Definition at line 3660 of file chan_skinny.c.

References ast_verbose(), BT_CUST_HINT, BT_CUST_LINESPEEDDIAL, BT_LINE, BT_NONE, BT_SPEEDDIAL, BUTTON_TEMPLATE_RES_MESSAGE, button_definition::buttonDefinition, button_definition_template::buttonDefinition, skinny_data::buttontemplate, skinny_req::data, button_template_res_message::definition, get_button_template(), htolel, skinny_speeddial::instance, skinny_line::instance, button_definition::instanceNumber, skinny_device::lines, skinny_speeddial::next, skinny_line::next, req_alloc(), s, and skinny_device::speeddials.

Referenced by handle_message().

03661 {
03662    struct skinny_device *d = s->device;
03663    struct skinny_line *l;
03664    int i;
03665 
03666    struct skinny_speeddial *sd;
03667    struct button_definition_template btn[42];
03668    int lineInstance = 1;
03669    int speeddialInstance = 1;
03670    int buttonCount = 0;
03671 
03672    if (!(req = req_alloc(sizeof(struct button_template_res_message), BUTTON_TEMPLATE_RES_MESSAGE)))
03673       return -1;
03674 
03675    memset(&btn, 0, sizeof(btn));
03676 
03677    get_button_template(s, btn);
03678 
03679    for (i=0; i<42; i++) {
03680       int btnSet = 0;
03681       switch (btn[i].buttonDefinition) {
03682          case BT_CUST_LINESPEEDDIAL:
03683             /* assume failure */
03684             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
03685             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
03686 
03687             for (l = d->lines; l; l = l->next) {
03688                if (l->instance == lineInstance) {
03689                   ast_verbose("Adding button: %d, %d\n", BT_LINE, lineInstance);
03690                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
03691                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
03692                   lineInstance++;
03693                   buttonCount++;
03694                   btnSet = 1;
03695                   break;
03696                }
03697             }
03698 
03699             if (!btnSet) {
03700                for (sd = d->speeddials; sd; sd = sd->next) {
03701                   if (sd->instance == speeddialInstance) {
03702                      ast_verbose("Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
03703                      req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
03704                      req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
03705                      speeddialInstance++;
03706                      buttonCount++;
03707                      btnSet = 1;
03708                      break;
03709                   }
03710                }
03711             }
03712             break;
03713          case BT_LINE:
03714             req->data.buttontemplate.definition[i].buttonDefinition = htolel(BT_NONE);
03715             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
03716 
03717             for (l = d->lines; l; l = l->next) {
03718                if (l->instance == lineInstance) {
03719                   ast_verbose("Adding button: %d, %d\n", BT_LINE, lineInstance);
03720                   req->data.buttontemplate.definition[i].buttonDefinition = BT_LINE;
03721                   req->data.buttontemplate.definition[i].instanceNumber = htolel(lineInstance);
03722                   lineInstance++;
03723                   buttonCount++;
03724                   btnSet = 1;
03725                   break;
03726                }
03727             }
03728             break;
03729          case BT_SPEEDDIAL:
03730             req->data.buttontemplate.definition[i].buttonDefinition = BT_NONE;
03731             req->data.buttontemplate.definition[i].instanceNumber = 0;
03732 
03733             for (sd = d->speeddials; sd; sd = sd->next) {
03734                if (sd->instance == speeddialInstance) {
03735                   ast_verbose("Adding button: %d, %d\n", BT_SPEEDDIAL, speeddialInstance);
03736                   req->data.buttontemplate.definition[i].buttonDefinition = BT_SPEEDDIAL;
03737                   req->data.buttontemplate.definition[i].instanceNumber = htolel(speeddialInstance);
03738                   speeddialInstance++;
03739                   buttonCount++;
03740                   btnSet = 1;
03741                   break;
03742                }
03743             }
03744             break;
03745          case BT_CUST_HINT:
03746             break;
03747          case BT_NONE:
03748             break;
03749          default:
03750             ast_verbose("Adding button: %d, %d\n", btn[i].buttonDefinition, 0);
03751             req->data.buttontemplate.definition[i].buttonDefinition = htolel(btn[i].buttonDefinition);
03752             req->data.buttontemplate.definition[i].instanceNumber = htolel(0);
03753             buttonCount++;
03754             btnSet = 1;
03755             break;
03756       }
03757    }
03758 
03759    req->data.buttontemplate.buttonOffset = htolel(0);
03760    req->data.buttontemplate.buttonCount = htolel(buttonCount);
03761    req->data.buttontemplate.totalButtonCount = htolel(buttonCount);
03762 
03763    if (skinnydebug)
03764       ast_verbose("Sending %d template to %s\n",
03765                d->type,
03766                d->name);
03767    transmit_response(s, req);
03768    return 1;
03769 }

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

Definition at line 3547 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), skinny_line::capability, skinny_device::capability, capabilities_res_message::caps, skinny_data::caps, station_capabilities::codec, codec_skinny2ast(), capabilities_res_message::count, skinny_req::data, letohl, skinny_device::lines, skinny_line::lock, LOG_WARNING, skinny_line::next, s, SKINNY_MAX_CAPABILITIES, and skinnydebug.

Referenced by handle_message().

03548 {
03549    struct skinny_device *d = s->device;
03550    struct skinny_line *l;
03551    uint32_t count = 0;
03552    int codecs = 0;
03553    int i;
03554 
03555    count = letohl(req->data.caps.count);
03556    if (count > SKINNY_MAX_CAPABILITIES) {
03557       count = SKINNY_MAX_CAPABILITIES;
03558       ast_log(LOG_WARNING, "Received more capabilities than we can handle (%d).  Ignoring the rest.\n", SKINNY_MAX_CAPABILITIES);
03559    }
03560 
03561    for (i = 0; i < count; i++) {
03562       int acodec = 0;
03563       int scodec = 0;
03564       scodec = letohl(req->data.caps.caps[i].codec);
03565       acodec = codec_skinny2ast(scodec);
03566       if (skinnydebug)
03567          ast_verbose("Adding codec capability '%d (%d)'\n", acodec, scodec);
03568       codecs |= acodec;
03569    }
03570 
03571    d->capability &= codecs;
03572    ast_verbose("Device capability set to '%d'\n", d->capability);
03573    for (l = d->lines; l; l = l->next) {
03574       ast_mutex_lock(&l->lock);
03575       l->capability = d->capability;
03576       ast_mutex_unlock(&l->lock);
03577    }
03578 
03579    return 1;
03580 }

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

Definition at line 3874 of file chan_skinny.c.

References ast_copy_string(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, AST_STATE_DOWN, ast_verbose(), enbloc_call_message::calledParty, skinny_subchannel::callid, ast_channel::context, skinny_req::data, skinny_data::enbloccallmessage, errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, skinny_device::lastcallreference, skinny_device::lastlineinstance, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::parent, s, SKINNY_DIALTONE, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_SILENCE, skinnydebug, t, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), and transmit_tone().

Referenced by handle_message().

03875 {
03876    struct skinny_device *d = s->device;
03877    struct skinny_line *l;
03878    struct skinny_subchannel *sub = NULL;
03879    struct ast_channel *c;
03880    pthread_t t;
03881 
03882    if (skinnydebug)
03883       ast_verbose("Received Enbloc Call: %s\n", req->data.enbloccallmessage.calledParty);
03884 
03885    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
03886 
03887    if (!sub) {
03888       l = find_line_by_instance(d, d->lastlineinstance);
03889       if (!l) {
03890          return 0;
03891       }
03892    } else {
03893       l = sub->parent;
03894    }
03895 
03896    c = skinny_new(l, AST_STATE_DOWN);
03897 
03898    if(!c) {
03899       ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
03900    } else {
03901       l->hookstate = SKINNY_OFFHOOK;
03902 
03903       sub = c->tech_pvt;
03904       transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03905       if (skinnydebug)
03906          ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
03907       transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
03908       transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03909 
03910       if (!ast_ignore_pattern(c->context, req->data.enbloccallmessage.calledParty)) {
03911          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03912       }
03913       ast_copy_string(c->exten, req->data.enbloccallmessage.calledParty, sizeof(c->exten));
03914       if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
03915          ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
03916          ast_hangup(c);
03917       }
03918    }
03919    
03920    return 1;
03921 }

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

Definition at line 4236 of file chan_skinny.c.

Referenced by handle_message().

04237 {
04238    /* XXX umm...okay?  Why do I care? */
04239    return 1;
04240 }

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

Definition at line 3099 of file chan_skinny.c.

Referenced by handle_message().

03100 {
03101    /* no response necessary */
03102    return 1;
03103 }

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

Definition at line 3046 of file chan_skinny.c.

References do_housekeeping(), KEEP_ALIVE_ACK_MESSAGE, req_alloc(), s, and transmit_response().

Referenced by handle_message().

03047 {
03048    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
03049       return -1;
03050 
03051    transmit_response(s, req);
03052    do_housekeeping(s);
03053    return 1;
03054 }

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

Definition at line 3105 of file chan_skinny.c.

References ast_channel::_state, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_log(), ast_queue_frame(), ast_verbose(), keypad_button_message::button, keypad_button_message::callReference, skinny_req::data, f, find_subchannel_by_instance_reference(), skinny_data::keypad, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, keypad_button_message::lineInstance, LOG_WARNING, skinny_line::name, skinny_subchannel::next, skinny_subchannel::owner, skinny_subchannel::parent, s, and skinnydebug.

Referenced by handle_message().

03106 {
03107    struct skinny_subchannel *sub = NULL;
03108    struct skinny_line *l;
03109    struct skinny_device *d = s->device;
03110    struct ast_frame f = { 0, };
03111    char dgt;
03112    int digit;
03113    int lineInstance;
03114    int callReference;
03115 
03116    digit = letohl(req->data.keypad.button);
03117    lineInstance = letohl(req->data.keypad.lineInstance);
03118    callReference = letohl(req->data.keypad.callReference);
03119 
03120    if (digit == 14) {
03121       dgt = '*';
03122    } else if (digit == 15) {
03123       dgt = '#';
03124    } else if (digit >= 0 && digit <= 9) {
03125       dgt = '0' + digit;
03126    } else {
03127       /* digit=10-13 (A,B,C,D ?), or
03128        * digit is bad value
03129        *
03130        * probably should not end up here, but set
03131        * value for backward compatibility, and log
03132        * a warning.
03133        */
03134       dgt = '0' + digit;
03135       ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
03136    }
03137 
03138    f.subclass = dgt;
03139 
03140    f.src = "skinny";
03141 
03142    if (lineInstance && callReference)
03143       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
03144    else
03145       sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
03146 
03147    if (!sub)
03148       return 0;
03149 
03150    l = sub->parent;
03151    if (sub->owner) {
03152       if (sub->owner->_state == 0) {
03153          f.frametype = AST_FRAME_DTMF_BEGIN;
03154          ast_queue_frame(sub->owner, &f);
03155       }
03156       /* XXX MUST queue this frame to all lines in threeway call if threeway call is active */
03157       f.frametype = AST_FRAME_DTMF_END;
03158       ast_queue_frame(sub->owner, &f);
03159       /* XXX This seriously needs to be fixed */
03160       if (sub->next && sub->next->owner) {
03161          if (sub->owner->_state == 0) {
03162             f.frametype = AST_FRAME_DTMF_BEGIN;
03163             ast_queue_frame(sub->next->owner, &f);
03164          }
03165          f.frametype = AST_FRAME_DTMF_END;
03166          ast_queue_frame(sub->next->owner, &f);
03167       }
03168    } else {
03169       if (skinnydebug)
03170          ast_verbose("No owner: %s\n", l->name);
03171    }
03172    return 1;
03173 }

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

Definition at line 3607 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, devicelock, find_line_by_instance(), skinny_line::instance, skinny_line::label, letohl, skinny_data::line, LINE_STAT_RES_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::lineNumber, line_state_req_message::lineNumber, skinny_data::linestat, skinny_line::name, req_alloc(), s, and transmit_response().

Referenced by handle_message().

03608 {
03609    struct skinny_device *d = s->device;
03610    struct skinny_line *l;
03611    int instance;
03612 
03613    instance = letohl(req->data.line.lineNumber);
03614 
03615    ast_mutex_lock(&devicelock);
03616 
03617    l = find_line_by_instance(d, instance);
03618 
03619    if (!l) {
03620       return 0;
03621    }
03622 
03623    ast_mutex_unlock(&devicelock);
03624 
03625    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
03626       return -1;
03627 
03628    req->data.linestat.lineNumber = letohl(instance);
03629    memcpy(req->data.linestat.lineDirNumber, l->name,
03630          sizeof(req->data.linestat.lineDirNumber));
03631    memcpy(req->data.linestat.lineDisplayName, l->label,
03632          sizeof(req->data.linestat.lineDisplayName));
03633    transmit_response(s,req);
03634    return 1;
03635 }

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

Definition at line 4248 of file chan_skinny.c.

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

Referenced by skinny_session().

04249 {
04250    int res = 0;
04251    struct skinny_device *d = s->device;
04252    struct skinny_subchannel *sub;
04253    int lineInstance;
04254    int callReference;
04255 
04256    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
04257       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
04258       free(req);
04259       return 0;
04260    }
04261 
04262    switch(letohl(req->e))  {
04263    case KEEP_ALIVE_MESSAGE:
04264       res = handle_keep_alive_message(req, s);
04265       break;
04266    case REGISTER_MESSAGE:
04267       if (skinnydebug)
04268          ast_verbose("Device %s is attempting to register\n", req->data.reg.name);
04269 
04270       res = handle_register_message(req, s);
04271       break;
04272    case IP_PORT_MESSAGE:
04273       res = handle_ip_port_message(req, s);
04274       break;
04275    case KEYPAD_BUTTON_MESSAGE:
04276       if (skinnydebug)
04277          ast_verbose("Collected digit: [%d]\n", letohl(req->data.keypad.button));
04278 
04279       lineInstance = letohl(req->data.keypad.lineInstance);
04280       callReference = letohl(req->data.keypad.callReference);
04281 
04282       sub = find_subchannel_by_instance_reference(d, lineInstance, callReference);
04283 
04284       if (sub && (sub->owner && sub->owner->_state <  AST_STATE_UP)) {
04285          char dgt;
04286          int digit = letohl(req->data.keypad.button);
04287          size_t len;
04288 
04289          if (digit == 14) {
04290             dgt = '*';
04291          } else if (digit == 15) {
04292             dgt = '#';
04293          } else if (digit >= 0 && digit <= 9) {
04294             dgt = '0' + digit;
04295          } else {
04296             /* digit=10-13 (A,B,C,D ?), or
04297             * digit is bad value
04298             *
04299             * probably should not end up here, but set
04300             * value for backward compatibility, and log
04301             * a warning.
04302             */
04303             dgt = '0' + digit;
04304             ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
04305          }
04306 
04307          len = strlen(d->exten);
04308          if (len < sizeof(d->exten) - 1) {
04309             d->exten[len] = dgt;
04310             d->exten[len+1] = '\0';
04311          } else {
04312             ast_log(LOG_WARNING, "Dropping digit with value %d because digit queue is full\n", dgt);
04313          }
04314       } else
04315          res = handle_keypad_button_message(req, s);
04316       break;
04317    case ENBLOC_CALL_MESSAGE:
04318       res = handle_enbloc_call_message(req, s);
04319       break;
04320    case STIMULUS_MESSAGE:
04321       res = handle_stimulus_message(req, s);
04322       break;
04323    case OFFHOOK_MESSAGE:
04324       res = handle_offhook_message(req, s);
04325       break;
04326    case ONHOOK_MESSAGE:
04327       res = handle_onhook_message(req, s);
04328       break;
04329    case CAPABILITIES_RES_MESSAGE:
04330       if (skinnydebug)
04331          ast_verbose("Received CapabilitiesRes\n");
04332 
04333       res = handle_capabilities_res_message(req, s);
04334       break;
04335    case SPEED_DIAL_STAT_REQ_MESSAGE:
04336       if (skinnydebug)
04337          ast_verbose("Received SpeedDialStatRequest\n");
04338 
04339       res = handle_speed_dial_stat_req_message(req, s);
04340       break;
04341    case LINE_STATE_REQ_MESSAGE:
04342       if (skinnydebug)
04343          ast_verbose("Received LineStatRequest\n");
04344       res = handle_line_state_req_message(req, s);
04345       break;
04346    case TIME_DATE_REQ_MESSAGE:
04347       if (skinnydebug)
04348          ast_verbose("Received Time/Date Request\n");
04349 
04350       res = handle_time_date_req_message(req, s);
04351       break;
04352    case BUTTON_TEMPLATE_REQ_MESSAGE:
04353       if (skinnydebug)
04354          ast_verbose("Buttontemplate requested\n");
04355 
04356       res = handle_button_template_req_message(req, s);
04357       break;
04358    case VERSION_REQ_MESSAGE:
04359       if (skinnydebug)
04360          ast_verbose("Version Request\n");
04361 
04362       res = handle_version_req_message(req, s);
04363       break;
04364    case SERVER_REQUEST_MESSAGE:
04365       if (skinnydebug)
04366          ast_verbose("Received Server Request\n");
04367 
04368       res = handle_server_request_message(req, s);
04369       break;
04370    case ALARM_MESSAGE:
04371       res = handle_alarm_message(req, s);
04372       break;
04373    case OPEN_RECEIVE_CHANNEL_ACK_MESSAGE:
04374       if (skinnydebug)
04375          ast_verbose("Received Open Receive Channel Ack\n");
04376 
04377       res = handle_open_receive_channel_ack_message(req, s);
04378       break;
04379    case SOFT_KEY_SET_REQ_MESSAGE:
04380       if (skinnydebug)
04381          ast_verbose("Received SoftKeySetReq\n");
04382 
04383       res = handle_soft_key_set_req_message(req, s);
04384       break;
04385    case SOFT_KEY_EVENT_MESSAGE:
04386       res = handle_soft_key_event_message(req, s);
04387       break;
04388    case UNREGISTER_MESSAGE:
04389       if (skinnydebug)
04390          ast_verbose("Received Unregister Request\n");
04391 
04392       res = handle_unregister_message(req, s);
04393       break;
04394    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
04395       if (skinnydebug)
04396          ast_verbose("Received SoftKey Template Request\n");
04397 
04398       res = handle_soft_key_template_req_message(req, s);
04399       break;
04400    case HEADSET_STATUS_MESSAGE:
04401       res = handle_headset_status_message(req, s);
04402       break;
04403    case REGISTER_AVAILABLE_LINES_MESSAGE:
04404       res = handle_register_available_lines_message(req, s);
04405       break;
04406    default:
04407       if (skinnydebug)
04408          ast_verbose("RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
04409       break;
04410    }
04411    if (res >= 0 && req)
04412       free(req);
04413    return res;
04414 }

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

Definition at line 3414 of file chan_skinny.c.

References AST_CONTROL_ANSWER, ast_hangup(), ast_log(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose(), skinny_subchannel::callid, skinny_req::data, errno, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, LOG_DEBUG, LOG_WARNING, skinny_device::name, skinny_line::name, ast_channel::name, skinny_data::offhook, skinny_subchannel::onhold, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, s, SKINNY_CONNECTED, SKINNY_DIALTONE, SKINNY_LAMP_ON, skinny_new(), SKINNY_OFFHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, skinny_ss(), skinnydebug, start_rtp(), STIMULUS_LINE, t, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_tone(), offhook_message::unknown1, and offhook_message::unknown2.

Referenced by handle_message().

03415 {
03416    struct skinny_device *d = s->device;
03417    struct skinny_line *l;
03418    struct skinny_subchannel *sub;
03419    struct ast_channel *c;
03420    pthread_t t;
03421    int unknown1;
03422    int unknown2;
03423 
03424    unknown1 = letohl(req->data.offhook.unknown1);
03425    unknown2 = letohl(req->data.offhook.unknown2);
03426 
03427    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
03428 
03429    if (!sub) {
03430       l = find_line_by_instance(d, d->lastlineinstance);
03431       if (!l) {
03432          return 0;
03433       }
03434    } else {
03435       l = sub->parent;
03436    }
03437 
03438    transmit_ringer_mode(s, SKINNY_RING_OFF);
03439    l->hookstate = SKINNY_OFFHOOK;
03440 
03441    if (sub && sub->onhold) {
03442       return 1;
03443    }
03444 
03445    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03446 
03447    if (sub && sub->outgoing) {
03448       /* We're answering a ringing call */
03449       ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
03450       transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03451       transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03452       transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
03453       transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
03454       start_rtp(sub);
03455       ast_setstate(sub->owner, AST_STATE_UP);
03456    } else {
03457       if (sub && sub->owner) {
03458          ast_log(LOG_DEBUG, "Current sub [%s] already has owner\n", sub->owner->name);
03459       } else {
03460          c = skinny_new(l, AST_STATE_DOWN);
03461          if(c) {
03462             sub = c->tech_pvt;
03463             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03464             if (skinnydebug)
03465                ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
03466             transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
03467             transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03468             transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
03469 
03470             /* start the switch thread */
03471             if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
03472                ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03473                ast_hangup(c);
03474             }
03475          } else {
03476             ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
03477          }
03478       }
03479    }
03480    return 1;
03481 }

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

Definition at line 3483 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ast_log(), ast_queue_hangup(), ast_verbose(), attempt_transfer(), skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_req::data, do_housekeeping(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, skinny_device::lastcallreference, skinny_device::lastlineinstance, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::next, skinny_subchannel::onhold, skinny_data::onhook, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, skinny_subchannel::rtp, s, SKINNY_CX_RECVONLY, SKINNY_ONHOOK, skinnydebug, skinny_line::transfer, transmit_callstate(), onhook_message::unknown1, and onhook_message::unknown2.

Referenced by handle_message().

03484 {
03485    struct skinny_device *d = s->device;
03486    struct skinny_line *l;
03487    struct skinny_subchannel *sub;
03488    int unknown1;
03489    int unknown2;
03490 
03491    unknown1 = letohl(req->data.onhook.unknown1);
03492    unknown2 = letohl(req->data.onhook.unknown2);
03493 
03494    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
03495 
03496    if (!sub) {
03497       return 0;
03498    }
03499    l = sub->parent;
03500 
03501    if (l->hookstate == SKINNY_ONHOOK) {
03502       /* Something else already put us back on hook */
03503       return 0;
03504    }
03505    l->hookstate = SKINNY_ONHOOK;
03506 
03507    if (sub->onhold) {
03508       return 0;
03509    }
03510 
03511    sub->cxmode = SKINNY_CX_RECVONLY;
03512    transmit_callstate(s, l->instance, l->hookstate, sub->callid);
03513    if (skinnydebug)
03514       ast_verbose("Skinny %s@%s went on hook\n", l->name, d->name);
03515    if (l->transfer && (sub->owner && sub->next && sub->next->owner) && ((!sub->outgoing) || (sub->next && !sub->next->outgoing))) {
03516       /* We're allowed to transfer, we have two active calls and
03517          we made at least one of the calls.  Let's try and transfer */
03518 
03519 #if 0
03520       if ((res = attempt_transfer(p)) < 0) {
03521          if (sub->next && sub->next->owner) {
03522             sub->next->alreadygone = 1;
03523             ast_queue_hangup(sub->next->owner,1);
03524          }
03525       } else if (res) {
03526          ast_log(LOG_WARNING, "Transfer attempt failed\n");
03527          return 0;
03528       }
03529 #endif
03530    } else {
03531       /* Hangup the current call */
03532       /* If there is another active call, skinny_hangup will ring the phone with the other call */
03533       if (sub->owner) {
03534          sub->alreadygone = 1;
03535          ast_queue_hangup(sub->owner);
03536       } else {
03537          ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
03538             l->name, d->name, sub->callid);
03539       }
03540    }
03541    if ((l->hookstate == SKINNY_ONHOOK) && (sub->next && !sub->next->rtp)) {
03542       do_housekeeping(s);
03543    }
03544    return 1;
03545 }

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

Definition at line 3805 of file chan_skinny.c.

References ast_best_codec(), ast_codec_pref_getsize(), ast_inet_ntoa(), ast_log(), ast_rtp_get_us(), ast_rtp_set_peer(), ast_verbose(), media_qualifier::bitRate, ast_format_list::bits, skinny_subchannel::callid, skinny_line::capability, codec_ast2skinny(), start_media_transmission_message::conferenceId, ast_format_list::cur_ms, skinny_req::data, find_subchannel_by_reference(), htolel, open_receive_channel_ack_message::ipAddr, letohl, LOG_ERROR, skinny_data::openreceivechannelack, skinny_device::ourip, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_subchannel::parent, open_receive_channel_ack_message::passThruId, start_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, open_receive_channel_ack_message::port, media_qualifier::precedence, skinny_line::prefs, start_media_transmission_message::qualifier, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, req_alloc(), skinny_subchannel::rtp, s, skinnydebug, START_MEDIA_TRANSMISSION_MESSAGE, skinny_data::startmedia, open_receive_channel_ack_message::status, transmit_response(), and media_qualifier::vad.

Referenced by handle_message().

03806 {
03807    struct skinny_device *d = s->device;
03808    struct skinny_line *l;
03809    struct skinny_subchannel *sub;
03810    struct ast_format_list fmt;
03811    struct sockaddr_in sin;
03812    struct sockaddr_in us;
03813    uint32_t addr;
03814    int port;
03815    int status;
03816    int passthruid;
03817 
03818    status = letohl(req->data.openreceivechannelack.status);
03819    if (status) {
03820       ast_log(LOG_ERROR, "Open Receive Channel Failure\n");
03821       return 0;
03822    }
03823    addr = letohl(req->data.openreceivechannelack.ipAddr);
03824    port = letohl(req->data.openreceivechannelack.port);
03825    passthruid = letohl(req->data.openreceivechannelack.passThruId);
03826 
03827    sin.sin_family = AF_INET;
03828    sin.sin_addr.s_addr = addr;
03829    sin.sin_port = htons(port);
03830 
03831    sub = find_subchannel_by_reference(d, passthruid);
03832 
03833    if (!sub)
03834       return 0;
03835 
03836    l = sub->parent;
03837 
03838    if (sub->rtp) {
03839       ast_rtp_set_peer(sub->rtp, &sin);
03840       ast_rtp_get_us(sub->rtp, &us);
03841    } else {
03842       ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
03843       return 0;
03844    }
03845 
03846    if (skinnydebug) {
03847       ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
03848       ast_verbose("ourip = %s:%d\n", ast_inet_ntoa(d->ourip), ntohs(us.sin_port));
03849    }
03850 
03851    if (!(req = req_alloc(sizeof(struct start_media_transmission_message), START_MEDIA_TRANSMISSION_MESSAGE)))
03852       return -1;
03853 
03854    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
03855 
03856    if (skinnydebug)
03857       ast_verbose("Setting payloadType to '%d' (%d ms)\n", fmt.bits, fmt.cur_ms);
03858 
03859    req->data.startmedia.conferenceId = htolel(sub->callid);
03860    req->data.startmedia.passThruPartyId = htolel(sub->callid);
03861    req->data.startmedia.remoteIp = htolel(d->ourip.s_addr);
03862    req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
03863    req->data.startmedia.packetSize = htolel(fmt.cur_ms);
03864    req->data.startmedia.payloadType = htolel(codec_ast2skinny(fmt.bits));
03865    req->data.startmedia.qualifier.precedence = htolel(127);
03866    req->data.startmedia.qualifier.vad = htolel(0);
03867    req->data.startmedia.qualifier.packets = htolel(0);
03868    req->data.startmedia.qualifier.bitRate = htolel(0);
03869    transmit_response(s, req);
03870 
03871    return 1;
03872 }

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

Definition at line 4242 of file chan_skinny.c.

Referenced by handle_message().

04243 {
04244    /* XXX I have no clue what this is for, but my phone was sending it, so... */
04245    return 1;
04246 }

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

Definition at line 3056 of file chan_skinny.c.

References ast_atomic_fetchadd_int(), ast_log(), ast_verbose(), CAPABILITIES_REQ_MESSAGE, skinny_req::data, date_format, register_ack_message::dateTemplate, register_rej_message::errMsg, htolel, keep_alive, register_ack_message::keepAlive, LOG_ERROR, register_message::name, name, option_verbose, skinny_data::reg, skinny_data::regack, REGISTER_ACK_MESSAGE, REGISTER_REJ_MESSAGE, skinny_data::regrej, req_alloc(), register_ack_message::res, skinny_req::res, register_ack_message::res2, s, register_ack_message::secondaryKeepAlive, skinny_register(), skinnydebug, transmit_response(), unauth_sessions, and VERBOSE_PREFIX_3.

Referenced by handle_message().

03057 {
03058    char name[16];
03059    int res;
03060 
03061    memcpy(&name, req->data.reg.name, sizeof(name));
03062 
03063    res = skinny_register(req, s);
03064    if (!res) {
03065       ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", name);
03066       if (!(req = req_alloc(sizeof(struct register_rej_message), REGISTER_REJ_MESSAGE)))
03067          return -1;
03068 
03069       snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
03070       transmit_response(s, req);
03071       return 0;
03072    }
03073    ast_atomic_fetchadd_int(&unauth_sessions, -1);
03074    if (option_verbose > 2)
03075       ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfully registered\n", name);
03076 
03077    if (!(req = req_alloc(sizeof(struct register_ack_message), REGISTER_ACK_MESSAGE)))
03078       return -1;
03079 
03080    req->data.regack.res[0] = '0';
03081    req->data.regack.res[1] = '\0';
03082    req->data.regack.keepAlive = htolel(keep_alive);
03083    memcpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate));
03084    req->data.regack.res2[0] = '0';
03085    req->data.regack.res2[1] = '\0';
03086    req->data.regack.secondaryKeepAlive = htolel(keep_alive);
03087    transmit_response(s, req);
03088    if (skinnydebug)
03089       ast_verbose("Requesting capabilities\n");
03090 
03091    if (!(req = req_alloc(0, CAPABILITIES_REQ_MESSAGE)))
03092       return -1;
03093 
03094    transmit_response(s, req);
03095 
03096    return res;
03097 }

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

Definition at line 3782 of file chan_skinny.c.

References skinny_req::data, htolel, ourhost, skinny_device::ourip, ourport, req_alloc(), s, 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().

03783 {
03784    struct skinny_device *d = s->device;
03785    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
03786       return -1;
03787 
03788    memcpy(req->data.serverres.server[0].serverName, ourhost,
03789          sizeof(req->data.serverres.server[0].serverName));
03790    req->data.serverres.serverListenPort[0] = htolel(ourport);
03791    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
03792    transmit_response(s, req);
03793    return 1;
03794 }

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

Definition at line 3956 of file chan_skinny.c.

References skinny_subchannel::alreadygone, AST_CONTROL_ANSWER, ast_copy_string(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_pthread_create, ast_queue_control(), ast_queue_hangup(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose(), attempt_transfer(), skinny_subchannel::callid, soft_key_event_message::callreference, ast_channel::context, skinny_subchannel::cxmode, skinny_req::data, skinny_line::dnd, do_housekeeping(), errno, ast_channel::exten, find_line_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, soft_key_event_message::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_RINGOUT, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_line::lastnumberdialed, letohl, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_subchannel::next, skinny_subchannel::onhold, option_verbose, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::rtp, s, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), skinnydebug, SOFTKEY_ANSWER, SOFTKEY_BKSPC, SOFTKEY_CFWDALL, SOFTKEY_CFWDBUSY, SOFTKEY_CFWDNOANSWER, SOFTKEY_CONFRN, 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_FORWARDALL, STIMULUS_LINE, t, ast_channel::tech_pvt, skinny_line::transfer, transmit_callstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

03957 {
03958    struct skinny_device *d = s->device;
03959    struct skinny_line *l;
03960    struct skinny_subchannel *sub = NULL;
03961    struct ast_channel *c;
03962    pthread_t t;
03963    int event;
03964    int instance;
03965    int callreference;
03966 
03967    event = letohl(req->data.softkeyeventmessage.softKeyEvent);
03968    instance = letohl(req->data.softkeyeventmessage.instance);
03969    callreference = letohl(req->data.softkeyeventmessage.callreference);
03970 
03971    if (instance) {
03972       l = find_line_by_instance(d, instance);
03973       if (callreference) {
03974          sub = find_subchannel_by_instance_reference(d, instance, callreference);
03975       } else {
03976          sub = find_subchannel_by_instance_reference(d, instance, d->lastcallreference);
03977       }
03978    } else {
03979       l = find_line_by_instance(d, d->lastlineinstance);
03980    }
03981 
03982    if (!l) {
03983       if (skinnydebug)
03984          ast_verbose("Received Softkey Event: %d(%d/%d)\n", event, instance, callreference);
03985       return 0;
03986    }
03987 
03988    switch(event) {
03989    case SOFTKEY_NONE:
03990       if (skinnydebug)
03991          ast_verbose("Received Softkey Event: None(%d/%d)\n", instance, callreference);
03992       break;
03993    case SOFTKEY_REDIAL:
03994       if (skinnydebug)
03995          ast_verbose("Received Softkey Event: Redial(%d/%d)\n", instance, callreference);
03996 
03997 #if 0
03998       if (!sub || !sub->owner) {
03999          c = skinny_new(l, AST_STATE_DOWN);
04000       } else {
04001          c = sub->owner;
04002       }
04003 
04004       if(!c) {
04005          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04006       } else {
04007          sub = c->tech_pvt;
04008          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04009          if (skinnydebug)
04010             ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04011          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04012          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04013          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
04014 
04015          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
04016             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04017          }
04018          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
04019          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
04020             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
04021             ast_hangup(c);
04022          }
04023       }
04024 #endif
04025       break;
04026    case SOFTKEY_NEWCALL:  /* Actually the DIAL softkey */
04027       if (skinnydebug)
04028          ast_verbose("Received Softkey Event: New Call(%d/%d)\n", instance, callreference);
04029 
04030       if (!sub || !sub->owner) {
04031          c = skinny_new(l, AST_STATE_DOWN);
04032       } else {
04033          c = sub->owner;
04034       }
04035 
04036       if (!c) {
04037          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
04038       } else {
04039          sub = c->tech_pvt;
04040          if (l->hookstate == SKINNY_ONHOOK) {
04041             l->hookstate = SKINNY_OFFHOOK;
04042             transmit_speaker_mode(s, SKINNY_SPEAKERON);
04043             transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04044          }
04045 
04046          if (skinnydebug)
04047             ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
04048          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
04049          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
04050          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
04051 
04052          /* start the switch thread */
04053          if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
04054             ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
04055             ast_hangup(c);
04056          }
04057       }
04058       break;
04059    case SOFTKEY_HOLD:
04060       if (skinnydebug)
04061          ast_verbose("Received Softkey Event: Hold(%d/%d)\n", instance, callreference);
04062 
04063       if (sub) {
04064          if (sub->onhold) {
04065             skinny_unhold(sub);
04066          } else {
04067             skinny_hold(sub);
04068          }
04069       }
04070             
04071       break;
04072    case SOFTKEY_TRNSFER:
04073       if (skinnydebug)
04074          ast_verbose("Received Softkey Event: Transfer(%d/%d)\n", instance, callreference);
04075       /* XXX figure out how to transfer */
04076       break;
04077    case SOFTKEY_CFWDALL:
04078       if (skinnydebug)
04079          ast_verbose("Received Softkey Event: Forward All(%d/%d)\n", instance, callreference);
04080 
04081       /* Do not disturb */
04082       if (l->dnd != 0){
04083          if (option_verbose > 2)
04084             ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n", l->name, d->name);
04085          l->dnd = 0;
04086          transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
04087          transmit_displaynotify(s, "DnD disabled", 10);
04088       } else {
04089          if (option_verbose > 2)
04090             ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n", l->name, d->name);
04091          l->dnd = 1;
04092          transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
04093          transmit_displaynotify(s, "DnD enabled", 10);
04094       }
04095       break;
04096    case SOFTKEY_CFWDBUSY:
04097       if (skinnydebug)
04098          ast_verbose("Received Softkey Event: Forward Busy (%d/%d)\n", instance, callreference);
04099       break;
04100    case SOFTKEY_CFWDNOANSWER:
04101       if (skinnydebug)
04102          ast_verbose("Received Softkey Event: Forward No Answer (%d/%d)\n", instance, callreference);
04103       break;
04104    case SOFTKEY_BKSPC:
04105       if (skinnydebug)
04106          ast_verbose("Received Softkey Event: Backspace(%d/%d)\n", instance, callreference);
04107       break;
04108    case SOFTKEY_ENDCALL:
04109       if (skinnydebug)
04110          ast_verbose("Received Softkey Event: End Call(%d/%d)\n", instance, callreference);
04111 
04112       if (l->hookstate == SKINNY_ONHOOK) {
04113          /* Something else already put us back on hook */
04114          break;
04115       }
04116       if (sub) {
04117          sub->cxmode = SKINNY_CX_RECVONLY;
04118          l->hookstate = SKINNY_ONHOOK;
04119          transmit_callstate(s, l->instance, l->hookstate, sub->callid);
04120          if (skinnydebug)
04121             ast_verbose("Skinny %s@%s went on hook\n", l->name, d->name);
04122          if (l->transfer && (sub->owner && sub->next && sub->next->owner) && ((!sub->outgoing) || (sub->next && !sub->next->outgoing))) {
04123             /* We're allowed to transfer, we have two active calls and
04124                we made at least one of the calls.  Let's try and transfer */
04125 
04126 #if 0
04127             if ((res = attempt_transfer(p)) < 0) {
04128                if (sub->next && sub->next->owner) {
04129                   sub->next->alreadygone = 1;
04130                   ast_queue_hangup(sub->next->owner, 1);
04131                }
04132             } else if (res) {
04133                ast_log(LOG_WARNING, "Transfer attempt failed\n");
04134                break;
04135             }
04136 #endif
04137          } else {
04138             /* Hangup the current call */
04139             /* If there is another active call, skinny_hangup will ring the phone with the other call */
04140             if (sub->owner) {
04141                sub->alreadygone = 1;
04142                ast_queue_hangup(sub->owner);
04143             } else {
04144                ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
04145                   l->name, d->name, sub->callid);
04146             }
04147          }
04148          if ((l->hookstate == SKINNY_ONHOOK) && (sub->next && !sub->next->rtp)) {
04149             do_housekeeping(s);
04150          }
04151       }
04152       break;
04153    case SOFTKEY_RESUME:
04154       if (skinnydebug)
04155          ast_verbose("Received Softkey Event: Resume(%d/%d)\n", instance, callreference);
04156       break;
04157    case SOFTKEY_ANSWER:
04158       if (skinnydebug)
04159          ast_verbose("Received Softkey Event: Answer(%d/%d)\n", instance, callreference);
04160 
04161       transmit_ringer_mode(s,SKINNY_RING_OFF);
04162       transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
04163 
04164       l->hookstate = SKINNY_OFFHOOK;
04165 
04166       if (sub && sub->outgoing) {
04167          /* We're answering a ringing call */
04168          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
04169          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
04170          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
04171          transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
04172          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
04173          start_rtp(sub);
04174          ast_setstate(sub->owner, AST_STATE_UP);
04175       }
04176       break;
04177    case SOFTKEY_INFO:
04178       if (skinnydebug)
04179          ast_verbose("Received Softkey Event: Info(%d/%d)\n", instance, callreference);
04180       break;
04181    case SOFTKEY_CONFRN:
04182       if (skinnydebug)
04183          ast_verbose("Received Softkey Event: Conference(%d/%d)\n", instance, callreference);
04184       /* XXX determine the best way to pull off a conference.  Meetme? */
04185       break;
04186    case SOFTKEY_PARK:
04187       if (skinnydebug)
04188          ast_verbose("Received Softkey Event: Park Call(%d/%d)\n", instance, callreference);
04189       /* XXX Park the call */
04190       break;
04191    case SOFTKEY_JOIN:
04192       if (skinnydebug)
04193          ast_verbose("Received Softkey Event: Join(%d/%d)\n", instance, callreference);
04194       break;
04195    case SOFTKEY_MEETME:
04196       /* XXX How is this different from CONFRN? */
04197       if (skinnydebug)
04198          ast_verbose("Received Softkey Event: Meetme(%d/%d)\n", instance, callreference);
04199       break;
04200    case SOFTKEY_PICKUP:
04201       if (skinnydebug)
04202          ast_verbose("Received Softkey Event: Pickup(%d/%d)\n", instance, callreference);
04203       break;
04204    case SOFTKEY_GPICKUP:
04205       if (skinnydebug)
04206          ast_verbose("Received Softkey Event: Group Pickup(%d/%d)\n", instance, callreference);
04207       break;
04208    default:
04209       if (skinnydebug)
04210          ast_verbose("Received unknown Softkey Event: %d(%d/%d)\n", event, instance, callreference);
04211       break;
04212    }
04213    return 1;
04214 }

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

Definition at line 3924 of file chan_skinny.c.

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

Referenced by handle_message().

03925 {
03926    int i;
03927    int x;
03928    int y;
03929    const struct soft_key_definitions *softkeymode = soft_key_default_definitions;
03930 
03931    if (!(req = req_alloc(sizeof(struct soft_key_set_res_message), SOFT_KEY_SET_RES_MESSAGE)))
03932       return -1;
03933 
03934    req->data.softkeysets.softKeySetOffset = htolel(0);
03935    req->data.softkeysets.softKeySetCount = htolel(11);
03936    req->data.softkeysets.totalSoftKeySetCount = htolel(11);
03937    for (x = 0; x < sizeof(soft_key_default_definitions) / sizeof(struct soft_key_definitions); x++) {
03938       const uint8_t *defaults = softkeymode->defaults;
03939       /* XXX I wanted to get the size of the array dynamically, but that wasn't wanting to work.
03940          This will have to do for now. */
03941       for (y = 0; y < softkeymode->count; y++) {
03942          for (i = 0; i < (sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition)); i++) {
03943             if (defaults[y] == i+1) {
03944                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyTemplateIndex[y] = htolel(i+1);
03945                req->data.softkeysets.softKeySetDefinition[softkeymode->mode].softKeyInfoIndex[y] = htolel(i+301);
03946             }
03947          }
03948       }
03949       softkeymode++;
03950    }
03951    transmit_response(s,req);
03952    transmit_selectsoftkeys(s, 0, 0, KEYDEF_ONHOOK);
03953    return 1;
03954 }

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

Definition at line 4221 of file chan_skinny.c.

References skinny_req::data, htolel, req_alloc(), s, 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().

04222 {
04223    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
04224       return -1;
04225 
04226    req->data.softkeytemplate.softKeyOffset = htolel(0);
04227    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
04228    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
04229    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
04230       soft_key_template_default,
04231       sizeof(soft_key_template_default));
04232    transmit_response(s,req);
04233    return 1;
04234 }

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

Definition at line 3582 of file chan_skinny.c.

References ast_copy_string(), skinny_req::data, skinny_speeddial::exten, find_speeddial_by_instance(), htolel, skinny_speeddial::instance, skinny_speeddial::label, letohl, req_alloc(), s, 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().

03583 {
03584    struct skinny_device *d = s->device;
03585    struct skinny_speeddial *sd;
03586    int instance;
03587 
03588    instance = letohl(req->data.speeddialreq.speedDialNumber);
03589 
03590    sd = find_speeddial_by_instance(d, instance);
03591 
03592    if (!sd) {
03593       return 0;
03594    }
03595 
03596    if (!(req = req_alloc(sizeof(struct speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
03597       return -1;
03598 
03599    req->data.speeddialreq.speedDialNumber = htolel(instance);
03600    ast_copy_string(req->data.speeddial.speedDialDirNumber, sd->exten, sizeof(req->data.speeddial.speedDialDirNumber));
03601    ast_copy_string(req->data.speeddial.speedDialDisplayName, sd->label, sizeof(req->data.speeddial.speedDialDisplayName));
03602 
03603    transmit_response(s, req);
03604    return 1;
03605 }

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

Definition at line 3175 of file chan_skinny.c.

References AST_CONTROL_ANSWER, ast_copy_string(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_log(), ast_matchmore_extension(), ast_pthread_create, ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_strlen_zero(), ast_verbose(), skinny_subchannel::callid, stimulus_message::callreference, skinny_line::cid_num, ast_channel::context, skinny_req::data, skinny_line::dnd, errno, ast_channel::exten, find_line_by_instance(), find_speeddial_by_instance(), find_subchannel_by_instance_reference(), skinny_line::hookstate, skinny_line::instance, KEYDEF_CONNECTED, KEYDEF_OFFHOOK, KEYDEF_RINGOUT, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_line::lastnumberdialed, letohl, LOG_DEBUG, LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::onhold, option_verbose, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_subchannel::parent, s, SKINNY_CONNECTED, SKINNY_DIALTONE, skinny_hold(), SKINNY_LAMP_OFF, SKINNY_LAMP_ON, skinny_new(), skinny_newcall(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, SKINNY_SPEAKERON, skinny_ss(), skinny_unhold(), skinnydebug, start_rtp(), stimulus_message::stimulus, skinny_data::stimulus, STIMULUS_CALLPARK, STIMULUS_CONFERENCE, STIMULUS_DISPLAY, STIMULUS_FORWARDALL, STIMULUS_FORWARDBUSY, STIMULUS_FORWARDNOANSWER, STIMULUS_HOLD, STIMULUS_LINE, STIMULUS_REDIAL, STIMULUS_SPEEDDIAL, STIMULUS_TRANSFER, STIMULUS_VOICEMAIL, stimulus_message::stimulusInstance, t, ast_channel::tech_pvt, transmit_callstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), transmit_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

03176 {
03177    struct skinny_device *d = s->device;
03178    struct skinny_line *l;
03179    struct skinny_subchannel *sub;
03180    /*struct skinny_speeddial *sd;*/
03181    struct ast_channel *c;
03182    pthread_t t;
03183    int event;
03184    int instance;
03185    int callreference;
03186    /*int res = 0;*/
03187 
03188    event = letohl(req->data.stimulus.stimulus);
03189    instance = letohl(req->data.stimulus.stimulusInstance);
03190    callreference = letohl(req->data.stimulus.callreference); 
03191    if (skinnydebug)
03192       ast_verbose("callreference in handle_stimulus_message is '%d'\n", callreference);
03193 
03194    /*  Note that this call should be using the passed in instance and callreference */
03195    sub = find_subchannel_by_instance_reference(d, d->lastlineinstance, d->lastcallreference);
03196 
03197    if (!sub) {
03198       l = find_line_by_instance(d, d->lastlineinstance);
03199       if (!l) {
03200          return 0;
03201       }
03202    } else {
03203       l = sub->parent;
03204    }
03205 
03206    switch(event) {
03207    case STIMULUS_REDIAL:
03208       if (skinnydebug)
03209          ast_verbose("Received Stimulus: Redial(%d/%d)\n", instance, callreference);
03210 
03211 #if 0
03212       if (ast_strlen_zero(l->lastnumberdialed)) {
03213          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
03214          l->hookstate = SKINNY_ONHOOK;
03215          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
03216          transmit_callstate(s, l->instance, SKINNY_ONHOOK, instance);
03217          break;
03218       }
03219 
03220       c = skinny_new(l, AST_STATE_DOWN);
03221       if(!c) {
03222          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
03223       } else {
03224          sub = c->tech_pvt;
03225          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03226          if (skinnydebug)
03227             ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
03228          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
03229          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03230          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
03231 
03232          if (!ast_ignore_pattern(c->context, l->lastnumberdialed)) {
03233             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03234          }
03235          ast_copy_string(c->exten, l->lastnumberdialed, sizeof(c->exten));
03236          if (ast_pthread_create(&t, NULL, skinny_newcall, c)) {
03237             ast_log(LOG_WARNING, "Unable to create new call thread: %s\n", strerror(errno));
03238             ast_hangup(c);
03239          }
03240       }
03241 #endif
03242       break;
03243    case STIMULUS_SPEEDDIAL:
03244       if (skinnydebug)
03245          ast_verbose("Received Stimulus: SpeedDial(%d/%d)\n", instance, callreference);
03246 
03247 #if 0
03248       if (!(sd = find_speeddial_by_instance(d, instance))) {
03249          return 0;
03250       }
03251 
03252       if (ast_strlen_zero(l->lastnumberdialed)) {
03253          ast_log(LOG_WARNING, "Attempted redial, but no previously dialed number found.\n");
03254          l->hookstate = SKINNY_ONHOOK;
03255          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
03256          transmit_callstate(s, l->instance, SKINNY_ONHOOK, instance);
03257          break;
03258       }
03259 
03260       c = skinny_new(l, AST_STATE_DOWN);
03261       if(c) {
03262          sub = c->tech_pvt;
03263          l = sub->parent;
03264          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03265          if (skinnydebug)
03266             ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
03267          transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
03268          transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03269          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGOUT);
03270 
03271          if (!ast_ignore_pattern(c->context, sd->exten)) {
03272             transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03273          }
03274          if (ast_exists_extension(c, c->context, sd->exten, 1, l->cid_num)) {
03275             if (!ast_matchmore_extension(c, c->context, sd->exten, 1, l->cid_num)) {
03276                ast_copy_string(c->exten, sd->exten, sizeof(c->exten));
03277                ast_copy_string(l->lastnumberdialed, sd->exten, sizeof(l->lastnumberdialed));
03278                skinny_newcall(c);
03279                break;
03280             }
03281          }
03282       } else {
03283          ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
03284       }
03285 #endif
03286       break;
03287    case STIMULUS_HOLD:
03288       if (skinnydebug)
03289          ast_verbose("Received Stimulus: Hold(%d/%d)\n", instance, callreference);
03290 
03291       if (!sub)
03292          break;
03293 
03294       if (sub->onhold) {
03295          skinny_unhold(sub);
03296       } else {
03297          skinny_hold(sub);
03298       }
03299       break;
03300    case STIMULUS_TRANSFER:
03301       if (skinnydebug)
03302          ast_verbose("Received Stimulus: Transfer(%d/%d)\n", instance, callreference);
03303       /* XXX figure out how to transfer */
03304       break;
03305    case STIMULUS_CONFERENCE:
03306       if (skinnydebug)
03307          ast_verbose("Received Stimulus: Conference(%d/%d)\n", instance, callreference);
03308       /* XXX determine the best way to pull off a conference.  Meetme? */
03309       break;
03310    case STIMULUS_VOICEMAIL:
03311       if (skinnydebug)
03312          ast_verbose("Received Stimulus: Voicemail(%d/%d)\n", instance, callreference);
03313       /* XXX Find and dial voicemail extension */
03314       break;
03315    case STIMULUS_CALLPARK:
03316       if (skinnydebug)
03317          ast_verbose("Received Stimulus: Park Call(%d/%d)\n", instance, callreference);
03318       /* XXX Park the call */
03319       break;
03320    case STIMULUS_FORWARDALL:
03321       if (skinnydebug)
03322          ast_verbose("Received Stimulus: Forward All(%d/%d)\n", instance, callreference);
03323       /* Why is DND under FORWARDALL? */
03324       /* Because it's the same thing. */
03325 
03326       /* Do not disturb */
03327       if (l->dnd != 0){
03328          if (option_verbose > 2)
03329             ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n", l->name, d->name);
03330          l->dnd = 0;
03331          transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
03332          transmit_displaynotify(s, "DnD disabled", 10);
03333       } else {
03334          if (option_verbose > 2)
03335             ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n", l->name, d->name);
03336          l->dnd = 1;
03337          transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
03338          transmit_displaynotify(s, "DnD enabled", 10);
03339       }
03340       break;
03341    case STIMULUS_FORWARDBUSY:
03342       if (skinnydebug)
03343          ast_verbose("Received Stimulus: Forward Busy (%d/%d)\n", instance, callreference);
03344       break;
03345    case STIMULUS_FORWARDNOANSWER:
03346       if (skinnydebug)
03347          ast_verbose("Received Stimulus: Forward No Answer (%d/%d)\n", instance, callreference);
03348       break;
03349    case STIMULUS_DISPLAY:
03350       /* Not sure what this is */
03351       if (skinnydebug)
03352          ast_verbose("Received Stimulus: Display(%d/%d)\n", instance, callreference);
03353       break;
03354    case STIMULUS_LINE:
03355       if (skinnydebug)
03356          ast_verbose("Received Stimulus: Line(%d/%d)\n", instance, callreference);
03357 
03358       l = find_line_by_instance(s->device, instance);
03359 
03360       if (!l) {
03361          return 0;
03362       }
03363 
03364       /* turn the speaker on */
03365       transmit_speaker_mode(s, SKINNY_SPEAKERON);
03366       transmit_ringer_mode(s, SKINNY_RING_OFF);
03367       transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03368 
03369       l->hookstate = SKINNY_OFFHOOK;
03370 
03371       if (sub && sub->outgoing) {
03372          /* We're answering a ringing call */
03373          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
03374          transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03375          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
03376          transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
03377          transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
03378          transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
03379          start_rtp(sub);
03380          ast_setstate(sub->owner, AST_STATE_UP);
03381       } else {
03382          if (sub && sub->owner) {
03383             ast_log(LOG_DEBUG, "Current subchannel [%s] already has owner\n", sub->owner->name);
03384          } else {
03385             c = skinny_new(l, AST_STATE_DOWN);
03386             if(c) {
03387                sub = c->tech_pvt;
03388                transmit_callstate(s, l->instance, SKINNY_OFFHOOK, sub->callid);
03389                if (skinnydebug)
03390                   ast_verbose("Attempting to Clear display on Skinny %s@%s\n", l->name, d->name);
03391                transmit_displaymessage(s, NULL, l->instance, sub->callid); /* clear display */
03392                transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
03393                transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_OFFHOOK);
03394 
03395                /* start the switch thread */
03396                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
03397                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
03398                   ast_hangup(c);
03399                }
03400             } else {
03401                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", l->name, d->name);
03402             }
03403          }
03404       }
03405       break;
03406    default:
03407       if (skinnydebug)
03408          ast_verbose("RECEIVED UNKNOWN STIMULUS:  %d(%d/%d)\n", event, instance, callreference);
03409       break;
03410    }
03411    return 1;
03412 }

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

Definition at line 3637 of file chan_skinny.c.

References 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(), s, definetimedate_message::seconds, definetimedate_message::timestamp, transmit_response(), and definetimedate_message::year.

Referenced by do_housekeeping(), and handle_message().

03638 {
03639    time_t timer;
03640    struct tm *cmtime;
03641 
03642    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
03643       return -1;
03644 
03645    timer = time(NULL);
03646    cmtime = localtime(&timer);
03647    req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
03648    req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
03649    req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
03650    req->data.definetimedate.day = htolel(cmtime->tm_mday);
03651    req->data.definetimedate.hour = htolel(cmtime->tm_hour);
03652    req->data.definetimedate.minute = htolel(cmtime->tm_min);
03653    req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
03654    req->data.definetimedate.milliseconds = htolel(0);
03655    req->data.definetimedate.timestamp = htolel(timer);
03656    transmit_response(s, req);
03657    return 1;
03658 }

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

Definition at line 4216 of file chan_skinny.c.

References s, and skinny_unregister().

Referenced by handle_message().

04217 {
04218    return skinny_unregister(req, s);
04219 }

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

Definition at line 3771 of file chan_skinny.c.

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

Referenced by handle_message().

03772 {
03773    struct skinny_device *d = s->device;
03774    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
03775       return -1;
03776 
03777    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
03778    transmit_response(s, req);
03779    return 1;
03780 }

static int load_module ( void   )  [static]

Definition at line 4986 of file chan_skinny.c.

References ast_channel_register(), ast_cli_register_multiple(), ast_log(), AST_MODULE_LOAD_DECLINE, ast_rtp_proto_register(), cli_skinny, htolel, io, io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), skinny_rtp, skinny_tech, and soft_key_template_default.

04987 {
04988    int res = 0;
04989 
04990    for (; res < (sizeof(soft_key_template_default) / sizeof(soft_key_template_default[0])); res++) {
04991       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
04992    }
04993    /* load and parse config */
04994    res = reload_config();
04995    if (res == -1) {
04996       return AST_MODULE_LOAD_DECLINE;
04997    }
04998 
04999    /* Make sure we can register our skinny channel type */
05000    if (ast_channel_register(&skinny_tech)) {
05001       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
05002       return -1;
05003    }
05004 
05005    ast_rtp_proto_register(&skinny_rtp);
05006    ast_cli_register_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
05007    sched = sched_context_create();
05008    if (!sched) {
05009       ast_log(LOG_WARNING, "Unable to create schedule context\n");
05010    }
05011    io = io_context_create();
05012    if (!io) {
05013       ast_log(LOG_WARNING, "Unable to create I/O context\n");
05014    }
05015    /* And start the monitor for the first time */
05016    restart_monitor();
05017 
05018    return res;
05019 }

static int reload_config ( void   )  [static]

Definition at line 4764 of file chan_skinny.c.

References __ourip, accept_t, accept_thread(), ahp, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_gethostbyname(), ast_inet_ntoa(), ast_jb_read_conf(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_parse_allow_disallow(), ast_pthread_create_background, ast_variable_browse(), ast_verbose(), auth_limit, auth_timeout, bindaddr, build_device(), config, date_format, DEFAULT_AUTH_LIMIT, DEFAULT_AUTH_TIMEOUT, default_capability, default_jbconf, default_prefs, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, devicelock, devices, errno, global_jbconf, hp, keep_alive, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::name, ast_variable::name, netlock, skinny_device::next, ast_variable::next, option_verbose, ourhost, ourport, skinnysock, ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

04765 {
04766    int on = 1;
04767    struct ast_config *cfg;
04768    struct ast_variable *v;
04769    char *cat;
04770    struct skinny_device *d;
04771    int oldport = ntohs(bindaddr.sin_port);
04772 
04773    if (gethostname(ourhost, sizeof(ourhost))) {
04774       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
04775       return 0;
04776    }
04777    cfg = ast_config_load(config);
04778 
04779    /* We *must* have a config file otherwise stop immediately */
04780    if (!cfg) {
04781       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
04782       return -1;
04783    }
04784    memset(&bindaddr, 0, sizeof(bindaddr));
04785    memset(&default_prefs, 0, sizeof(default_prefs));
04786 
04787    /* Copy the default jb config over global_jbconf */
04788    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04789 
04790    /* load the general section */
04791    v = ast_variable_browse(cfg, "general");
04792    while (v) {
04793       /* handle jb conf */
04794       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04795          v = v->next;
04796          continue;
04797       }
04798 
04799       /* Create the interface list */
04800       if (!strcasecmp(v->name, "bindaddr")) {
04801          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04802             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04803          } else {
04804             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04805          }
04806       } else if (!strcasecmp(v->name, "keepalive")) {
04807          keep_alive = atoi(v->value);
04808       } else if (!strcasecmp(v->name, "authtimeout")) {
04809          int timeout = atoi(v->value);
04810 
04811          if (timeout < 1) {
04812             ast_log(LOG_WARNING, "Invalid authtimeout value '%s', using default value\n", v->value);
04813             auth_timeout = DEFAULT_AUTH_TIMEOUT;
04814          } else {
04815             auth_timeout = timeout;
04816          }
04817       } else if (!strcasecmp(v->name, "authlimit")) {
04818          int limit = atoi(v->value);
04819 
04820          if (limit < 1) {
04821             ast_log(LOG_WARNING, "Invalid authlimit value '%s', using default value\n", v->value);
04822             auth_limit = DEFAULT_AUTH_LIMIT;
04823          } else {
04824             auth_limit = limit;
04825          }
04826       } else if (!strcasecmp(v->name, "dateformat")) {
04827          memcpy(date_format, v->value, sizeof(date_format));
04828       } else if (!strcasecmp(v->name, "allow")) {
04829          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
04830       } else if (!strcasecmp(v->name, "disallow")) {
04831          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
04832       } else if (!strcasecmp(v->name, "bindport") || !strcasecmp(v->name, "port")) {
04833          if (sscanf(v->value, "%5d", &ourport) == 1) {
04834             bindaddr.sin_port = htons(ourport);
04835          } else {
04836             ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
04837          }
04838          if (!strcasecmp(v->name, "port")) { /*! \todo Remove 'port' option after 1.4 */
04839             ast_log(LOG_WARNING, "Option 'port' at line %d of %s has been deprecated.  Please use 'bindport' instead.\n", v->lineno, config);
04840          }
04841       }
04842       v = v->next;
04843    }
04844 
04845    if (ntohl(bindaddr.sin_addr.s_addr)) {
04846       __ourip = bindaddr.sin_addr;
04847    } else {
04848       hp = ast_gethostbyname(ourhost, &ahp);
04849       if (!hp) {
04850          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
04851          ast_config_destroy(cfg);
04852          return 0;
04853       }
04854       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04855    }
04856    if (!ntohs(bindaddr.sin_port)) {
04857       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
04858    }
04859    bindaddr.sin_family = AF_INET;
04860 
04861    /* load the device sections */
04862    cat = ast_category_browse(cfg, NULL);
04863    while(cat) {
04864       if (!strcasecmp(cat, "general")) {
04865          /* Nothing to do */
04866 #if 0
04867       } else if (!strncasecmp(cat, "paging-", 7)) {
04868          p = build_paging_device(cat, ast_variable_browse(cfg, cat));
04869          if (p) {
04870          }
04871 #endif
04872       } else {
04873          d = build_device(cat, ast_variable_browse(cfg, cat));
04874          if (d) {
04875             if (option_verbose > 2)
04876                ast_verbose(VERBOSE_PREFIX_3 "Added device '%s'\n", d->name);
04877             ast_mutex_lock(&devicelock);
04878             d->next = devices;
04879             devices = d;
04880             ast_mutex_unlock(&devicelock);
04881          }
04882       }
04883       cat = ast_category_browse(cfg, cat);
04884    }
04885    ast_mutex_lock(&netlock);
04886    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
04887       close(skinnysock);
04888       skinnysock = -1;
04889    }
04890    if (skinnysock < 0) {
04891       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
04892       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
04893          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
04894          ast_config_destroy(cfg);
04895          ast_mutex_unlock(&netlock);
04896          return 0;
04897       }
04898       if (skinnysock < 0) {
04899          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
04900       } else {
04901          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04902             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04903                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04904                      strerror(errno));
04905             close(skinnysock);
04906             skinnysock = -1;
04907             ast_config_destroy(cfg);
04908             ast_mutex_unlock(&netlock);
04909             return 0;
04910          }
04911          if (listen(skinnysock,DEFAULT_SKINNY_BACKLOG)) {
04912                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
04913                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04914                      strerror(errno));
04915                close(skinnysock);
04916                skinnysock = -1;
04917                ast_config_destroy(cfg);
04918                ast_mutex_unlock(&netlock);
04919                return 0;
04920          }
04921          if (option_verbose > 1)
04922             ast_verbose(VERBOSE_PREFIX_2 "Skinny listening on %s:%d\n",
04923                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04924          ast_pthread_create_background(&accept_t,NULL, accept_thread, NULL);
04925       }
04926    }
04927    ast_mutex_unlock(&netlock);
04928    ast_config_destroy(cfg);
04929    return 1;
04930 }

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

Definition at line 1244 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_line_state_req_message(), handle_open_receive_channel_ack_message(), handle_register_message(), handle_server_request_message(), handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), handle_speed_dial_stat_req_message(), handle_time_date_req_message(), handle_version_req_message(), skinny_hold(), skinny_reset_device(), skinny_unhold(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_dialednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), transmit_speaker_mode(), and transmit_tone().

01245 {
01246    struct skinny_req *req;
01247 
01248    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01249       return NULL;
01250 
01251    req->len = htolel(size+4);
01252    req->e = htolel(response_message);
01253 
01254    return req;
01255 }

static int restart_monitor ( void   )  [static]

Definition at line 4700 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, monitor_thread, and monlock.

04701 {
04702    /* If we're supposed to be stopped -- stay stopped */
04703    if (monitor_thread == AST_PTHREADT_STOP)
04704       return 0;
04705 
04706    ast_mutex_lock(&monlock);
04707    if (monitor_thread == pthread_self()) {
04708       ast_mutex_unlock(&monlock);
04709       ast_log(LOG_WARNING, "Cannot kill myself\n");
04710       return -1;
04711    }
04712    if (monitor_thread != AST_PTHREADT_NULL) {
04713       /* Wake up the thread */
04714       pthread_kill(monitor_thread, SIGURG);
04715    } else {
04716       /* Start a new monitor */
04717       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
04718          ast_mutex_unlock(&monlock);
04719          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04720          return -1;
04721       }
04722    }
04723    ast_mutex_unlock(&monlock);
04724    return 0;
04725 }

static int skinny_answer ( struct ast_channel ast  )  [static]

Definition at line 2591 of file chan_skinny.c.

References ast_channel::_state, ast_copy_string(), AST_MAX_EXTENSION, ast_setstate(), AST_STATE_UP, ast_verbose(), skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, skinny_subchannel::cxmode, ast_channel::exten, exten, skinny_line::instance, KEYDEF_CONNECTED, ast_channel::macroexten, skinny_device::name, skinny_line::name, ast_channel::name, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, s, S_OR, skinny_device::session, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_SILENCE, skinnydebug, start_rtp(), skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_selectsoftkeys(), and transmit_tone().

02592 {
02593    int res = 0;
02594    struct skinny_subchannel *sub = ast->tech_pvt;
02595    struct skinny_line *l = sub->parent;
02596    struct skinny_device *d = l->parent;
02597    struct skinnysession *s = d->session;
02598    char exten[AST_MAX_EXTENSION] = "";
02599 
02600    ast_copy_string(exten, S_OR(ast->macroexten, ast->exten), sizeof(exten));
02601 
02602    sub->cxmode = SKINNY_CX_SENDRECV;
02603    if (!sub->rtp) {
02604       start_rtp(sub);
02605    }
02606    if (skinnydebug)
02607       ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, d->name, sub->callid);
02608    if (ast->_state != AST_STATE_UP) {
02609       ast_setstate(ast, AST_STATE_UP);
02610    }
02611 
02612    transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
02613    /* order matters here...
02614       for some reason, transmit_callinfo must be before transmit_callstate,
02615       or you won't get keypad messages in some situations. */
02616    transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2);
02617    transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
02618    transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_CONNECTED);
02619    transmit_dialednumber(s, exten, l->instance, sub->callid);
02620    transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
02621    return res;
02622 }

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

Definition at line 2495 of file chan_skinny.c.

References ast_channel::_state, AST_CONTROL_BUSY, AST_CONTROL_RINGING, ast_log(), ast_queue_control(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RESERVED, AST_STATE_RINGING, ast_verbose(), skinny_subchannel::callid, ast_channel::cid, skinny_line::cid_name, ast_callerid::cid_name, skinny_line::cid_num, ast_callerid::cid_num, skinny_line::dnd, skinny_line::hookstate, skinny_line::instance, KEYDEF_RINGIN, LOG_ERROR, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, s, skinny_device::session, SKINNY_ALERT, SKINNY_CALLWAITTONE, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, skinnydebug, STIMULUS_LINE, skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_selectsoftkeys(), and VERBOSE_PREFIX_3.

02496 {
02497    int res = 0;
02498    int tone = 0;
02499    struct skinny_subchannel *sub = ast->tech_pvt;
02500    struct skinny_line *l = sub->parent;
02501    struct skinny_device *d = l->parent;
02502    struct skinnysession *s = d->session;
02503 
02504    if (!d->registered) {
02505       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
02506       return -1;
02507    }
02508 
02509    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
02510       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
02511       return -1;
02512    }
02513 
02514    if (skinnydebug)
02515       ast_verbose(VERBOSE_PREFIX_3 "skinny_call(%s)\n", ast->name);
02516 
02517    if (l->dnd) {
02518       ast_queue_control(ast, AST_CONTROL_BUSY);
02519       return -1;
02520    }
02521 
02522    switch (l->hookstate) {
02523    case SKINNY_OFFHOOK:
02524       tone = SKINNY_CALLWAITTONE;
02525       break;
02526    case SKINNY_ONHOOK:
02527       tone = SKINNY_ALERT;
02528       break;
02529    default:
02530       ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
02531       break;
02532    }
02533 
02534    transmit_callstate(s, l->instance, SKINNY_RINGIN, sub->callid);
02535    transmit_selectsoftkeys(s, l->instance, sub->callid, KEYDEF_RINGIN);
02536    transmit_displaypromptstatus(s, "Ring-In", 0, l->instance, sub->callid);
02537    transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
02538    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
02539    transmit_ringer_mode(s, SKINNY_RING_INSIDE);
02540 
02541    ast_setstate(ast, AST_STATE_RINGING);
02542    ast_queue_control(ast, AST_CONTROL_RINGING);
02543    sub->outgoing = 1;
02544    return res;
02545 }

static int skinny_do_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1869 of file chan_skinny.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and skinnydebug.

01870 {
01871    if (argc != 3) {
01872       return RESULT_SHOWUSAGE;
01873    }
01874    skinnydebug = 1;
01875    ast_cli(fd, "Skinny Debugging Enabled\n");
01876    return RESULT_SUCCESS;
01877 }

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

Definition at line 2710 of file chan_skinny.c.

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

02711 {
02712    struct skinny_subchannel *sub = newchan->tech_pvt;
02713    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
02714    if (sub->owner != oldchan) {
02715       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
02716       return -1;
02717    }
02718    sub->owner = newchan;
02719    return 0;
02720 }

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

Definition at line 1839 of file chan_skinny.c.

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

01840 {
01841    struct skinny_subchannel *sub = NULL;
01842 
01843    if (!(sub = c->tech_pvt) || !(sub->rtp))
01844       return AST_RTP_GET_FAILED;
01845 
01846    *rtp = sub->rtp;
01847 
01848    return AST_RTP_TRY_NATIVE;
01849 }

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

Definition at line 1827 of file chan_skinny.c.

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

01828 {
01829    struct skinny_subchannel *sub = NULL;
01830 
01831    if (!(sub = c->tech_pvt) || !(sub->vrtp))
01832       return AST_RTP_GET_FAILED;
01833 
01834    *rtp = sub->vrtp;
01835 
01836    return AST_RTP_TRY_NATIVE;
01837 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

Definition at line 2547 of file chan_skinny.c.

References skinny_subchannel::alreadygone, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_destroy(), ast_verbose(), skinny_subchannel::callid, do_housekeeping(), skinny_line::hookstate, skinny_line::instance, skinny_subchannel::lock, LOG_DEBUG, skinny_device::name, skinny_line::name, ast_channel::name, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_LAMP_OFF, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, skinnydebug, STIMULUS_LINE, ast_channel::tech_pvt, transmit_callstate(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_tone(), skinny_line::type, and TYPE_LINE.

02548 {
02549    struct skinny_subchannel *sub = ast->tech_pvt;
02550    struct skinny_line *l;
02551    struct skinny_device *d;
02552    struct skinnysession *s;
02553 
02554    if (!sub) {
02555       ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
02556       return 0;
02557    }
02558    l = sub->parent;
02559    d = l->parent;
02560    s = d->session;
02561    if (skinnydebug)
02562       ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, d->name);
02563 
02564    if (d->registered) {
02565       if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_OFFHOOK)) {
02566          l->hookstate = SKINNY_ONHOOK;
02567          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
02568          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
02569          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
02570       } else if ((l->type = TYPE_LINE) && (l->hookstate == SKINNY_ONHOOK)) {
02571          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
02572          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
02573          transmit_ringer_mode(s, SKINNY_RING_OFF);
02574          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
02575          do_housekeeping(s);
02576       }
02577    }
02578    ast_mutex_lock(&sub->lock);
02579    sub->owner = NULL;
02580    ast->tech_pvt = NULL;
02581    sub->alreadygone = 0;
02582    sub->outgoing = 0;
02583    if (sub->rtp) {
02584       ast_rtp_destroy(sub->rtp);
02585       sub->rtp = NULL;
02586    }
02587    ast_mutex_unlock(&sub->lock);
02588    return 0;
02589 }

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

Definition at line 2973 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, AST_CONTROL_HOLD, ast_queue_control_data(), ast_strlen_zero(), ast_verbose(), skinny_subchannel::callid, CLOSE_RECEIVE_CHANNEL_MESSAGE, skinny_data::closereceivechannel, stop_media_transmission_message::conferenceId, close_receive_channel_message::conferenceId, skinny_req::data, htolel, skinny_line::instance, activate_call_plane_message::lineInstance, skinny_line::mohsuggest, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, close_receive_channel_message::partyId, stop_media_transmission_message::passThruPartyId, req_alloc(), s, S_OR, skinny_device::session, SKINNY_LAMP_BLINK, skinnydebug, STIMULUS_LINE, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_data::stopmedia, skinny_line::sub, transmit_lamp_indication(), and transmit_response().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

02974 {
02975    struct skinny_line *l = sub->parent;
02976    struct skinny_device *d = l->parent;
02977    struct skinnysession *s = d->session;
02978    struct skinny_req *req;
02979 
02980    /* Don't try to hold a channel that doesn't exist */
02981    if (!sub || !sub->owner)
02982       return 0;
02983 
02984    /* Channel needs to be put on hold */
02985    if (skinnydebug)
02986       ast_verbose("Putting on Hold(%d)\n", l->instance);
02987 
02988    ast_queue_control_data(sub->owner, AST_CONTROL_HOLD,
02989       S_OR(l->mohsuggest, NULL),
02990       !ast_strlen_zero(l->mohsuggest) ? strlen(l->mohsuggest) + 1 : 0);
02991 
02992    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
02993       return 0;
02994 
02995    req->data.activatecallplane.lineInstance = htolel(l->instance);
02996    transmit_response(s, req);
02997 
02998    if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
02999       return 0;
03000 
03001    req->data.closereceivechannel.conferenceId = htolel(sub->callid);
03002    req->data.closereceivechannel.partyId = htolel(sub->callid);
03003    transmit_response(s, req);
03004 
03005    if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
03006       return 0;
03007 
03008    req->data.stopmedia.conferenceId = htolel(sub->callid);
03009    req->data.stopmedia.passThruPartyId = htolel(sub->callid);
03010    transmit_response(s, req);
03011 
03012    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
03013    sub->onhold = 1;
03014    return 1;
03015 }

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

Definition at line 2790 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCCHANGE, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), ast_rtp_change_source(), ast_rtp_new_source(), AST_SOFTHANGUP_DEV, ast_softhangup_nolock(), AST_STATE_UP, ast_verbose(), skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_name, ast_callerid::cid_num, control2str(), skinny_device::earlyrtp, ast_channel::exten, exten, skinny_line::instance, LOG_NOTICE, LOG_WARNING, ast_channel::macroexten, skinny_line::mohinterpret, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_subchannel::rtp, s, S_OR, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, skinnydebug, skinny_line::sub, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_dialednumber(), transmit_displaypromptstatus(), transmit_tone(), and VERBOSE_PREFIX_3.

02791 {
02792    struct skinny_subchannel *sub = ast->tech_pvt;
02793    struct skinny_line *l = sub->parent;
02794    struct skinny_device *d = l->parent;
02795    struct skinnysession *s = d->session;
02796    char exten[AST_MAX_EXTENSION] = "";
02797 
02798    if (!s) {
02799       ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
02800       return -1;
02801    }
02802 
02803    ast_copy_string(exten, S_OR(ast->macroexten, ast->exten), sizeof(exten));
02804 
02805    if (skinnydebug)
02806       ast_verbose(VERBOSE_PREFIX_3 "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
02807    switch(ind) {
02808    case AST_CONTROL_RINGING:
02809       if (ast->_state != AST_STATE_UP) {
02810          if (!sub->progress) {
02811             if (!d->earlyrtp) {
02812                transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid);
02813             }
02814             transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
02815             transmit_dialednumber(s, exten, l->instance, sub->callid);
02816             transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
02817             transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
02818             sub->ringing = 1;
02819             if (!d->earlyrtp) {
02820                break;
02821             }
02822          }
02823       }
02824       return -1; /* Tell asterisk to provide inband signalling */
02825    case AST_CONTROL_BUSY:
02826       if (ast->_state != AST_STATE_UP) {
02827          if (!d->earlyrtp) {
02828             transmit_tone(s, SKINNY_BUSYTONE, l->instance, sub->callid);
02829          }
02830          transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid);
02831          sub->alreadygone = 1;
02832          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
02833          if (!d->earlyrtp) {
02834             break;
02835          }
02836       }
02837       return -1; /* Tell asterisk to provide inband signalling */
02838    case AST_CONTROL_CONGESTION:
02839       if (ast->_state != AST_STATE_UP) {
02840          if (!d->earlyrtp) {
02841             transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
02842          }
02843          transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid);
02844          sub->alreadygone = 1;
02845          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
02846          if (!d->earlyrtp) {
02847             break;
02848          }
02849       }
02850       return -1; /* Tell asterisk to provide inband signalling */
02851    case AST_CONTROL_PROGRESS:
02852       if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
02853          if (!d->earlyrtp) {
02854             transmit_tone(s, SKINNY_ALERT, l->instance, sub->callid);
02855          }
02856          transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
02857          transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
02858          transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, exten, exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
02859          sub->progress = 1;
02860          if (!d->earlyrtp) {
02861             break;
02862          }
02863       }
02864       return -1; /* Tell asterisk to provide inband signalling */
02865    case -1:  /* STOP_TONE */
02866       transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
02867       break;
02868    case AST_CONTROL_HOLD:
02869       ast_moh_start(ast, data, l->mohinterpret);
02870       break;
02871    case AST_CONTROL_UNHOLD:
02872       ast_moh_stop(ast);
02873       break;
02874    case AST_CONTROL_PROCEEDING:
02875       break;
02876    case AST_CONTROL_SRCUPDATE:
02877       ast_rtp_new_source(sub->rtp);
02878       break;
02879    case AST_CONTROL_SRCCHANGE:
02880       ast_rtp_change_source(sub->rtp);
02881       break;
02882    default:
02883       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
02884       return -1; /* Tell asterisk to provide inband signalling */
02885    }
02886    return 0;
02887 }

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

Definition at line 2889 of file chan_skinny.c.

References accountcode, skinny_line::accountcode, ast_channel::adsicpe, ast_channel::amaflags, skinny_line::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_calloc, ast_channel_alloc(), ast_copy_string(), ast_hangup(), ast_jb_configure(), ast_log(), ast_module_ref(), ast_mutex_init(), ast_pbx_start(), ast_rtp_fd(), AST_STATE_DOWN, AST_STATE_RING, ast_strdup, ast_string_field_set, ast_strlen_zero(), ast_verbose(), skinny_line::call_forward, skinny_line::callgroup, ast_channel::callgroup, skinny_subchannel::callid, callnums, skinny_line::capability, ast_channel::cid, ast_callerid::cid_ani, skinny_line::cid_name, skinny_line::cid_num, ast_channel::context, skinny_line::context, skinny_subchannel::cxmode, default_capability, ast_channel::exten, skinny_line::exten, ast_channel::fds, global_jbconf, skinny_line::instance, language, skinny_line::language, skinny_device::lastcallreference, skinny_device::lastlineinstance, skinny_subchannel::lock, LOG_WARNING, skinny_device::name, skinny_line::name, skinny_line::nat, skinny_subchannel::nat, ast_channel::nativeformats, skinny_subchannel::next, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_subchannel::parent, skinny_line::parent, skinny_line::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, skinny_subchannel::rtp, SKINNY_CX_INACTIVE, skinny_tech, skinnydebug, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, and ast_channel::writeformat.

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

02890 {
02891    struct ast_channel *tmp;
02892    struct skinny_subchannel *sub;
02893    struct skinny_device *d = l->parent;
02894    int fmt;
02895 
02896    tmp = ast_channel_alloc(1, state, l->cid_num, l->cid_name, l->accountcode, l->exten, l->context, l->amaflags, "Skinny/%s@%s-%d", l->name, d->name, callnums);
02897    if (!tmp) {
02898       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02899       return NULL;
02900    } else {
02901       sub = ast_calloc(1, sizeof(struct skinny_subchannel));
02902       if (!sub) {
02903          ast_log(LOG_WARNING, "Unable to allocate Skinny subchannel\n");
02904          return NULL;
02905       } else {
02906          ast_mutex_init(&sub->lock);
02907 
02908          sub->owner = tmp;
02909          sub->callid = callnums++;
02910          d->lastlineinstance = l->instance;
02911          d->lastcallreference = sub->callid;
02912          sub->cxmode = SKINNY_CX_INACTIVE;
02913          sub->nat = l->nat;
02914          sub->parent = l;
02915          sub->onhold = 0;
02916 
02917          sub->next = l->sub;
02918          l->sub = sub;
02919       }
02920       tmp->tech = &skinny_tech;
02921       tmp->tech_pvt = sub;
02922       tmp->nativeformats = l->capability;
02923       if (!tmp->nativeformats)
02924          tmp->nativeformats = default_capability;
02925       fmt = ast_best_codec(tmp->nativeformats);
02926       if (skinnydebug)
02927          ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
02928       if (sub->rtp) {
02929          tmp->fds[0] = ast_rtp_fd(sub->rtp);
02930       }
02931       if (state == AST_STATE_RING) {
02932          tmp->rings = 1;
02933       }
02934       tmp->writeformat = fmt;
02935       tmp->rawwriteformat = fmt;
02936       tmp->readformat = fmt;
02937       tmp->rawreadformat = fmt;
02938       if (!ast_strlen_zero(l->language))
02939          ast_string_field_set(tmp, language, l->language);
02940       if (!ast_strlen_zero(l->accountcode))
02941          ast_string_field_set(tmp, accountcode, l->accountcode);
02942       if (l->amaflags)
02943          tmp->amaflags = l->amaflags;
02944 
02945       ast_module_ref(ast_module_info->self);
02946       tmp->callgroup = l->callgroup;
02947       tmp->pickupgroup = l->pickupgroup;
02948       ast_string_field_set(tmp, call_forward, l->call_forward);
02949       ast_copy_string(tmp->context, l->context, sizeof(tmp->context));
02950       ast_copy_string(tmp->exten, l->exten, sizeof(tmp->exten));
02951 
02952       /* Don't use ast_set_callerid() here because it will
02953        * generate a needless NewCallerID event */
02954       tmp->cid.cid_ani = ast_strdup(l->cid_num);
02955 
02956       tmp->priority = 1;
02957       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
02958 
02959       if (sub->rtp)
02960          ast_jb_configure(tmp, &global_jbconf);
02961 
02962       if (state != AST_STATE_DOWN) {
02963          if (ast_pbx_start(tmp)) {
02964             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
02965             ast_hangup(tmp);
02966             tmp = NULL;
02967          }
02968       }
02969    }
02970    return tmp;
02971 }

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

Definition at line 2369 of file chan_skinny.c.

References ast_copy_string(), ast_log(), ast_pbx_run(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_ani, skinny_line::cid_name, skinny_line::cid_num, ast_channel::exten, skinny_line::hidecallerid, skinny_line::instance, skinny_line::lastnumberdialed, LOG_WARNING, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, s, skinny_device::session, SKINNY_REORDER, start_rtp(), skinny_line::sub, ast_channel::tech_pvt, and transmit_tone().

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

02370 {
02371    struct ast_channel *c = data;
02372    struct skinny_subchannel *sub = c->tech_pvt;
02373    struct skinny_line *l = sub->parent;
02374    struct skinny_device *d = l->parent;
02375    struct skinnysession *s = d->session;
02376    int res = 0;
02377 
02378    ast_copy_string(l->lastnumberdialed, c->exten, sizeof(l->lastnumberdialed));
02379    ast_set_callerid(c,
02380       l->hidecallerid ? "" : l->cid_num,
02381       l->hidecallerid ? "" : l->cid_name,
02382       c->cid.cid_ani ? NULL : l->cid_num);
02383    ast_setstate(c, AST_STATE_RING);
02384    if (!sub->rtp) {
02385       start_rtp(sub);
02386    }
02387    res = ast_pbx_run(c);
02388    if (res) {
02389       ast_log(LOG_WARNING, "PBX exited non-zero\n");
02390       transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
02391    }
02392    return NULL;
02393 }

static int skinny_no_debug ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1879 of file chan_skinny.c.

References ast_cli(), RESULT_SHOWUSAGE, RESULT_SUCCESS, and skinnydebug.

01880 {
01881    if (argc != 4) {
01882       return RESULT_SHOWUSAGE;
01883    }
01884    skinnydebug = 0;
01885    ast_cli(fd, "Skinny Debugging Disabled\n");
01886    return RESULT_SUCCESS;
01887 }

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

Definition at line 2672 of file chan_skinny.c.

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

02673 {
02674    struct ast_frame *fr;
02675    struct skinny_subchannel *sub = ast->tech_pvt;
02676    ast_mutex_lock(&sub->lock);
02677    fr = skinny_rtp_read(sub);
02678    ast_mutex_unlock(&sub->lock);
02679    return fr;
02680 }

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

Definition at line 1421 of file chan_skinny.c.

References __ourip, ast_apply_ha(), ast_copy_string(), ast_log(), ast_mutex_lock(), ast_strlen_zero(), skinny_req::data, devicelock, devices, skinny_device::ha, skinny_device::id, letohl, LOG_WARNING, register_message::name, skinny_device::next, skinny_data::reg, skinny_device::registered, s, skinny_device::session, register_message::type, skinny_device::type, version_id, and skinny_device::version_id.

Referenced by handle_register_message().

01422 {
01423    struct skinny_device *d;
01424    struct sockaddr_in sin;
01425    socklen_t slen;
01426 
01427    ast_mutex_lock(&devicelock);
01428    for (d = devices; d; d = d->next) {
01429       if (!strcasecmp(req->data.reg.name, d->id)
01430             && ast_apply_ha(d->ha, &(s->sin))) {
01431          s->device = d;
01432          d->type = letohl(req->data.reg.type);
01433          if (ast_strlen_zero(d->version_id)) {
01434             ast_copy_string(d->version_id, version_id, sizeof(d->version_id));
01435          }
01436          d->registered = 1;
01437          d->session = s;
01438 
01439          slen = sizeof(sin);
01440          if (getsockname(s->fd, (struct sockaddr *)&sin, &slen)) {
01441             ast_log(LOG_WARNING, "Cannot get socket name\n");
01442             sin.sin_addr = __ourip;
01443          }
01444          d->ourip = sin.sin_addr;
01445          break;
01446       }
01447    }
01448    ast_mutex_unlock(&devicelock);
01449    if (!d) {
01450       return 0;
01451    }
01452    return 1;
01453 }

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

Definition at line 4547 of file chan_skinny.c.

References ast_calloc, ast_log(), ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, skinny_req::e, free, letohl, LOG_ERROR, s, skinny_header_size, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

04548 {
04549    struct skinny_req *req;
04550    int *bufaddr;
04551 
04552    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
04553       return NULL;
04554 
04555    ast_mutex_lock(&s->lock);
04556    memcpy(req, s->inbuf, skinny_header_size);
04557    bufaddr = (int *)(s->inbuf);
04558    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
04559 
04560    ast_mutex_unlock(&s->lock);
04561 
04562    if (letohl(req->e) < 0) {
04563       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
04564       free(req);
04565       return NULL;
04566    }
04567 
04568    return req;
04569 }

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

Definition at line 4727 of file chan_skinny.c.

References ast_copy_string(), AST_FORMAT_MAX_AUDIO, ast_log(), AST_STATE_DOWN, ast_strlen_zero(), ast_verbose(), find_line_by_name(), LOG_NOTICE, LOG_WARNING, option_verbose, restart_monitor(), skinny_new(), and VERBOSE_PREFIX_3.

04728 {
04729    int oldformat;
04730    
04731    struct skinny_line *l;
04732    struct ast_channel *tmpc = NULL;
04733    char tmp[256];
04734    char *dest = data;
04735 
04736    oldformat = format;
04737    
04738    if (!(format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1))) {
04739       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
04740       return NULL;   
04741    }     
04742 
04743    ast_copy_string(tmp, dest, sizeof(tmp));
04744    if (ast_strlen_zero(tmp)) {
04745       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
04746       return NULL;
04747    }
04748    l = find_line_by_name(tmp);
04749    if (!l) {
04750       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
04751       return NULL;
04752    }
04753    if (option_verbose > 2) {
04754       ast_verbose(VERBOSE_PREFIX_3 "skinny_request(%s)\n", tmp);
04755    }
04756    tmpc = skinny_new(l, AST_STATE_DOWN);
04757    if (!tmpc) {
04758       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
04759    }
04760    restart_monitor();
04761    return tmpc;
04762 }

static int skinny_reset_device ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 1907 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), skinny_req::data, devicelock, devices, skinny_device::id, skinny_device::next, option_verbose, req_alloc(), skinny_data::reset, RESET_MESSAGE, reset_message::resetType, RESULT_SHOWUSAGE, RESULT_SUCCESS, skinny_device::session, transmit_response(), and VERBOSE_PREFIX_3.

01908 {
01909    struct skinny_device *d;
01910    struct skinny_req *req;
01911 
01912    if (argc < 3 || argc > 4) {
01913       return RESULT_SHOWUSAGE;
01914    }
01915    ast_mutex_lock(&devicelock);
01916 
01917    for (d = devices; d; d = d->next) {
01918       int fullrestart = 0;
01919       if (!strcasecmp(argv[2], d->id) || !strcasecmp(argv[2], "all")) {
01920          if (!(d->session))
01921             continue;
01922 
01923          if (!(req = req_alloc(sizeof(struct reset_message), RESET_MESSAGE)))
01924             continue;
01925 
01926          if (argc == 4 && !strcasecmp(argv[3], "restart"))
01927             fullrestart = 1;
01928 
01929          if (fullrestart)
01930             req->data.reset.resetType = 2;
01931          else
01932             req->data.reset.resetType = 1;
01933 
01934          if (option_verbose > 2)
01935             ast_verbose(VERBOSE_PREFIX_3 "%s device %s.\n", (fullrestart) ? "Restarting" : "Resetting", d->id);
01936          transmit_response(d->session, req);
01937       }
01938    }
01939    ast_mutex_unlock(&devicelock);
01940    return RESULT_SUCCESS;
01941 }

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

Definition at line 2625 of file chan_skinny.c.

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

Referenced by skinny_read().

02626 {
02627    struct ast_channel *ast = sub->owner;
02628    struct ast_frame *f;
02629 
02630    if (!sub->rtp) {
02631       /* We have no RTP allocated for this channel */
02632       return &ast_null_frame;
02633    }
02634 
02635    switch(ast->fdno) {
02636    case 0:
02637       f = ast_rtp_read(sub->rtp);   /* RTP Audio */
02638       break;
02639    case 1:
02640       f = ast_rtcp_read(sub->rtp);  /* RTCP Control Channel */
02641       break;
02642    case 2:
02643       f = ast_rtp_read(sub->vrtp);  /* RTP Video */
02644       break;
02645    case 3:
02646       f = ast_rtcp_read(sub->vrtp); /* RTCP Control Channel for video */
02647       break;
02648 #if 0
02649    case 5:
02650       /* Not yet supported */
02651       f = ast_udptl_read(sub->udptl);  /* UDPTL for T.38 */
02652       break;
02653 #endif
02654    default:
02655       f = &ast_null_frame;
02656    }
02657 
02658    if (ast) {
02659       /* We already hold the channel lock */
02660       if (f->frametype == AST_FRAME_VOICE) {
02661          if (f->subclass != ast->nativeformats) {
02662             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
02663             ast->nativeformats = f->subclass;
02664             ast_set_read_format(ast, ast->readformat);
02665             ast_set_write_format(ast, ast->writeformat);
02666          }
02667       }
02668    }
02669    return f;
02670 }

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

Definition at line 2722 of file chan_skinny.c.

02723 {
02724    return -1; /* Start inband indications */
02725 }

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

Definition at line 2727 of file chan_skinny.c.

References skinny_subchannel::callid, skinny_line::instance, skinny_line::parent, skinny_subchannel::parent, skinny_device::session, skinny_line::sub, ast_channel::tech_pvt, and transmit_tone().

02728 {
02729 #if 0
02730    struct skinny_subchannel *sub = ast->tech_pvt;
02731    struct skinny_line *l = sub->parent;
02732    struct skinny_device *d = l->parent;
02733    int tmp;
02734    /* not right */
02735    sprintf(tmp, "%d", digit);
02736    transmit_tone(d->session, digit, l->instance, sub->callid);
02737 #endif
02738    return -1; /* Stop inband indications */
02739 }

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

Definition at line 4571 of file chan_skinny.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), destroy_session(), errno, get_input(), handle_message(), LOG_NOTICE, option_verbose, skinny_req::res, s, skinny_req_parse(), and VERBOSE_PREFIX_3.

Referenced by accept_thread().

04572 {
04573    int res;
04574    struct skinny_req *req;
04575    struct skinnysession *s = data;
04576 
04577    if (option_verbose > 2)
04578       ast_verbose(VERBOSE_PREFIX_3 "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
04579 
04580    for (;;) {
04581       res = get_input(s);
04582       if (res < 0) {
04583          break;
04584       }
04585 
04586       if (res > 0)
04587       {
04588          if (!(req = skinny_req_parse(s))) {
04589             destroy_session(s);
04590             return NULL;
04591          }
04592 
04593          res = handle_message(req, s);
04594          if (res < 0) {
04595             destroy_session(s);
04596             return NULL;
04597          }
04598       }
04599    }
04600    ast_log(LOG_NOTICE, "Skinny Session returned: %s\n", strerror(errno));
04601 
04602    if (s) 
04603       destroy_session(s);
04604    
04605    return 0;
04606 }

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

Definition at line 1851 of file chan_skinny.c.

References ast_channel::tech_pvt.

01852 {
01853    struct skinny_subchannel *sub;
01854    sub = c->tech_pvt;
01855    if (sub) {
01856       /* transmit_modify_with_sdp(sub, rtp); @@FIXME@@ if needed */
01857       return 0;
01858    }
01859    return -1;
01860 }

static int skinny_show_devices ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2032 of file chan_skinny.c.

References ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), device2str(), devicelock, devices, skinny_device::id, skinny_device::lines, skinny_device::name, skinny_line::next, skinny_device::next, skinny_device::registered, RESULT_SHOWUSAGE, skinny_device::session, skinnysession::sin, and skinny_device::type.

02033 {
02034    struct skinny_device *d;
02035    struct skinny_line *l;
02036    int numlines = 0;
02037 
02038    if (argc != 3) {
02039       return RESULT_SHOWUSAGE;
02040    }
02041    ast_mutex_lock(&devicelock);
02042 
02043    ast_cli(fd, "Name                 DeviceId         IP              Type            R NL\n");
02044    ast_cli(fd, "-------------------- ---------------- --------------- --------------- - --\n");
02045    for (d = devices; d; d = d->next) {
02046       numlines = 0;
02047       for (l = d->lines; l; l = l->next) {
02048          numlines++;
02049       }
02050 
02051       ast_cli(fd, "%-20s %-16s %-15s %-15s %c %2d\n",
02052             d->name,
02053             d->id,
02054             d->session?ast_inet_ntoa(d->session->sin.sin_addr):"",
02055             device2str(d->type),
02056             d->registered?'Y':'N',
02057             numlines);
02058    }
02059    ast_mutex_unlock(&devicelock);
02060    return RESULT_SUCCESS;
02061 }

static int skinny_show_lines ( int  fd,
int  argc,
char *  argv[] 
) [static]

Definition at line 2063 of file chan_skinny.c.

References ast_cli(), ast_mutex_lock(), devicelock, devices, skinny_line::instance, skinny_line::label, skinny_device::lines, skinny_line::name, skinny_device::name, skinny_line::next, skinny_device::next, and RESULT_SHOWUSAGE.

02064 {
02065    struct skinny_device *d;
02066    struct skinny_line *l;
02067 
02068    if (argc != 3) {
02069       return RESULT_SHOWUSAGE;
02070    }
02071    ast_mutex_lock(&devicelock);
02072 
02073    ast_cli(fd, "Device Name          Instance Name                 Label               \n");
02074    ast_cli(fd, "-------------------- -------- -------------------- --------------------\n");
02075    for (d = devices; d; d = d->next) {
02076       for (l = d->lines; l; l = l->next) {
02077          ast_cli(fd, "%-20s %8d %-20s %-20s\n",
02078             d->name,
02079             l->instance,
02080             l->name,
02081             l->label);
02082       }
02083    }
02084 
02085    ast_mutex_unlock(&devicelock);
02086    return RESULT_SUCCESS;
02087 }

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

Definition at line 2395 of file chan_skinny.c.

References ast_channel::_state, ast_canmatch_extension(), ast_copy_string(), 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_verbose(), skinny_line::call_forward, skinny_subchannel::callid, ast_channel::cid, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, ast_channel::exten, skinny_device::exten, firstdigittimeout, gendigittimeout, skinny_line::instance, skinny_line::lastnumberdialed, len(), LOG_DEBUG, LOG_WARNING, matchdigittimeout, ast_channel::name, skinny_device::name, skinny_line::name, option_verbose, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, s, skinny_device::session, SKINNY_DIALTONE, skinny_newcall(), SKINNY_REORDER, SKINNY_SILENCE, skinny_line::sub, ast_channel::tech_pvt, transmit_tone(), and VERBOSE_PREFIX_3.

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

02396 {
02397    struct ast_channel *c = data;
02398    struct skinny_subchannel *sub = c->tech_pvt;
02399    struct skinny_line *l = sub->parent;
02400    struct skinny_device *d = l->parent;
02401    struct skinnysession *s = d->session;
02402    int len = 0;
02403    int timeout = firstdigittimeout;
02404    int res = 0;
02405    int getforward=0;
02406    int loop_pause = 100;
02407 
02408    if (option_verbose > 2)
02409       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, d->name);
02410    len = strlen(d->exten);
02411 
02412    while (len < AST_MAX_EXTENSION-1) {
02413 
02414       res = 1;  /* Assume we will get a digit */
02415       while (strlen(d->exten) == len) {
02416          ast_safe_sleep(c, loop_pause);
02417          timeout -= loop_pause;
02418          if (timeout <= 0){
02419             res = 0;
02420             break;
02421          }
02422       }
02423 
02424       len = strlen(d->exten);
02425 
02426       if (!ast_ignore_pattern(c->context, d->exten)) {
02427          transmit_tone(s, SKINNY_SILENCE, l->instance, sub->callid);
02428       }
02429 
02430       if (ast_exists_extension(c, c->context, d->exten, 1, l->cid_num)) {
02431          if (!res || !ast_matchmore_extension(c, c->context, d->exten, 1, l->cid_num)) {
02432             if (getforward) {
02433                /* Record this as the forwarding extension */
02434                ast_copy_string(l->call_forward, d->exten, sizeof(l->call_forward));
02435                if (option_verbose > 2)
02436                   ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
02437                      l->call_forward, c->name);
02438                transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
02439                if (res) {
02440                   break;
02441                }
02442                ast_safe_sleep(c, 500);
02443                ast_indicate(c, -1);
02444                ast_safe_sleep(c, 1000);
02445                memset(d->exten, 0, sizeof(d->exten));
02446                transmit_tone(s, SKINNY_DIALTONE, l->instance, sub->callid);
02447                len = 0;
02448                getforward = 0;
02449             } else {
02450                ast_copy_string(c->exten, d->exten, sizeof(c->exten));
02451                ast_copy_string(l->lastnumberdialed, d->exten, sizeof(l->lastnumberdialed));
02452                memset (d->exten, 0, sizeof(d->exten));
02453                skinny_newcall(c);
02454                return NULL;
02455             }
02456          } else {
02457             /* It's a match, but they just typed a digit, and there is an ambiguous match,
02458                so just set the timeout to matchdigittimeout and wait some more */
02459             timeout = matchdigittimeout;
02460          }
02461       } else if (res == 0) {
02462          ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
02463          memset(d->exten, 0, sizeof(d->exten));
02464          transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
02465          if (sub->owner && sub->owner->_state != AST_STATE_UP) {
02466             ast_indicate(c, -1);
02467             ast_hangup(c);
02468          }
02469          return NULL;
02470       } else if (!ast_canmatch_extension(c, c->context, d->exten, 1, c->cid.cid_num) &&
02471             ((d->exten[0] != '*') || (!ast_strlen_zero(d->exten) > 2))) {
02472          ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", d->exten, c->cid.cid_num ? c->cid.cid_num : "<Unknown Caller>", c->context);
02473          memset(d->exten, 0, sizeof(d->exten));
02474          transmit_tone(s, SKINNY_REORDER, l->instance, sub->callid);
02475          /* hang out for 3 seconds to let congestion play */
02476          ast_safe_sleep(c, 3000);
02477          break;
02478       }
02479       if (!timeout) {
02480          timeout = gendigittimeout;
02481       }
02482       if (len && !ast_ignore_pattern(c->context, d->exten)) {
02483          ast_indicate(c, -1);
02484       }
02485    }
02486    if (c)
02487       ast_hangup(c);
02488 
02489    memset(d->exten, 0, sizeof(d->exten));
02490    return NULL;
02491 }

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

Definition at line 3017 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_data::activatecallplane, AST_CONTROL_UNHOLD, ast_queue_control(), ast_verbose(), skinny_req::data, htolel, skinny_line::instance, activate_call_plane_message::lineInstance, skinny_subchannel::onhold, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, req_alloc(), s, skinny_device::session, SKINNY_LAMP_ON, skinnydebug, STIMULUS_LINE, skinny_line::sub, transmit_connect(), transmit_lamp_indication(), and transmit_response().

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

03018 {
03019    struct skinny_line *l = sub->parent;
03020    struct skinny_device *d = l->parent;
03021    struct skinnysession *s = d->session;
03022    struct skinny_req *req;
03023 
03024    /* Don't try to unhold a channel that doesn't exist */
03025    if (!sub || !sub->owner)
03026       return 0;
03027 
03028    /* Channel is on hold, so we will unhold */
03029    if (skinnydebug)
03030       ast_verbose("Taking off Hold(%d)\n", l->instance);
03031 
03032    ast_queue_control(sub->owner, AST_CONTROL_UNHOLD);
03033 
03034    if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
03035       return 0;
03036 
03037    req->data.activatecallplane.lineInstance = htolel(l->instance);
03038    transmit_response(s, req);
03039 
03040    transmit_connect(s, sub);
03041    transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_ON);
03042    sub->onhold = 0;
03043    return 1;
03044 }

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

Definition at line 1455 of file chan_skinny.c.

References skinny_device::registered, s, and skinny_device::session.

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

01456 {
01457    struct skinny_device *d;
01458 
01459    d = s->device;
01460 
01461    if (d) {
01462       d->session = NULL;
01463       d->registered = 0;
01464    }
01465 
01466    return -1; /* main loop will destroy the session */
01467 }

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

Definition at line 2682 of file chan_skinny.c.

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

02683 {
02684    struct skinny_subchannel *sub = ast->tech_pvt;
02685    int res = 0;
02686    if (frame->frametype != AST_FRAME_VOICE) {
02687       if (frame->frametype == AST_FRAME_IMAGE) {
02688          return 0;
02689       } else {
02690          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
02691          return 0;
02692       }
02693    } else {
02694       if (!(frame->subclass & ast->nativeformats)) {
02695          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
02696             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
02697          return -1;
02698       }
02699    }
02700    if (sub) {
02701       ast_mutex_lock(&sub->lock);
02702       if (sub->rtp) {
02703          res = ast_rtp_write(sub->rtp, frame);
02704       }
02705       ast_mutex_unlock(&sub->lock);
02706    }
02707    return res;
02708 }

static void start_rtp ( struct skinny_subchannel sub  )  [static]

Definition at line 2334 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtcp_fd(), ast_rtp_codec_setpref(), ast_rtp_fd(), ast_rtp_new_with_bindaddr(), ast_rtp_setnat(), bindaddr, ast_channel::fds, io, skinny_subchannel::lock, skinny_line::nat, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_line::prefs, skinny_subchannel::rtp, skinny_device::session, skinny_line::sub, transmit_connect(), and skinny_subchannel::vrtp.

02335 {
02336    struct skinny_line *l = sub->parent;
02337    struct skinny_device *d = l->parent;
02338    int hasvideo = 0;
02339 
02340    ast_mutex_lock(&sub->lock);
02341    /* Allocate the RTP */
02342    sub->rtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02343    if (hasvideo)
02344       sub->vrtp = ast_rtp_new_with_bindaddr(sched, io, 1, 0, bindaddr.sin_addr);
02345    
02346    if (sub->rtp && sub->owner) {
02347       sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
02348       sub->owner->fds[1] = ast_rtcp_fd(sub->rtp);
02349    }
02350    if (hasvideo && sub->vrtp && sub->owner) {
02351       sub->owner->fds[2] = ast_rtp_fd(sub->vrtp);
02352       sub->owner->fds[3] = ast_rtcp_fd(sub->vrtp);
02353    }
02354    if (sub->rtp) {
02355       ast_rtp_setnat(sub->rtp, l->nat);
02356    }
02357    if (sub->vrtp) {
02358       ast_rtp_setnat(sub->vrtp, l->nat);
02359    }
02360    /* Set Frame packetization */
02361    if (sub->rtp)
02362       ast_rtp_codec_setpref(sub->rtp, &l->prefs);
02363 
02364    /* Create the RTP connection */
02365    transmit_connect(d->session, sub);
02366    ast_mutex_unlock(&sub->lock);
02367 }

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

Definition at line 1532 of file chan_skinny.c.

References ast_copy_string(), ast_verbose(), 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(), s, skinnydebug, transmit_response(), and call_info_message::type.

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

01533 {
01534    struct skinny_req *req;
01535 
01536    if (!(req = req_alloc(sizeof(struct call_info_message), CALL_INFO_MESSAGE)))
01537       return;
01538 
01539    if (skinnydebug)
01540          ast_verbose("Setting Callinfo to %s(%s) from %s(%s) on %s(%d)\n", fromname, fromnum, toname, tonum, s->device->name, instance);
01541 
01542    if (fromname) {
01543       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
01544    }
01545    if (fromnum) {
01546       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
01547    }
01548    if (toname) {
01549       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
01550    }
01551    if (tonum) {
01552       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
01553    }
01554    req->data.callinfo.instance = htolel(instance);
01555    req->data.callinfo.reference = htolel(callid);
01556    req->data.callinfo.type = htolel(calltype);
01557    transmit_response(s, req);
01558 }

static void transmit_callstate ( struct skinnysession s,
int  instance,
int  state,
unsigned  callid 
) [static]

Definition at line 1744 of file chan_skinny.c.

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

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

01745 {
01746    struct skinny_req *req;
01747 
01748    if (state == SKINNY_ONHOOK) {
01749       if (!(req = req_alloc(sizeof(struct close_receive_channel_message), CLOSE_RECEIVE_CHANNEL_MESSAGE)))
01750          return;
01751 
01752       req->data.closereceivechannel.conferenceId = htolel(callid);
01753       req->data.closereceivechannel.partyId = htolel(callid);
01754       transmit_response(s, req);
01755 
01756       if (!(req = req_alloc(sizeof(struct stop_media_transmission_message), STOP_MEDIA_TRANSMISSION_MESSAGE)))
01757          return;
01758 
01759       req->data.stopmedia.conferenceId = htolel(callid);
01760       req->data.stopmedia.passThruPartyId = htolel(callid);
01761       transmit_response(s, req);
01762 
01763       transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
01764 
01765       transmit_displaypromptstatus(s, NULL, 0, instance, callid);
01766    }
01767 
01768    if (!(req = req_alloc(sizeof(struct call_state_message), CALL_STATE_MESSAGE)))
01769       return;
01770 
01771    req->data.callstate.callState = htolel(state);
01772    req->data.callstate.lineInstance = htolel(instance);
01773    req->data.callstate.callReference = htolel(callid);
01774    transmit_response(s, req);
01775 
01776    if (state == SKINNY_ONHOOK) {
01777       transmit_selectsoftkeys(s, 0, 0, KEYDEF_ONHOOK);
01778    }
01779 
01780    if (state == SKINNY_OFFHOOK || state == SKINNY_ONHOOK) {
01781       if (!(req = req_alloc(sizeof(struct activate_call_plane_message), ACTIVATE_CALL_PLANE_MESSAGE)))
01782          return;
01783 
01784       req->data.activatecallplane.lineInstance = htolel(instance);
01785       transmit_response(s, req);
01786    }
01787 }

static void transmit_connect ( struct skinnysession s,
struct skinny_subchannel sub 
) [static]

Definition at line 1560 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, skinny_line::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, skinny_subchannel::parent, open_receive_channel_message::partyId, skinny_line::prefs, req_alloc(), s, skinny_line::sub, and transmit_response().

Referenced by skinny_unhold(), and start_rtp().

01561 {
01562    struct skinny_req *req;
01563    struct skinny_line *l = sub->parent;
01564    struct ast_format_list fmt;
01565 
01566    if (!(req = req_alloc(sizeof(struct open_receive_channel_message), OPEN_RECEIVE_CHANNEL_MESSAGE)))
01567       return;
01568 
01569    fmt = ast_codec_pref_getsize(&l->prefs, ast_best_codec(l->capability));
01570 
01571    req->data.openreceivechannel.conferenceId = htolel(sub->callid);
01572    req->data.openreceivechannel.partyId = htolel(sub->callid);
01573    req->data.openreceivechannel.packets = htolel(fmt.cur_ms);
01574    req->data.openreceivechannel.capability = htolel(codec_ast2skinny(fmt.bits));
01575    req->data.openreceivechannel.echo = htolel(0);
01576    req->data.openreceivechannel.bitrate = htolel(0);
01577    transmit_response(s, req);
01578 }

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

Definition at line 1730 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(), s, and transmit_response().

Referenced by skinny_answer(), and skinny_indicate().

01731 {
01732    struct skinny_req *req;
01733 
01734    if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
01735       return;
01736 
01737    ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
01738    req->data.dialednumber.lineInstance = htolel(instance);
01739    req->data.dialednumber.callReference = htolel(callid);
01740 
01741    transmit_response(s, req);
01742 }

static void transmit_displaymessage ( struct skinnysession s,
const char *  text,
int  instance,
int  reference 
) [static]

Definition at line 1660 of file chan_skinny.c.

References ast_copy_string(), ast_verbose(), clear_prompt_message::callReference, CLEAR_DISPLAY_MESSAGE, skinny_data::clearpromptstatus, skinny_req::data, skinny_data::displaytext, DISPLAYTEXT_MESSAGE, clear_prompt_message::lineInstance, req_alloc(), s, skinnydebug, displaytext_message::text, and transmit_response().

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

01661 {
01662    struct skinny_req *req;
01663 
01664    if (text == 0) {
01665       if (!(req = req_alloc(0, CLEAR_DISPLAY_MESSAGE)))
01666          return;
01667 
01668       req->data.clearpromptstatus.lineInstance = instance;
01669       req->data.clearpromptstatus.callReference = reference;
01670 
01671       if (skinnydebug)
01672          ast_verbose("Clearing Display\n");
01673    } else {
01674       if (!(req = req_alloc(sizeof(struct displaytext_message), DISPLAYTEXT_MESSAGE)))
01675          return;
01676 
01677       ast_copy_string(req->data.displaytext.text, text, sizeof(req->data.displaytext.text));
01678       if (skinnydebug)
01679          ast_verbose("Displaying message '%s'\n", req->data.displaytext.text);
01680    }
01681 
01682    transmit_response(s, req);
01683 }

static void transmit_displaynotify ( struct skinnysession s,
const char *  text,
int  t 
) [static]

Definition at line 1685 of file chan_skinny.c.

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

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

01686 {
01687    struct skinny_req *req;
01688 
01689    if (!(req = req_alloc(sizeof(struct display_notify_message), DISPLAY_NOTIFY_MESSAGE)))
01690       return;
01691 
01692    ast_copy_string(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage));
01693    req->data.displaynotify.displayTimeout = htolel(t);
01694 
01695    if (skinnydebug)
01696       ast_verbose("Displaying notify '%s'\n", text);
01697 
01698    transmit_response(s, req);
01699 }

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

Definition at line 1701 of file chan_skinny.c.

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

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

01702 {
01703    struct skinny_req *req;
01704 
01705    if (text == 0) {
01706       if (!(req = req_alloc(sizeof(struct clear_prompt_message), CLEAR_PROMPT_MESSAGE)))
01707          return;
01708 
01709       req->data.clearpromptstatus.lineInstance = htolel(instance);
01710       req->data.clearpromptstatus.callReference = htolel(callid);
01711 
01712       if (skinnydebug)
01713          ast_verbose("Clearing Prompt\n");
01714    } else {
01715       if (!(req = req_alloc(sizeof(struct display_prompt_status_message), DISPLAY_PROMPT_STATUS_MESSAGE)))
01716          return;
01717 
01718       ast_copy_string(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage));
01719       req->data.displaypromptstatus.messageTimeout = htolel(t);
01720       req->data.displaypromptstatus.lineInstance = htolel(instance);
01721       req->data.displaypromptstatus.callReference = htolel(callid);
01722 
01723       if (skinnydebug)
01724          ast_verbose("Displaying Prompt Status '%s'\n", text);
01725    }
01726 
01727    transmit_response(s, req);
01728 }

static void transmit_lamp_indication ( struct skinnysession s,
int  stimulus,
int  instance,
int  indication 
) [static]

Definition at line 1622 of file chan_skinny.c.

References skinny_req::data, set_lamp_message::deviceStimulus, htolel, req_alloc(), s, 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(), skinny_call(), skinny_hangup(), skinny_hold(), and skinny_unhold().

01623 {
01624    struct skinny_req *req;
01625 
01626    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
01627       return;
01628 
01629    req->data.setlamp.stimulus = htolel(stimulus);
01630    req->data.setlamp.stimulusInstance = htolel(instance);
01631    req->data.setlamp.deviceStimulus = htolel(indication);
01632    transmit_response(s, req);
01633 }

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

Definition at line 1469 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), skinny_req::data, skinny_req::e, errno, skinny_req::len, letohl, LOG_VERBOSE, LOG_WARNING, s, skinny_header_size, SKINNY_MAX_PACKET, skinny_unregister(), and skinnydebug.

01470 {
01471    int res = 0;
01472 
01473    if (!s) {
01474       ast_log(LOG_WARNING, "Asked to transmit to a non-existant session!\n");
01475       return -1;
01476    }
01477 
01478    ast_mutex_lock(&s->lock);
01479 
01480    if (skinnydebug)
01481       ast_log(LOG_VERBOSE, "writing packet type %04X (%d bytes) to socket %d\n", letohl(req->e), letohl(req->len)+8, s->fd);
01482 
01483    if (letohl(req->len > SKINNY_MAX_PACKET) || letohl(req->len < 0)) {
01484       ast_log(LOG_WARNING, "transmit_response: the length of the request is out of bounds\n");
01485       ast_mutex_unlock(&s->lock);
01486       return -1;
01487    }
01488 
01489    memset(s->outbuf,0,sizeof(s->outbuf));
01490    memcpy(s->outbuf, req, skinny_header_size);
01491    memcpy(s->outbuf+skinny_header_size, &req->data, letohl(req->len));
01492 
01493    res = write(s->fd, s->outbuf, letohl(req->len)+8);
01494 
01495    if (res != letohl(req->len)+8) {
01496       ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
01497       if (res == -1) {
01498          if (skinnydebug)
01499             ast_log(LOG_WARNING, "Transmit: Skinny Client was lost, unregistering\n");
01500          skinny_unregister(NULL, s);
01501       }
01502       
01503    }
01504    
01505    ast_mutex_unlock(&s->lock);
01506    return 1;
01507 }

static void transmit_ringer_mode ( struct skinnysession s,
int  mode 
) [static]

Definition at line 1635 of file chan_skinny.c.

References ast_verbose(), skinny_req::data, htolel, req_alloc(), set_ringer_message::ringerMode, s, SET_RINGER_MESSAGE, skinny_data::setringer, skinnydebug, 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().

01636 {
01637    struct skinny_req *req;
01638 
01639    if (skinnydebug)
01640       ast_verbose("Setting ringer mode to '%d'.\n", mode);
01641 
01642    if (!(req = req_alloc(sizeof(struct set_ringer_message), SET_RINGER_MESSAGE)))
01643       return;
01644 
01645    req->data.setringer.ringerMode = htolel(mode);
01646    /* XXX okay, I don't quite know what this is, but here's what happens (on a 7960).
01647       Note: The phone will always show as ringing on the display.
01648 
01649       1: phone will audibly ring over and over
01650       2: phone will audibly ring only once
01651       any other value, will NOT cause the phone to audibly ring
01652    */
01653    req->data.setringer.unknown1 = htolel(1);
01654    /* XXX the value here doesn't seem to change anything.  Must be higher than 0.
01655       Perhaps a packet capture can shed some light on this. */
01656    req->data.setringer.unknown2 = htolel(1);
01657    transmit_response(s, req);
01658 }

static void transmit_selectsoftkeys ( struct skinnysession s,
int  instance,
int  callid,
int  softkey 
) [static]

Definition at line 1608 of file chan_skinny.c.

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

Referenced by handle_offhook_message(), handle_soft_key_event_message(), handle_soft_key_set_req_message(), handle_stimulus_message(), skinny_answer(), skinny_call(), and transmit_callstate().

01609 {
01610    struct skinny_req *req;
01611 
01612    if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
01613       return;
01614 
01615    req->data.selectsoftkey.instance = htolel(instance);
01616    req->data.selectsoftkey.reference = htolel(callid);
01617    req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
01618    req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
01619    transmit_response(s, req);
01620 }

static void transmit_speaker_mode ( struct skinnysession s,
int  mode 
) [static]

Definition at line 1509 of file chan_skinny.c.

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

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

01510 {
01511    struct skinny_req *req;
01512 
01513    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
01514       return;
01515 
01516    req->data.setspeaker.mode = htolel(mode);
01517    transmit_response(s, req);
01518 }

static void transmit_tone ( struct skinnysession s,
int  tone,
int  instance,
int  reference 
) [static]

Definition at line 1580 of file chan_skinny.c.

References skinny_req::data, htolel, stop_tone_message::instance, start_tone_message::instance, stop_tone_message::reference, start_tone_message::reference, req_alloc(), s, SKINNY_NOTONE, START_TONE_MESSAGE, skinny_data::starttone, STOP_TONE_MESSAGE, skinny_data::stoptone, start_tone_message::tone, 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(), skinny_newcall(), skinny_senddigit_end(), and skinny_ss().

01581 {
01582    struct skinny_req *req;
01583 
01584    if (tone == SKINNY_NOTONE) {
01585       /* This is bad, mmm'kay? */
01586       return;
01587    }
01588 
01589    if (tone > 0) {
01590       if (!(req = req_alloc(sizeof(struct start_tone_message), START_TONE_MESSAGE)))
01591          return;
01592       req->data.starttone.tone = htolel(tone);
01593       req->data.starttone.instance = htolel(instance);
01594       req->data.starttone.reference = htolel(reference);
01595    } else {
01596       if (!(req = req_alloc(sizeof(struct stop_tone_message), STOP_TONE_MESSAGE)))
01597          return;
01598       req->data.stoptone.instance = htolel(instance);
01599       req->data.stoptone.reference = htolel(reference);
01600    }
01601 
01602    if (tone > 0) {
01603       req->data.starttone.tone = htolel(tone);
01604    }
01605    transmit_response(s, req);
01606 }

static int unload_module ( void   )  [static]

Definition at line 5021 of file chan_skinny.c.

References accept_t, skinny_subchannel::alreadygone, ast_channel_unregister(), ast_cli_unregister_multiple(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_NULL, AST_PTHREADT_STOP, ast_rtp_proto_unregister(), ast_softhangup(), AST_SOFTHANGUP_APPUNLOAD, cli_skinny, delete_devices(), skinnysession::device, skinnysession::fd, free, skinny_device::lines, skinnysession::lock, skinny_subchannel::lock, skinny_line::lock, monitor_thread, monlock, netlock, skinny_subchannel::next, skinny_line::next, skinny_device::next, skinny_subchannel::owner, s, sched_context_destroy(), sessionlock, skinny_rtp, skinny_tech, skinnysock, and skinny_line::sub.

05022 {
05023    struct skinnysession *s, *slast;
05024    struct skinny_device *d;
05025    struct skinny_line *l;
05026    struct skinny_subchannel *sub;
05027 
05028    ast_mutex_lock(&sessionlock);
05029    /* Destroy all the interfaces and free their memory */
05030    s = sessions;
05031    while(s) {
05032       slast = s;
05033       s = s->next;
05034       for (d = slast->device; d; d = d->next) {
05035          for (l = d->lines; l; l = l->next) {
05036             ast_mutex_lock(&l->lock);
05037             for (sub = l->sub; sub; sub = sub->next) {
05038                ast_mutex_lock(&sub->lock);
05039                if (sub->owner) {
05040                   sub->alreadygone = 1;
05041                   ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
05042                }
05043                ast_mutex_unlock(&sub->lock);
05044             }
05045             ast_mutex_unlock(&l->lock);
05046          }
05047       }
05048       if (slast->fd > -1)
05049          close(slast->fd);
05050       ast_mutex_destroy(&slast->lock);
05051       free(slast);
05052    }
05053    sessions = NULL;
05054    ast_mutex_unlock(&sessionlock);
05055 
05056    delete_devices();
05057 
05058    ast_mutex_lock(&monlock);
05059    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
05060       pthread_cancel(monitor_thread);
05061       pthread_kill(monitor_thread, SIGURG);
05062       pthread_join(monitor_thread, NULL);
05063    }
05064    monitor_thread = AST_PTHREADT_STOP;
05065    ast_mutex_unlock(&monlock);
05066 
05067    ast_mutex_lock(&netlock);
05068    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
05069       pthread_cancel(accept_t);
05070       pthread_kill(accept_t, SIGURG);
05071       pthread_join(accept_t, NULL);
05072    }
05073    accept_t = AST_PTHREADT_STOP;
05074    ast_mutex_unlock(&netlock);
05075 
05076    ast_rtp_proto_unregister(&skinny_rtp);
05077    ast_channel_unregister(&skinny_tech);
05078    ast_cli_unregister_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
05079 
05080    close(skinnysock);
05081    if (sched)
05082       sched_context_destroy(sched);
05083 
05084    return 0;
05085 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "361d7bb937402d51e4658efb5b4d76e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 5090 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 790 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 794 of file chan_skinny.c.

Referenced by reload_config(), and unload_module().

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 814 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 791 of file chan_skinny.c.

Referenced by __ast_http_load(), __set_address_from_contact(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_sip_ouraddrfor(), check_via(), create_addr(), dnsmgr_refresh(), festival_exec(), gtalk_load_config(), gtalk_update_stun(), launch_netscript(), parse_register_contact(), process_sdp(), process_via(), realtime_peer(), realtime_user(), reload_config(), rtcp_do_debug_ip(), rtcp_do_debug_ip_deprecated(), rtp_do_debug_ip(), set_destination(), sip_devicestate(), sip_do_debug_ip(), and udptl_do_debug_ip().

int amaflags = 0 [static]

Definition at line 816 of file chan_skinny.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 5090 of file chan_skinny.c.

int auth_limit = DEFAULT_AUTH_LIMIT [static]

Definition at line 104 of file chan_skinny.c.

Referenced by accept_thread(), and reload_config().

int auth_timeout = DEFAULT_AUTH_TIMEOUT [static]

Definition at line 103 of file chan_skinny.c.

Referenced by get_input(), and reload_config().

struct sockaddr_in bindaddr [static]

Definition at line 787 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 817 of file chan_skinny.c.

Referenced by skinny_new().

int callreturn = 0 [static]

Definition at line 807 of file chan_skinny.c.

int callwaiting = 0 [static]

Definition at line 806 of file chan_skinny.c.

int cancallforward = 0 [static]

Definition at line 812 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 800 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 799 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

Definition at line 2109 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

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

Definition at line 81 of file chan_skinny.c.

char context[AST_MAX_CONTEXT] = "default" [static]

Definition at line 795 of file chan_skinny.c.

struct ast_threadstorage control2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = control2str_threadbuf_init , } [static]

Definition at line 146 of file chan_skinny.c.

Referenced by control2str().

ast_group_t cur_callergroup = 0 [static]

Definition at line 803 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 804 of file chan_skinny.c.

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

Definition at line 106 of file chan_skinny.c.

Referenced by handle_register_message(), and reload_config().

char debug_usage[] [static]

Initial value:

"Usage: skinny set debug\n"
"       Enables dumping of Skinny packets for debugging purposes\n"

Definition at line 2097 of file chan_skinny.c.

int default_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW [static]

Definition at line 83 of file chan_skinny.c.

Referenced by build_device(), reload_config(), and skinny_new().

struct ast_jb_conf default_jbconf [static]

Global jitterbuffer configuration - by default, jb is disabled

Definition at line 134 of file chan_skinny.c.

struct ast_codec_pref default_prefs [static]

Definition at line 84 of file chan_skinny.c.

struct ast_threadstorage device2str_threadbuf = { .once = PTHREAD_ONCE_INIT , .key_init = device2str_threadbuf_init , } [static]

Definition at line 143 of file chan_skinny.c.

Referenced by device2str().

ast_mutex_t devicelock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 931 of file chan_skinny.c.

Referenced by delete_devices(), find_line_by_name(), handle_line_state_req_message(), reload_config(), skinny_register(), skinny_reset_device(), skinny_show_devices(), and skinny_show_lines().

struct skinny_device * devices [static]

Referenced by complete_skinny_reset(), delete_devices(), find_line_by_name(), reload_config(), skinny_register(), skinny_reset_device(), skinny_show_devices(), and skinny_show_lines().

int firstdigittimeout = 16000 [static]

Definition at line 942 of file chan_skinny.c.

int gendigittimeout = 8000 [static]

Definition at line 945 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 141 of file chan_skinny.c.

struct hostent* hp

Definition at line 792 of file chan_skinny.c.

Referenced by __ast_http_load(), __set_address_from_contact(), ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_gethostbyname(), ast_sip_ouraddrfor(), build_peer(), check_via(), connect_sphinx(), create_addr(), dnsmgr_refresh(), get_ip_and_port_from_sdp(), gtalk_load_config(), gtalk_update_stun(), iax_template_parse(), launch_netscript(), parse_register_contact(), process_sdp(), process_sdp_c(), process_via(), realtime_peer(), realtime_user(), reload_config(), rtcp_do_debug_ip(), rtcp_do_debug_ip_deprecated(), rtp_do_debug_ip(), set_config(), set_destination(), sip_devicestate(), sip_do_debug_ip(), and udptl_do_debug_ip().

int immediate = 0 [static]

Definition at line 805 of file chan_skinny.c.

struct io_context* io [static]

Definition at line 921 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 102 of file chan_skinny.c.

Referenced by get_input(), handle_register_message(), and reload_config().

char language[MAX_LANGUAGE] = "" [static]

Definition at line 796 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = "" [static]

Definition at line 801 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 815 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 948 of file chan_skinny.c.

char mohinterpret[MAX_MUSICCLASS] = "default" [static]

Definition at line 797 of file chan_skinny.c.

char mohsuggest[MAX_MUSICCLASS] = "" [static]

Definition at line 798 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 939 of file chan_skinny.c.

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

Definition at line 925 of file chan_skinny.c.

int mwiblink = 0 [static]

Definition at line 809 of file chan_skinny.c.

Referenced by build_device().

int nat = 0 [static]

Definition at line 802 of file chan_skinny.c.

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

Definition at line 927 of file chan_skinny.c.

char no_debug_usage[] [static]

Initial value:

"Usage: skinny set debug off\n"
"       Disables dumping of Skinny packets for debugging purposes\n"

Definition at line 2101 of file chan_skinny.c.

char ourhost[256] [static]

Definition at line 788 of file chan_skinny.c.

int ourport [static]

Definition at line 789 of file chan_skinny.c.

char reset_usage[] [static]

Initial value:

"Usage: skinny reset <DeviceId|all> [restart]\n"
"       Causes a Skinny device to reset itself, optionally with a full restart\n"

Definition at line 2105 of file chan_skinny.c.

struct sched_context* sched = NULL [static]

Definition at line 920 of file chan_skinny.c.

ast_mutex_t sessionlock = ((ast_mutex_t) PTHREAD_MUTEX_INITIALIZER ) [static]

Definition at line 929 of file chan_skinny.c.

Referenced by accept_thread(), destroy_session(), and unload_module().

struct skinnysession * sessions [static]

char show_devices_usage[] [static]

Initial value:

"Usage: skinny show devices\n"
"       Lists all devices known to the Skinny subsystem.\n"

Definition at line 2089 of file chan_skinny.c.

char show_lines_usage[] [static]

Initial value:

"Usage: skinny show lines\n"
"       Lists all lines known to the Skinny subsystem.\n"

Definition at line 2093 of file chan_skinny.c.

int skinny_header_size = 12

Definition at line 778 of file chan_skinny.c.

Referenced by skinny_req_parse(), and transmit_response().

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 1862 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1089 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 784 of file chan_skinny.c.

Referenced by accept_thread(), get_input(), handle_alarm_message(), handle_capabilities_res_message(), handle_enbloc_call_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_answer(), skinny_call(), skinny_do_debug(), skinny_hangup(), skinny_hold(), skinny_indicate(), skinny_new(), skinny_no_debug(), skinny_unhold(), transmit_callinfo(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_response(), and transmit_ringer_mode().

int skinnysock = -1 [static]

Definition at line 793 of file chan_skinny.c.

Referenced by accept_thread(), reload_config(), and unload_module().

const uint8_t soft_key_default_connected[] [static]

Definition at line 576 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 620 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 606 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 615 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 638 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 598 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 629 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 585 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 567 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 592 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 624 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 634 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[]

Definition at line 540 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), handle_soft_key_template_req_message(), and load_module().

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

Definition at line 80 of file chan_skinny.c.

int threewaycalling = 0 [static]

Definition at line 808 of file chan_skinny.c.

int transfer = 0 [static]

Definition at line 811 of file chan_skinny.c.

int unauth_sessions = 0 [static]

Definition at line 105 of file chan_skinny.c.

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

Definition at line 107 of file chan_skinny.c.

Referenced by skinny_register().


Generated on Sat Aug 6 00:39:52 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7