Thu Dec 17 23:51:45 2009

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_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 = "6989f2ec67f8497e38c12890500c525b" , .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 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER }
static int mwiblink = 0
static int nat = 0
static ast_mutex_t netlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, 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 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 705 of file chan_skinny.c.

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

#define ALARM_MESSAGE   0x0020

Definition at line 227 of file chan_skinny.c.

Referenced by handle_message().

#define BT_AUTOANSWER   STIMULUS_AUTOANSWER

Definition at line 421 of file chan_skinny.c.

#define BT_CALLPARK   STIMULUS_CALLPARK

Definition at line 423 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CALLPICKUP   STIMULUS_CALLPICKUP

Definition at line 424 of file chan_skinny.c.

#define BT_CONFERENCE   STIMULUS_CONFERENCE

Definition at line 422 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_CUST_HINT   0xB1

Definition at line 431 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define BT_CUST_LINESPEEDDIAL   0xB0

Definition at line 430 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_DISPLAY   STIMULUS_DISPLAY

Definition at line 418 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDALL   STIMULUS_FORWARDALL

Definition at line 415 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_FORWARDBUSY   STIMULUS_FORWARDBUSY

Definition at line 416 of file chan_skinny.c.

#define BT_FORWARDNOANSWER   STIMULUS_FORWARDNOANSWER

Definition at line 417 of file chan_skinny.c.

#define BT_HOLD   STIMULUS_HOLD

Definition at line 413 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_LINE   STIMULUS_LINE

Definition at line 419 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_NONE   0x00

Definition at line 425 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_REDIAL   STIMULUS_REDIAL

Definition at line 411 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_SPEEDDIAL   STIMULUS_SPEEDDIAL

Definition at line 412 of file chan_skinny.c.

Referenced by get_button_template(), and handle_button_template_req_message().

#define BT_TRANSFER   STIMULUS_TRANSFER

Definition at line 414 of file chan_skinny.c.

Referenced by get_button_template().

#define BT_VOICEMAIL   STIMULUS_VOICEMAIL

Definition at line 420 of file chan_skinny.c.

Referenced by get_button_template().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E

Definition at line 223 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097

Definition at line 382 of file chan_skinny.c.

Referenced by handle_button_template_req_message().

#define CALL_INFO_MESSAGE   0x008F

Definition at line 332 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111

Definition at line 677 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B

Definition at line 453 of file chan_skinny.c.

Referenced by handle_register_message().

#define CAPABILITIES_RES_MESSAGE   0x0010

Definition at line 195 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE   0x009A

Definition at line 451 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLEAR_NOTIFY_MESSAGE   0x0115

Definition at line 450 of file chan_skinny.c.

#define CLEAR_PROMPT_MESSAGE   0x0113

Definition at line 693 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define CLOSE_RECEIVE_CHANNEL_MESSAGE   0x0106

Definition at line 489 of file chan_skinny.c.

Referenced by skinny_hold(), and transmit_callstate().

#define CONTROL2STR_BUFSIZE   100

Definition at line 142 of file chan_skinny.c.

Referenced by control2str().

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

Referenced by handle_time_date_req_message().

#define DEVICE2STR_BUFSIZE   15

Definition at line 139 of file chan_skinny.c.

Referenced by device2str().

#define DIALED_NUMBER_MESSAGE   0x011D

Definition at line 710 of file chan_skinny.c.

Referenced by transmit_dialednumber().

#define DISPLAY_NOTIFY_MESSAGE   0x0114

Definition at line 699 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112

Definition at line 685 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE   0x0099

Definition at line 445 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define ENBLOC_CALL_MESSAGE   0x0004

Definition at line 171 of file chan_skinny.c.

Referenced by handle_message().

#define HEADSET_STATUS_MESSAGE   0x002B

Definition at line 254 of file chan_skinny.c.

Referenced by handle_message().

#define htolel (  )     (x)

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

#define IP_PORT_MESSAGE   0x0002

Definition at line 161 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE   0x0100

Definition at line 476 of file chan_skinny.c.

Referenced by handle_keep_alive_message().

#define KEEP_ALIVE_MESSAGE   0x0000

Definition at line 148 of file chan_skinny.c.

Referenced by handle_message().

#define KEYDEF_CONNECTED   1

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

#define KEYDEF_CONNWITHTRANS   5

Definition at line 508 of file chan_skinny.c.

#define KEYDEF_DADFD   6

Definition at line 509 of file chan_skinny.c.

#define KEYDEF_OFFHOOK   4

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

#define KEYDEF_ONHOLD   2

Definition at line 505 of file chan_skinny.c.

#define KEYDEF_ONHOOK   0

Definition at line 503 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message(), and transmit_callstate().

#define KEYDEF_RINGIN   3

Definition at line 506 of file chan_skinny.c.

Referenced by skinny_call().

#define KEYDEF_RINGOUT   8

Definition at line 511 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define KEYDEF_UNKNOWN   10

Definition at line 513 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003

Definition at line 163 of file chan_skinny.c.

Referenced by handle_message().

#define letohl (  )     (x)

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

#define LINE_STAT_RES_MESSAGE   0x0092

Definition at line 361 of file chan_skinny.c.

Referenced by handle_line_state_req_message().

#define LINE_STATE_REQ_MESSAGE   0x000B

Definition at line 217 of file chan_skinny.c.

Referenced by handle_message().

#define OFFHOOK_MESSAGE   0x0006

Definition at line 183 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE   0x0007

Definition at line 189 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_ACK_MESSAGE   0x0022

Definition at line 235 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECEIVE_CHANNEL_MESSAGE   0x0105

Definition at line 478 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE   0x0081

Definition at line 257 of file chan_skinny.c.

Referenced by handle_register_message().

#define REGISTER_AVAILABLE_LINES_MESSAGE   0x002D

Definition at line 255 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE   0x0001

Definition at line 151 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE   0x009D

Definition at line 455 of file chan_skinny.c.

Referenced by handle_register_message().

#define RESET_MESSAGE   0x009F

Definition at line 471 of file chan_skinny.c.

Referenced by skinny_reset_device().

#define SELECT_SOFT_KEYS_MESSAGE   0x0110

Definition at line 669 of file chan_skinny.c.

Referenced by transmit_selectsoftkeys().

#define SERVER_REQUEST_MESSAGE   0x0012

Definition at line 225 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE   0x009E

Definition at line 460 of file chan_skinny.c.

Referenced by handle_server_request_message().

#define SET_LAMP_MESSAGE   0x0086

Definition at line 288 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_MICROPHONE_MESSAGE   0x0089

Definition at line 301 of file chan_skinny.c.

#define SET_RINGER_MESSAGE   0x0085

Definition at line 280 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE   0x0088

Definition at line 295 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT   0x24

Definition at line 876 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6

Definition at line 864 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23

Definition at line 875 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLWAIT   9

Definition at line 867 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D

Definition at line 878 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CONGESTION   7

Definition at line 865 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5

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

#define SKINNY_CX_CONFERENCE   3

Definition at line 900 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4

Definition at line 902 of file chan_skinny.c.

Referenced by skinny_new().

#define SKINNY_CX_MUTE   4

Definition at line 901 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1

Definition at line 897 of file chan_skinny.c.

Referenced by handle_onhook_message(), and handle_soft_key_event_message().

#define SKINNY_CX_SENDONLY   0

Definition at line 896 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2

Definition at line 898 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DEVICE_12   4

Definition at line 819 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SP   3

Definition at line 818 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_12SPPLUS   2

Definition at line 817 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30SPPLUS   1

Definition at line 816 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_30VIP   5

Definition at line 820 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7902   30008

Definition at line 846 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7905   20000

Definition at line 842 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7906   369

Definition at line 835 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7910   6

Definition at line 821 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7911   307

Definition at line 830 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7912   30007

Definition at line 845 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7914   124

Definition at line 828 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7920   30002

Definition at line 843 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7921   365

Definition at line 834 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7931   348

Definition at line 833 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7935   9

Definition at line 824 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7936   30019

Definition at line 849 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7937   431

Definition at line 837 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7940   8

Definition at line 823 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941   115

Definition at line 826 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7941GE   309

Definition at line 832 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7942   434

Definition at line 838 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7945   435

Definition at line 839 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7960   7

Definition at line 822 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961   30018

Definition at line 848 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7961GE   308

Definition at line 831 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7962   404

Definition at line 836 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7965   436

Definition at line 840 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7970   30006

Definition at line 844 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7971   119

Definition at line 827 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7975   437

Definition at line 841 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_7985   302

Definition at line 829 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_ATA186   12

Definition at line 825 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_CIPC   30016

Definition at line 847 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_NONE   0

Definition at line 815 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DEVICE_SCCPGATEWAY_AN   30027

Definition at line 850 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_SCCPGATEWAY_BRI   30028

Definition at line 851 of file chan_skinny.c.

Referenced by device2str(), and get_button_template().

#define SKINNY_DEVICE_UNKNOWN   -1

Definition at line 814 of file chan_skinny.c.

Referenced by device2str().

#define SKINNY_DIALTONE   0x21

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

#define SKINNY_INVALID   14

Definition at line 871 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5

Definition at line 885 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_hold().

#define SKINNY_LAMP_FLASH   4

Definition at line 884 of file chan_skinny.c.

#define SKINNY_LAMP_OFF   1

Definition at line 881 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 882 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 883 of file chan_skinny.c.

#define SKINNY_MAX_CAPABILITIES   18

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

#define SKINNY_MICON   1

Definition at line 856 of file chan_skinny.c.

#define SKINNY_NOTONE   0x7F

Definition at line 879 of file chan_skinny.c.

Referenced by transmit_tone().

#define SKINNY_OFFHOOK   1

Definition at line 859 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 860 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 869 of file chan_skinny.c.

#define SKINNY_PROGRESS   12

Definition at line 870 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25

Definition at line 877 of file chan_skinny.c.

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

#define SKINNY_RING_FEATURE   4

Definition at line 890 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2

Definition at line 888 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1

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

#define SKINNY_RINGIN   4

Definition at line 862 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RINGOUT   3

Definition at line 861 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00

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

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

#define SKINNY_SPEAKERON   1

Definition at line 853 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define SKINNY_TRANSFER   10

Definition at line 868 of file chan_skinny.c.

#define SOFT_KEY_EVENT_MESSAGE   0x0026

Definition at line 245 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_REQ_MESSAGE   0x0025

Definition at line 243 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE   0x0109

Definition at line 654 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028

Definition at line 253 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108

Definition at line 496 of file chan_skinny.c.

Referenced by handle_soft_key_template_req_message().

#define SOFTKEY_ANSWER   0x0B

Definition at line 526 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_BKSPC   0x08

Definition at line 523 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDALL   0x05

Definition at line 520 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDBUSY   0x06

Definition at line 521 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CFWDNOANSWER   0x07

Definition at line 522 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_CONFRN   0x0D

Definition at line 528 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_ENDCALL   0x09

Definition at line 524 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_GPICKUP   0x12

Definition at line 533 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_HOLD   0x03

Definition at line 518 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_INFO   0x0C

Definition at line 527 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_JOIN   0x0F

Definition at line 530 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_MEETME   0x10

Definition at line 531 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NEWCALL   0x02

Definition at line 517 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_NONE   0x00

Definition at line 515 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PARK   0x0E

Definition at line 529 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_PICKUP   0x11

Definition at line 532 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_REDIAL   0x01

Definition at line 516 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_RESUME   0x0A

Definition at line 525 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SOFTKEY_TRNSFER   0x04

Definition at line 519 of file chan_skinny.c.

Referenced by handle_soft_key_event_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A

Definition at line 212 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091

Definition at line 354 of file chan_skinny.c.

Referenced by handle_speed_dial_stat_req_message().

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A

Definition at line 306 of file chan_skinny.c.

Referenced by handle_open_receive_channel_ack_message().

#define START_TONE_MESSAGE   0x0082

Definition at line 266 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER   0x11

Definition at line 404 of file chan_skinny.c.

#define STIMULUS_CALLPARK   0x7E

Definition at line 406 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_CALLPICKUP   0x7F

Definition at line 407 of file chan_skinny.c.

#define STIMULUS_CONFERENCE   0x7D

Definition at line 405 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_DISPLAY   0x08

Definition at line 401 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDALL   0x05

Definition at line 398 of file chan_skinny.c.

Referenced by handle_soft_key_event_message(), and handle_stimulus_message().

#define STIMULUS_FORWARDBUSY   0x06

Definition at line 399 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_FORWARDNOANSWER   0x07

Definition at line 400 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_HOLD   0x03

Definition at line 396 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_LINE   0x09

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

Referenced by handle_message().

#define STIMULUS_NONE   0xFF

Definition at line 408 of file chan_skinny.c.

#define STIMULUS_REDIAL   0x01

Definition at line 394 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_SPEEDDIAL   0x02

Definition at line 395 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_TRANSFER   0x04

Definition at line 397 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STIMULUS_VOICEMAIL   0x0F

Definition at line 403 of file chan_skinny.c.

Referenced by handle_stimulus_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B

Definition at line 325 of file chan_skinny.c.

Referenced by skinny_hold(), and transmit_callstate().

#define STOP_TONE_MESSAGE   0x0083

Definition at line 274 of file chan_skinny.c.

Referenced by transmit_tone().

#define TIME_DATE_REQ_MESSAGE   0x000D

Definition at line 222 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE   2

Definition at line 893 of file chan_skinny.c.

#define TYPE_TRUNK   1

Definition at line 892 of file chan_skinny.c.

#define UNREGISTER_MESSAGE   0x0027

Definition at line 252 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE   0x000F

Definition at line 224 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE   0x0098

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

static void __unreg_module ( void   )  [static]

Definition at line 5020 of file chan_skinny.c.

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

Definition at line 4573 of file chan_skinny.c.

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

04574 {
04575    int as;
04576    struct sockaddr_in sin;
04577    socklen_t sinlen;
04578    struct skinnysession *s;
04579    struct protoent *p;
04580    int arg = 1;
04581    pthread_attr_t attr;
04582    pthread_t tcp_thread;
04583 
04584    pthread_attr_init(&attr);
04585    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
04586 
04587    for (;;) {
04588       sinlen = sizeof(sin);
04589       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
04590       if (as < 0) {
04591          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
04592          continue;
04593       }
04594       p = getprotobyname("tcp");
04595       if(p) {
04596          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
04597             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
04598          }
04599       }
04600       if (!(s = ast_calloc(1, sizeof(struct skinnysession))))
04601          continue;
04602 
04603       memcpy(&s->sin, &sin, sizeof(sin));
04604       ast_mutex_init(&s->lock);
04605       s->fd = as;
04606       ast_mutex_lock(&sessionlock);
04607       s->next = sessions;
04608       sessions = s;
04609       ast_mutex_unlock(&sessionlock);
04610 
04611       if (ast_pthread_create(&tcp_thread, &attr, skinny_session, s)) {
04612          destroy_session(s);
04613       }
04614    }
04615    if (skinnydebug)
04616       ast_verbose("killing accept thread\n");
04617    close(as);
04618    pthread_attr_destroy(&attr);
04619    return 0;
04620 }

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

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

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

static int codec_ast2skinny ( int  astcodec  )  [static]

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

01393 {
01394    switch (astcodec) {
01395    case AST_FORMAT_ALAW:
01396       return SKINNY_CODEC_ALAW;
01397    case AST_FORMAT_ULAW:
01398       return SKINNY_CODEC_ULAW;
01399    case AST_FORMAT_G723_1:
01400       return SKINNY_CODEC_G723_1;
01401    case AST_FORMAT_G729A:
01402       return SKINNY_CODEC_G729A;
01403    case AST_FORMAT_G726_AAL2: /* XXX Is this right? */
01404       return SKINNY_CODEC_G726_32;
01405    case AST_FORMAT_H261:
01406       return SKINNY_CODEC_H261;
01407    case AST_FORMAT_H263:
01408       return SKINNY_CODEC_H263;
01409    default:
01410       return 0;
01411    }
01412 }

static int codec_skinny2ast ( enum skinny_codecs  skinnycodec  )  [static]

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

01371 {
01372    switch (skinnycodec) {
01373    case SKINNY_CODEC_ALAW:
01374       return AST_FORMAT_ALAW;
01375    case SKINNY_CODEC_ULAW:
01376       return AST_FORMAT_ULAW;
01377    case SKINNY_CODEC_G723_1:
01378       return AST_FORMAT_G723_1;
01379    case SKINNY_CODEC_G729A:
01380       return AST_FORMAT_G729A;
01381    case SKINNY_CODEC_G726_32:
01382       return AST_FORMAT_G726_AAL2; /* XXX Is this right? */
01383    case SKINNY_CODEC_H261:
01384       return AST_FORMAT_H261;
01385    case SKINNY_CODEC_H263:
01386       return AST_FORMAT_H263;
01387    default:
01388       return 0;
01389    }
01390 }

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

Definition at line 1883 of file chan_skinny.c.

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

01884 {
01885    struct skinny_device *d;
01886 
01887    char *result = NULL;
01888    int wordlen = strlen(word);
01889    int which = 0;
01890 
01891    if (pos == 2) {
01892       for (d = devices; d && !result; d = d->next) {
01893          if (!strncasecmp(word, d->id, wordlen) && ++which > state)
01894             result = ast_strdup(d->id);
01895       }
01896    }
01897 
01898    return result;
01899 }

static char* control2str ( int  ind  )  [static]

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

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

static void control2str_threadbuf_init ( void   )  [static]

Definition at line 141 of file chan_skinny.c.

00152 {

static void delete_devices ( void   )  [static]

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

04863 {
04864    struct skinny_device *d, *dlast;
04865    struct skinny_line *l, *llast;
04866    struct skinny_speeddial *sd, *sdlast;
04867    struct skinny_addon *a, *alast;
04868 
04869    ast_mutex_lock(&devicelock);
04870 
04871    /* Delete all devices */
04872    for (d=devices;d;) {
04873       /* Delete all lines for this device */
04874       for (l=d->lines;l;) {
04875          llast = l;
04876          l = l->next;
04877          ast_mutex_destroy(&llast->lock);
04878          free(llast);
04879       }
04880       /* Delete all speeddials for this device */
04881       for (sd=d->speeddials;sd;) {
04882          sdlast = sd;
04883          sd = sd->next;
04884          ast_mutex_destroy(&sdlast->lock);
04885          free(sdlast);
04886       }
04887       /* Delete all addons for this device */
04888       for (a=d->addons;a;) {
04889          alast = a;
04890          a = a->next;
04891          ast_mutex_destroy(&alast->lock);
04892          free(alast);
04893       }
04894       dlast = d;
04895       d = d->next;
04896       free(dlast);
04897    }
04898    devices=NULL;
04899    ast_mutex_unlock(&devicelock);
04900 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 4406 of file chan_skinny.c.

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

04407 {
04408    struct skinnysession *cur, *prev = NULL;
04409    ast_mutex_lock(&sessionlock);
04410    cur = sessions;
04411    while(cur) {
04412       if (cur == s) {
04413          break;
04414       }
04415       prev = cur;
04416       cur = cur->next;
04417    }
04418    if (cur) {
04419       if (prev) {
04420          prev->next = cur->next;
04421       } else {
04422          sessions = cur->next;
04423       }
04424       if (s->fd > -1) {
04425          close(s->fd);
04426       }
04427       ast_mutex_destroy(&s->lock);
04428       free(s);
04429    } else {
04430       ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
04431    }
04432    ast_mutex_unlock(&sessionlock);
04433 }

static char* device2str ( int  type  )  [static]

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

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

static void device2str_threadbuf_init ( void   )  [static]

Definition at line 138 of file chan_skinny.c.

00152 {

static void do_housekeeping ( struct skinnysession s  )  [static]

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

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

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

Definition at line 4622 of file chan_skinny.c.

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

04623 {
04624    int res;
04625 
04626    /* This thread monitors all the interfaces which are not yet in use
04627       (and thus do not have a separate thread) indefinitely */
04628    /* From here on out, we die whenever asked */
04629    for(;;) {
04630       pthread_testcancel();
04631       /* Wait for sched or io */
04632       res = ast_sched_wait(sched);
04633       if ((res < 0) || (res > 1000)) {
04634          res = 1000;
04635       }
04636       res = ast_io_wait(io, res);
04637       ast_mutex_lock(&monlock);
04638       if (res >= 0) {
04639          ast_sched_runq(sched);
04640       }
04641       ast_mutex_unlock(&monlock);
04642    }
04643    /* Never reached */
04644    return NULL;
04645 
04646 }

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

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

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

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

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

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

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

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

01356 {
01357    struct skinny_speeddial *sd;
01358 
01359    for (sd = d->speeddials; sd; sd = sd->next) {
01360       if (sd->instance == instance)
01361          break;
01362    }
01363 
01364    if (!sd) {
01365       ast_log(LOG_WARNING, "Could not find speeddial with instance '%d' on device '%s'\n", instance, d->name);
01366    }
01367    return sd;
01368 }

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

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

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

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

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

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

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

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

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

static int get_input ( struct skinnysession s  )  [static]

Definition at line 4435 of file chan_skinny.c.

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

04436 {
04437    int res;
04438    int dlen = 0;
04439    int *bufaddr;
04440    struct pollfd fds[1];
04441 
04442    fds[0].fd = s->fd;
04443    fds[0].events = POLLIN;
04444    fds[0].revents = 0;
04445    res = ast_poll(fds, 1, (keep_alive * 1100)); /* If nothing has happen, client is dead */
04446                    /* we add 10% to the keep_alive to deal */
04447                    /* with network delays, etc */
04448    if (res < 0) {
04449       if (errno != EINTR) {
04450          ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
04451          return res;
04452       }
04453    } else if (res == 0) {
04454       if (skinnydebug)
04455          ast_verbose("Skinny Client was lost, unregistering\n");
04456       skinny_unregister(NULL, s);
04457       return -1;
04458    }
04459            
04460    if (fds[0].revents) {
04461       ast_mutex_lock(&s->lock);
04462       memset(s->inbuf,0,sizeof(s->inbuf));
04463       res = read(s->fd, s->inbuf, 4);
04464       if (res < 0) {
04465          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
04466 
04467          if (skinnydebug)
04468             ast_verbose("Skinny Client was lost, unregistering\n");
04469          
04470          skinny_unregister(NULL,s);
04471          ast_mutex_unlock(&s->lock);
04472          return res;
04473       } else if (res != 4) {
04474          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.  Expected 4 but got %d.\n", res);
04475          ast_mutex_unlock(&s->lock);
04476          
04477          if (res == 0) {
04478             if (skinnydebug)
04479                ast_verbose("Skinny Client was lost, unregistering\n");
04480             skinny_unregister(NULL, s);
04481          }
04482            
04483          return -1;
04484       }
04485       
04486       bufaddr = (int *)s->inbuf;
04487       dlen = letohl(*bufaddr);
04488       if (dlen < 4) {
04489          ast_log(LOG_WARNING, "Skinny Client sent invalid data.\n");
04490          ast_mutex_unlock(&s->lock);
04491          return -1;
04492       }
04493       if (dlen+8 > sizeof(s->inbuf)) {
04494          dlen = sizeof(s->inbuf) - 8;
04495       }
04496       *bufaddr = htolel(dlen);
04497 
04498       res = read(s->fd, s->inbuf+4, dlen+4);
04499       ast_mutex_unlock(&s->lock);
04500       if (res < 0) {
04501          ast_log(LOG_WARNING, "read() returned error: %s\n", strerror(errno));
04502          return res;
04503       } else if (res != (dlen+4)) {
04504          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
04505          return -1;
04506       }
04507       return res;
04508    }
04509    return 0;
04510 }

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

Definition at line 3786 of file chan_skinny.c.

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

Referenced by handle_message().

03787 {
03788    /* no response necessary */
03789    if (skinnydebug)
03790       ast_verbose("Received Alarm Message: %s\n", req->data.alarm.displayMessage);
03791 
03792    return 1;
03793 }

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

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

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

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

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

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

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

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

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

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

Definition at line 4226 of file chan_skinny.c.

Referenced by handle_message().

04227 {
04228    /* XXX umm...okay?  Why do I care? */
04229    return 1;
04230 }

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

Definition at line 3089 of file chan_skinny.c.

Referenced by handle_message().

03090 {
03091    /* no response necessary */
03092    return 1;
03093 }

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

Definition at line 3037 of file chan_skinny.c.

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

Referenced by handle_message().

03038 {
03039    if (!(req = req_alloc(0, KEEP_ALIVE_ACK_MESSAGE)))
03040       return -1;
03041 
03042    transmit_response(s, req);
03043    do_housekeeping(s);
03044    return 1;
03045 }

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

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

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

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

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

03598 {
03599    struct skinny_device *d = s->device;
03600    struct skinny_line *l;
03601    int instance;
03602 
03603    instance = letohl(req->data.line.lineNumber);
03604 
03605    ast_mutex_lock(&devicelock);
03606 
03607    l = find_line_by_instance(d, instance);
03608 
03609    if (!l) {
03610       return 0;
03611    }
03612 
03613    ast_mutex_unlock(&devicelock);
03614 
03615    if (!(req = req_alloc(sizeof(struct line_stat_res_message), LINE_STAT_RES_MESSAGE)))
03616       return -1;
03617 
03618    req->data.linestat.lineNumber = letohl(instance);
03619    memcpy(req->data.linestat.lineDirNumber, l->name,
03620          sizeof(req->data.linestat.lineDirNumber));
03621    memcpy(req->data.linestat.lineDisplayName, l->label,
03622          sizeof(req->data.linestat.lineDisplayName));
03623    transmit_response(s,req);
03624    return 1;
03625 }

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

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

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

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

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

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

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

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

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

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

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

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

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

Definition at line 4232 of file chan_skinny.c.

Referenced by handle_message().

04233 {
04234    /* XXX I have no clue what this is for, but my phone was sending it, so... */
04235    return 1;
04236 }

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

Definition at line 3047 of file chan_skinny.c.

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

Referenced by handle_message().

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

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

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

03773 {
03774    struct skinny_device *d = s->device;
03775    if (!(req = req_alloc(sizeof(struct server_res_message), SERVER_RES_MESSAGE)))
03776       return -1;
03777 
03778    memcpy(req->data.serverres.server[0].serverName, ourhost,
03779          sizeof(req->data.serverres.server[0].serverName));
03780    req->data.serverres.serverListenPort[0] = htolel(ourport);
03781    req->data.serverres.serverIpAddr[0] = htolel(d->ourip.s_addr);
03782    transmit_response(s, req);
03783    return 1;
03784 }

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

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

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

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

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

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

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

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

04212 {
04213    if (!(req = req_alloc(sizeof(struct soft_key_template_res_message), SOFT_KEY_TEMPLATE_RES_MESSAGE)))
04214       return -1;
04215 
04216    req->data.softkeytemplate.softKeyOffset = htolel(0);
04217    req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
04218    req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(struct soft_key_template_definition));
04219    memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
04220       soft_key_template_default,
04221       sizeof(soft_key_template_default));
04222    transmit_response(s,req);
04223    return 1;
04224 }

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

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

03573 {
03574    struct skinny_device *d = s->device;
03575    struct skinny_speeddial *sd;
03576    int instance;
03577 
03578    instance = letohl(req->data.speeddialreq.speedDialNumber);
03579 
03580    sd = find_speeddial_by_instance(d, instance);
03581 
03582    if (!sd) {
03583       return 0;
03584    }
03585 
03586    if (!(req = req_alloc(sizeof(struct speed_dial_stat_res_message), SPEED_DIAL_STAT_RES_MESSAGE)))
03587       return -1;
03588 
03589    req->data.speeddialreq.speedDialNumber = htolel(instance);
03590    ast_copy_string(req->data.speeddial.speedDialDirNumber, sd->exten, sizeof(req->data.speeddial.speedDialDirNumber));
03591    ast_copy_string(req->data.speeddial.speedDialDisplayName, sd->label, sizeof(req->data.speeddial.speedDialDisplayName));
03592 
03593    transmit_response(s, req);
03594    return 1;
03595 }

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

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

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

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

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

03628 {
03629    time_t timer;
03630    struct tm *cmtime;
03631 
03632    if (!(req = req_alloc(sizeof(struct definetimedate_message), DEFINETIMEDATE_MESSAGE)))
03633       return -1;
03634 
03635    timer = time(NULL);
03636    cmtime = localtime(&timer);
03637    req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
03638    req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
03639    req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
03640    req->data.definetimedate.day = htolel(cmtime->tm_mday);
03641    req->data.definetimedate.hour = htolel(cmtime->tm_hour);
03642    req->data.definetimedate.minute = htolel(cmtime->tm_min);
03643    req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
03644    req->data.definetimedate.milliseconds = htolel(0);
03645    req->data.definetimedate.timestamp = htolel(timer);
03646    transmit_response(s, req);
03647    return 1;
03648 }

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

Definition at line 4206 of file chan_skinny.c.

References s, and skinny_unregister().

Referenced by handle_message().

04207 {
04208    return skinny_unregister(req, s);
04209 }

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

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

03762 {
03763    struct skinny_device *d = s->device;
03764    if (!(req = req_alloc(sizeof(struct version_res_message), VERSION_RES_MESSAGE)))
03765       return -1;
03766 
03767    ast_copy_string(req->data.version.version, d->version_id, sizeof(req->data.version.version));
03768    transmit_response(s, req);
03769    return 1;
03770 }

static int load_module ( void   )  [static]

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

04917 {
04918    int res = 0;
04919 
04920    for (; res < (sizeof(soft_key_template_default) / sizeof(soft_key_template_default[0])); res++) {
04921       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
04922    }
04923    /* load and parse config */
04924    res = reload_config();
04925    if (res == -1) {
04926       return AST_MODULE_LOAD_DECLINE;
04927    }
04928 
04929    /* Make sure we can register our skinny channel type */
04930    if (ast_channel_register(&skinny_tech)) {
04931       ast_log(LOG_ERROR, "Unable to register channel class 'Skinny'\n");
04932       return -1;
04933    }
04934 
04935    ast_rtp_proto_register(&skinny_rtp);
04936    ast_cli_register_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
04937    sched = sched_context_create();
04938    if (!sched) {
04939       ast_log(LOG_WARNING, "Unable to create schedule context\n");
04940    }
04941    io = io_context_create();
04942    if (!io) {
04943       ast_log(LOG_WARNING, "Unable to create I/O context\n");
04944    }
04945    /* And start the monitor for the first time */
04946    restart_monitor();
04947 
04948    return res;
04949 }

static int reload_config ( void   )  [static]

Definition at line 4712 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(), bindaddr, build_device(), config, date_format, 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.

04713 {
04714    int on = 1;
04715    struct ast_config *cfg;
04716    struct ast_variable *v;
04717    char *cat;
04718    struct skinny_device *d;
04719    int oldport = ntohs(bindaddr.sin_port);
04720 
04721    if (gethostname(ourhost, sizeof(ourhost))) {
04722       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
04723       return 0;
04724    }
04725    cfg = ast_config_load(config);
04726 
04727    /* We *must* have a config file otherwise stop immediately */
04728    if (!cfg) {
04729       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
04730       return -1;
04731    }
04732    memset(&bindaddr, 0, sizeof(bindaddr));
04733    memset(&default_prefs, 0, sizeof(default_prefs));
04734 
04735    /* Copy the default jb config over global_jbconf */
04736    memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
04737 
04738    /* load the general section */
04739    v = ast_variable_browse(cfg, "general");
04740    while (v) {
04741       /* handle jb conf */
04742       if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
04743          v = v->next;
04744          continue;
04745       }
04746 
04747       /* Create the interface list */
04748       if (!strcasecmp(v->name, "bindaddr")) {
04749          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
04750             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
04751          } else {
04752             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
04753          }
04754       } else if (!strcasecmp(v->name, "keepalive")) {
04755          keep_alive = atoi(v->value);
04756       } else if (!strcasecmp(v->name, "dateformat")) {
04757          memcpy(date_format, v->value, sizeof(date_format));
04758       } else if (!strcasecmp(v->name, "allow")) {
04759          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 1);
04760       } else if (!strcasecmp(v->name, "disallow")) {
04761          ast_parse_allow_disallow(&default_prefs, &default_capability, v->value, 0);
04762       } else if (!strcasecmp(v->name, "bindport") || !strcasecmp(v->name, "port")) {
04763          if (sscanf(v->value, "%5d", &ourport) == 1) {
04764             bindaddr.sin_port = htons(ourport);
04765          } else {
04766             ast_log(LOG_WARNING, "Invalid bindport '%s' at line %d of %s\n", v->value, v->lineno, config);
04767          }
04768          if (!strcasecmp(v->name, "port")) { /*! \todo Remove 'port' option after 1.4 */
04769             ast_log(LOG_WARNING, "Option 'port' at line %d of %s has been deprecated.  Please use 'bindport' instead.\n", v->lineno, config);
04770          }
04771       }
04772       v = v->next;
04773    }
04774 
04775    if (ntohl(bindaddr.sin_addr.s_addr)) {
04776       __ourip = bindaddr.sin_addr;
04777    } else {
04778       hp = ast_gethostbyname(ourhost, &ahp);
04779       if (!hp) {
04780          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
04781          ast_config_destroy(cfg);
04782          return 0;
04783       }
04784       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
04785    }
04786    if (!ntohs(bindaddr.sin_port)) {
04787       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
04788    }
04789    bindaddr.sin_family = AF_INET;
04790 
04791    /* load the device sections */
04792    cat = ast_category_browse(cfg, NULL);
04793    while(cat) {
04794       if (!strcasecmp(cat, "general")) {
04795          /* Nothing to do */
04796 #if 0
04797       } else if (!strncasecmp(cat, "paging-", 7)) {
04798          p = build_paging_device(cat, ast_variable_browse(cfg, cat));
04799          if (p) {
04800          }
04801 #endif
04802       } else {
04803          d = build_device(cat, ast_variable_browse(cfg, cat));
04804          if (d) {
04805             if (option_verbose > 2)
04806                ast_verbose(VERBOSE_PREFIX_3 "Added device '%s'\n", d->name);
04807             ast_mutex_lock(&devicelock);
04808             d->next = devices;
04809             devices = d;
04810             ast_mutex_unlock(&devicelock);
04811          }
04812       }
04813       cat = ast_category_browse(cfg, cat);
04814    }
04815    ast_mutex_lock(&netlock);
04816    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
04817       close(skinnysock);
04818       skinnysock = -1;
04819    }
04820    if (skinnysock < 0) {
04821       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
04822       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
04823          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
04824          ast_config_destroy(cfg);
04825          ast_mutex_unlock(&netlock);
04826          return 0;
04827       }
04828       if (skinnysock < 0) {
04829          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
04830       } else {
04831          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
04832             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
04833                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04834                      strerror(errno));
04835             close(skinnysock);
04836             skinnysock = -1;
04837             ast_config_destroy(cfg);
04838             ast_mutex_unlock(&netlock);
04839             return 0;
04840          }
04841          if (listen(skinnysock,DEFAULT_SKINNY_BACKLOG)) {
04842                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
04843                   ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port),
04844                      strerror(errno));
04845                close(skinnysock);
04846                skinnysock = -1;
04847                ast_config_destroy(cfg);
04848                ast_mutex_unlock(&netlock);
04849                return 0;
04850          }
04851          if (option_verbose > 1)
04852             ast_verbose(VERBOSE_PREFIX_2 "Skinny listening on %s:%d\n",
04853                ast_inet_ntoa(bindaddr.sin_addr), ntohs(bindaddr.sin_port));
04854          ast_pthread_create_background(&accept_t,NULL, accept_thread, NULL);
04855       }
04856    }
04857    ast_mutex_unlock(&netlock);
04858    ast_config_destroy(cfg);
04859    return 1;
04860 }

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

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

01239 {
01240    struct skinny_req *req;
01241 
01242    if (!(req = ast_calloc(1, skinny_header_size + size + 4)))
01243       return NULL;
01244 
01245    req->len = htolel(size+4);
01246    req->e = htolel(response_message);
01247 
01248    return req;
01249 }

static int restart_monitor ( void   )  [static]

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

04649 {
04650    /* If we're supposed to be stopped -- stay stopped */
04651    if (monitor_thread == AST_PTHREADT_STOP)
04652       return 0;
04653 
04654    ast_mutex_lock(&monlock);
04655    if (monitor_thread == pthread_self()) {
04656       ast_mutex_unlock(&monlock);
04657       ast_log(LOG_WARNING, "Cannot kill myself\n");
04658       return -1;
04659    }
04660    if (monitor_thread != AST_PTHREADT_NULL) {
04661       /* Wake up the thread */
04662       pthread_kill(monitor_thread, SIGURG);
04663    } else {
04664       /* Start a new monitor */
04665       if (ast_pthread_create_background(&monitor_thread, NULL, do_monitor, NULL) < 0) {
04666          ast_mutex_unlock(&monlock);
04667          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04668          return -1;
04669       }
04670    }
04671    ast_mutex_unlock(&monlock);
04672    return 0;
04673 }

static int skinny_answer ( struct ast_channel ast  )  [static]

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

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

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

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

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

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

Definition at line 1863 of file chan_skinny.c.

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

01864 {
01865    if (argc != 3) {
01866       return RESULT_SHOWUSAGE;
01867    }
01868    skinnydebug = 1;
01869    ast_cli(fd, "Skinny Debugging Enabled\n");
01870    return RESULT_SUCCESS;
01871 }

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

Definition at line 2704 of file chan_skinny.c.

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

02705 {
02706    struct skinny_subchannel *sub = newchan->tech_pvt;
02707    ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
02708    if (sub->owner != oldchan) {
02709       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
02710       return -1;
02711    }
02712    sub->owner = newchan;
02713    return 0;
02714 }

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

Definition at line 1833 of file chan_skinny.c.

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

01834 {
01835    struct skinny_subchannel *sub = NULL;
01836 
01837    if (!(sub = c->tech_pvt) || !(sub->rtp))
01838       return AST_RTP_GET_FAILED;
01839 
01840    *rtp = sub->rtp;
01841 
01842    return AST_RTP_TRY_NATIVE;
01843 }

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

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

01822 {
01823    struct skinny_subchannel *sub = NULL;
01824 
01825    if (!(sub = c->tech_pvt) || !(sub->vrtp))
01826       return AST_RTP_GET_FAILED;
01827 
01828    *rtp = sub->vrtp;
01829 
01830    return AST_RTP_TRY_NATIVE;
01831 }

static int skinny_hangup ( struct ast_channel ast  )  [static]

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

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

static int skinny_hold ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 2784 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_HOLD, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, AST_CONTROL_SRCUPDATE, AST_CONTROL_UNHOLD, ast_copy_string(), ast_log(), AST_MAX_EXTENSION, ast_moh_start(), ast_moh_stop(), 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.

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

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

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

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

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

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

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

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

Definition at line 1873 of file chan_skinny.c.

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

01874 {
01875    if (argc != 4) {
01876       return RESULT_SHOWUSAGE;
01877    }
01878    skinnydebug = 0;
01879    ast_cli(fd, "Skinny Debugging Disabled\n");
01880    return RESULT_SUCCESS;
01881 }

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

Definition at line 2666 of file chan_skinny.c.

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

02667 {
02668    struct ast_frame *fr;
02669    struct skinny_subchannel *sub = ast->tech_pvt;
02670    ast_mutex_lock(&sub->lock);
02671    fr = skinny_rtp_read(sub);
02672    ast_mutex_unlock(&sub->lock);
02673    return fr;
02674 }

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

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

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

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

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

04513 {
04514    struct skinny_req *req;
04515    int *bufaddr;
04516 
04517    if (!(req = ast_calloc(1, SKINNY_MAX_PACKET)))
04518       return NULL;
04519 
04520    ast_mutex_lock(&s->lock);
04521    memcpy(req, s->inbuf, skinny_header_size);
04522    bufaddr = (int *)(s->inbuf);
04523    memcpy(&req->data, s->inbuf+skinny_header_size, letohl(*bufaddr)-4);
04524 
04525    ast_mutex_unlock(&s->lock);
04526 
04527    if (letohl(req->e) < 0) {
04528       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
04529       free(req);
04530       return NULL;
04531    }
04532 
04533    return req;
04534 }

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

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

04676 {
04677    int oldformat;
04678    
04679    struct skinny_line *l;
04680    struct ast_channel *tmpc = NULL;
04681    char tmp[256];
04682    char *dest = data;
04683 
04684    oldformat = format;
04685    
04686    if (!(format &= ((AST_FORMAT_MAX_AUDIO << 1) - 1))) {
04687       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
04688       return NULL;   
04689    }     
04690 
04691    ast_copy_string(tmp, dest, sizeof(tmp));
04692    if (ast_strlen_zero(tmp)) {
04693       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
04694       return NULL;
04695    }
04696    l = find_line_by_name(tmp);
04697    if (!l) {
04698       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
04699       return NULL;
04700    }
04701    if (option_verbose > 2) {
04702       ast_verbose(VERBOSE_PREFIX_3 "skinny_request(%s)\n", tmp);
04703    }
04704    tmpc = skinny_new(l, AST_STATE_DOWN);
04705    if (!tmpc) {
04706       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
04707    }
04708    restart_monitor();
04709    return tmpc;
04710 }

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

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

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

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

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

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

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

Definition at line 2716 of file chan_skinny.c.

02717 {
02718    return -1; /* Start inband indications */
02719 }

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

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

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

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

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

04537 {
04538    int res;
04539    struct skinny_req *req;
04540    struct skinnysession *s = data;
04541 
04542    if (option_verbose > 2)
04543       ast_verbose(VERBOSE_PREFIX_3 "Starting Skinny session from %s\n", ast_inet_ntoa(s->sin.sin_addr));
04544 
04545    for (;;) {
04546       res = get_input(s);
04547       if (res < 0) {
04548          break;
04549       }
04550 
04551       if (res > 0)
04552       {
04553          if (!(req = skinny_req_parse(s))) {
04554             destroy_session(s);
04555             return NULL;
04556          }
04557 
04558          res = handle_message(req, s);
04559          if (res < 0) {
04560             destroy_session(s);
04561             return NULL;
04562          }
04563       }
04564    }
04565    ast_log(LOG_NOTICE, "Skinny Session returned: %s\n", strerror(errno));
04566 
04567    if (s) 
04568       destroy_session(s);
04569    
04570    return 0;
04571 }

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

References ast_channel::tech_pvt.

01846 {
01847    struct skinny_subchannel *sub;
01848    sub = c->tech_pvt;
01849    if (sub) {
01850       /* transmit_modify_with_sdp(sub, rtp); @@FIXME@@ if needed */
01851       return 0;
01852    }
01853    return -1;
01854 }

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

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

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

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

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

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

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

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

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

static int skinny_unhold ( struct skinny_subchannel sub  )  [static]

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

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

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

Definition at line 1449 of file chan_skinny.c.

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

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

01450 {
01451    struct skinny_device *d;
01452 
01453    d = s->device;
01454 
01455    if (d) {
01456       d->session = NULL;
01457       d->registered = 0;
01458    }
01459 
01460    return -1; /* main loop will destroy the session */
01461 }

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

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

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

static void start_rtp ( struct skinny_subchannel sub  )  [static]

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

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

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

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

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

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

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

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

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

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

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

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

01725 {
01726    struct skinny_req *req;
01727 
01728    if (!(req = req_alloc(sizeof(struct dialed_number_message), DIALED_NUMBER_MESSAGE)))
01729       return;
01730 
01731    ast_copy_string(req->data.dialednumber.dialedNumber, text, sizeof(req->data.dialednumber.dialedNumber));
01732    req->data.dialednumber.lineInstance = htolel(instance);
01733    req->data.dialednumber.callReference = htolel(callid);
01734 
01735    transmit_response(s, req);
01736 }

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

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

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

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

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

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

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

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

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

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

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

01617 {
01618    struct skinny_req *req;
01619 
01620    if (!(req = req_alloc(sizeof(struct set_lamp_message), SET_LAMP_MESSAGE)))
01621       return;
01622 
01623    req->data.setlamp.stimulus = htolel(stimulus);
01624    req->data.setlamp.stimulusInstance = htolel(instance);
01625    req->data.setlamp.deviceStimulus = htolel(indication);
01626    transmit_response(s, req);
01627 }

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

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

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

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

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

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

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

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

01603 {
01604    struct skinny_req *req;
01605 
01606    if (!(req = req_alloc(sizeof(struct select_soft_keys_message), SELECT_SOFT_KEYS_MESSAGE)))
01607       return;
01608 
01609    req->data.selectsoftkey.instance = htolel(instance);
01610    req->data.selectsoftkey.reference = htolel(callid);
01611    req->data.selectsoftkey.softKeySetIndex = htolel(softkey);
01612    req->data.selectsoftkey.validKeyMask = htolel(0xFFFFFFFF);
01613    transmit_response(s, req);
01614 }

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

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

01504 {
01505    struct skinny_req *req;
01506 
01507    if (!(req = req_alloc(sizeof(struct set_speaker_message), SET_SPEAKER_MESSAGE)))
01508       return;
01509 
01510    req->data.setspeaker.mode = htolel(mode);
01511    transmit_response(s, req);
01512 }

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

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

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

static int unload_module ( void   )  [static]

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

04952 {
04953    struct skinnysession *s, *slast;
04954    struct skinny_device *d;
04955    struct skinny_line *l;
04956    struct skinny_subchannel *sub;
04957 
04958    ast_mutex_lock(&sessionlock);
04959    /* Destroy all the interfaces and free their memory */
04960    s = sessions;
04961    while(s) {
04962       slast = s;
04963       s = s->next;
04964       for (d = slast->device; d; d = d->next) {
04965          for (l = d->lines; l; l = l->next) {
04966             ast_mutex_lock(&l->lock);
04967             for (sub = l->sub; sub; sub = sub->next) {
04968                ast_mutex_lock(&sub->lock);
04969                if (sub->owner) {
04970                   sub->alreadygone = 1;
04971                   ast_softhangup(sub->owner, AST_SOFTHANGUP_APPUNLOAD);
04972                }
04973                ast_mutex_unlock(&sub->lock);
04974             }
04975             ast_mutex_unlock(&l->lock);
04976          }
04977       }
04978       if (slast->fd > -1)
04979          close(slast->fd);
04980       ast_mutex_destroy(&slast->lock);
04981       free(slast);
04982    }
04983    sessions = NULL;
04984    ast_mutex_unlock(&sessionlock);
04985 
04986    delete_devices();
04987 
04988    ast_mutex_lock(&monlock);
04989    if ((monitor_thread != AST_PTHREADT_NULL) && (monitor_thread != AST_PTHREADT_STOP)) {
04990       pthread_cancel(monitor_thread);
04991       pthread_kill(monitor_thread, SIGURG);
04992       pthread_join(monitor_thread, NULL);
04993    }
04994    monitor_thread = AST_PTHREADT_STOP;
04995    ast_mutex_unlock(&monlock);
04996 
04997    ast_mutex_lock(&netlock);
04998    if (accept_t && (accept_t != AST_PTHREADT_STOP)) {
04999       pthread_cancel(accept_t);
05000       pthread_kill(accept_t, SIGURG);
05001       pthread_join(accept_t, NULL);
05002    }
05003    accept_t = AST_PTHREADT_STOP;
05004    ast_mutex_unlock(&netlock);
05005 
05006    ast_rtp_proto_unregister(&skinny_rtp);
05007    ast_channel_unregister(&skinny_tech);
05008    ast_cli_unregister_multiple(cli_skinny, sizeof(cli_skinny) / sizeof(struct ast_cli_entry));
05009 
05010    close(skinnysock);
05011    if (sched)
05012       sched_context_destroy(sched);
05013 
05014    return 0;
05015 }


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 = "6989f2ec67f8497e38c12890500c525b" , .load = load_module, .unload = unload_module, } [static]

Definition at line 5020 of file chan_skinny.c.

struct in_addr __ourip [static]

Definition at line 785 of file chan_skinny.c.

pthread_t accept_t [static]

Definition at line 789 of file chan_skinny.c.

Referenced by reload_config(), and unload_module().

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]

Definition at line 809 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 786 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(), 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 811 of file chan_skinny.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 5020 of file chan_skinny.c.

struct sockaddr_in bindaddr [static]

Definition at line 782 of file chan_skinny.c.

int callnums = 1 [static]

Definition at line 812 of file chan_skinny.c.

Referenced by skinny_new().

int callreturn = 0 [static]

Definition at line 802 of file chan_skinny.c.

int callwaiting = 0 [static]

Definition at line 801 of file chan_skinny.c.

int cancallforward = 0 [static]

Definition at line 807 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = "" [static]

Definition at line 795 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = "" [static]

Definition at line 794 of file chan_skinny.c.

struct ast_cli_entry cli_skinny[] [static]

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

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

Definition at line 141 of file chan_skinny.c.

Referenced by control2str().

ast_group_t cur_callergroup = 0 [static]

Definition at line 798 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]

Definition at line 799 of file chan_skinny.c.

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

Definition at line 101 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 2091 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 129 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 138 of file chan_skinny.c.

Referenced by device2str().

ast_mutex_t devicelock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

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

int gendigittimeout = 8000 [static]

Definition at line 940 of file chan_skinny.c.

struct ast_jb_conf global_jbconf [static]

Definition at line 136 of file chan_skinny.c.

struct hostent* hp

Definition at line 787 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(), 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 800 of file chan_skinny.c.

struct io_context* io [static]

Definition at line 916 of file chan_skinny.c.

int keep_alive = 120 [static]

Definition at line 100 of file chan_skinny.c.

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

char language[MAX_LANGUAGE] = "" [static]

Definition at line 791 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = "" [static]

Definition at line 796 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]

Definition at line 810 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]

Definition at line 943 of file chan_skinny.c.

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

Definition at line 792 of file chan_skinny.c.

char mohsuggest[MAX_MUSICCLASS] = "" [static]

Definition at line 793 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]

Definition at line 934 of file chan_skinny.c.

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

Definition at line 920 of file chan_skinny.c.

int mwiblink = 0 [static]

Definition at line 804 of file chan_skinny.c.

Referenced by build_device().

int nat = 0 [static]

Definition at line 797 of file chan_skinny.c.

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

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

char ourhost[256] [static]

Definition at line 783 of file chan_skinny.c.

int ourport [static]

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

struct sched_context* sched = NULL [static]

Definition at line 915 of file chan_skinny.c.

ast_mutex_t sessionlock = { PTHREAD_MUTEX_INITIALIZER , 1, { NULL }, { 0 }, 0, { NULL }, { 0 }, PTHREAD_MUTEX_INITIALIZER } [static]

Definition at line 924 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 2083 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 2087 of file chan_skinny.c.

int skinny_header_size = 12

Definition at line 773 of file chan_skinny.c.

Referenced by skinny_req_parse(), and transmit_response().

struct ast_rtp_protocol skinny_rtp [static]

Definition at line 1856 of file chan_skinny.c.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 1083 of file chan_skinny.c.

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

int skinnydebug = 0 [static]

Definition at line 779 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 788 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 571 of file chan_skinny.c.

const uint8_t soft_key_default_connwithconf[] [static]

Initial value:

Definition at line 615 of file chan_skinny.c.

const uint8_t soft_key_default_connwithtrans[] [static]

Definition at line 601 of file chan_skinny.c.

const uint8_t soft_key_default_dadfd[] [static]

Initial value:

Definition at line 610 of file chan_skinny.c.

struct soft_key_definitions soft_key_default_definitions[] [static]

Definition at line 633 of file chan_skinny.c.

Referenced by handle_soft_key_set_req_message().

const uint8_t soft_key_default_offhook[] [static]

Definition at line 593 of file chan_skinny.c.

const uint8_t soft_key_default_offhookwithfeat[] [static]

Initial value:

Definition at line 624 of file chan_skinny.c.

const uint8_t soft_key_default_onhold[] [static]

Definition at line 580 of file chan_skinny.c.

const uint8_t soft_key_default_onhook[] [static]

Definition at line 562 of file chan_skinny.c.

const uint8_t soft_key_default_ringin[] [static]

Initial value:

Definition at line 587 of file chan_skinny.c.

const uint8_t soft_key_default_ringout[] [static]

Initial value:

Definition at line 619 of file chan_skinny.c.

const uint8_t soft_key_default_unknown[] [static]

Initial value:

Definition at line 629 of file chan_skinny.c.

struct soft_key_template_definition soft_key_template_default[]

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

int transfer = 0 [static]

Definition at line 806 of file chan_skinny.c.

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

Definition at line 102 of file chan_skinny.c.

Referenced by skinny_register().


Generated on Thu Dec 17 23:51:46 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7