Asterisk.org: Developer Documentation (28 Oct 2009)

Wed Oct 28 15:48:37 2009

## Asterisk developer's documentation

# chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

`#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.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 dependency graph for chan_skinny.c:

Go to the source code of this file.

## Data Structures

struct | activate_call_plane_message
struct | button_defs
struct | button_template_res_message
struct | buttondefinition
struct | call_info_message
struct | call_state_message
struct | capabilities_res_message
struct | close_recieve_channel_message
struct | definetimedate_message
struct | dialled_number_message
struct | display_notify_message
struct | display_prompt_status_message
struct | displaytext_message
struct | keypad_button_message
struct | line_stat_res_message
struct | line_state_req_message
struct | media_qualifier
struct | open_recieve_channel_ack_message
struct | open_recieve_channel_message
struct | register_ack_message
struct | register_message
struct | register_rej_message
struct | select_soft_keys_message
struct | server_identifier
struct | server_res_message
struct | set_lamp_message
struct | set_ringer_message
struct | set_speaker_message
struct | skinny_device
struct | skinny_line
struct | skinny_paging_device
struct | skinny_req
struct | skinny_subchannel
struct | skinnysession
struct | soft_key_set_definition
struct | soft_key_sets
struct | soft_key_template
struct | soft_key_template_definition
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 | version_res_message

## Defines

#define | ACTIVATE_CALL_PLANE_MESSAGE 0x0116
#define | ALARM_MESSAGE 0x0020
#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 | CLOSE_RECIEVE_CHANNEL_MESSAGE 0x0106
#define | DEFAULT_SKINNY_BACKLOG 2
#define | DEFAULT_SKINNY_PORT 2000
#define | DEFINETIMEDATE_MESSAGE 0x0094
#define | DIALLED_NUMBER_MESSAGE 0x011D
#define | DISPLAY_NOTIFY_MESSAGE 0x0114
#define | DISPLAY_PROMPT_STATUS_MESSAGE 0x0112
#define | DISPLAYTEXT_MESSAGE 0x0099
#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 | 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 | MAX_SUBS 2
#define | OFFHOOK_MESSAGE 0x0006
#define | ONHOOK_MESSAGE 0x0007
#define | OPEN_RECIEVE_CHANNEL_ACK_MESSAGE 0x0022
#define | OPEN_RECIEVE_CHANNEL_MESSAGE 0x0105
#define | REGISTER_ACK_MESSAGE 0x0081
#define | REGISTER_MESSAGE 0x0001
#define | REGISTER_REJ_MESSAGE 0x009D
#define | SELECT_SOFT_KEYS_MESSAGE 0x0110
#define | SERVER_REQUEST_MESSAGE 0x0012
#define | SERVER_RES_MESSAGE 0x009E
#define | SET_LAMP_MESSAGE 0x0086
#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_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_PACKET 1000
#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_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 | 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 | SUB_ALT 1
#define | SUB_REAL 0
#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

## Typedefs

typedef struct buttondefinition | button_definition
typedef struct button_defs | button_defs_t
typedef unsigned short | UINT16
typedef unsigned int | UINT32
typedef unsigned char | UINT8

## Functions

static void * | accept_thread (void *ignore)
| AST_MUTEX_DEFINE_STATIC (devicelock)
| AST_MUTEX_DEFINE_STATIC (sessionlock)
| AST_MUTEX_DEFINE_STATIC (netlock)
| AST_MUTEX_DEFINE_STATIC (monlock)
| AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static struct skinny_device * | build_device (char *cat, struct ast_variable *v)
static char * | control2str (int ind)
static int | convert_cap (int capability)
static void | delete_devices (void)
char * | description ()
| Provides a description of the module.
static void | destroy_session (struct skinnysession *s)
static void | do_housekeeping (struct skinnysession *s)
static void * | do_monitor (void *data)
static struct skinny_subchannel * | find_subchannel_by_line (struct skinny_line *l)
static struct skinny_subchannel * | find_subchannel_by_name (char *dest)
static int | get_input (struct skinnysession *s)
static int | handle_message (skinny_req *req, struct skinnysession *s)
static int | has_voicemail (struct skinny_line *l)
char * | key ()
| Returns the ASTERISK_GPL_KEY.
int | load_module ()
| Initialize the module.
int | reload (void)
| Reload stuff.
static int | reload_config (void)
static skinny_req * | req_alloc (size_t size)
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 struct ast_rtp * | skinny_get_rtp_peer (struct ast_channel *chan)
static struct ast_rtp * | skinny_get_vrtp_peer (struct ast_channel *chan)
static int | skinny_hangup (struct ast_channel *ast)
static int | skinny_indicate (struct ast_channel *ast, int ind)
static struct ast_channel * | skinny_new (struct skinny_subchannel *sub, int state)
static int | skinny_no_debug (int fd, int argc, char *argv[])
static struct ast_frame * | skinny_read (struct ast_channel *ast)
static int | skinny_register (skinny_req *req, struct skinnysession *s)
static skinny_req * | skinny_req_parse (struct skinnysession *s)
static struct ast_channel * | skinny_request (const char *type, int format, void *data, int *cause)
static struct ast_frame * | skinny_rtp_read (struct skinny_subchannel *sub)
static int | skinny_senddigit (struct ast_channel *ast, char digit)
static void * | skinny_session (void *data)
static int | skinny_set_rtp_peer (struct ast_channel *chan, 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_write (struct ast_channel *ast, struct ast_frame *frame)
static void | start_rtp (struct skinny_subchannel *sub)
static void | transmit_callinfo (struct skinnysession *s, char *fromname, char *fromnum, char *toname, 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)
static void | transmit_diallednumber (struct skinnysession *s, char *text, int instance, int callid)
static void | transmit_displaymessage (struct skinnysession *s, char *text)
static void | transmit_displaynotify (struct skinnysession *s, char *text, int t)
static void | transmit_displaypromptstatus (struct skinnysession *s, 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, skinny_req *req)
static void | transmit_ringer_mode (struct skinnysession *s, int mode)
static void | transmit_speaker_mode (struct skinnysession *s, int mode)
static void | transmit_tone (struct skinnysession *s, int tone)
int | unload_module ()
| Cleanup all module structures, sockets, etc.
int | usecount ()
| Provides a usecount.

## Variables

static struct in_addr | __ourip
static pthread_t | accept_t
static char | accountcode [AST_MAX_ACCOUNT_CODE] = ""
struct ast_hostent | ahp
static int | amaflags = 0
static struct sockaddr_in | bindaddr
button_definition | button_def_12sp []
button_definition | button_def_30vip []
button_definition | button_def_7902 []
button_definition | button_def_7910 []
button_definition | button_def_7920 []
button_definition | button_def_7935 []
button_definition | button_def_7940 []
button_definition | button_def_7960 []
button_definition | button_def_7970 []
button_definition | button_def_none = { 0, STIMULUS_NONE }
button_defs_t | button_defs []
static int | callnums = 1
static int | callreturn = 0
static int | callwaiting = 0
static int | cancallforward = 0
static int | capability = AST_FORMAT_ULAW
static char | cid_name [AST_MAX_EXTENSION] = ""
static char | cid_num [AST_MAX_EXTENSION] = ""
static struct ast_cli_entry | cli_debug
static struct ast_cli_entry | cli_no_debug
static struct ast_cli_entry | cli_show_devices
static struct ast_cli_entry | cli_show_lines
static const char | config [] = "skinny.conf"
static char | context [AST_MAX_CONTEXT] = "default"
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 const char | desc [] = "Skinny Client Control Protocol (Skinny)"
static struct skinny_device * | devices
static int | firstdigittimeout = 16000
static int | gendigittimeout = 8000
struct hostent * | hp
static int | immediate = 0
static struct io_context * | io
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 pthread_t | monitor_thread = AST_PTHREADT_NULL
static char | musicclass [MAX_MUSICCLASS] = ""
static int | mwiblink = 0
static int | nat = 0
static char | no_debug_usage []
static char | ourhost [256]
static int | ourport
static struct sched_context * | sched
static struct skinnysession * | sessions
static char | show_devices_usage []
static char | show_lines_usage []
static struct ast_rtp_protocol | skinny_rtp
static struct ast_channel_tech | skinny_tech
static int | skinnydebug = 1
static int | skinnysock = -1
static const char * | soft_key_set_hack
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 const char | type [] = "Skinny"
static int | usecnt = 0
static char | version_id [16] = "P002F202"

## Detailed Description

Implementation of the Skinny protocol.

Author:
  Jeremy McNamara & Florian Overkamp

Definition in file chan_skinny.c.

## Define Documentation

#define ACTIVATE_CALL_PLANE_MESSAGE 0x0116

Definition at line 618 of file chan_skinny.c.

Referenced by transmit_callstate().

#define ALARM_MESSAGE 0x0020

Definition at line 183 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_REQ_MESSAGE 0x000E

Definition at line 181 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE 0x0097

Definition at line 320 of file chan_skinny.c.

Referenced by handle_message().

#define CALL_INFO_MESSAGE 0x008F

Definition at line 254 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE 0x0111

Definition at line 597 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE 0x009B

Definition at line 307 of file chan_skinny.c.

Referenced by handle_message().

#define CAPABILITIES_RES_MESSAGE 0x0010

Definition at line 154 of file chan_skinny.c.

Referenced by handle_message().

#define CLEAR_DISPLAY_MESSAGE 0x009A

Definition at line 300 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define CLOSE_RECIEVE_CHANNEL_MESSAGE 0x0106

Definition at line 498 of file chan_skinny.c.

Referenced by transmit_callstate().

#define DEFAULT_SKINNY_BACKLOG 2

Definition at line 84 of file chan_skinny.c.

Referenced by reload_config().

#define DEFAULT_SKINNY_PORT 2000

Definition at line 83 of file chan_skinny.c.

Referenced by build_device(), and reload_config().

#define DEFINETIMEDATE_MESSAGE 0x0094

Definition at line 282 of file chan_skinny.c.

Referenced by handle_message().

#define DIALLED_NUMBER_MESSAGE 0x011D

Definition at line 623 of file chan_skinny.c.

Referenced by transmit_diallednumber().

#define DISPLAY_NOTIFY_MESSAGE 0x0114

Definition at line 612 of file chan_skinny.c.

Referenced by transmit_displaynotify().

#define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112

Definition at line 604 of file chan_skinny.c.

Referenced by transmit_displaypromptstatus().

#define DISPLAYTEXT_MESSAGE 0x0099

Definition at line 295 of file chan_skinny.c.

Referenced by transmit_displaymessage().

#define htolel | ( | x |  | ) | (x)

Definition at line 99 of file chan_skinny.c.

Referenced by get_input(), handle_message(), load_module(), transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_diallednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), and transmit_tone().

#define htoles | ( | x |  | ) | (x)

Definition at line 100 of file chan_skinny.c.

#define IP_PORT_MESSAGE 0x0002

Definition at line 138 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_ACK_MESSAGE 0x0100

Definition at line 486 of file chan_skinny.c.

Referenced by handle_message().

#define KEEP_ALIVE_MESSAGE 0x0000

Definition at line 125 of file chan_skinny.c.

Referenced by handle_message().

#define KEYPAD_BUTTON_MESSAGE 0x0003

Definition at line 140 of file chan_skinny.c.

Referenced by handle_message().

#define letohl | ( | x |  | ) | (x)

Definition at line 97 of file chan_skinny.c.

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

#define letohs | ( | x |  | ) | (x)

Definition at line 98 of file chan_skinny.c.

#define LINE_STAT_RES_MESSAGE 0x0092

Definition at line 274 of file chan_skinny.c.

Referenced by handle_message().

#define LINE_STATE_REQ_MESSAGE 0x000B

Definition at line 174 of file chan_skinny.c.

Referenced by handle_message().

#define MAX_SUBS 2

Definition at line 711 of file chan_skinny.c.

#define OFFHOOK_MESSAGE 0x0006

Definition at line 151 of file chan_skinny.c.

Referenced by handle_message().

#define ONHOOK_MESSAGE 0x0007

Definition at line 152 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECIEVE_CHANNEL_ACK_MESSAGE 0x0022

Definition at line 185 of file chan_skinny.c.

Referenced by handle_message().

#define OPEN_RECIEVE_CHANNEL_MESSAGE 0x0105

Definition at line 488 of file chan_skinny.c.

Referenced by transmit_connect().

#define REGISTER_ACK_MESSAGE 0x0081

Definition at line 197 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_MESSAGE 0x0001

Definition at line 128 of file chan_skinny.c.

Referenced by handle_message().

#define REGISTER_REJ_MESSAGE 0x009D

Definition at line 302 of file chan_skinny.c.

Referenced by handle_message().

#define SELECT_SOFT_KEYS_MESSAGE 0x0110

Definition at line 589 of file chan_skinny.c.

#define SERVER_REQUEST_MESSAGE 0x0012

Definition at line 182 of file chan_skinny.c.

Referenced by handle_message().

#define SERVER_RES_MESSAGE 0x009E

Definition at line 309 of file chan_skinny.c.

Referenced by handle_message().

#define SET_LAMP_MESSAGE 0x0086

Definition at line 218 of file chan_skinny.c.

Referenced by transmit_lamp_indication().

#define SET_RINGER_MESSAGE 0x0085

Definition at line 213 of file chan_skinny.c.

Referenced by transmit_ringer_mode().

#define SET_SPEAKER_MESSAGE 0x0088

Definition at line 225 of file chan_skinny.c.

Referenced by transmit_speaker_mode().

#define SKINNY_ALERT 0x24

Definition at line 733 of file chan_skinny.c.

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY 6

Definition at line 721 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE 0x23

Definition at line 732 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLWAIT 9

Definition at line 724 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE 0x2D

Definition at line 735 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CONGESTION 7

Definition at line 722 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED 5

Definition at line 720 of file chan_skinny.c.

Referenced by handle_message(), and skinny_answer().

#define SKINNY_CX_CONF 3

Definition at line 756 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE 3

Definition at line 757 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE 4

Definition at line 759 of file chan_skinny.c.

Referenced by build_device().

#define SKINNY_CX_MUTE 4

Definition at line 758 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY 1

Definition at line 754 of file chan_skinny.c.

Referenced by handle_message().

#define SKINNY_CX_SENDONLY 0

Definition at line 753 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV 2

Definition at line 755 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DIALTONE 0x21

Definition at line 731 of file chan_skinny.c.

Referenced by handle_message(), and skinny_ss().

#define SKINNY_HOLD 8

Definition at line 723 of file chan_skinny.c.

#define SKINNY_INVALID 14

Definition at line 728 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK 5

Definition at line 742 of file chan_skinny.c.

Referenced by do_housekeeping(), and skinny_call().

#define SKINNY_LAMP_FLASH 4

Definition at line 741 of file chan_skinny.c.

#define SKINNY_LAMP_OFF 1

Definition at line 738 of file chan_skinny.c.

Referenced by do_housekeeping(), handle_message(), and skinny_hangup().

#define SKINNY_LAMP_ON 2

Definition at line 739 of file chan_skinny.c.

Referenced by do_housekeeping(), and handle_message().

#define SKINNY_LAMP_WINK 3

Definition at line 740 of file chan_skinny.c.

#define SKINNY_MAX_PACKET 1000

Definition at line 85 of file chan_skinny.c.

Referenced by handle_message(), and skinny_req_parse().

#define SKINNY_NOTONE 0x7F

Definition at line 736 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_OFFHOOK 1

Definition at line 716 of file chan_skinny.c.

Referenced by handle_message(), skinny_call(), skinny_hangup(), and transmit_callstate().

#define SKINNY_ONHOOK 2

Definition at line 717 of file chan_skinny.c.

Referenced by build_device(), handle_message(), skinny_call(), skinny_hangup(), and transmit_callstate().

#define SKINNY_PARK 11

Definition at line 726 of file chan_skinny.c.

#define SKINNY_PROGRESS 12

Definition at line 727 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER 0x25

Definition at line 734 of file chan_skinny.c.

Referenced by skinny_indicate(), and skinny_ss().

#define SKINNY_RING_FEATURE 4

Definition at line 747 of file chan_skinny.c.

#define SKINNY_RING_INSIDE 2

Definition at line 745 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF 1

Definition at line 744 of file chan_skinny.c.

Referenced by handle_message(), and skinny_hangup().

#define SKINNY_RING_OUTSIDE 3

Definition at line 746 of file chan_skinny.c.

#define SKINNY_RINGIN 4

Definition at line 719 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RINGOUT 3

Definition at line 718 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE 0x00

Definition at line 730 of file chan_skinny.c.

Referenced by handle_message(), skinny_hangup(), skinny_indicate(), and skinny_ss().

#define SKINNY_SPEAKEROFF 2

Definition at line 714 of file chan_skinny.c.

Referenced by skinny_hangup(), and transmit_callstate().

#define SKINNY_SPEAKERON 1

Definition at line 713 of file chan_skinny.c.

#define SKINNY_TRANSFER 10

Definition at line 725 of file chan_skinny.c.

#define SOFT_KEY_SET_REQ_MESSAGE 0x0025

Definition at line 193 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_SET_RES_MESSAGE 0x0109

Definition at line 539 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE 0x0028

Definition at line 195 of file chan_skinny.c.

Referenced by handle_message().

#define SOFT_KEY_TEMPLATE_RES_MESSAGE 0x0108

Definition at line 504 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A

Definition at line 169 of file chan_skinny.c.

Referenced by handle_message().

#define SPEED_DIAL_STAT_RES_MESSAGE 0x0091

Definition at line 267 of file chan_skinny.c.

Referenced by handle_message().

#define START_MEDIA_TRANSMISSION_MESSAGE 0x008A

Definition at line 230 of file chan_skinny.c.

Referenced by handle_message().

#define START_TONE_MESSAGE 0x0082

Definition at line 206 of file chan_skinny.c.

Referenced by transmit_tone().

#define STIMULUS_AUTOANSWER 0x11

Definition at line 337 of file chan_skinny.c.

#define STIMULUS_CALLPARK 0x7E

Definition at line 339 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_CALLPICKUP 0x7F

Definition at line 340 of file chan_skinny.c.

#define STIMULUS_CONFERENCE 0x7D

Definition at line 338 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_DISPLAY 0x08

Definition at line 334 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_FORWARDALL 0x05

Definition at line 331 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_FORWARDBUSY 0x06

Definition at line 332 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_FORWARDNOANSWER 0x07

Definition at line 333 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_HOLD 0x03

Definition at line 329 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_LINE 0x09

Definition at line 335 of file chan_skinny.c.

Referenced by handle_message(), skinny_call(), and skinny_hangup().

#define STIMULUS_MESSAGE 0x0005

Definition at line 145 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_NONE 0xFF

Definition at line 341 of file chan_skinny.c.

#define STIMULUS_REDIAL 0x01

Definition at line 327 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_SPEEDDIAL 0x02

Definition at line 328 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_TRANSFER 0x04

Definition at line 330 of file chan_skinny.c.

Referenced by handle_message().

#define STIMULUS_VOICEMAIL 0x0F

Definition at line 336 of file chan_skinny.c.

Referenced by do_housekeeping(), and handle_message().

#define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B

Definition at line 248 of file chan_skinny.c.

Referenced by transmit_callstate().

#define STOP_TONE_MESSAGE 0x0083

Definition at line 211 of file chan_skinny.c.

Referenced by transmit_tone().

#define SUB_ALT 1

Definition at line 710 of file chan_skinny.c.

#define SUB_REAL 0

Definition at line 709 of file chan_skinny.c.

#define TIME_DATE_REQ_MESSAGE 0x000D

Definition at line 179 of file chan_skinny.c.

Referenced by handle_message().

#define TYPE_LINE 2

Definition at line 750 of file chan_skinny.c.

#define TYPE_TRUNK 1

Definition at line 749 of file chan_skinny.c.

#define UNREGISTER_MESSAGE 0x0027

Definition at line 194 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_REQ_MESSAGE 0x000F

Definition at line 180 of file chan_skinny.c.

Referenced by handle_message().

#define VERSION_RES_MESSAGE 0x0098

Definition at line 481 of file chan_skinny.c.

Referenced by handle_message().

## Typedef Documentation

typedef struct buttondefinition button_definition

typedef struct button_defs button_defs_t

typedef unsigned short UINT16

Definition at line 93 of file chan_skinny.c.

typedef unsigned int UINT32

Definition at line 94 of file chan_skinny.c.

typedef unsigned char UINT8

Definition at line 92 of file chan_skinny.c.

## Function Documentation

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

Definition at line 2931 of file chan_skinny.c.

References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_verbose(), destroy_session(), skinnysession::fd, skinnysession::lock, LOG_NOTICE, LOG_WARNING, malloc, skinnysession::next, sessions, skinnysession::sin, and skinny_session().

    02932 {
    02933    int as;
    02934    struct sockaddr_in sin;
    02935    socklen_t sinlen;
    02936    struct skinnysession *s;
    02937    struct protoent *p;
    02938    int arg = 1;
    02939    pthread_attr_t attr;
    02940    pthread_t tcp_thread;
    02941
    02942    pthread_attr_init(&attr);
    02943    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
    02944
    02945    for (;;) {
    02946       sinlen = sizeof(sin);
    02947       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
    02948       if (as < 0) {
    02949          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
    02950          continue;
    02951       }
    02952       p = getprotobyname("tcp");
    02953       if(p) {
    02954          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
    02955             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
    02956          }
    02957       }
    02958       s = malloc(sizeof(struct skinnysession));
    02959       if (!s) {
    02960          ast_log(LOG_WARNING, "Failed to allocate Skinny session: %s\n", strerror(errno));
    02961          continue;
    02962       }
    02963       memset(s, 0, sizeof(struct skinnysession));
    02964       memcpy(&s->sin, &sin, sizeof(sin));
    02965       ast_mutex_init(&s->lock);
    02966       s->fd = as;
    02967       ast_mutex_lock(&sessionlock);
    02968       s->next = sessions;
    02969       sessions = s;
    02970       ast_mutex_unlock(&sessionlock);
    02971
    02972       if (ast_pthread_create(&tcp_thread, &attr, skinny_session, s)) {
    02973          destroy_session(s);
    02974       }
    02975    }
    02976    if (skinnydebug) {
    02977       ast_verbose("killing accept thread\n");
    02978    }
    02979    close(as);
    02980    pthread_attr_destroy(&attr);
    02981    return 0;
    02982 }

AST_MUTEX_DEFINE_STATIC | ( | devicelock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | sessionlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | netlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | monlock |  | ) |

AST_MUTEX_DEFINE_STATIC | ( | usecnt_lock |  | ) |

static struct skinny_device* build_device | ( | char * | cat,
|  | struct ast_variable * | v |
| ) |  |  | `[static, read]`

Definition at line 1481 of file chan_skinny.c.

References __ourip, skinny_device::addr, ast_append_ha(), ast_callerid_split(), ast_cdr_amaflags2int(), ast_get_group(), ast_get_ip(), ast_log(), ast_mutex_init(), ast_ouraddrfor(), ast_strlen_zero(), ast_true(), ast_verbose(), skinny_line::callgroup, skinny_subchannel::callid, skinny_line::callreturn, skinny_line::callwaiting, skinny_line::cancallforward, skinny_line::capability, skinny_line::cid_name, skinny_line::cid_num, skinny_line::context, skinny_subchannel::cxmode, DEFAULT_SKINNY_PORT, free, skinny_device::ha, skinny_line::hookstate, skinny_device::id, skinny_line::immediate, skinny_line::instance, skinny_line::label, skinny_line::language, ast_variable::lineno, skinny_device::lines, skinny_subchannel::lock, skinny_line::lock, LOG_ERROR, LOG_WARNING, skinny_line::mailbox, malloc, MAX_SUBS, skinny_device::model, skinny_line::msgstate, skinny_line::musicclass, skinny_line::mwiblink, skinny_line::name, ast_variable::name, skinny_device::name, skinny_subchannel::nat, ast_variable::next, skinny_line::next, skinny_subchannel::next, skinny_line::onhooktime, skinny_device::ourip, skinny_subchannel::parent, skinny_line::parent, skinny_line::pickupgroup, SKINNY_CX_INACTIVE, SKINNY_ONHOOK, skinny_line::sub, skinny_line::threewaycalling, skinny_line::transfer, skinny_line::type, TYPE_LINE, TYPE_TRUNK, ast_variable::value, VERBOSE_PREFIX_3, and skinny_device::version_id.

Referenced by reload_config().

    01482 {
    01483    struct skinny_device *d;
    01484    struct skinny_line *l;
    01485    struct skinny_subchannel *sub;
    01486    int i=0, y=0;
    01487
    01488    d = malloc(sizeof(struct skinny_device));
    01489    if (d) {
    01490       memset(d, 0, sizeof(struct skinny_device));
    01491       strncpy(d->name, cat, sizeof(d->name) - 1);
    01492       while(v) {
    01493          if (!strcasecmp(v->name, "host")) {
    01494             if (ast_get_ip(&d->addr, v->value)) {
    01495                free(d);
    01496                return NULL;
    01497             }
    01498          } else if (!strcasecmp(v->name, "port")) {
    01499             d->addr.sin_port = htons(atoi(v->value));
    01500          } else if (!strcasecmp(v->name, "device")) {
    01501                   strncpy(d->id, v->value, sizeof(d->id)-1);
    01502          } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
    01503             d->ha = ast_append_ha(v->name, v->value, d->ha);
    01504          } else if (!strcasecmp(v->name, "context")) {
    01505             strncpy(context, v->value, sizeof(context) - 1);
    01506          } else if (!strcasecmp(v->name, "version")) {
    01507                      strncpy(d->version_id, v->value, sizeof(d->version_id) -1);
    01508          } else if (!strcasecmp(v->name, "nat")) {
    01509             nat = ast_true(v->value);
    01510             } else if (!strcasecmp(v->name, "model")) {
    01511             strncpy(d->model, v->value, sizeof(d->model) - 1);
    01512          } else if (!strcasecmp(v->name, "callerid")) {
    01513             if (!strcasecmp(v->value, "asreceived")) {
    01514                cid_num[0] = '\0';
    01515                cid_name[0] = '\0';
    01516             } else {
    01517                ast_callerid_split(v->value, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
    01518             }
    01519          } else if (!strcasecmp(v->name, "language")) {
    01520             strncpy(language, v->value, sizeof(language)-1);
    01521                } else if (!strcasecmp(v->name, "accountcode")) {
    01522                   strncpy(accountcode, v->value, sizeof(accountcode)-1);
    01523                } else if (!strcasecmp(v->name, "amaflags")) {
    01524                   y = ast_cdr_amaflags2int(v->value);
    01525                   if (y < 0) {
    01526                   ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value, v->lineno);
    01527                   } else {
    01528                      amaflags = y;
    01529                      }
    01530          } else if (!strcasecmp(v->name, "musiconhold")) {
    01531                      strncpy(musicclass, v->value, sizeof(musicclass)-1);
    01532                   } else if (!strcasecmp(v->name, "callgroup")) {
    01533                      cur_callergroup = ast_get_group(v->value);
    01534                   } else if (!strcasecmp(v->name, "pickupgroup")) {
    01535                      cur_pickupgroup = ast_get_group(v->value);
    01536                   } else if (!strcasecmp(v->name, "immediate")) {
    01537                      immediate = ast_true(v->value);
    01538                   } else if (!strcasecmp(v->name, "cancallforward")) {
    01539                      cancallforward = ast_true(v->value);
    01540                   } else if (!strcasecmp(v->name, "mailbox")) {
    01541                      strncpy(mailbox, v->value, sizeof(mailbox) -1);
    01542             } else if (!strcasecmp(v->name, "callreturn")) {
    01543             callreturn = ast_true(v->value);
    01544                   } else if (!strcasecmp(v->name, "callwaiting")) {
    01545                      callwaiting = ast_true(v->value);
    01546                   } else if (!strcasecmp(v->name, "transfer")) {
    01547                      transfer = ast_true(v->value);
    01548                   } else if (!strcasecmp(v->name, "threewaycalling")) {
    01549                      threewaycalling = ast_true(v->value);
    01550                   } else if (!strcasecmp(v->name, "mwiblink")) {
    01551                      mwiblink = ast_true(v->value);
    01552             } else if (!strcasecmp(v->name, "linelabel")) {
    01553                   strncpy(linelabel, v->value, sizeof(linelabel)-1);
    01554                   } else if (!strcasecmp(v->name, "trunk") || !strcasecmp(v->name, "line")) {
    01555             l = malloc(sizeof(struct skinny_line));;
    01556             if (l) {
    01557                memset(l, 0, sizeof(struct skinny_line));
    01558                                         ast_mutex_init(&l->lock);
    01559                strncpy(l->name, v->value, sizeof(l->name) - 1);
    01560
    01561                /* XXX Should we check for uniqueness?? XXX */
    01562                strncpy(l->context, context, sizeof(l->context) - 1);
    01563                strncpy(l->cid_num, cid_num, sizeof(l->cid_num) - 1);
    01564                strncpy(l->cid_name, cid_name, sizeof(l->cid_name) - 1);
    01565                strncpy(l->label, linelabel, sizeof(l->label) - 1);
    01566                strncpy(l->language, language, sizeof(l->language) - 1);
    01567                   strncpy(l->musicclass, musicclass, sizeof(l->musicclass)-1);
    01568                strncpy(l->mailbox, mailbox, sizeof(l->mailbox)-1);
    01569                strncpy(l->mailbox, mailbox, sizeof(l->mailbox)-1);
    01570                if (!ast_strlen_zero(mailbox)) {
    01571                   ast_verbose(VERBOSE_PREFIX_3 "Setting mailbox '%s' on %s@%s\n", mailbox, d->name, l->name);
    01572                }
    01573                l->msgstate = -1;
    01574                l->capability = capability;
    01575                l->parent = d;
    01576                if (!strcasecmp(v->name, "trunk")) {
    01577                   l->type = TYPE_TRUNK;
    01578                } else {
    01579                   l->type = TYPE_LINE;
    01580                }
    01581                l->immediate = immediate;
    01582                l->callgroup = cur_callergroup;
    01583                l->pickupgroup = cur_pickupgroup;
    01584                l->callreturn = callreturn;
    01585                   l->cancallforward = cancallforward;
    01586                   l->callwaiting = callwaiting;
    01587                   l->transfer = transfer;
    01588                   l->threewaycalling = threewaycalling;
    01589                   l->mwiblink = mwiblink;
    01590                   l->onhooktime = time(NULL);
    01591                l->instance = 1;
    01592                   /* ASSUME we're onhook at this point*/
    01593                         l->hookstate = SKINNY_ONHOOK;
    01594
    01595                      for (i = 0; i < MAX_SUBS; i++) {
    01596                                  sub = malloc(sizeof(struct skinny_subchannel));
    01597                                  if (sub) {
    01598                                        ast_verbose(VERBOSE_PREFIX_3 "Allocating Skinny subchannel '%d' on %s@%s\n", i, l->name, d->name);
    01599                                        memset(sub, 0, sizeof(struct skinny_subchannel));
    01600                                                         ast_mutex_init(&sub->lock);
    01601                                     sub->parent = l;
    01602                                     /* Make a call*ID */
    01603                      sub->callid = callnums;
    01604                      callnums++;
    01605                                     sub->cxmode = SKINNY_CX_INACTIVE;
    01606                                     sub->nat = nat;
    01607                                     sub->next = l->sub;
    01608                                     l->sub = sub;
    01609                                  } else {
    01610                                     /* XXX Should find a way to clean up our memory */
    01611                                     ast_log(LOG_WARNING, "Out of memory allocating subchannel\n");
    01612                                     return NULL;
    01613                                  }
    01614                            }
    01615                   l->next = d->lines;
    01616                d->lines = l;
    01617                } else {
    01618                   /* XXX Should find a way to clean up our memory */
    01619                            ast_log(LOG_WARNING, "Out of memory allocating line\n");
    01620                            return NULL;
    01621             }
    01622          } else {
    01623             ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name, v->lineno);
    01624          }
    01625          v = v->next;
    01626       }
    01627
    01628       if (!d->lines) {
    01629          ast_log(LOG_ERROR, "A Skinny device must have at least one line!\n");
    01630          return NULL;
    01631       }
    01632       if (d->addr.sin_addr.s_addr && !ntohs(d->addr.sin_port)) {
    01633          d->addr.sin_port = htons(DEFAULT_SKINNY_PORT);
    01634       }
    01635       if (d->addr.sin_addr.s_addr) {
    01636          if (ast_ouraddrfor(&d->addr.sin_addr, &d->ourip)) {
    01637             memcpy(&d->ourip, &__ourip, sizeof(d->ourip));
    01638          }
    01639       } else {
    01640          memcpy(&d->ourip, &__ourip, sizeof(d->ourip));
    01641       }
    01642    }
    01643    return d;
    01644 }

static char* control2str | ( | int | ind | ) | `[static]`

Definition at line 2125 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, and AST_CONTROL_WINK.

    02125                                   {
    02126     static char tmp[100];
    02127
    02128     switch (ind) {
    02129         case AST_CONTROL_HANGUP:
    02130             return "Other end has hungup";
    02131         case AST_CONTROL_RING:
    02132             return "Local ring";
    02133         case AST_CONTROL_RINGING:
    02134             return "Remote end is ringing";
    02135         case AST_CONTROL_ANSWER:
    02136             return "Remote end has answered";
    02137         case AST_CONTROL_BUSY:
    02138             return "Remote end is busy";
    02139         case AST_CONTROL_TAKEOFFHOOK:
    02140             return "Make it go off hook";
    02141         case AST_CONTROL_OFFHOOK:
    02142             return "Line is off hook";
    02143         case AST_CONTROL_CONGESTION:
    02144             return "Congestion (circuits busy)";
    02145         case AST_CONTROL_FLASH:
    02146             return "Flash hook";
    02147         case AST_CONTROL_WINK:
    02148             return "Wink";
    02149         case AST_CONTROL_OPTION:
    02150             return "Set a low-level option";
    02151         case AST_CONTROL_RADIO_KEY:
    02152             return "Key Radio";
    02153         case AST_CONTROL_RADIO_UNKEY:
    02154             return "Un-Key Radio";
    02155         case AST_CONTROL_PROGRESS:
    02156             return "Remote end is making Progress";
    02157         case AST_CONTROL_PROCEEDING:
    02158             return "Remote end is proceeding";
    02159         case AST_CONTROL_HOLD:
    02160             return "Hold";
    02161         case AST_CONTROL_UNHOLD:
    02162             return "Unhold";
    02163    case -1:
    02164        return "Stop tone";
    02165     }
    02166     snprintf(tmp, 100, "UNKNOWN-%d", ind);
    02167     return tmp;
    02168 }

static int convert_cap | ( | int | capability | ) | `[static]`

Definition at line 1006 of file chan_skinny.c.

Referenced by handle_message(), and transmit_connect().

    01007 {
    01008    return 4; /* ulaw (this is not the same as asterisk's '4'  */
    01009
    01010 }

static void delete_devices | ( | void |  | ) | `[static]`

Definition at line 3222 of file chan_skinny.c.

References ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), devices, free, skinny_device::lines, skinny_line::lock, skinny_subchannel::lock, skinny_device::next, skinny_line::next, skinny_subchannel::next, and skinny_line::sub.

Referenced by reload().

    03223 {
    03224    struct skinny_device *d, *dlast;
    03225    struct skinny_line *l, *llast;
    03226    struct skinny_subchannel *sub, *slast;
    03227
    03228    ast_mutex_lock(&devicelock);
    03229
    03230    /* Delete all devices */
    03231    for (d=devices;d;) {
    03232       /* Delete all lines for this device */
    03233       for (l=d->lines;l;) {
    03234          /* Delete all subchannels for this line */
    03235          for (sub=l->sub;sub;) {
    03236             slast = sub;
    03237             sub = sub->next;
    03238             ast_mutex_destroy(&slast->lock);
    03239             free(slast);
    03240          }
    03241          llast = l;
    03242          l = l->next;
    03243          ast_mutex_destroy(&llast->lock);
    03244          free(llast);
    03245       }
    03246       dlast = d;
    03247       d = d->next;
    03248       free(dlast);
    03249    }
    03250    devices=NULL;
    03251    ast_mutex_unlock(&devicelock);
    03252 }

char* description | ( | void |  | ) |

Provides a description of the module.

Returns:
  a short description of your module

Definition at line 3365 of file chan_skinny.c.

    03366 {
    03367    return (char *) desc;
    03368 }

static void destroy_session | ( | struct skinnysession * | s | ) | `[static]`

Definition at line 2816 of file chan_skinny.c.

References ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), skinnysession::fd, free, skinnysession::lock, LOG_WARNING, skinnysession::next, and sessions.

    02817 {
    02818    struct skinnysession *cur, *prev = NULL;
    02819    ast_mutex_lock(&sessionlock);
    02820    cur = sessions;
    02821    while(cur) {
    02822       if (cur == s) {
    02823          break;
    02824       }
    02825       prev = cur;
    02826       cur = cur->next;
    02827    }
    02828    if (cur) {
    02829       if (prev) {
    02830          prev->next = cur->next;
    02831       } else {
    02832          sessions = cur->next;
    02833       }
    02834       if (s->fd > -1) {
    02835          close(s->fd);
    02836       }
    02837       ast_mutex_destroy(&s->lock);
    02838       free(s);
    02839    } else {
    02840       ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
    02841    }
    02842    ast_mutex_unlock(&sessionlock);
    02843 }

static void do_housekeeping | ( | struct skinnysession * | s | ) | `[static]`

Definition at line 1303 of file chan_skinny.c.

References ast_app_messagecount(), ast_verbose(), skinnysession::device, find_subchannel_by_line(), has_voicemail(), skinny_line::instance, skinny_device::lines, skinny_line::mailbox, skinny_line::mwiblink, skinny_device::name, skinny_line::name, skinny_line::parent, skinny_subchannel::parent, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, STIMULUS_VOICEMAIL, transmit_displaymessage(), and transmit_lamp_indication().

Referenced by handle_message(), and skinny_hangup().

    01304 {
    01305    int new;
    01306    int old;
    01307    struct skinny_subchannel *sub;
    01308    struct skinny_line *l = s->device->lines;
    01309
    01310    sub = find_subchannel_by_line(l);
    01311    transmit_displaymessage(s, NULL);
    01312
    01313    if (has_voicemail(sub->parent)) {
    01314       if (skinnydebug) {
    01315          ast_verbose("Checking for voicemail Skinny %s@%s\n", sub->parent->name, sub->parent->parent->name);
    01316       }
    01317       ast_app_messagecount(sub->parent->mailbox, &new, &old);
    01318       if (skinnydebug) {
    01319          ast_verbose("Skinny %s@%s has voicemail!\n", sub->parent->name, sub->parent->parent->name);
    01320       }
    01321       transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, l->mwiblink?SKINNY_LAMP_BLINK:SKINNY_LAMP_ON);
    01322    } else {
    01323       transmit_lamp_indication(s, STIMULUS_VOICEMAIL, l->instance, SKINNY_LAMP_OFF);
    01324    }
    01325
    01326 }

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

Definition at line 2984 of file chan_skinny.c.

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

    02985 {
    02986    int res;
    02987
    02988    /* This thread monitors all the interfaces which are not yet in use
    02989       (and thus do not have a separate thread) indefinitely */
    02990    /* From here on out, we die whenever asked */
    02991    for(;;) {
    02992       pthread_testcancel();
    02993       /* Wait for sched or io */
    02994       res = ast_sched_wait(sched);
    02995       if ((res < 0) || (res > 1000)) {
    02996          res = 1000;
    02997       }
    02998       res = ast_io_wait(io, res);
    02999       ast_mutex_lock(&monlock);
    03000       if (res >= 0) {
    03001          ast_sched_runq(sched);
    03002       }
    03003       ast_mutex_unlock(&monlock);
    03004    }
    03005    /* Never reached */
    03006    return NULL;
    03007
    03008 }

static struct skinny_subchannel* find_subchannel_by_line | ( | struct skinny_line * | l | ) | `[static, read]`

Definition at line 937 of file chan_skinny.c.

References skinny_line::sub.

Referenced by do_housekeeping(), and handle_message().

    00938 {
    00939    /* XXX Need to figure out how to determine which sub we want */
    00940    struct skinny_subchannel *sub = l->sub;
    00941    return sub;
    00942 }

static struct skinny_subchannel* find_subchannel_by_name | ( | char * | dest | ) | `[static, read]`

Definition at line 944 of file chan_skinny.c.

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

Referenced by skinny_request().

    00945 {
    00946    struct skinny_line *l;
    00947    struct skinny_device *d;
    00948    char line[256];
    00949    char *at;
    00950    char *device;
    00951
    00952    strncpy(line, dest, sizeof(line) - 1);
    00953    at = strchr(line, '@');
    00954    if (!at) {
    00955       ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
    00956       return NULL;
    00957    }
    00958    *at = '\0';
    00959    at++;
    00960    device = at;
    00961    ast_mutex_lock(&devicelock);
    00962    d = devices;
    00963    while(d) {
    00964       if (!strcasecmp(d->name, device)) {
    00965          if (skinnydebug) {
    00966             ast_verbose("Found device: %s\n", d->name);
    00967          }
    00968          /* Found the device */
    00969          l = d->lines;
    00970          while (l) {
    00971             /* Search for the right line */
    00972             if (!strcasecmp(l->name, line)) {
    00973                ast_mutex_unlock(&devicelock);
    00974                return l->sub;
    00975             }
    00976             l = l->next;
    00977          }
    00978       }
    00979       d = d->next;
    00980    }
    00981    /* Device not found*/
    00982    ast_mutex_unlock(&devicelock);
    00983    return NULL;
    00984 }

static int get_input | ( | struct skinnysession * | s | ) | `[static]`

Definition at line 2845 of file chan_skinny.c.

References ast_log(), pollfd::events, skinnysession::fd, pollfd::fd, htolel, skinnysession::inbuf, letohl, LOG_WARNING, poll(), and POLLIN.

    02846 {
    02847    int res;
    02848    int dlen = 0;
    02849    struct pollfd fds[1];
    02850
    02851    fds[0].fd = s->fd;
    02852    fds[0].events = POLLIN;
    02853    res = poll(fds, 1, -1);
    02854
    02855    if (res < 0) {
    02856       ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
    02857    } else if (res > 0) {
    02858       memset(s->inbuf,0,sizeof(s->inbuf));
    02859       res = read(s->fd, s->inbuf, 4);
    02860       if (res != 4) {
    02861          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
    02862          return -1;
    02863       }
    02864       dlen = letohl(*(int *)s->inbuf);
    02865       if (dlen < 4) {
    02866          ast_log(LOG_WARNING, "Skinny Client sent invalid data.\n");
    02867          return -1;
    02868       }
    02869       if (dlen+8 > sizeof(s->inbuf)) {
    02870          dlen = sizeof(s->inbuf) - 8;
    02871       }
    02872       *(int *)s->inbuf = htolel(dlen);
    02873       res = read(s->fd, s->inbuf+4, dlen+4);
    02874       if (res != (dlen+4)) {
    02875          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
    02876          return -1;
    02877       }
    02878    }
    02879    return res;
    02880 }

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

Definition at line 2303 of file chan_skinny.c.

References __ourip, ALARM_MESSAGE, skinny_subchannel::alreadygone, AST_CONTROL_ANSWER, AST_FRAME_DTMF, ast_hangup(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_queue_control(), ast_queue_frame(), ast_queue_hangup(), ast_rtp_get_us(), ast_rtp_set_peer(), ast_setstate(), AST_STATE_DOWN, AST_STATE_UP, ast_verbose(), attempt_transfer(), media_qualifier::bitRate, keypad_button_message::button, button_defs::button_def, BUTTON_TEMPLATE_REQ_MESSAGE, BUTTON_TEMPLATE_RES_MESSAGE, button_template_res_message::buttonCount, button_template_res_message::buttonOffset, skinny_req::buttontemplate, skinny_subchannel::callid, CAPABILITIES_REQ_MESSAGE, CAPABILITIES_RES_MESSAGE, skinny_line::capability, start_media_transmission_message::conferenceId, convert_cap(), skinny_subchannel::cxmode, skinny_req::data, register_ack_message::dateTemplate, definetimedate_message::day, definetimedate_message::dayofweek, skinny_req::definetimedate, DEFINETIMEDATE_MESSAGE, button_template_res_message::definition, skinnysession::device, skinny_line::dnd, do_housekeeping(), skinny_req::e, register_rej_message::errMsg, find_subchannel_by_line(), ast_frame::frametype, free, skinny_line::hookstate, definetimedate_message::hour, htolel, skinny_line::instance, IP_PORT_MESSAGE, open_recieve_channel_ack_message::ipAddr, KEEP_ALIVE_ACK_MESSAGE, KEEP_ALIVE_MESSAGE, register_ack_message::keepAlive, skinny_req::keypad, KEYPAD_BUTTON_MESSAGE, skinny_line::label, skinny_req::len, letohl, skinny_req::line, LINE_STAT_RES_MESSAGE, LINE_STATE_REQ_MESSAGE, line_stat_res_message::lineDirNumber, line_stat_res_message::lineDisplayName, line_stat_res_message::linenumber, line_state_req_message::lineNumber, skinny_device::lines, skinny_req::linestat, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, definetimedate_message::minute, skinny_device::model, definetimedate_message::month, ast_channel::name, skinny_line::name, skinny_device::name, register_message::name, name, skinny_subchannel::next, skinny_line::next, button_defs::num_buttons, OFFHOOK_MESSAGE, ONHOOK_MESSAGE, OPEN_RECIEVE_CHANNEL_ACK_MESSAGE, skinny_req::openrecievechannelack, option_verbose, skinny_device::ourip, skinny_subchannel::outgoing, skinny_subchannel::owner, media_qualifier::packets, start_media_transmission_message::packetSize, skinny_line::parent, skinny_subchannel::parent, start_media_transmission_message::passThruPartyId, start_media_transmission_message::payloadType, open_recieve_channel_ack_message::port, media_qualifier::precedence, start_media_transmission_message::qualifier, skinny_req::reg, skinny_req::regack, REGISTER_ACK_MESSAGE, REGISTER_MESSAGE, REGISTER_REJ_MESSAGE, skinny_req::regrej, start_media_transmission_message::remoteIp, start_media_transmission_message::remotePort, register_ack_message::res, register_ack_message::res2, skinny_subchannel::rtp, register_ack_message::secondaryKeepAlive, definetimedate_message::seconds, server_res_message::server, SERVER_REQUEST_MESSAGE, SERVER_RES_MESSAGE, server_res_message::serverIpAddr, server_res_message::serverListenPort, server_identifier::serverName, skinny_req::serverres, SKINNY_CONNECTED, SKINNY_CX_RECVONLY, SKINNY_DIALTONE, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_MAX_PACKET, skinny_new(), SKINNY_OFFHOOK, SKINNY_ONHOOK, skinny_register(), SKINNY_RING_OFF, SKINNY_SILENCE, skinny_ss(), SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_SET_RES_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SOFT_KEY_TEMPLATE_RES_MESSAGE, soft_key_template::softKeyCount, soft_key_template::softKeyOffset, soft_key_sets::softKeySetCount, soft_key_sets::softKeySetDefinition, soft_key_sets::softKeySetOffset, skinny_req::softkeysets, skinny_req::softkeytemplate, soft_key_template::softKeyTemplateDefinition, SPEED_DIAL_STAT_REQ_MESSAGE, SPEED_DIAL_STAT_RES_MESSAGE, skinny_req::speeddial, speed_dial_stat_res_message::speedDialDirNumber, speed_dial_stat_res_message::speedDialDisplayName, speed_dial_stat_req_message::speedDialNumber, skinny_req::speeddialreq, ast_frame::src, START_MEDIA_TRANSMISSION_MESSAGE, start_rtp(), skinny_req::startmedia, open_recieve_channel_ack_message::status, stimulus_message::stimulus, skinny_req::stimulus, STIMULUS_CALLPARK, STIMULUS_CONFERENCE, STIMULUS_DISPLAY, STIMULUS_FORWARDALL, STIMULUS_FORWARDBUSY, STIMULUS_FORWARDNOANSWER, STIMULUS_HOLD, STIMULUS_LINE, STIMULUS_MESSAGE, STIMULUS_REDIAL, STIMULUS_SPEEDDIAL, STIMULUS_TRANSFER, STIMULUS_VOICEMAIL, stimulus_message::stimulusInstance, ast_frame::subclass, t, TIME_DATE_REQ_MESSAGE, button_template_res_message::totalButtonCount, soft_key_template::totalSoftKeyCount, soft_key_sets::totalSoftKeySetCount, skinny_line::transfer, transmit_callstate(), transmit_displaymessage(), transmit_displaynotify(), transmit_lamp_indication(), transmit_response(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_tone(), button_defs::type, UNREGISTER_MESSAGE, media_qualifier::vad, VERBOSE_PREFIX_3, version_res_message::version, skinny_req::version, skinny_device::version_id, VERSION_REQ_MESSAGE, VERSION_RES_MESSAGE, and definetimedate_message::year.

Referenced by skinny_session().

    02304 {
    02305    struct skinny_subchannel *sub;
    02306    struct ast_channel *c;
    02307    struct ast_frame f = { 0, };
    02308    struct sockaddr_in sin;
    02309    struct sockaddr_in us;
    02310    struct skinny_line *lines;
    02311    char name[16];
    02312    char addr[4];
    02313    char d;
    02314    char iabuf[INET_ADDRSTRLEN];
    02315    int digit;
    02316    int res=0;
    02317    int speedDialNum;
    02318    int lineNumber;
    02319    int stimulus;
    02320    int stimulusInstance;
    02321    int status;
    02322    int port;
    02323    int i;
    02324    time_t timer;
    02325    struct tm *cmtime;
    02326    pthread_t t;
    02327    button_defs_t *b, *buse;
    02328
    02329    if ((!s->device) && (letohl(req->e) != REGISTER_MESSAGE && letohl(req->e) != ALARM_MESSAGE)) {
    02330       ast_log(LOG_WARNING, "Client sent message #%d without first registering.\n", req->e);
    02331       free(req);
    02332       return 0;
    02333    }
    02334
    02335    switch(letohl(req->e))  {
    02336    case ALARM_MESSAGE:
    02337       /* no response necessary */
    02338       break;
    02339    case REGISTER_MESSAGE:
    02340       if (skinnydebug) {
    02341          ast_verbose("Device %s is attempting to register\n", req->data.reg.name);
    02342       }
    02343       res = skinny_register(req, s);
    02344       if (!res) {
    02345          ast_log(LOG_ERROR, "Rejecting Device %s: Device not found\n", req->data.reg.name);
    02346          memcpy(&name, req->data.reg.name, sizeof(req->data.reg.name));
    02347          memset(req, 0, sizeof(skinny_req));
    02348          req->len = htolel(sizeof(register_rej_message)+4);
    02349          req->e = htolel(REGISTER_REJ_MESSAGE);
    02350          snprintf(req->data.regrej.errMsg, sizeof(req->data.regrej.errMsg), "No Authority: %s", name);
    02351          transmit_response(s, req);
    02352          break;
    02353       }
    02354       if (option_verbose > 2) {
    02355          ast_verbose(VERBOSE_PREFIX_3 "Device '%s' successfuly registered\n", s->device->name);
    02356       }
    02357       memset(req, 0, SKINNY_MAX_PACKET);
    02358       req->len = htolel(sizeof(register_ack_message)+4);
    02359       req->e = htolel(REGISTER_ACK_MESSAGE);
    02360       req->data.regack.res[0] = '0';
    02361       req->data.regack.res[1] = '\0';
    02362       req->data.regack.keepAlive = htolel(keep_alive);
    02363       strncpy(req->data.regack.dateTemplate, date_format, sizeof(req->data.regack.dateTemplate) - 1);
    02364       req->data.regack.res2[0] = '0';
    02365       req->data.regack.res2[1] = '\0';
    02366       req->data.regack.secondaryKeepAlive = htolel(keep_alive);
    02367       transmit_response(s, req);
    02368       if (skinnydebug) {
    02369          ast_verbose("Requesting capabilities\n");
    02370       }
    02371       memset(req, 0, SKINNY_MAX_PACKET);
    02372       req->len = htolel(4);
    02373       req->e = htolel(CAPABILITIES_REQ_MESSAGE);
    02374       transmit_response(s, req);
    02375       break;
    02376    case UNREGISTER_MESSAGE:
    02377       /* XXX Acutally unregister the device */
    02378       break;
    02379    case IP_PORT_MESSAGE:
    02380       /* no response necessary */
    02381       break;
    02382    case STIMULUS_MESSAGE:
    02383       stimulus = letohl(req->data.stimulus.stimulus);
    02384       stimulusInstance = letohl(req->data.stimulus.stimulusInstance);
    02385
    02386       switch(stimulus) {
    02387       case STIMULUS_REDIAL:
    02388          /* If we can keep an array of dialed frames we can implement a quick
    02389             and dirty redial, feeding the frames we last got into the queue
    02390             function */
    02391          if (skinnydebug) {
    02392             ast_verbose("Recieved Stimulus: Redial(%d)\n", stimulusInstance);
    02393          }
    02394          break;
    02395       case STIMULUS_SPEEDDIAL:
    02396          if (skinnydebug) {
    02397             ast_verbose("Recieved Stimulus: SpeedDial(%d)\n", stimulusInstance);
    02398          }
    02399          break;
    02400       case STIMULUS_HOLD:
    02401          /* start moh? set RTP to 0.0.0.0? */
    02402          if (skinnydebug) {
    02403             ast_verbose("Recieved Stimulus: Hold(%d)\n", stimulusInstance);
    02404          }
    02405          break;
    02406       case STIMULUS_TRANSFER:
    02407          if (skinnydebug) {
    02408             ast_verbose("Recieved Stimulus: Transfer(%d)\n", stimulusInstance);
    02409          }
    02410          transmit_tone(s, SKINNY_DIALTONE);
    02411          /* XXX figure out how to transfer */
    02412          break;
    02413       case STIMULUS_CONFERENCE:
    02414          if (skinnydebug) {
    02415             ast_verbose("Recieved Stimulus: Transfer(%d)\n", stimulusInstance);
    02416          }
    02417          transmit_tone(s, SKINNY_DIALTONE);
    02418          /* XXX determine the best way to pull off a conference.  Meetme?  */
    02419          break;
    02420       case STIMULUS_VOICEMAIL:
    02421          if (skinnydebug) {
    02422             ast_verbose("Recieved Stimulus: Voicemail(%d)\n", stimulusInstance);
    02423          }
    02424          /* XXX Find and dial voicemail extension */
    02425          break;
    02426       case STIMULUS_CALLPARK:
    02427          if (skinnydebug) {
    02428             ast_verbose("Recieved Stimulus: Park Call(%d)\n", stimulusInstance);
    02429          }
    02430          /* XXX Park the call */
    02431          break;
    02432       case STIMULUS_FORWARDALL:
    02433          /* Why is DND under FORWARDALL ? */
    02434
    02435          /* Do not disturb */
    02436          transmit_tone(s, SKINNY_DIALTONE);
    02437          if (s->device->lines->dnd != 0){
    02438             if (option_verbose > 2) {
    02439                ast_verbose(VERBOSE_PREFIX_3 "Disabling DND on %s@%s\n",find_subchannel_by_line(s->device->lines)->parent->name,find_subchannel_by_line(s->device->lines)->parent->name);
    02440             }
    02441             s->device->lines->dnd = 0;
    02442             transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_ON);
    02443             transmit_displaynotify(s, "DnD disabled",10);
    02444          } else {
    02445             if (option_verbose > 2) {
    02446                ast_verbose(VERBOSE_PREFIX_3 "Enabling DND on %s@%s\n",find_subchannel_by_line(s->device->lines)->parent->name,find_subchannel_by_line(s->device->lines)->parent->name);
    02447             }
    02448             s->device->lines->dnd = 1;
    02449             transmit_lamp_indication(s, STIMULUS_FORWARDALL, 1, SKINNY_LAMP_OFF);
    02450             transmit_displaynotify(s, "DnD enabled",10);
    02451          }
    02452          break;
    02453       case STIMULUS_FORWARDBUSY:
    02454       case STIMULUS_FORWARDNOANSWER:
    02455          /* Gonna be fun, not */
    02456          if (skinnydebug) {
    02457             ast_verbose("Recieved Stimulus: Forward (%d)\n", stimulusInstance);
    02458          }
    02459          break;
    02460       case STIMULUS_DISPLAY:
    02461          /* Not sure what this is */
    02462          if (skinnydebug) {
    02463             ast_verbose("Recieved Stimulus: Display(%d)\n", stimulusInstance);
    02464          }
    02465          break;
    02466       case STIMULUS_LINE:
    02467          if (skinnydebug) {
    02468             ast_verbose("Recieved Stimulus: Line(%d)\n", stimulusInstance);
    02469          }
    02470          sub = find_subchannel_by_line(s->device->lines);
    02471          /* turn the speaker on */
    02472          transmit_speaker_mode(s, 1);
    02473       break;
    02474       default:
    02475          ast_verbose("RECEIVED UNKNOWN STIMULUS:  %d(%d)\n", stimulus, stimulusInstance);
    02476          break;
    02477       }
    02478       break;
    02479    case VERSION_REQ_MESSAGE:
    02480       if (skinnydebug) {
    02481          ast_verbose("Version Request\n");
    02482       }
    02483       memset(req, 0, SKINNY_MAX_PACKET);
    02484       req->len = htolel(sizeof(version_res_message)+4);
    02485       req->e = htolel(VERSION_RES_MESSAGE);
    02486       snprintf(req->data.version.version, sizeof(req->data.version.version), s->device->version_id);
    02487       transmit_response(s, req);
    02488       break;
    02489    case SERVER_REQUEST_MESSAGE:
    02490       if (skinnydebug) {
    02491          ast_verbose("Recieved Server Request\n");
    02492       }
    02493       memset(req, 0, SKINNY_MAX_PACKET);
    02494       req->len = htolel(sizeof(server_res_message)+4);
    02495       req->e = htolel(SERVER_RES_MESSAGE);
    02496       memcpy(req->data.serverres.server[0].serverName, ourhost,
    02497             sizeof(req->data.serverres.server[0].serverName));
    02498       req->data.serverres.serverListenPort[0] = htolel(ourport);
    02499       req->data.serverres.serverIpAddr[0] = htolel(__ourip.s_addr);
    02500       transmit_response(s, req);
    02501       break;
    02502    case BUTTON_TEMPLATE_REQ_MESSAGE:
    02503       if (skinnydebug) {
    02504          ast_verbose("Buttontemplate requested\n");
    02505       }
    02506       sub = find_subchannel_by_line(s->device->lines);
    02507       memset(req, 0, SKINNY_MAX_PACKET);
    02508       req->e = htolel(BUTTON_TEMPLATE_RES_MESSAGE);
    02509       req->len = htolel(sizeof(button_template_res_message)+4);
    02510
    02511       /* Find a matching button definition, default to first in the
    02512          list */
    02513       buse = button_defs;
    02514       for(b=button_defs; b->type; b++) {
    02515          if (!strcmp(s->device->model, b->type)) {
    02516             buse = b;
    02517          }
    02518       }
    02519       req->data.buttontemplate.buttonOffset = 0;
    02520       req->data.buttontemplate.buttonCount  = htolel(buse->num_buttons);
    02521       req->data.buttontemplate.totalButtonCount = htolel(buse->num_buttons);
    02522       for (i=0; i<42; i++) {
    02523          if (i < buse->num_buttons) {
    02524             memcpy(&(req->data.buttontemplate.definition[i]),
    02525                &(buse->button_def[i]),
    02526                sizeof(button_definition));
    02527          } else {
    02528             memcpy(&(req->data.buttontemplate.definition[i]),
    02529                &(button_def_none),
    02530                sizeof(button_definition));
    02531          }
    02532       }
    02533
    02534       if (skinnydebug) {
    02535          ast_verbose("Sending %s template to %s@%s (%s)\n",
    02536                   buse->type,
    02537                   sub->parent->name,
    02538                   sub->parent->parent->name,
    02539                   s->device->model);
    02540       }
    02541       transmit_response(s, req);
    02542       break;
    02543    case SOFT_KEY_SET_REQ_MESSAGE:
    02544       if (skinnydebug)  {
    02545          ast_verbose("Received SoftKeySetReq\n");
    02546       }
    02547       memset(req, 0, SKINNY_MAX_PACKET);
    02548       req->len = htolel(sizeof(soft_key_sets)+4);
    02549       req->e = htolel(SOFT_KEY_SET_RES_MESSAGE);
    02550       req->data.softkeysets.softKeySetOffset = 0;
    02551       req->data.softkeysets.softKeySetCount = htolel(11);
    02552       req->data.softkeysets.totalSoftKeySetCount = htolel(11);
    02553       /* XXX Wicked hack XXX */
    02554       memcpy(req->data.softkeysets.softKeySetDefinition,
    02555             soft_key_set_hack,
    02556             sizeof(req->data.softkeysets.softKeySetDefinition));
    02557       transmit_response(s,req);
    02558       break;
    02559    case SOFT_KEY_TEMPLATE_REQ_MESSAGE:
    02560       if (skinnydebug) {
    02561          ast_verbose("Recieved SoftKey Template Request\n");
    02562       }
    02563       memset(req, 0, SKINNY_MAX_PACKET);
    02564       req->len = htolel(sizeof(soft_key_template)+4);
    02565       req->e = htolel(SOFT_KEY_TEMPLATE_RES_MESSAGE);
    02566       req->data.softkeytemplate.softKeyOffset = 0;
    02567       req->data.softkeytemplate.softKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
    02568       req->data.softkeytemplate.totalSoftKeyCount = htolel(sizeof(soft_key_template_default) / sizeof(soft_key_template_definition));
    02569       memcpy(req->data.softkeytemplate.softKeyTemplateDefinition,
    02570             soft_key_template_default,
    02571             sizeof(soft_key_template_default));
    02572       transmit_response(s,req);
    02573       break;
    02574    case TIME_DATE_REQ_MESSAGE:
    02575       if (skinnydebug) {
    02576          ast_verbose("Received Time/Date Request\n");
    02577       }
    02578       memset(req, 0, SKINNY_MAX_PACKET);
    02579       req->len = htolel(sizeof(definetimedate_message)+4);
    02580       req->e = htolel(DEFINETIMEDATE_MESSAGE);
    02581       timer=time(NULL);
    02582       cmtime = localtime(&timer);
    02583       req->data.definetimedate.year = htolel(cmtime->tm_year+1900);
    02584       req->data.definetimedate.month = htolel(cmtime->tm_mon+1);
    02585       req->data.definetimedate.dayofweek = htolel(cmtime->tm_wday);
    02586       req->data.definetimedate.day = htolel(cmtime->tm_mday);
    02587       req->data.definetimedate.hour = htolel(cmtime->tm_hour);
    02588       req->data.definetimedate.minute = htolel(cmtime->tm_min);
    02589       req->data.definetimedate.seconds = htolel(cmtime->tm_sec);
    02590       transmit_response(s, req);
    02591       break;
    02592    case SPEED_DIAL_STAT_REQ_MESSAGE:
    02593       /* Not really sure how Speed Dial's are different than the
    02594          Softkey templates */
    02595       speedDialNum = letohl(req->data.speeddialreq.speedDialNumber);
    02596       memset(req, 0, SKINNY_MAX_PACKET);
    02597       req->len = htolel(sizeof(speed_dial_stat_res_message)+4);
    02598       req->e = htolel(SPEED_DIAL_STAT_RES_MESSAGE);
    02599 #if 0
    02600       /* XXX Do this right XXX */
    02601       /* If the redial function works the way I think it will, a modification of it
    02602          can work here was well. Yikes. */
    02603       req->data.speeddialreq.speedDialNumber = speedDialNum;
    02604       snprintf(req->data.speeddial.speedDialDirNumber, sizeof(req->data.speeddial.speedDialDirNumber), "31337");
    02605       snprintf(req->data.speeddial.speedDialDisplayName,  sizeof(req->data.speeddial.speedDialDisplayName),"Asterisk Rules!");
    02606 #endif
    02607       transmit_response(s, req);
    02608       break;
    02609    case LINE_STATE_REQ_MESSAGE:
    02610       lineNumber = letohl(req->data.line.lineNumber);
    02611       if (skinnydebug) {
    02612          ast_verbose("Received LineStateReq\n");
    02613       }
    02614       memset(req, 0, SKINNY_MAX_PACKET);
    02615       req->len = htolel(sizeof(line_stat_res_message)+4);
    02616       req->e = htolel(LINE_STAT_RES_MESSAGE);
    02617       sub = find_subchannel_by_line(s->device->lines);
    02618       if (!sub) {
    02619          ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
    02620          return 0;
    02621       }
    02622       lines = sub->parent;
    02623       ast_mutex_lock(&devicelock);
    02624       for (i=1; i < lineNumber; i++) {
    02625          lines = lines->next;
    02626       }
    02627       ast_mutex_unlock(&devicelock);
    02628       req->data.linestat.linenumber = letohl(lineNumber);
    02629       memcpy(req->data.linestat.lineDirNumber, lines->name,
    02630             sizeof(req->data.linestat.lineDirNumber));
    02631       memcpy(req->data.linestat.lineDisplayName, lines->label,
    02632             sizeof(req->data.linestat.lineDisplayName));
    02633       transmit_response(s,req);
    02634       break;
    02635    case CAPABILITIES_RES_MESSAGE:
    02636       if (skinnydebug) {
    02637          ast_verbose("Received CapabilitiesRes\n");
    02638       }
    02639       /* XXX process the capabilites  */
    02640       break;
    02641    case KEEP_ALIVE_MESSAGE:
    02642       memset(req, 0, SKINNY_MAX_PACKET);
    02643       req->len = htolel(4);
    02644       req->e = htolel(KEEP_ALIVE_ACK_MESSAGE);
    02645       transmit_response(s, req);
    02646       do_housekeeping(s);
    02647       break;
    02648    case OFFHOOK_MESSAGE:
    02649       transmit_ringer_mode(s,SKINNY_RING_OFF);
    02650       transmit_lamp_indication(s, STIMULUS_LINE, s->device->lines->instance, SKINNY_LAMP_ON);
    02651       sub = find_subchannel_by_line(s->device->lines);
    02652       if (!sub) {
    02653          ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
    02654          return 0;
    02655       }
    02656       sub->parent->hookstate = SKINNY_OFFHOOK;
    02657
    02658       if (sub->outgoing) {
    02659          /* We're answering a ringing call */
    02660          ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
    02661          transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, sub->callid);
    02662          transmit_tone(s, SKINNY_SILENCE);
    02663          transmit_callstate(s, s->device->lines->instance, SKINNY_CONNECTED, sub->callid);
    02664          start_rtp(sub);
    02665          ast_setstate(sub->owner, AST_STATE_UP);
    02666          /* XXX select the appropriate soft key here */
    02667       } else {
    02668          if (!sub->owner) {
    02669             transmit_callstate(s, s->device->lines->instance, SKINNY_OFFHOOK, sub->callid);
    02670             if (skinnydebug) {
    02671                ast_verbose("Attempting to Clear display on Skinny %s@%s\n",sub->parent->name, sub->parent->parent->name);
    02672             }
    02673             transmit_displaymessage(s, NULL); /* clear display */
    02674             transmit_tone(s, SKINNY_DIALTONE);
    02675             c = skinny_new(sub, AST_STATE_DOWN);
    02676             if(c) {
    02677                /* start the switch thread */
    02678                if (ast_pthread_create(&t, NULL, skinny_ss, c)) {
    02679                   ast_log(LOG_WARNING, "Unable to create switch thread: %s\n", strerror(errno));
    02680                   ast_hangup(c);
    02681                }
    02682             } else {
    02683                ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
    02684             }
    02685          } else {
    02686             ast_log(LOG_DEBUG, "Current sub [%s] already has owner\n", sub->owner->name);
    02687          }
    02688       }
    02689       break;
    02690    case ONHOOK_MESSAGE:
    02691       sub = find_subchannel_by_line(s->device->lines);
    02692       if (sub->parent->hookstate == SKINNY_ONHOOK) {
    02693          /* Somthing else already put us back on hook */
    02694          break;
    02695       }
    02696       sub->cxmode = SKINNY_CX_RECVONLY;
    02697       sub->parent->hookstate = SKINNY_ONHOOK;
    02698       transmit_callstate(s, s->device->lines->instance, sub->parent->hookstate,sub->callid);
    02699       if (skinnydebug) {
    02700          ast_verbose("Skinny %s@%s went on hook\n",sub->parent->name, sub->parent->parent->name);
    02701          }
    02702                if (sub->parent->transfer && (sub->owner && sub->next->owner) && ((!sub->outgoing) || (!sub->next->outgoing))) {
    02703          /* We're allowed to transfer, we have two active calls and */
    02704          /* we made at least one of the calls.  Let's try and transfer */
    02705
    02706 #if 0
    02707                if ((res = attempt_transfer(p)) < 0) {
    02708              if (p->sub->next->owner) {
    02709                sub->next->alreadygone = 1;
    02710                ast_queue_hangup(sub->next->owner,1);
    02711             }
    02712          } else if (res) {
    02713             ast_log(LOG_WARNING, "Transfer attempt failed\n");
    02714             return -1;
    02715                   }
    02716 #endif
    02717       } else {
    02718                /* Hangup the current call */
    02719                /* If there is another active call, skinny_hangup will ring the phone with the other call */
    02720                if (sub->owner) {
    02721                   sub->alreadygone = 1;
    02722                   ast_queue_hangup(sub->owner);
    02723                } else {
    02724                   ast_log(LOG_WARNING, "Skinny(%s@%s-%d) channel already destroyed\n",
    02725                              sub->parent->name, sub->parent->parent->name, sub->callid);
    02726                }
    02727             }
    02728             if ((sub->parent->hookstate == SKINNY_ONHOOK) && (!sub->next->rtp)) {
    02729          do_housekeeping(s);
    02730          }
    02731       break;
    02732    case KEYPAD_BUTTON_MESSAGE:
    02733       digit = letohl(req->data.keypad.button);
    02734       if (skinnydebug) {
    02735          ast_verbose("Collected digit: [%d]\n", digit);
    02736       }
    02737       f.frametype = AST_FRAME_DTMF;
    02738       if (digit == 14) {
    02739          d = '*';
    02740       } else if (digit == 15) {
    02741          d = '#';
    02742       } else if (digit >=0 && digit <= 9) {
    02743          d = '0' + digit;
    02744       } else {
    02745          /* digit=10-13 (A,B,C,D ?), or
    02746           * digit is bad value
    02747           *
    02748           * probably should not end up here, but set
    02749           * value for backward compatibility, and log
    02750           * a warning.
    02751           */
    02752          d = '0' + digit;
    02753          ast_log(LOG_WARNING, "Unsupported digit %d\n", digit);
    02754       }
    02755       f.subclass  = d;
    02756       f.src = "skinny";
    02757       sub = find_subchannel_by_line(s->device->lines);
    02758       if (sub->owner) {
    02759          /* XXX MUST queue this frame to all subs in threeway call if threeway call is active */
    02760          ast_queue_frame(sub->owner, &f);
    02761                   if (sub->next->owner) {
    02762             ast_queue_frame(sub->next->owner, &f);
    02763                   }
    02764          } else {
    02765          ast_verbose("No owner: %s\n", s->device->lines->name);
    02766       }
    02767       break;
    02768    case OPEN_RECIEVE_CHANNEL_ACK_MESSAGE:
    02769       ast_verbose("Recieved Open Recieve Channel Ack\n");
    02770       status = letohl(req->data.openrecievechannelack.status);
    02771       if (status) {
    02772          ast_log(LOG_ERROR, "Open Recieve Channel Failure\n");
    02773          break;
    02774       }
    02775       /* ENDIAN */
    02776       memcpy(addr, req->data.openrecievechannelack.ipAddr, sizeof(addr));
    02777       port = htolel(req->data.openrecievechannelack.port);
    02778       sin.sin_family = AF_INET;
    02779       /* I smell endian problems */
    02780       memcpy(&sin.sin_addr, addr, sizeof(sin.sin_addr));
    02781       sin.sin_port = htons(port);
    02782       if (skinnydebug) {
    02783          ast_verbose("ipaddr = %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), sin.sin_addr), ntohs(sin.sin_port));
    02784       }
    02785       sub = find_subchannel_by_line(s->device->lines);
    02786       if (sub->rtp) {
    02787          ast_rtp_set_peer(sub->rtp, &sin);
    02788          ast_rtp_get_us(sub->rtp, &us);
    02789       } else {
    02790          ast_log(LOG_ERROR, "No RTP structure, this is very bad\n");
    02791          break;
    02792       }
    02793       memset(req, 0, SKINNY_MAX_PACKET);
    02794          req->len = htolel(sizeof(start_media_transmission_message)+4);
    02795          req->e = htolel(START_MEDIA_TRANSMISSION_MESSAGE);
    02796          req->data.startmedia.conferenceId = 0;
    02797          req->data.startmedia.passThruPartyId = 0;
    02798          memcpy(req->data.startmedia.remoteIp, &s->device->ourip, 4); /* Endian? */
    02799          req->data.startmedia.remotePort = htolel(ntohs(us.sin_port));
    02800          req->data.startmedia.packetSize = htolel(20);
    02801          req->data.startmedia.payloadType = htolel(convert_cap(s->device->lines->capability));
    02802          req->data.startmedia.qualifier.precedence = htolel(127);
    02803          req->data.startmedia.qualifier.vad = 0;
    02804          req->data.startmedia.qualifier.packets = 0;
    02805          req->data.startmedia.qualifier.bitRate = 0;
    02806          transmit_response(s, req);
    02807       break;
    02808    default:
    02809       ast_verbose("RECEIVED UNKNOWN MESSAGE TYPE:  %x\n", letohl(req->e));
    02810       break;
    02811    }
    02812    free(req);
    02813    return 1;
    02814 }

static int has_voicemail | ( | struct skinny_line * | l | ) | `[static]`

Definition at line 1297 of file chan_skinny.c.

References ast_app_has_voicemail(), and skinny_line::mailbox.

    01298 {
    01299    return ast_app_has_voicemail(l->mailbox, NULL);
    01300 }

char* key | ( | void |  | ) |

Returns the ASTERISK_GPL_KEY.

This returns the ASTERISK_GPL_KEY, signifiying that you agree to the terms of the GPL stated in the ASTERISK_GPL_KEY. Your module will not load if it does not return the EXACT message:

     char *key(void) {
             return ASTERISK_GPL_KEY;
     }

Returns:
  ASTERISK_GPL_KEY

Definition at line 3360 of file chan_skinny.c.

References ASTERISK_GPL_KEY.

    03361 {
    03362    return ASTERISK_GPL_KEY;
    03363 }

int load_module | ( | void |  | ) |

Initialize the module.

This function is called at module load time. Put all code in here that needs to set up your module's hardware, software, registrations, etc.

Returns:
  This function should return 0 on success and non-zero on failure. If the module is not loaded successfully, Asterisk will call its unload_module() function.

Initialize the Agents module. This function is being called by Asterisk when loading the module. Among other thing it registers applications, cli commands and reads the cofiguration file.

Returns:
  int Always 0.

TE STUFF END

Definition at line 3263 of file chan_skinny.c.

References ast_channel_register(), ast_cli_register(), ast_log(), ast_rtp_proto_register(), htolel, io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), and soft_key_template_definition::softKeyEvent.

    03264 {
    03265    int res = 0;
    03266
    03267    for (; res < (sizeof(soft_key_template_default) / sizeof(soft_key_template_default[0])); res++) {
    03268       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
    03269    }
    03270    /* load and parse config */
    03271    res = reload_config();
    03272
    03273    ast_rtp_proto_register(&skinny_rtp);
    03274    ast_cli_register(&cli_show_devices);
    03275    ast_cli_register(&cli_show_lines);
    03276    ast_cli_register(&cli_debug);
    03277    ast_cli_register(&cli_no_debug);
    03278    sched = sched_context_create();
    03279    if (!sched) {
    03280       ast_log(LOG_WARNING, "Unable to create schedule context\n");
    03281    }
    03282    io = io_context_create();
    03283    if (!io) {
    03284       ast_log(LOG_WARNING, "Unable to create I/O context\n");
    03285    }
    03286    /* And start the monitor for the first time */
    03287    restart_monitor();
    03288
    03289    /* Announce our presence to Asterisk */
    03290    if (!res) {
    03291       /* Make sure we can register our skinny channel type */
    03292       if (ast_channel_register(&skinny_tech)) {
    03293          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
    03294          return -1;
    03295       }
    03296    }
    03297    return res;
    03298 }

int reload | ( | void |  | ) |

Reload stuff.

This function is where any reload routines take place. Re-read config files, change signalling, whatever is appropriate on a reload.

Returns:
  The return value is not used.

Definition at line 3254 of file chan_skinny.c.

References delete_devices(), reload_config(), and restart_monitor().

    03255 {
    03256    delete_devices();
    03257    reload_config();
    03258    restart_monitor();
    03259    return 0;
    03260 }

static int reload_config | ( | void |  | ) | `[static]`

Definition at line 3076 of file chan_skinny.c.

References __ourip, accept_thread(), ahp, ast_category_browse(), ast_config_destroy(), ast_config_load(), ast_getformatbyname(), ast_gethostbyname(), ast_inet_ntoa(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_variable_browse(), ast_verbose(), bindaddr, build_device(), cfg, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, devices, format, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::name, ast_variable::name, skinny_device::next, ast_variable::next, option_verbose, ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

    03077 {
    03078    int on = 1;
    03079    struct ast_config *cfg;
    03080    struct ast_variable *v;
    03081    int format;
    03082    char *cat;
    03083    char iabuf[INET_ADDRSTRLEN];
    03084    struct skinny_device *d;
    03085    int oldport = ntohs(bindaddr.sin_port);
    03086
    03087    if (gethostname(ourhost, sizeof(ourhost))) {
    03088       ast_log(LOG_WARNING, "Unable to get hostname, Skinny disabled\n");
    03089       return 0;
    03090    }
    03091    cfg = ast_config_load(config);
    03092
    03093    /* We *must* have a config file otherwise stop immediately */
    03094    if (!cfg) {
    03095       ast_log(LOG_NOTICE, "Unable to load config %s, Skinny disabled\n", config);
    03096       return 0;
    03097    }
    03098    /* load the general section */
    03099    memset(&bindaddr, 0, sizeof(bindaddr));
    03100    v = ast_variable_browse(cfg, "general");
    03101    while(v) {
    03102       /* Create the interface list */
    03103       if (!strcasecmp(v->name, "bindaddr")) {
    03104          if (!(hp = ast_gethostbyname(v->value, &ahp))) {
    03105             ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
    03106          } else {
    03107             memcpy(&bindaddr.sin_addr, hp->h_addr, sizeof(bindaddr.sin_addr));
    03108          }
    03109       } else if (!strcasecmp(v->name, "keepAlive")) {
    03110          keep_alive = atoi(v->value);
    03111       } else if (!strcasecmp(v->name, "dateFormat")) {
    03112          strncpy(date_format, v->value, sizeof(date_format) - 1);
    03113       } else if (!strcasecmp(v->name, "allow")) {
    03114          format = ast_getformatbyname(v->value);
    03115          if (format < 1) {
    03116             ast_log(LOG_WARNING, "Cannot allow unknown format '%s'\n", v->value);
    03117          } else {
    03118             capability |= format;
    03119          }
    03120       } else if (!strcasecmp(v->name, "disallow")) {
    03121          format = ast_getformatbyname(v->value);
    03122          if (format < 1) {
    03123             ast_log(LOG_WARNING, "Cannot disallow unknown format '%s'\n", v->value);
    03124          } else {
    03125             capability &= ~format;
    03126          }
    03127       } else if (!strcasecmp(v->name, "port")) {
    03128          if (sscanf(v->value, "%30d", &ourport) == 1) {
    03129             bindaddr.sin_port = htons(ourport);
    03130          } else {
    03131             ast_log(LOG_WARNING, "Invalid port number '%s' at line %d of %s\n", v->value, v->lineno, config);
    03132          }
    03133       }
    03134       v = v->next;
    03135    }
    03136    if (ntohl(bindaddr.sin_addr.s_addr)) {
    03137       memcpy(&__ourip, &bindaddr.sin_addr, sizeof(__ourip));
    03138    } else {
    03139       hp = ast_gethostbyname(ourhost, &ahp);
    03140       if (!hp) {
    03141          ast_log(LOG_WARNING, "Unable to get our IP address, Skinny disabled\n");
    03142          ast_config_destroy(cfg);
    03143          return 0;
    03144       }
    03145       memcpy(&__ourip, hp->h_addr, sizeof(__ourip));
    03146    }
    03147    if (!ntohs(bindaddr.sin_port)) {
    03148       bindaddr.sin_port = ntohs(DEFAULT_SKINNY_PORT);
    03149    }
    03150    bindaddr.sin_family = AF_INET;
    03151
    03152    /* load the device sections */
    03153    cat = ast_category_browse(cfg, NULL);
    03154    while(cat) {
    03155       if (!strcasecmp(cat, "general")) {
    03156         /* Nothing to do */
    03157 #if 0
    03158       } else if (!strncasecmp(cat, "paging-", 7)) {
    03159          p = build_paging_device(cat, ast_variable_browse(cfg, cat));
    03160          if (p) {
    03161          }
    03162 #endif
    03163       } else {
    03164          d = build_device(cat, ast_variable_browse(cfg, cat));
    03165          if (d) {
    03166             if (option_verbose > 2) {
    03167                ast_verbose(VERBOSE_PREFIX_3 "Added device '%s'\n", d->name);
    03168                      }
    03169             ast_mutex_lock(&devicelock);
    03170             d->next = devices;
    03171             devices = d;
    03172             ast_mutex_unlock(&devicelock);
    03173          }
    03174       }
    03175       cat = ast_category_browse(cfg, cat);
    03176    }
    03177    ast_mutex_lock(&netlock);
    03178    if ((skinnysock > -1) && (ntohs(bindaddr.sin_port) != oldport)) {
    03179       close(skinnysock);
    03180       skinnysock = -1;
    03181    }
    03182    if (skinnysock < 0) {
    03183       skinnysock = socket(AF_INET, SOCK_STREAM, 0);
    03184       if(setsockopt(skinnysock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) {
    03185          ast_log(LOG_ERROR, "Set Socket Options failed: errno %d, %s\n", errno, strerror(errno));
    03186          ast_config_destroy(cfg);
    03187          return 0;
    03188       }
    03189       if (skinnysock < 0) {
    03190          ast_log(LOG_WARNING, "Unable to create Skinny socket: %s\n", strerror(errno));
    03191       } else {
    03192          if (bind(skinnysock, (struct sockaddr *)&bindaddr, sizeof(bindaddr)) < 0) {
    03193             ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
    03194                   ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
    03195                      strerror(errno));
    03196             close(skinnysock);
    03197             skinnysock = -1;
    03198             ast_config_destroy(cfg);
    03199             return 0;
    03200          }
    03201          if (listen(skinnysock,DEFAULT_SKINNY_BACKLOG)) {
    03202                ast_log(LOG_WARNING, "Failed to start listening to %s:%d: %s\n",
    03203                   ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port),
    03204                      strerror(errno));
    03205                close(skinnysock);
    03206                skinnysock = -1;
    03207                ast_config_destroy(cfg);
    03208                return 0;
    03209          }
    03210          if (option_verbose > 1) {
    03211             ast_verbose(VERBOSE_PREFIX_2 "Skinny listening on %s:%d\n",
    03212                ast_inet_ntoa(iabuf, sizeof(iabuf), bindaddr.sin_addr), ntohs(bindaddr.sin_port));
    03213          }
    03214          ast_pthread_create(&accept_t,NULL, accept_thread, NULL);
    03215       }
    03216    }
    03217    ast_mutex_unlock(&netlock);
    03218    ast_config_destroy(cfg);
    03219    return 0;
    03220 }

static skinny_req* req_alloc | ( | size_t | size | ) | `[static]`

Definition at line 926 of file chan_skinny.c.

References malloc.

Referenced by transmit_callinfo(), transmit_callstate(), transmit_connect(), transmit_diallednumber(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), and transmit_tone().

    00927 {
    00928    skinny_req *req;
    00929    req = malloc(size+12);
    00930    if (!req) {
    00931       return NULL;
    00932    }
    00933    memset(req, 0, size+12);
    00934    return req;
    00935 }

static int restart_monitor | ( | void |  | ) | `[static]`

Definition at line 3010 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, AST_PTHREADT_NULL, AST_PTHREADT_STOP, do_monitor(), LOG_ERROR, and LOG_WARNING.

    03011 {
    03012    /* If we're supposed to be stopped -- stay stopped */
    03013    if (monitor_thread == AST_PTHREADT_STOP)
    03014       return 0;
    03015    if (ast_mutex_lock(&monlock)) {
    03016       ast_log(LOG_WARNING, "Unable to lock monitor\n");
    03017       return -1;
    03018    }
    03019    if (monitor_thread == pthread_self()) {
    03020       ast_mutex_unlock(&monlock);
    03021       ast_log(LOG_WARNING, "Cannot kill myself\n");
    03022       return -1;
    03023    }
    03024    if (monitor_thread != AST_PTHREADT_NULL) {
    03025       /* Wake up the thread */
    03026       pthread_kill(monitor_thread, SIGURG);
    03027    } else {
    03028       /* Start a new monitor */
    03029       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
    03030          ast_mutex_unlock(&monlock);
    03031          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
    03032          return -1;
    03033       }
    03034    }
    03035    ast_mutex_unlock(&monlock);
    03036    return 0;
    03037 }

static int skinny_answer | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 2023 of file chan_skinny.c.

References ast_channel::_state, ast_setstate(), AST_STATE_UP, ast_verbose(), skinny_subchannel::callid, skinny_subchannel::cxmode, skinny_line::instance, skinny_device::name, skinny_line::name, ast_channel::name, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, skinny_device::session, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_NOTONE, start_rtp(), ast_channel::tech_pvt, transmit_callstate(), transmit_displaypromptstatus(), and transmit_tone().

    02024 {
    02025     int res = 0;
    02026     struct skinny_subchannel *sub = ast->tech_pvt;
    02027     struct skinny_line *l = sub->parent;
    02028     struct skinnysession *s = l->parent->session;
    02029
    02030     sub->cxmode = SKINNY_CX_SENDRECV;
    02031     if (!sub->rtp) {
    02032       start_rtp(sub);
    02033     }
    02034     ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, l->parent->name, sub->callid);
    02035     if (ast->_state != AST_STATE_UP) {
    02036    ast_setstate(ast, AST_STATE_UP);
    02037     }
    02038     transmit_tone(s, SKINNY_NOTONE);
    02039     transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
    02040     transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
    02041     return res;
    02042 }

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

Definition at line 1895 of file chan_skinny.c.

References ast_channel::_state, ast_build_string(), 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, LOG_ERROR, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_device::registered, skinny_device::session, SKINNY_ALERT, SKINNY_CALLWAITTONE, SKINNY_LAMP_BLINK, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_INSIDE, SKINNY_RINGIN, STIMULUS_LINE, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_displaymessage(), transmit_displaypromptstatus(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_tone(), and VERBOSE_PREFIX_3.

    01896 {
    01897    int res = 0;
    01898    int tone = 0;
    01899    struct skinny_line *l;
    01900         struct skinny_subchannel *sub;
    01901    struct skinnysession *session;
    01902
    01903    sub = ast->tech_pvt;
    01904         l = sub->parent;
    01905    session = l->parent->session;
    01906
    01907    if (!l->parent->registered) {
    01908       ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
    01909       return -1;
    01910    }
    01911
    01912    if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
    01913       ast_log(LOG_WARNING, "skinny_call called on %s, neither down nor reserved\n", ast->name);
    01914       return -1;
    01915    }
    01916
    01917         if (skinnydebug) {
    01918          ast_verbose(VERBOSE_PREFIX_3 "skinny_call(%s)\n", ast->name);
    01919       }
    01920
    01921    if (l->dnd) {
    01922       ast_queue_control(ast, AST_CONTROL_BUSY);
    01923       return -1;
    01924    }
    01925
    01926    switch (l->hookstate) {
    01927         case SKINNY_OFFHOOK:
    01928                tone = SKINNY_CALLWAITTONE;
    01929                break;
    01930         case SKINNY_ONHOOK:
    01931       tone = SKINNY_ALERT;
    01932       break;
    01933         default:
    01934                ast_log(LOG_ERROR, "Don't know how to deal with hookstate %d\n", l->hookstate);
    01935                break;
    01936       }
    01937
    01938    transmit_lamp_indication(session, STIMULUS_LINE, l->instance, SKINNY_LAMP_BLINK);
    01939    transmit_ringer_mode(session, SKINNY_RING_INSIDE);
    01940
    01941    if (ast->cid.cid_num) {
    01942       char ciddisplay[41];
    01943       char *work;
    01944       size_t size = sizeof(ciddisplay);
    01945
    01946       /* For now, we'll assume that if it is 10 numbers, it is a standard NANPA number */
    01947       if (strlen(ast->cid.cid_num) == 10) {
    01948          ast_build_string(&work, &size, "(xxx)xxx-xxxx      %s",
    01949                 ast->cid.cid_name ? ast->cid.cid_name : "");
    01950          memcpy(&ciddisplay[1], ast->cid.cid_num, 3);
    01951          memcpy(&ciddisplay[5], &ast->cid.cid_num[3], 3);
    01952          memcpy(&ciddisplay[9], &ast->cid.cid_num[6], 4);
    01953       } else {
    01954          if (strlen(ast->cid.cid_num) < 41) {
    01955             ast_build_string(&work, &size, "%s -- %s", ast->cid.cid_num,
    01956                    ast->cid.cid_name ? ast->cid.cid_name : "");
    01957          } else {
    01958             strncpy(ciddisplay, "Number too long!", 15);
    01959          }
    01960       }
    01961       if (skinnydebug) {
    01962          ast_verbose("Trying to send: '%s'\n",ciddisplay);
    01963       }
    01964       transmit_displaymessage(session, ciddisplay);
    01965    } else {
    01966       transmit_displaymessage(session, "Unknown Name");
    01967    }
    01968    transmit_tone(session, tone);
    01969    transmit_callstate(session, l->instance, SKINNY_RINGIN, sub->callid);
    01970    transmit_displaypromptstatus(session, "Ring-In", 0, l->instance, sub->callid);
    01971    transmit_callinfo(session, ast->cid.cid_name, ast->cid.cid_num, l->cid_name, l->cid_num, l->instance, sub->callid, 1);
    01972
    01973    /* XXX need to deal with softkeys */
    01974
    01975    ast_setstate(ast, AST_STATE_RINGING);
    01976    ast_queue_control(ast, AST_CONTROL_RINGING);
    01977    sub->outgoing = 1;
    01978    return res;
    01979 }

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

Definition at line 1363 of file chan_skinny.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    01364 {
    01365    if (argc != 2) {
    01366       return RESULT_SHOWUSAGE;
    01367    }
    01368    skinnydebug = 1;
    01369    ast_cli(fd, "Skinny Debugging Enabled\n");
    01370    return RESULT_SUCCESS;
    01371 }

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

Definition at line 2101 of file chan_skinny.c.

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

    02102 {
    02103    struct skinny_subchannel *sub = newchan->tech_pvt;
    02104       ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
    02105    if (sub->owner != oldchan) {
    02106       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
    02107       return -1;
    02108    }
    02109    sub->owner = newchan;
    02110    return 0;
    02111 }

static struct ast_rtp* skinny_get_rtp_peer | ( | struct ast_channel * | chan | ) | `[static, read]`

Definition at line 1335 of file chan_skinny.c.

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

    01336 {
    01337    struct skinny_subchannel *sub;
    01338    sub = chan->tech_pvt;
    01339    if (sub && sub->rtp) {
    01340       return sub->rtp;
    01341    }
    01342    return NULL;
    01343 }

static struct ast_rtp* skinny_get_vrtp_peer | ( | struct ast_channel * | chan | ) | `[static, read]`

Definition at line 1330 of file chan_skinny.c.

    01331 {
    01332    return NULL;
    01333 }

static int skinny_hangup | ( | struct ast_channel * | ast | ) | `[static]`

Definition at line 1981 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, skinny_device::session, SKINNY_LAMP_OFF, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, 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.

    01982 {
    01983     struct skinny_subchannel *sub = ast->tech_pvt;
    01984     struct skinny_line *l = sub->parent;
    01985     struct skinnysession *s = l->parent->session;
    01986
    01987     if (skinnydebug) {
    01988         ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
    01989     }
    01990     if (!ast->tech_pvt) {
    01991         ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
    01992         return 0;
    01993     }
    01994
    01995     if (l->parent->registered) {
    01996    if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_OFFHOOK)) {
    01997          sub->parent->hookstate = SKINNY_ONHOOK;
    01998          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
    01999          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
    02000          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
    02001       } else if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_ONHOOK)) {
    02002          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
    02003          transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
    02004          transmit_ringer_mode(s, SKINNY_RING_OFF);
    02005          transmit_tone(s, SKINNY_SILENCE);
    02006          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
    02007          do_housekeeping(s);
    02008       }
    02009     }
    02010     ast_mutex_lock(&sub->lock);
    02011     sub->owner = NULL;
    02012     ast->tech_pvt = NULL;
    02013     sub->alreadygone = 0;
    02014     sub->outgoing = 0;
    02015     if (sub->rtp) {
    02016         ast_rtp_destroy(sub->rtp);
    02017         sub->rtp = NULL;
    02018     }
    02019     ast_mutex_unlock(&sub->lock);
    02020     return 0;
    02021 }

static int skinny_indicate | ( | struct ast_channel * | ast,
|  | int | ind |
| ) |  |  | `[static]`

Definition at line 2171 of file chan_skinny.c.

References ast_channel::_state, skinny_subchannel::alreadygone, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_PROCEEDING, AST_CONTROL_PROGRESS, AST_CONTROL_RINGING, ast_log(), 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(), ast_channel::exten, skinny_line::instance, LOG_WARNING, ast_channel::name, skinny_subchannel::outgoing, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::progress, skinny_subchannel::ringing, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_diallednumber(), transmit_displaypromptstatus(), transmit_tone(), and VERBOSE_PREFIX_3.

    02172 {
    02173    struct skinny_subchannel *sub = ast->tech_pvt;
    02174    struct skinny_line *l = sub->parent;
    02175    struct skinnysession *s = l->parent->session;
    02176
    02177       if (skinnydebug) {
    02178          ast_verbose(VERBOSE_PREFIX_3 "Asked to indicate '%s' condition on channel %s\n", control2str(ind), ast->name);
    02179       }
    02180    switch(ind) {
    02181    case AST_CONTROL_RINGING:
    02182       if (ast->_state != AST_STATE_UP) {
    02183          if (!sub->progress) {
    02184             transmit_tone(s, SKINNY_ALERT);
    02185             transmit_callstate(s, l->instance, SKINNY_RINGOUT, sub->callid);
    02186             transmit_diallednumber(s, ast->exten, l->instance, sub->callid);
    02187             transmit_displaypromptstatus(s, "Ring Out", 0, l->instance, sub->callid);
    02188             transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
    02189             sub->ringing = 1;
    02190             break;
    02191          }
    02192       }
    02193       return -1;
    02194    case AST_CONTROL_BUSY:
    02195       if (ast->_state != AST_STATE_UP) {
    02196          transmit_tone(s, SKINNY_BUSYTONE);
    02197          transmit_callstate(s, l->instance, SKINNY_BUSY, sub->callid);
    02198          sub->alreadygone = 1;
    02199          ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
    02200                         break;
    02201                 }
    02202                 return -1;
    02203    case AST_CONTROL_CONGESTION:
    02204       if (ast->_state != AST_STATE_UP) {
    02205          transmit_tone(s, SKINNY_REORDER);
    02206          transmit_callstate(s, l->instance, SKINNY_CONGESTION, sub->callid);
    02207          sub->alreadygone = 1;
    02208                         ast_softhangup_nolock(ast, AST_SOFTHANGUP_DEV);
    02209                         break;
    02210                 }
    02211                 return -1;
    02212    case AST_CONTROL_PROGRESS:
    02213                 if ((ast->_state != AST_STATE_UP) && !sub->progress && !sub->outgoing) {
    02214          transmit_tone(s, SKINNY_ALERT);
    02215          transmit_callstate(s, l->instance, SKINNY_PROGRESS, sub->callid);
    02216          transmit_displaypromptstatus(s, "Call Progress", 0, l->instance, sub->callid);
    02217          transmit_callinfo(s, ast->cid.cid_name, ast->cid.cid_num, ast->exten, ast->exten, l->instance, sub->callid, 2); /* 2 = outgoing from phone */
    02218                         sub->progress = 1;
    02219                         break;
    02220                 }
    02221                 return -1;
    02222    case -1:
    02223       transmit_tone(s, SKINNY_SILENCE);
    02224       break;
    02225    case AST_CONTROL_PROCEEDING:
    02226       break;
    02227    default:
    02228       ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
    02229       return -1;
    02230    }
    02231    return 0;
    02232 }

static struct ast_channel* skinny_new | ( | struct skinny_subchannel * | sub,
|  | int | state |
| ) |  |  | `[static, read]`

Definition at line 2234 of file chan_skinny.c.

References ast_channel::accountcode, skinny_line::accountcode, ast_channel::adsicpe, ast_channel::amaflags, skinny_line::amaflags, AST_ADSI_UNAVAILABLE, ast_best_codec(), ast_channel_alloc(), ast_hangup(), ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_pbx_start(), ast_rtp_fd(), ast_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_verbose(), skinny_line::call_forward, ast_channel::call_forward, skinny_line::callgroup, ast_channel::callgroup, skinny_subchannel::callid, skinny_line::capability, ast_channel::cid, ast_callerid::cid_name, skinny_line::cid_name, ast_callerid::cid_num, skinny_line::cid_num, skinny_line::context, ast_channel::context, skinny_line::exten, ast_channel::exten, ast_channel::fds, fmt, ast_channel::language, skinny_line::language, LOG_WARNING, skinny_device::name, skinny_line::name, ast_channel::name, ast_channel::nativeformats, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::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, strdup, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, usecnt_lock, and ast_channel::writeformat.

Referenced by handle_message(), and skinny_request().

    02235 {
    02236    struct ast_channel *tmp;
    02237    struct skinny_line *l = sub->parent;
    02238    int fmt;
    02239    l = sub->parent;
    02240    tmp = ast_channel_alloc(1);
    02241    if (tmp) {
    02242       tmp->tech = &skinny_tech;
    02243       tmp->nativeformats = l->capability;
    02244       if (!tmp->nativeformats)
    02245          tmp->nativeformats = capability;
    02246       fmt = ast_best_codec(tmp->nativeformats);
    02247       ast_verbose("skinny_new: tmp->nativeformats=%d fmt=%d\n", tmp->nativeformats, fmt);
    02248       snprintf(tmp->name, sizeof(tmp->name), "Skinny/%s@%s-%d", l->name, l->parent->name, sub->callid);
    02249       if (sub->rtp) {
    02250          tmp->fds[0] = ast_rtp_fd(sub->rtp);
    02251       }
    02252       tmp->type = type;
    02253       ast_setstate(tmp, state);
    02254       if (state == AST_STATE_RING) {
    02255          tmp->rings = 1;
    02256       }
    02257       tmp->writeformat = fmt;
    02258       tmp->rawwriteformat = fmt;
    02259       tmp->readformat = fmt;
    02260       tmp->rawreadformat = fmt;
    02261       tmp->tech_pvt = sub;
    02262       if (!ast_strlen_zero(l->language)) {
    02263          strncpy(tmp->language, l->language, sizeof(tmp->language)-1);
    02264       }
    02265       if (!ast_strlen_zero(l->accountcode)) {
    02266          strncpy(tmp->accountcode, l->accountcode, sizeof(tmp->accountcode)-1);
    02267       }
    02268       if (l->amaflags) {
    02269          tmp->amaflags = l->amaflags;
    02270       }
    02271       sub->owner = tmp;
    02272       ast_mutex_lock(&usecnt_lock);
    02273       usecnt++;
    02274       ast_mutex_unlock(&usecnt_lock);
    02275       ast_update_use_count();
    02276       tmp->callgroup = l->callgroup;
    02277       tmp->pickupgroup = l->pickupgroup;
    02278       strncpy(tmp->call_forward, l->call_forward, sizeof(tmp->call_forward) - 1);
    02279       strncpy(tmp->context, l->context, sizeof(tmp->context)-1);
    02280       strncpy(tmp->exten,l->exten, sizeof(tmp->exten)-1);
    02281
    02282       if (!ast_strlen_zero(l->cid_num))
    02283          tmp->cid.cid_num = strdup(l->cid_num);
    02284       if (!ast_strlen_zero(l->cid_name))
    02285          tmp->cid.cid_name = strdup(l->cid_name);
    02286
    02287       tmp->priority = 1;
    02288       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
    02289
    02290       if (state != AST_STATE_DOWN) {
    02291          if (ast_pbx_start(tmp)) {
    02292             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
    02293             ast_hangup(tmp);
    02294             tmp = NULL;
    02295          }
    02296       }
    02297    } else {
    02298       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
    02299     }
    02300     return tmp;
    02301 }

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

Definition at line 1373 of file chan_skinny.c.

References ast_cli(), RESULT_SHOWUSAGE, and RESULT_SUCCESS.

    01374 {
    01375    if (argc != 3) {
    01376       return RESULT_SHOWUSAGE;
    01377    }
    01378    skinnydebug = 0;
    01379    ast_cli(fd, "Skinny Debugging Disabled\n");
    01380    return RESULT_SUCCESS;
    01381 }

static struct ast_frame * skinny_read | ( | struct ast_channel * | ast | ) | `[static, read]`

Definition at line 2063 of file chan_skinny.c.

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

    02064 {
    02065    struct ast_frame *fr;
    02066    struct skinny_subchannel *sub = ast->tech_pvt;
    02067    ast_mutex_lock(&sub->lock);
    02068    fr = skinny_rtp_read(sub);
    02069    ast_mutex_unlock(&sub->lock);
    02070    return fr;
    02071 }

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

Definition at line 1646 of file chan_skinny.c.

References ast_apply_ha(), ast_mutex_lock(), ast_mutex_unlock(), ast_strlen_zero(), skinny_req::data, skinnysession::device, devices, skinny_device::ha, skinny_device::id, letohl, register_message::name, skinny_device::next, skinny_req::reg, skinny_device::registered, skinny_device::session, skinnysession::sin, register_message::type, skinny_device::type, and skinny_device::version_id.

Referenced by handle_message().

    01647 {
    01648    struct skinny_device *d;
    01649
    01650    ast_mutex_lock(&devicelock);
    01651    d = devices;
    01652    while (d) {
    01653       if (!strcasecmp(req->data.reg.name, d->id)
    01654             && ast_apply_ha(d->ha, &(s->sin))) {
    01655          s->device = d;
    01656          d->type = letohl(req->data.reg.type);
    01657          if (ast_strlen_zero(d->version_id)) {
    01658             strncpy(d->version_id, version_id, sizeof(d->version_id) - 1);
    01659          }
    01660          d->registered = 1;
    01661          d->session = s;
    01662          break;
    01663       }
    01664       d = d->next;
    01665    }
    01666    ast_mutex_unlock(&devicelock);
    01667    if (!d) {
    01668       return 0;
    01669    }
    01670    return 1;
    01671 }

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

Definition at line 2882 of file chan_skinny.c.

References ast_log(), skinny_req::e, skinnysession::fd, free, skinnysession::inbuf, letohl, LOG_ERROR, malloc, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

    02883 {
    02884    skinny_req *req;
    02885
    02886    req = malloc(SKINNY_MAX_PACKET);
    02887    if (!req) {
    02888       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    02889       return NULL;
    02890    }
    02891    memset(req, 0, sizeof(skinny_req));
    02892    /* +8 to account for reserved and length fields */
    02893    memcpy(req, s->inbuf, letohl(*(int*)(s->inbuf))+8);
    02894    if (letohl(req->e) < 0) {
    02895       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
    02896       free(req);
    02897       return NULL;
    02898    }
    02899    return req;
    02900 }

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

Definition at line 3039 of file chan_skinny.c.

References ast_log(), AST_STATE_DOWN, ast_strlen_zero(), ast_verbose(), skinny_line::callwaiting, skinny_line::dnd, find_subchannel_by_name(), LOG_NOTICE, LOG_WARNING, skinny_subchannel::next, option_verbose, skinny_subchannel::owner, skinny_subchannel::parent, restart_monitor(), skinny_new(), and VERBOSE_PREFIX_3.

    03040 {
    03041    int oldformat;
    03042    struct skinny_subchannel *sub;
    03043    struct ast_channel *tmpc = NULL;
    03044    char tmp[256];
    03045    char *dest = data;
    03046
    03047    oldformat = format;
    03048    format &= capability;
    03049    if (!format) {
    03050       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
    03051       return NULL;
    03052    }
    03053    strncpy(tmp, dest, sizeof(tmp) - 1);
    03054    if (ast_strlen_zero(tmp)) {
    03055       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
    03056       return NULL;
    03057    }
    03058    sub = find_subchannel_by_name(tmp);
    03059    if (!sub) {
    03060       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
    03061       return NULL;
    03062    }
    03063       if (option_verbose > 2) {
    03064          ast_verbose(VERBOSE_PREFIX_3 "skinny_request(%s)\n", tmp);
    03065          ast_verbose(VERBOSE_PREFIX_3 "Skinny cw: %d, dnd: %d, so: %d, sno: %d\n",
    03066                      sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
    03067       }
    03068    tmpc = skinny_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
    03069    if (!tmpc) {
    03070       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
    03071    }
    03072    restart_monitor();
    03073    return tmpc;
    03074 }

static struct ast_frame* skinny_rtp_read | ( | struct skinny_subchannel * | sub | ) | `[static, read]`

Definition at line 2044 of file chan_skinny.c.

References AST_FRAME_VOICE, ast_log(), ast_rtp_read(), ast_set_read_format(), ast_set_write_format(), ast_frame::frametype, LOG_DEBUG, ast_channel::nativeformats, skinny_subchannel::owner, ast_channel::readformat, skinny_subchannel::rtp, ast_frame::subclass, and ast_channel::writeformat.

Referenced by skinny_read().

    02045 {
    02046    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
    02047    struct ast_frame *f;
    02048    f = ast_rtp_read(sub->rtp);
    02049    if (sub->owner) {
    02050       /* We already hold the channel lock */
    02051       if (f->frametype == AST_FRAME_VOICE) {
    02052          if (f->subclass != sub->owner->nativeformats) {
    02053             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
    02054             sub->owner->nativeformats = f->subclass;
    02055             ast_set_read_format(sub->owner, sub->owner->readformat);
    02056             ast_set_write_format(sub->owner, sub->owner->writeformat);
    02057          }
    02058       }
    02059    }
    02060    return f;
    02061 }

static int skinny_senddigit | ( | struct ast_channel * | ast,
|  | char | digit |
| ) |  |  | `[static]`

Definition at line 2113 of file chan_skinny.c.

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

    02114 {
    02115 #if 0
    02116    struct skinny_subchannel *sub = ast->tech_pvt;
    02117    int tmp;
    02118    /* not right */
    02119    sprintf(tmp, "%d", digit);
    02120    transmit_tone(sub->parent->parent->session, digit);
    02121 #endif
    02122    return -1;
    02123 }

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

Definition at line 2902 of file chan_skinny.c.

References ast_inet_ntoa(), ast_log(), ast_verbose(), destroy_session(), get_input(), handle_message(), LOG_NOTICE, skinnysession::sin, skinny_req_parse(), and VERBOSE_PREFIX_3.

Referenced by accept_thread(), and unload_module().

    02903 {
    02904    int res;
    02905    skinny_req *req;
    02906    struct skinnysession *s = data;
    02907    char iabuf[INET_ADDRSTRLEN];
    02908
    02909    ast_verbose(VERBOSE_PREFIX_3 "Starting Skinny session from %s\n",  ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
    02910    for (;;) {
    02911       res = 0;
    02912       res = get_input(s);
    02913       if (res < 0) {
    02914          break;
    02915       }
    02916       req = skinny_req_parse(s);
    02917       if (!req) {
    02918          return NULL;
    02919       }
    02920       res = handle_message(req, s);
    02921       if (res < 0) {
    02922          destroy_session(s);
    02923          return NULL;
    02924       }
    02925    }
    02926    ast_log(LOG_NOTICE, "Skinny Session returned: %s\n", strerror(errno));
    02927    destroy_session(s);
    02928    return 0;
    02929 }

static int skinny_set_rtp_peer | ( | struct ast_channel * | chan,
|  | struct ast_rtp * | rtp,
|  | struct ast_rtp * | vrtp,
|  | int | codecs,
|  | int | nat_active |
| ) |  |  | `[static]`

Definition at line 1345 of file chan_skinny.c.

References ast_channel::tech_pvt.

    01346 {
    01347    struct skinny_subchannel *sub;
    01348    sub = chan->tech_pvt;
    01349    if (sub) {
    01350       /* transmit_modify_with_sdp(sub, rtp); @@FIXME@@ if needed */
    01351       return 0;
    01352    }
    01353    return -1;
    01354 }

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

Definition at line 1383 of file chan_skinny.c.

References skinny_device::addr, ast_cli(), ast_inet_ntoa(), ast_mutex_lock(), ast_mutex_unlock(), devices, skinny_device::id, skinny_device::lines, skinny_device::model, skinny_device::name, skinny_device::next, skinny_line::next, skinny_device::registered, RESULT_SHOWUSAGE, RESULT_SUCCESS, and skinny_device::type.

    01384 {
    01385    struct skinny_device  *d;
    01386    struct skinny_line *l;
    01387    int numlines = 0;
    01388    char iabuf[INET_ADDRSTRLEN];
    01389
    01390    if (argc != 3) {
    01391       return RESULT_SHOWUSAGE;
    01392    }
    01393    ast_mutex_lock(&devicelock);
    01394    d = devices;
    01395
    01396    ast_cli(fd, "Name                 DeviceId         IP              TypeId R Model  NL\n");
    01397    ast_cli(fd, "-------------------- ---------------- --------------- ------ - ------ --\n");
    01398    while(d) {
    01399       l = d->lines;
    01400       numlines = 0;
    01401       while(l) { numlines++; l = l->next; }
    01402
    01403       ast_cli(fd, "%-20s %-16s %-16s %6X %c %-6s %2d\n",
    01404             d->name,
    01405             d->id,
    01406             ast_inet_ntoa(iabuf, sizeof(iabuf), d->addr.sin_addr),
    01407             d->type,
    01408             d->registered?'Y':'N',
    01409             d->model,
    01410             numlines);
    01411
    01412       d = d->next;
    01413    }
    01414    ast_mutex_unlock(&devicelock);
    01415    return RESULT_SUCCESS;
    01416 }

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

Definition at line 1418 of file chan_skinny.c.

References ast_cli(), ast_mutex_lock(), ast_mutex_unlock(), devices, skinny_line::instance, skinny_line::label, skinny_device::lines, skinny_line::name, skinny_device::name, skinny_device::next, skinny_line::next, skinny_subchannel::owner, skinny_line::parent, RESULT_SHOWUSAGE, RESULT_SUCCESS, skinny_subchannel::rtp, and skinny_line::sub.

    01419 {
    01420    struct skinny_device  *d;
    01421    struct skinny_line *l;
    01422
    01423    if (argc != 3) {
    01424       return RESULT_SHOWUSAGE;
    01425    }
    01426    ast_mutex_lock(&devicelock);
    01427    d = devices;
    01428    while(d) {
    01429       l = d->lines;
    01430       while (l) {
    01431          ast_cli(fd, "%-20s %2d %-20s %-20s  %c  %c\n",
    01432             l->parent->name,
    01433             l->instance,
    01434             l->name,
    01435             l->label,
    01436             l->sub->owner?'Y':'N',
    01437             l->sub->rtp?'Y':'N');
    01438          l = l->next;
    01439       }
    01440       d = d->next;
    01441    }
    01442    ast_mutex_unlock(&devicelock);
    01443    return RESULT_SUCCESS;
    01444 }

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

Definition at line 1689 of file chan_skinny.c.

References ast_bridged_channel(), ast_canmatch_extension(), ast_db_put(), ast_exists_extension(), ast_hangup(), ast_ignore_pattern(), ast_indicate(), ast_log(), ast_masq_park_call(), ast_matchmore_extension(), AST_MAX_EXTENSION, ast_parking_ext(), ast_pbx_run(), ast_pickup_call(), ast_pickup_ext(), ast_safe_sleep(), ast_say_digit_str(), ast_set_callerid(), ast_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), skinny_line::call_forward, skinny_line::callreturn, skinny_line::callwaiting, skinny_line::cancallforward, ast_channel::cid, skinny_line::cid_name, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, skinny_line::dnd, ast_channel::exten, exten, skinny_line::hidecallerid, ast_channel::language, skinny_line::lastcallerid, LOG_DEBUG, LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::next, option_verbose, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_device::session, SKINNY_DIALTONE, SKINNY_REORDER, SKINNY_SILENCE, ast_channel::tech_pvt, transmit_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

    01690 {
    01691    struct ast_channel *chan = data;
    01692    struct skinny_subchannel *sub = chan->tech_pvt;
    01693    struct skinny_line *l = sub->parent;
    01694    struct skinnysession *s = l->parent->session;
    01695    char exten[AST_MAX_EXTENSION] = "";
    01696    int len = 0;
    01697    int timeout = firstdigittimeout;
    01698    int res;
    01699    int getforward=0;
    01700
    01701    if (option_verbose > 2) {
    01702       ast_verbose( VERBOSE_PREFIX_3 "Starting simple switch on '%s@%s'\n", l->name, l->parent->name);
    01703    }
    01704    while(len < AST_MAX_EXTENSION-1) {
    01705          res = ast_waitfordigit(chan, timeout);
    01706          timeout = 0;
    01707          if (res < 0) {
    01708          if (skinnydebug) {
    01709             ast_verbose("Skinny(%s@%s): waitfordigit returned < 0\n", l->name, l->parent->name);
    01710             }
    01711          ast_indicate(chan, -1);
    01712          ast_hangup(chan);
    01713                   return NULL;
    01714          } else if (res)  {
    01715                   exten[len++]=res;
    01716                   exten[len] = '\0';
    01717          }
    01718          if (!ast_ignore_pattern(chan->context, exten)) {
    01719          transmit_tone(s, SKINNY_SILENCE);
    01720          }
    01721          if (ast_exists_extension(chan, chan->context, exten, 1, l->cid_num)) {
    01722                   if (!res || !ast_matchmore_extension(chan, chan->context, exten, 1, l->cid_num)) {
    01723                      if (getforward) {
    01724                            /* Record this as the forwarding extension */
    01725                            strncpy(l->call_forward, exten, sizeof(l->call_forward) - 1);
    01726                            if (option_verbose > 2) {
    01727                                  ast_verbose(VERBOSE_PREFIX_3 "Setting call forward to '%s' on channel %s\n",
    01728                                        l->call_forward, chan->name);
    01729                            }
    01730                            transmit_tone(s, SKINNY_DIALTONE);
    01731                   if (res) {
    01732                         break;
    01733                   }
    01734                ast_safe_sleep(chan, 500);
    01735                         ast_indicate(chan, -1);
    01736                ast_safe_sleep(chan, 1000);
    01737                            memset(exten, 0, sizeof(exten));
    01738                   transmit_tone(s, SKINNY_DIALTONE);
    01739                            len = 0;
    01740                            getforward = 0;
    01741                      } else  {
    01742                            strncpy(chan->exten, exten, sizeof(chan->exten)-1);
    01743
    01744                            if (!ast_strlen_zero(l->cid_num)) {
    01745                   ast_set_callerid(chan,
    01746                      l->hidecallerid ? "" : l->cid_num,
    01747                      l->hidecallerid ? "" : l->cid_name,
    01748                      NULL);
    01749                               ast_setstate(chan, AST_STATE_RING);
    01750                               res = ast_pbx_run(chan);
    01751                               if (res) {
    01752                                     ast_log(LOG_WARNING, "PBX exited non-zero\n");
    01753                      transmit_tone(s, SKINNY_REORDER);
    01754                               }
    01755                               return NULL;
    01756                         }
    01757             }
    01758                   } else {
    01759                      /* It's a match, but they just typed a digit, and there is an ambiguous match,
    01760                            so just set the timeout to matchdigittimeout and wait some more */
    01761                         timeout = matchdigittimeout;
    01762               }
    01763       } else if (res == 0) {
    01764                   ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
    01765             transmit_tone(s, SKINNY_REORDER);
    01766                ast_hangup(chan);
    01767                return NULL;
    01768          } else if (l->callwaiting && !strcmp(exten, "*70")) {
    01769                   if (option_verbose > 2) {
    01770                         ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
    01771                   }
    01772                /* Disable call waiting if enabled */
    01773                l->callwaiting = 0;
    01774                transmit_tone(s, SKINNY_DIALTONE);
    01775          len = 0;
    01776                memset(exten, 0, sizeof(exten));\
    01777                timeout = firstdigittimeout;
    01778           } else if (!strcmp(exten,ast_pickup_ext())) {
    01779                /* Scan all channels and see if any there
    01780                       * ringing channqels with that have call groups
    01781                    * that equal this channels pickup group
    01782                    */
    01783                   if (ast_pickup_call(chan)) {
    01784                      ast_log(LOG_WARNING, "No call pickup possible...\n");
    01785             transmit_tone(s, SKINNY_REORDER);
    01786                   }
    01787               ast_hangup(chan);
    01788                   return NULL;
    01789                } else if (!l->hidecallerid && !strcmp(exten, "*67")) {
    01790                if (option_verbose > 2) {
    01791                    ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
    01792                   }
    01793                /* Disable Caller*ID if enabled */
    01794               l->hidecallerid = 1;
    01795          ast_set_callerid(chan, "", "", NULL);
    01796                   transmit_tone(s, SKINNY_DIALTONE);
    01797                len = 0;
    01798                memset(exten, 0, sizeof(exten));
    01799                   timeout = firstdigittimeout;
    01800          } else if (l->callreturn && !strcmp(exten, "*69")) {
    01801                res = 0;
    01802                if (!ast_strlen_zero(l->lastcallerid)) {
    01803                      res = ast_say_digit_str(chan, l->lastcallerid, "", chan->language);
    01804                }
    01805                if (!res) {
    01806                      transmit_tone(s, SKINNY_DIALTONE);
    01807          }
    01808                break;
    01809          } else if (!strcmp(exten, "*78")) {
    01810                   /* Do not disturb */
    01811                   if (option_verbose > 2) {
    01812                         ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
    01813                   }
    01814                transmit_tone(s, SKINNY_DIALTONE);
    01815                   l->dnd = 1;
    01816                   getforward = 0;
    01817                   memset(exten, 0, sizeof(exten));
    01818                   len = 0;
    01819          } else if (!strcmp(exten, "*79")) {
    01820                /* Do not disturb */
    01821                if (option_verbose > 2) {
    01822                      ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
    01823                   }
    01824          transmit_tone(s, SKINNY_DIALTONE);
    01825               l->dnd = 0;
    01826                   getforward = 0;
    01827                   memset(exten, 0, sizeof(exten));
    01828                   len = 0;
    01829          } else if (l->cancallforward && !strcmp(exten, "*72")) {
    01830                transmit_tone(s, SKINNY_DIALTONE);
    01831                getforward = 1;
    01832                memset(exten, 0, sizeof(exten));
    01833                len = 0;
    01834             } else if (l->cancallforward && !strcmp(exten, "*73")) {
    01835                if (option_verbose > 2) {
    01836                   ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
    01837                }
    01838                transmit_tone(s, SKINNY_DIALTONE);
    01839                memset(l->call_forward, 0, sizeof(l->call_forward));
    01840                getforward = 0;
    01841                memset(exten, 0, sizeof(exten));
    01842                len = 0;
    01843             } else if (!strcmp(exten, ast_parking_ext()) &&
    01844                         sub->next->owner &&
    01845                         ast_bridged_channel(sub->next->owner)) {
    01846                /* This is a three way call, the main call being a real channel,
    01847                         and we're parking the first call. */
    01848                      ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
    01849                if (option_verbose > 2) {
    01850                         ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
    01851                }
    01852                break;
    01853             } else if (!ast_strlen_zero(l->lastcallerid) && !strcmp(exten, "*60")) {
    01854                if (option_verbose > 2) {
    01855                      ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", l->lastcallerid);
    01856                }
    01857                   res = ast_db_put("blacklist", l->lastcallerid, "1");
    01858                   if (!res) {
    01859                         transmit_tone(s, SKINNY_DIALTONE);
    01860                   memset(exten, 0, sizeof(exten));
    01861                         len = 0;
    01862                }
    01863             } else if (l->hidecallerid && !strcmp(exten, "*82")) {
    01864                if (option_verbose > 2) {
    01865                      ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
    01866                }
    01867                /* Enable Caller*ID if enabled */
    01868                l->hidecallerid = 0;
    01869          ast_set_callerid(chan, l->cid_num, l->cid_name, NULL);
    01870                   transmit_tone(s, SKINNY_DIALTONE);
    01871                   len = 0;
    01872                   memset(exten, 0, sizeof(exten));
    01873                timeout = firstdigittimeout;
    01874             } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
    01875                            ((exten[0] != '*') || (!ast_strlen_zero(exten) > 2))) {
    01876                   ast_log(LOG_WARNING, "Can't match [%s] from '%s' in context %s\n", exten, chan->cid.cid_num ? chan->cid.cid_num : "<Unknown Caller>", chan->context);
    01877                   transmit_tone(s, SKINNY_REORDER);
    01878          /* hang out for 3 seconds to let congestion play */
    01879             ast_safe_sleep(chan, 3000);
    01880             break;
    01881             }
    01882             if (!timeout) {
    01883                   timeout = gendigittimeout;
    01884       }
    01885          if (len && !ast_ignore_pattern(chan->context, exten)) {
    01886          ast_indicate(chan, -1);
    01887       }
    01888       }
    01889    ast_hangup(chan);
    01890    return NULL;
    01891 }

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

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

    02074 {
    02075    struct skinny_subchannel *sub = ast->tech_pvt;
    02076    int res = 0;
    02077    if (frame->frametype != AST_FRAME_VOICE) {
    02078       if (frame->frametype == AST_FRAME_IMAGE) {
    02079          return 0;
    02080       } else {
    02081          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
    02082          return 0;
    02083       }
    02084    } else {
    02085       if (!(frame->subclass & ast->nativeformats)) {
    02086          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
    02087             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
    02088          return -1;
    02089       }
    02090    }
    02091    if (sub) {
    02092       ast_mutex_lock(&sub->lock);
    02093       if (sub->rtp) {
    02094          res =  ast_rtp_write(sub->rtp, frame);
    02095       }
    02096       ast_mutex_unlock(&sub->lock);
    02097    }
    02098    return res;
    02099 }

static void start_rtp | ( | struct skinny_subchannel * | sub | ) | `[static]`

Definition at line 1673 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_fd(), ast_rtp_new(), ast_rtp_setnat(), ast_channel::fds, skinny_subchannel::lock, skinny_subchannel::nat, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, skinny_device::session, and transmit_connect().

    01674 {
    01675    ast_mutex_lock(&sub->lock);
    01676    /* Allocate the RTP */
    01677    sub->rtp = ast_rtp_new(sched, io, 1, 0);
    01678    if (sub->rtp && sub->owner) {
    01679       sub->owner->fds[0] = ast_rtp_fd(sub->rtp);
    01680    }
    01681    if (sub->rtp) {
    01682       ast_rtp_setnat(sub->rtp, sub->nat);
    01683    }
    01684    /* Create the RTP connection */
    01685    transmit_connect(sub->parent->parent->session);
    01686    ast_mutex_unlock(&sub->lock);
    01687 }

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

Definition at line 1073 of file chan_skinny.c.

References ast_log(), CALL_INFO_MESSAGE, call_info_message::calledParty, call_info_message::calledPartyName, skinny_req::callinfo, call_info_message::callingParty, call_info_message::callingPartyName, skinny_req::data, skinny_req::e, htolel, call_info_message::instance, skinny_req::len, LOG_ERROR, call_info_message::reference, req_alloc(), transmit_response(), and call_info_message::type.

Referenced by skinny_call(), and skinny_indicate().

    01074 {
    01075    skinny_req *req;
    01076
    01077    req = req_alloc(sizeof(struct call_info_message));
    01078    if (!req) {
    01079       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01080       return;
    01081    }
    01082
    01083    req->len = htolel(sizeof(struct call_info_message));
    01084    req->e = htolel(CALL_INFO_MESSAGE);
    01085
    01086    if (fromname) {
    01087       ast_copy_string(req->data.callinfo.callingPartyName, fromname, sizeof(req->data.callinfo.callingPartyName));
    01088    }
    01089    if (fromnum) {
    01090       ast_copy_string(req->data.callinfo.callingParty, fromnum, sizeof(req->data.callinfo.callingParty));
    01091    }
    01092    if (toname) {
    01093       ast_copy_string(req->data.callinfo.calledPartyName, toname, sizeof(req->data.callinfo.calledPartyName));
    01094    }
    01095    if (tonum) {
    01096       ast_copy_string(req->data.callinfo.calledParty, tonum, sizeof(req->data.callinfo.calledParty));
    01097    }
    01098    req->data.callinfo.instance = htolel(instance);
    01099    req->data.callinfo.reference = htolel(callid);
    01100    req->data.callinfo.type = htolel(calltype);
    01101    transmit_response(s, req);
    01102 }

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

Definition at line 1027 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, skinny_req::activatecallplane, ast_log(), CALL_STATE_MESSAGE, call_state_message::callReference, call_state_message::callState, skinny_req::callstate, CLOSE_RECIEVE_CHANNEL_MESSAGE, skinny_req::closerecievechannel, stop_media_transmission_message::conferenceId, close_recieve_channel_message::conferenceId, skinny_req::data, skinny_req::e, htolel, skinny_req::len, activate_call_plane_message::lineInstance, call_state_message::lineInstance, LOG_ERROR, close_recieve_channel_message::partyId, stop_media_transmission_message::passThruPartyId, req_alloc(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, STOP_MEDIA_TRANSMISSION_MESSAGE, skinny_req::stopmedia, transmit_response(), and transmit_speaker_mode().

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

    01028 {
    01029    skinny_req *req;
    01030    int memsize = sizeof(struct call_state_message);
    01031
    01032    req = req_alloc(memsize);
    01033    if (!req) {
    01034       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01035       return;
    01036    }
    01037    if (state == SKINNY_ONHOOK) {
    01038       transmit_speaker_mode(s, SKINNY_SPEAKEROFF);
    01039    }
    01040    req->len = htolel(sizeof(call_state_message)+4);
    01041    req->e = htolel(CALL_STATE_MESSAGE);
    01042    req->data.callstate.callState = htolel(state);
    01043    req->data.callstate.lineInstance = htolel(instance);
    01044    req->data.callstate.callReference = htolel(callid);
    01045    transmit_response(s, req);
    01046    if (state == SKINNY_OFFHOOK) {
    01047       memset(req, 0, memsize);
    01048       req->len = htolel(sizeof(activate_call_plane_message)+4);
    01049       req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
    01050       req->data.activatecallplane.lineInstance = htolel(instance);
    01051       transmit_response(s, req);
    01052    } else if (state == SKINNY_ONHOOK) {
    01053       memset(req, 0, memsize);
    01054       req->len = htolel(sizeof(activate_call_plane_message)+4);
    01055       req->e = htolel(ACTIVATE_CALL_PLANE_MESSAGE);
    01056       req->data.activatecallplane.lineInstance = 0;
    01057       transmit_response(s, req);
    01058       memset(req, 0, memsize);
    01059       req->len = htolel(sizeof(close_recieve_channel_message)+4);
    01060       req->e = htolel(CLOSE_RECIEVE_CHANNEL_MESSAGE);
    01061       req->data.closerecievechannel.conferenceId = 0;
    01062       req->data.closerecievechannel.partyId = 0;
    01063       transmit_response(s, req);
    01064       memset(req, 0, memsize);
    01065                 req->len = htolel(sizeof(stop_media_transmission_message)+4);
    01066                 req->e = htolel(STOP_MEDIA_TRANSMISSION_MESSAGE);
    01067                 req->data.stopmedia.conferenceId = 0;
    01068                 req->data.stopmedia.passThruPartyId = 0;
    01069                 transmit_response(s, req);
    01070    }
    01071 }

static void transmit_connect | ( | struct skinnysession * | s | ) | `[static]`

Definition at line 1104 of file chan_skinny.c.

References ast_log(), open_recieve_channel_message::bitrate, skinny_line::capability, open_recieve_channel_message::capability, open_recieve_channel_message::conferenceId, convert_cap(), skinny_req::data, skinnysession::device, skinny_req::e, open_recieve_channel_message::echo, htolel, skinny_req::len, skinny_device::lines, LOG_ERROR, OPEN_RECIEVE_CHANNEL_MESSAGE, skinny_req::openrecievechannel, open_recieve_channel_message::packets, open_recieve_channel_message::partyId, req_alloc(), and transmit_response().

Referenced by start_rtp().

    01105 {
    01106    skinny_req *req;
    01107    struct skinny_line *l = s->device->lines;
    01108
    01109    req = req_alloc(sizeof(struct open_recieve_channel_message));
    01110    if (!req) {
    01111       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01112       return;
    01113    }
    01114    req->len = htolel(sizeof(struct open_recieve_channel_message));
    01115    req->e = htolel(OPEN_RECIEVE_CHANNEL_MESSAGE);
    01116    req->data.openrecievechannel.conferenceId = 0;
    01117    req->data.openrecievechannel.partyId = 0;
    01118    req->data.openrecievechannel.packets = htolel(20);
    01119    req->data.openrecievechannel.capability = htolel(convert_cap(l->capability));
    01120    req->data.openrecievechannel.echo = 0;
    01121    req->data.openrecievechannel.bitrate = 0;
    01122    transmit_response(s, req);
    01123 }

static void transmit_diallednumber | ( | struct skinnysession * | s,
|  | char * | text,
|  | int | instance,
|  | int | callid |
| ) |  |  | `[static]`

Definition at line 1277 of file chan_skinny.c.

References ast_log(), dialled_number_message::callReference, skinny_req::data, DIALLED_NUMBER_MESSAGE, dialled_number_message::dialledNumber, skinny_req::diallednumber, skinny_req::e, htolel, skinny_req::len, dialled_number_message::lineInstance, LOG_ERROR, req_alloc(), and transmit_response().

Referenced by skinny_indicate().

    01278 {
    01279    skinny_req *req;
    01280
    01281    req = req_alloc(sizeof(struct dialled_number_message));
    01282
    01283         if (!req) {
    01284                 ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01285                 return;
    01286         }
    01287
    01288    req->e = htolel(DIALLED_NUMBER_MESSAGE);
    01289    req->len = htolel(sizeof(dialled_number_message) + 4);
    01290    strncpy(req->data.diallednumber.dialledNumber, text, sizeof(req->data.diallednumber.dialledNumber)-1);
    01291    req->data.diallednumber.lineInstance = htolel(instance);
    01292         req->data.diallednumber.callReference = htolel(callid);
    01293
    01294    transmit_response(s, req);
    01295 }

static void transmit_displaymessage | ( | struct skinnysession * | s,
|  | char * | text |
| ) |  |  | `[static]`

Definition at line 1203 of file chan_skinny.c.

References ast_log(), ast_verbose(), CLEAR_DISPLAY_MESSAGE, skinny_req::data, skinny_req::displaytext, DISPLAYTEXT_MESSAGE, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), displaytext_message::text, and transmit_response().

Referenced by do_housekeeping(), handle_message(), and skinny_call().

    01204 {
    01205    skinny_req *req;
    01206
    01207    if (text == 0) {
    01208       req = req_alloc(4);
    01209       req->len = htolel(4);
    01210       req->e = htolel(CLEAR_DISPLAY_MESSAGE);
    01211    } else {
    01212       req = req_alloc(sizeof(struct displaytext_message));
    01213
    01214       strncpy(req->data.displaytext.text, text, sizeof(req->data.displaytext.text)-1);
    01215       req->len = htolel(sizeof(displaytext_message) + 4);
    01216       req->e = htolel(DISPLAYTEXT_MESSAGE);
    01217       if (skinnydebug) {
    01218          ast_verbose("Displaying message '%s'\n", req->data.displaytext.text);
    01219       }
    01220    }
    01221
    01222    if (!req) {
    01223       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01224       return;
    01225    }
    01226    transmit_response(s, req);
    01227 }

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

Definition at line 1229 of file chan_skinny.c.

References ast_log(), ast_verbose(), skinny_req::data, DISPLAY_NOTIFY_MESSAGE, display_notify_message::displayMessage, skinny_req::displaynotify, display_notify_message::displayTimeout, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), and transmit_response().

Referenced by handle_message().

    01230 {
    01231    skinny_req *req;
    01232
    01233    req = req_alloc(sizeof(struct display_notify_message));
    01234
    01235         if (!req) {
    01236                 ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01237                 return;
    01238         }
    01239
    01240    req->e = htolel(DISPLAY_NOTIFY_MESSAGE);
    01241    req->len = htolel(sizeof(display_notify_message) + 4);
    01242    strncpy(req->data.displaynotify.displayMessage, text, sizeof(req->data.displaynotify.displayMessage)-1);
    01243    req->data.displaynotify.displayTimeout = htolel(t);
    01244
    01245    if (skinnydebug) {
    01246       ast_verbose("Displaying notify '%s'\n", text);
    01247    }
    01248
    01249    transmit_response(s, req);
    01250 }

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

Definition at line 1252 of file chan_skinny.c.

References ast_log(), ast_verbose(), display_prompt_status_message::callReference, skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_req::displaypromptstatus, skinny_req::e, htolel, skinny_req::len, display_prompt_status_message::lineInstance, LOG_ERROR, display_prompt_status_message::messageTimeout, display_prompt_status_message::promptMessage, req_alloc(), and transmit_response().

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

    01253 {
    01254    skinny_req *req;
    01255
    01256    req = req_alloc(sizeof(struct display_prompt_status_message));
    01257
    01258         if (!req) {
    01259                 ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01260                 return;
    01261         }
    01262
    01263    req->e = htolel(DISPLAY_PROMPT_STATUS_MESSAGE);
    01264    req->len = htolel(sizeof(display_prompt_status_message) + 4);
    01265    strncpy(req->data.displaypromptstatus.promptMessage, text, sizeof(req->data.displaypromptstatus.promptMessage)-1);
    01266    req->data.displaypromptstatus.messageTimeout = htolel(t);
    01267    req->data.displaypromptstatus.lineInstance = htolel(instance);
    01268    req->data.displaypromptstatus.callReference = htolel(callid);
    01269
    01270    if (skinnydebug) {
    01271       ast_verbose("Displaying Prompt Status '%s'\n", text);
    01272    }
    01273
    01274    transmit_response(s, req);
    01275 }

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

Definition at line 1171 of file chan_skinny.c.

References ast_log(), skinny_req::data, set_lamp_message::deviceStimulus, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), SET_LAMP_MESSAGE, skinny_req::setlamp, set_lamp_message::stimulus, set_lamp_message::stimulusInstance, and transmit_response().

Referenced by do_housekeeping(), handle_message(), skinny_call(), and skinny_hangup().

    01172 {
    01173    skinny_req *req;
    01174
    01175    req = req_alloc(sizeof(struct set_lamp_message));
    01176    if (!req) {
    01177       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01178       return;
    01179    }
    01180    req->len = htolel(sizeof(set_lamp_message)+4);
    01181    req->e = htolel(SET_LAMP_MESSAGE);
    01182    req->data.setlamp.stimulus = htolel(stimulus);
    01183    req->data.setlamp.stimulusInstance = htolel(instance);
    01184    req->data.setlamp.deviceStimulus = htolel(indication);
    01185    transmit_response(s, req);
    01186 }

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

Definition at line 986 of file chan_skinny.c.

References ast_log(), ast_mutex_lock(), ast_mutex_unlock(), ast_verbose(), skinny_req::e, skinnysession::fd, skinny_req::len, letohl, skinnysession::lock, and LOG_WARNING.

    00987 {
    00988    int res = 0;
    00989    ast_mutex_lock(&s->lock);
    00990
    00991 #if 0
    00992    if (skinnydebug) {
    00993       ast_verbose("writing packet type %04X (%d bytes) to socket %d\n", letohl(req->e), letohl(req->len)+8, s->fd);
    00994    }
    00995 #endif
    00996
    00997    res = write(s->fd, req, letohl(req->len)+8);
    00998    if (res != letohl(req->len)+8) {
    00999       ast_log(LOG_WARNING, "Transmit: write only sent %d out of %d bytes: %s\n", res, letohl(req->len)+8, strerror(errno));
    01000    }
    01001    ast_mutex_unlock(&s->lock);
    01002    return 1;
    01003 }

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

Definition at line 1188 of file chan_skinny.c.

References ast_log(), skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), set_ringer_message::ringerMode, SET_RINGER_MESSAGE, skinny_req::setringer, and transmit_response().

Referenced by handle_message(), skinny_call(), and skinny_hangup().

    01189 {
    01190    skinny_req *req;
    01191
    01192    req = req_alloc(sizeof(struct set_ringer_message));
    01193    if (!req) {
    01194       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01195       return;
    01196    }
    01197    req->len = htolel(sizeof(set_ringer_message)+4);
    01198    req->e = htolel(SET_RINGER_MESSAGE);
    01199    req->data.setringer.ringerMode = htolel(mode);
    01200    transmit_response(s, req);
    01201 }

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

Definition at line 1012 of file chan_skinny.c.

References ast_log(), skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, set_speaker_message::mode, req_alloc(), SET_SPEAKER_MESSAGE, skinny_req::setspeaker, and transmit_response().

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

    01013 {
    01014    skinny_req *req;
    01015
    01016    req = req_alloc(sizeof(struct set_speaker_message));
    01017    if (!req) {
    01018       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01019       return;
    01020    }
    01021    req->len = htolel(sizeof(set_speaker_message)+4);
    01022    req->e = htolel(SET_SPEAKER_MESSAGE);
    01023    req->data.setspeaker.mode = htolel(mode);
    01024    transmit_response(s, req);
    01025 }

static void transmit_tone | ( | struct skinnysession * | s,
|  | int | tone |
| ) |  |  | `[static]`

Definition at line 1125 of file chan_skinny.c.

References ast_log(), skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), START_TONE_MESSAGE, skinny_req::starttone, STOP_TONE_MESSAGE, start_tone_message::tone, and transmit_response().

Referenced by handle_message(), skinny_answer(), skinny_call(), skinny_hangup(), skinny_indicate(), skinny_senddigit(), and skinny_ss().

    01126 {
    01127    skinny_req *req;
    01128
    01129    if (tone > 0) {
    01130       req = req_alloc(sizeof(struct start_tone_message));
    01131    } else {
    01132       req = req_alloc(4);
    01133    }
    01134    if (!req) {
    01135       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
    01136       return;
    01137    }
    01138    if (tone > 0) {
    01139       req->len = htolel(sizeof(start_tone_message)+4);
    01140       req->e = htolel(START_TONE_MESSAGE);
    01141       req->data.starttone.tone = htolel(tone);
    01142    } else {
    01143       req->len = htolel(4);
    01144       req->e = htolel(STOP_TONE_MESSAGE);
    01145    }
    01146    transmit_response(s, req);
    01147 }

int unload_module | ( | void |  | ) |

Cleanup all module structures, sockets, etc.

This is called at exit. Any registrations and memory allocations need to be unregistered and free'd here. Nothing else will do these for you (until exit).

Returns:
  Zero on success, or non-zero on error.

Definition at line 3300 of file chan_skinny.c.

References ast_channel_unregister(), ast_cli_register(), ast_log(), ast_mutex_destroy(), ast_mutex_lock(), ast_mutex_unlock(), AST_PTHREADT_STOP, ast_rtp_proto_register(), free, iflist, LOG_WARNING, oh323_pvt::next, and skinny_session().

    03301 {
    03302 #if 0
    03303    struct skinny_session *session, s;
    03304    struct skinny_subchannel *sub;
    03305    struct skinny_line *line = session;
    03306
    03307    /* close all IP connections */
    03308    if (!ast_mutex_lock(&devicelock)) {
    03309       /* Terminate tcp listener thread */
    03310    } else {
    03311       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    03312       return -1;
    03313    }
    03314    if (!ast_mutex_lock(&monlock)) {
    03315       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
    03316          pthread_cancel(monitor_thread);
    03317          pthread_kill(monitor_thread, SIGURG);
    03318          pthread_join(monitor_thread, NULL);
    03319       }
    03320       monitor_thread = AST_PTHREADT_STOP;
    03321       ast_mutex_unlock(&monlock);
    03322    } else {
    03323       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    03324       return -1;
    03325    }
    03326    if (!ast_mutex_lock(&iflock)) {
    03327       /* Destroy all the interfaces and free their memory */
    03328       p = iflist;
    03329       while(p) {
    03330          pl = p;
    03331          p = p->next;
    03332          /* Free associated memory */
    03333          ast_mutex_destroy(&pl->lock);
    03334          free(pl);
    03335       }
    03336       iflist = NULL;
    03337       ast_mutex_unlock(&iflock);
    03338    } else {
    03339       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
    03340       return -1;
    03341    }
    03342
    03343         ast_rtp_proto_register(&skinny_rtp);
    03344    ast_channel_unregister(&skinny_tech);
    03345         ast_cli_register(&cli_show_devices);
    03346         ast_cli_register(&cli_show_lines);
    03347         ast_cli_register(&cli_debug);
    03348         ast_cli_register(&cli_no_debug);
    03349
    03350    return 0;
    03351 #endif
    03352    return -1;
    03353 }

int usecount | ( | void |  | ) |

Provides a usecount.

This function will be called by various parts of asterisk. Basically, all it has to do is to return a usecount when called. You will need to maintain your usecount within the module somewhere. The usecount should be how many channels provided by this module are in use.

Returns:
  The module's usecount.

Definition at line 3355 of file chan_skinny.c.

    03356 {
    03357    return usecnt;
    03358 }

## Variable Documentation

struct in_addr __ourip`[static]`

Definition at line 682 of file chan_skinny.c.

pthread_t accept_t`[static]`

Definition at line 685 of file chan_skinny.c.

char accountcode[AST_MAX_ACCOUNT_CODE] = ""`[static]`

Definition at line 704 of file chan_skinny.c.

struct ast_hostent ahp

Definition at line 683 of file chan_skinny.c.

Referenced by reload_config(), and rpt_exec().

int amaflags = 0`[static]`

Definition at line 706 of file chan_skinny.c.

struct sockaddr_in bindaddr`[static]`

Definition at line 679 of file chan_skinny.c.

button_definition button_def_12sp[]

Definition at line 370 of file chan_skinny.c.

button_definition button_def_30vip[]

Definition at line 343 of file chan_skinny.c.

button_definition button_def_7902[]

Definition at line 385 of file chan_skinny.c.

button_definition button_def_7910[]

Definition at line 400 of file chan_skinny.c.

button_definition button_def_7920[]

Definition at line 413 of file chan_skinny.c.

button_definition button_def_7935[]

Initial value:

     {
       { 1, STIMULUS_LINE },
       { 2, STIMULUS_LINE }
    }

Definition at line 422 of file chan_skinny.c.

button_definition button_def_7940[]

Initial value:

     {
       { 1, STIMULUS_LINE },
       { 2, STIMULUS_LINE }
    }

Definition at line 427 of file chan_skinny.c.

button_definition button_def_7960[]

Definition at line 432 of file chan_skinny.c.

button_definition button_def_7970[]

Definition at line 441 of file chan_skinny.c.

button_definition button_def_none = { 0, STIMULUS_NONE }

Definition at line 452 of file chan_skinny.c.

button_defs_t button_defs[]

Definition at line 460 of file chan_skinny.c.

int callnums = 1`[static]`

Definition at line 707 of file chan_skinny.c.

int callreturn = 0`[static]`

Definition at line 697 of file chan_skinny.c.

int callwaiting = 0`[static]`

Definition at line 696 of file chan_skinny.c.

int cancallforward = 0`[static]`

Definition at line 702 of file chan_skinny.c.

int capability = AST_FORMAT_ULAW`[static]`

Definition at line 81 of file chan_skinny.c.

char cid_name[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 690 of file chan_skinny.c.

char cid_num[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 689 of file chan_skinny.c.

struct ast_cli_entry cli_debug`[static]`

Initial value:

       { { "skinny", "debug", NULL }, skinny_do_debug, "Enable Skinny debugging", debug_usage }

Definition at line 1468 of file chan_skinny.c.

struct ast_cli_entry cli_no_debug`[static]`

Initial value:

       { { "skinny", "no", "debug", NULL }, skinny_no_debug, "Disable Skinny debugging", no_debug_usage }

Definition at line 1471 of file chan_skinny.c.

struct ast_cli_entry cli_show_devices`[static]`

Initial value:

       { { "skinny", "show", "devices", NULL }, skinny_show_devices, "Show defined Skinny devices", show_devices_usage }

Definition at line 1462 of file chan_skinny.c.

struct ast_cli_entry cli_show_lines`[static]`

Initial value:

       { { "skinny", "show", "lines", NULL }, skinny_show_lines, "Show defined Skinny lines per device", show_lines_usage }

Definition at line 1465 of file chan_skinny.c.

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

Definition at line 78 of file chan_skinny.c.

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

Definition at line 686 of file chan_skinny.c.

ast_group_t cur_callergroup = 0`[static]`

Definition at line 693 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0`[static]`

Definition at line 694 of file chan_skinny.c.

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

Definition at line 88 of file chan_skinny.c.

char debug_usage[]`[static]`

Initial value:

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

Definition at line 1454 of file chan_skinny.c.

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

Definition at line 75 of file chan_skinny.c.

struct skinny_device * devices`[static]`

Referenced by delete_devices(), find_subchannel_by_name(), reload_config(), skinny_register(), skinny_show_devices(), and skinny_show_lines().

int firstdigittimeout = 16000`[static]`

Definition at line 798 of file chan_skinny.c.

int gendigittimeout = 8000`[static]`

Definition at line 801 of file chan_skinny.c.

struct hostent* hp

Definition at line 683 of file chan_skinny.c.

Referenced by ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_sip_ouraddrfor(), build_peer(), check_via(), connect_asterisk(), create_addr(), iax2_register(), iax_template_parse(), launch_netscript(), parse_ok_contact(), parse_register_contact(), process_sdp(), realtime_peer(), realtime_user(), refresh_list(), reload_config(), rpt_exec(), rtp_do_debug_ip(), set_config(), set_destination(), sip_devicestate(), and sip_do_debug_ip().

int immediate = 0`[static]`

Definition at line 695 of file chan_skinny.c.

struct io_context* io`[static]`

Definition at line 773 of file chan_skinny.c.

int keep_alive = 120`[static]`

Definition at line 87 of file chan_skinny.c.

char language[MAX_LANGUAGE] = ""`[static]`

Definition at line 687 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = ""`[static]`

Definition at line 691 of file chan_skinny.c.

char mailbox[AST_MAX_EXTENSION]`[static]`

Definition at line 705 of file chan_skinny.c.

int matchdigittimeout = 3000`[static]`

Definition at line 804 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL`[static]`

Definition at line 795 of file chan_skinny.c.

char musicclass[MAX_MUSICCLASS] = ""`[static]`

Definition at line 688 of file chan_skinny.c.

int mwiblink = 0`[static]`

Definition at line 699 of file chan_skinny.c.

int nat = 0`[static]`

Definition at line 692 of file chan_skinny.c.

char no_debug_usage[]`[static]`

Initial value:

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

Definition at line 1458 of file chan_skinny.c.

char ourhost[256]`[static]`

Definition at line 680 of file chan_skinny.c.

int ourport`[static]`

Definition at line 681 of file chan_skinny.c.

struct sched_context* sched`[static]`

Definition at line 772 of file chan_skinny.c.

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

struct ast_rtp_protocol skinny_rtp`[static]`

Definition at line 1356 of file chan_skinny.c.

struct ast_channel_tech skinny_tech`[static]`

Definition at line 909 of file chan_skinny.c.

int skinnydebug = 1`[static]`

Definition at line 676 of file chan_skinny.c.

int skinnysock = -1`[static]`

Definition at line 684 of file chan_skinny.c.

const char* soft_key_set_hack`[static]`

Definition at line 540 of file chan_skinny.c.

soft_key_template_definition soft_key_template_default[]

Definition at line 511 of file chan_skinny.c.

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

Definition at line 76 of file chan_skinny.c.

int threewaycalling = 0`[static]`

Definition at line 698 of file chan_skinny.c.

int transfer = 0`[static]`

Definition at line 701 of file chan_skinny.c.

const char type[] = "Skinny"`[static]`

Definition at line 77 of file chan_skinny.c.

int usecnt = 0`[static]`

Definition at line 776 of file chan_skinny.c.

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

Definition at line 89 of file chan_skinny.c.