Sun Aug 6 15:06:31 2006

Asterisk developer's documentation


Main Page | Modules | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals | Related Pages

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.

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 activate_call_plane_message activate_call_plane_message
typedef buttondefinition button_definition
typedef button_defs button_defs_t
typedef button_template_res_message button_template_res_message
typedef call_info_message call_info_message
typedef call_state_message call_state_message
typedef capabilities_res_message capabilities_res_message
typedef close_recieve_channel_message close_recieve_channel_message
typedef definetimedate_message definetimedate_message
typedef dialled_number_message dialled_number_message
typedef display_notify_message display_notify_message
typedef display_prompt_status_message display_prompt_status_message
typedef displaytext_message displaytext_message
typedef keypad_button_message keypad_button_message
typedef line_stat_res_message line_stat_res_message
typedef line_state_req_message line_state_req_message
typedef media_qualifier media_qualifier
typedef open_recieve_channel_ack_message open_recieve_channel_ack_message
typedef open_recieve_channel_message open_recieve_channel_message
typedef register_ack_message register_ack_message
typedef register_message register_message
typedef register_rej_message register_rej_message
typedef select_soft_keys_message select_soft_keys_message
typedef server_identifier server_identifier
typedef server_res_message server_res_message
typedef set_lamp_message set_lamp_message
typedef set_ringer_message set_ringer_message
typedef set_speaker_message set_speaker_message
typedef soft_key_set_definition soft_key_set_definition
typedef soft_key_sets soft_key_sets
typedef soft_key_template soft_key_template
typedef soft_key_template_definition soft_key_template_definition
typedef speed_dial_stat_req_message speed_dial_stat_req_message
typedef speed_dial_stat_res_message speed_dial_stat_res_message
typedef start_media_transmission_message start_media_transmission_message
typedef start_tone_message start_tone_message
typedef station_capabilities station_capabilities
typedef stimulus_message stimulus_message
typedef stop_media_transmission_message stop_media_transmission_message
typedef unsigned short UINT16
typedef unsigned int UINT32
typedef unsigned char UINT8
typedef version_res_message version_res_message

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_devicebuild_device (char *cat, struct ast_variable *v)
static char * control2str (int ind)
static int convert_cap (int capability)
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_subchannelfind_subchannel_by_line (struct skinny_line *l)
static struct skinny_subchannelfind_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_reqreq_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_rtpskinny_get_rtp_peer (struct ast_channel *chan)
static struct ast_rtpskinny_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_channelskinny_new (struct skinny_subchannel *sub, int state)
static int skinny_no_debug (int fd, int argc, char *argv[])
static struct ast_frameskinny_read (struct ast_channel *ast)
static int skinny_register (skinny_req *req, struct skinnysession *s)
static skinny_reqskinny_req_parse (struct skinnysession *s)
static struct ast_channelskinny_request (const char *type, int format, void *data, int *cause)
static struct ast_frameskinny_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] = ""
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_devicedevices
static int firstdigittimeout = 16000
static int gendigittimeout = 8000
hostent * hp
static int immediate = 0
static struct io_contextio
static int keep_alive = 120
static char language [MAX_LANGUAGE] = ""
static char linelabel [AST_MAX_EXTENSION] = ""
static char mailbox [AST_MAX_EXTENSION]
static int matchdigittimeout = 3000
static 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_contextsched
static struct skinnysessionsessions
static char show_devices_usage []
static char show_lines_usage []
static struct ast_rtp_protocol skinny_rtp
static const 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 pthread_t tcp_thread
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)
 

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)
 

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)
 

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)
 

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

Referenced by skinny_call(), and skinny_indicate().

#define SKINNY_BUSY   6
 

Definition at line 722 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_BUSYTONE   0x23
 

Definition at line 733 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CALLWAIT   9
 

Definition at line 725 of file chan_skinny.c.

#define SKINNY_CALLWAITTONE   0x2D
 

Definition at line 736 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_CONGESTION   7
 

Definition at line 723 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_CONNECTED   5
 

Definition at line 721 of file chan_skinny.c.

Referenced by handle_message(), and skinny_answer().

#define SKINNY_CX_CONF   3
 

Definition at line 757 of file chan_skinny.c.

#define SKINNY_CX_CONFERENCE   3
 

Definition at line 758 of file chan_skinny.c.

#define SKINNY_CX_INACTIVE   4
 

Definition at line 760 of file chan_skinny.c.

Referenced by build_device().

#define SKINNY_CX_MUTE   4
 

Definition at line 759 of file chan_skinny.c.

#define SKINNY_CX_RECVONLY   1
 

Definition at line 755 of file chan_skinny.c.

Referenced by handle_message().

#define SKINNY_CX_SENDONLY   0
 

Definition at line 754 of file chan_skinny.c.

#define SKINNY_CX_SENDRECV   2
 

Definition at line 756 of file chan_skinny.c.

Referenced by skinny_answer().

#define SKINNY_DIALTONE   0x21
 

Definition at line 732 of file chan_skinny.c.

Referenced by handle_message(), and skinny_ss().

#define SKINNY_HOLD   8
 

Definition at line 724 of file chan_skinny.c.

#define SKINNY_INVALID   14
 

Definition at line 729 of file chan_skinny.c.

#define SKINNY_LAMP_BLINK   5
 

Definition at line 743 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_LAMP_FLASH   4
 

Definition at line 742 of file chan_skinny.c.

#define SKINNY_LAMP_OFF   1
 

Definition at line 739 of file chan_skinny.c.

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

#define SKINNY_LAMP_ON   2
 

Definition at line 740 of file chan_skinny.c.

Referenced by handle_message().

#define SKINNY_LAMP_WINK   3
 

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

Referenced by skinny_answer().

#define SKINNY_OFFHOOK   1
 

Definition at line 717 of file chan_skinny.c.

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

#define SKINNY_ONHOOK   2
 

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

#define SKINNY_PROGRESS   12
 

Definition at line 728 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_REORDER   0x25
 

Definition at line 735 of file chan_skinny.c.

Referenced by skinny_indicate(), and skinny_ss().

#define SKINNY_RING_FEATURE   4
 

Definition at line 748 of file chan_skinny.c.

#define SKINNY_RING_INSIDE   2
 

Definition at line 746 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RING_OFF   1
 

Definition at line 745 of file chan_skinny.c.

Referenced by handle_message(), and skinny_hangup().

#define SKINNY_RING_OUTSIDE   3
 

Definition at line 747 of file chan_skinny.c.

#define SKINNY_RINGIN   4
 

Definition at line 720 of file chan_skinny.c.

Referenced by skinny_call().

#define SKINNY_RINGOUT   3
 

Definition at line 719 of file chan_skinny.c.

Referenced by skinny_indicate().

#define SKINNY_SILENCE   0x00
 

Definition at line 731 of file chan_skinny.c.

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

#define SKINNY_SPEAKEROFF   2
 

Definition at line 715 of file chan_skinny.c.

Referenced by skinny_hangup(), and transmit_callstate().

#define SKINNY_SPEAKERON   1
 

Definition at line 714 of file chan_skinny.c.

#define SKINNY_TRANSFER   10
 

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

#define SUB_REAL   0
 

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

#define TYPE_TRUNK   1
 

Definition at line 750 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 activate_call_plane_message activate_call_plane_message
 

typedef struct buttondefinition button_definition
 

typedef struct button_defs button_defs_t
 

typedef struct button_template_res_message button_template_res_message
 

typedef struct call_info_message call_info_message
 

typedef struct call_state_message call_state_message
 

typedef struct capabilities_res_message capabilities_res_message
 

typedef struct close_recieve_channel_message close_recieve_channel_message
 

typedef struct definetimedate_message definetimedate_message
 

typedef struct dialled_number_message dialled_number_message
 

typedef struct display_notify_message display_notify_message
 

typedef struct display_prompt_status_message display_prompt_status_message
 

typedef struct displaytext_message displaytext_message
 

typedef struct keypad_button_message keypad_button_message
 

typedef struct line_stat_res_message line_stat_res_message
 

typedef struct line_state_req_message line_state_req_message
 

typedef struct media_qualifier media_qualifier
 

typedef struct open_recieve_channel_ack_message open_recieve_channel_ack_message
 

typedef struct open_recieve_channel_message open_recieve_channel_message
 

typedef struct register_ack_message register_ack_message
 

typedef struct register_message register_message
 

typedef struct register_rej_message register_rej_message
 

typedef struct select_soft_keys_message select_soft_keys_message
 

typedef struct server_identifier server_identifier
 

typedef struct server_res_message server_res_message
 

typedef struct set_lamp_message set_lamp_message
 

typedef struct set_ringer_message set_ringer_message
 

typedef struct set_speaker_message set_speaker_message
 

typedef struct soft_key_set_definition soft_key_set_definition
 

typedef struct soft_key_sets soft_key_sets
 

typedef struct soft_key_template soft_key_template
 

typedef struct soft_key_template_definition soft_key_template_definition
 

typedef struct speed_dial_stat_req_message speed_dial_stat_req_message
 

typedef struct speed_dial_stat_res_message speed_dial_stat_res_message
 

typedef struct start_media_transmission_message start_media_transmission_message
 

typedef struct start_tone_message start_tone_message
 

typedef struct station_capabilities station_capabilities
 

typedef struct stimulus_message stimulus_message
 

typedef struct stop_media_transmission_message stop_media_transmission_message
 

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.

typedef struct version_res_message version_res_message
 


Function Documentation

static void* accept_thread void *  ignore  )  [static]
 

Definition at line 2924 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, skinny_session(), skinnydebug, skinnysock, and tcp_thread.

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

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]
 

Definition at line 1482 of file chan_skinny.c.

References __ourip, accountcode, amaflags, 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_subchannel::callid, callnums, callreturn, callwaiting, cancallforward, capability, cid_name, cid_num, context, cur_callergroup, cur_pickupgroup, skinny_subchannel::cxmode, DEFAULT_SKINNY_PORT, free, immediate, language, linelabel, ast_variable::lineno, skinny_subchannel::lock, LOG_ERROR, LOG_WARNING, mailbox, malloc, MAX_SUBS, musicclass, mwiblink, ast_variable::name, skinny_subchannel::nat, nat, ast_variable::next, skinny_subchannel::next, skinny_subchannel::parent, SKINNY_CX_INACTIVE, SKINNY_ONHOOK, threewaycalling, transfer, TYPE_LINE, TYPE_TRUNK, ast_variable::value, and VERBOSE_PREFIX_3.

Referenced by reload_config().

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

static char* control2str int  ind  )  [static]
 

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

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

static int convert_cap int  capability  )  [static]
 

Definition at line 1007 of file chan_skinny.c.

Referenced by handle_message(), and transmit_connect().

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

void delete_devices void   ) 
 

Definition at line 3213 of file chan_skinny.c.

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

Referenced by reload().

03214 {
03215    struct skinny_device *d, *dlast;
03216    struct skinny_line *l, *llast;
03217    struct skinny_subchannel *sub, *slast;
03218    
03219    ast_mutex_lock(&devicelock);
03220    
03221    /* Delete all devices */
03222    for (d=devices;d;) {    
03223       /* Delete all lines for this device */
03224       for (l=d->lines;l;) {
03225          /* Delete all subchannels for this line */
03226          for (sub=l->sub;sub;) {
03227             slast = sub;
03228             sub = sub->next;
03229             ast_mutex_destroy(&slast->lock);
03230             free(slast);
03231          }
03232          llast = l;
03233          l = l->next;
03234          ast_mutex_destroy(&llast->lock);
03235          free(llast);
03236       }
03237       dlast = d;
03238       d = d->next;
03239       free(dlast);
03240    }
03241    devices=NULL;
03242    ast_mutex_unlock(&devicelock);
03243 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 3356 of file chan_skinny.c.

References desc.

03357 {
03358    return (char *) desc;
03359 }

static void destroy_session struct skinnysession s  )  [static]
 

Definition at line 2812 of file chan_skinny.c.

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

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

static void do_housekeeping struct skinnysession s  )  [static]
 

Definition at line 1304 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_OFF, skinnydebug, STIMULUS_VOICEMAIL, transmit_displaymessage(), and transmit_lamp_indication().

Referenced by handle_message(), and skinny_hangup().

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

static void* do_monitor void *  data  )  [static]
 

Definition at line 2975 of file chan_skinny.c.

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

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

static struct skinny_subchannel* find_subchannel_by_line struct skinny_line l  )  [static]
 

Definition at line 938 of file chan_skinny.c.

References skinny_line::sub.

Referenced by do_housekeeping(), and handle_message().

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

static struct skinny_subchannel* find_subchannel_by_name char *  dest  )  [static]
 

Definition at line 945 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, skinnydebug, and skinny_line::sub.

Referenced by skinny_request().

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

static int get_input struct skinnysession s  )  [static]
 

Definition at line 2841 of file chan_skinny.c.

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

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

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

Definition at line 2299 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(), button_defs::button_def, BUTTON_TEMPLATE_REQ_MESSAGE, BUTTON_TEMPLATE_RES_MESSAGE, skinny_subchannel::callid, CAPABILITIES_REQ_MESSAGE, CAPABILITIES_RES_MESSAGE, convert_cap(), skinny_subchannel::cxmode, skinny_req::data, date_format, DEFINETIMEDATE_MESSAGE, skinnysession::device, skinny_line::dnd, do_housekeeping(), skinny_req::e, find_subchannel_by_line(), ast_frame::frametype, free, skinny_line::hookstate, htolel, skinny_line::instance, IP_PORT_MESSAGE, keep_alive, KEEP_ALIVE_ACK_MESSAGE, KEEP_ALIVE_MESSAGE, KEYPAD_BUTTON_MESSAGE, skinny_line::label, skinny_req::len, letohl, LINE_STAT_RES_MESSAGE, LINE_STATE_REQ_MESSAGE, skinny_device::lines, LOG_DEBUG, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::model, ast_channel::name, skinny_line::name, skinny_device::name, name, skinny_subchannel::next, skinny_line::next, button_defs::num_buttons, OFFHOOK_MESSAGE, ONHOOK_MESSAGE, OPEN_RECIEVE_CHANNEL_ACK_MESSAGE, option_verbose, ourhost, ourport, skinny_subchannel::outgoing, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, REGISTER_ACK_MESSAGE, REGISTER_MESSAGE, REGISTER_REJ_MESSAGE, skinny_subchannel::rtp, SERVER_REQUEST_MESSAGE, SERVER_RES_MESSAGE, 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(), skinnydebug, soft_key_set_hack, SOFT_KEY_SET_REQ_MESSAGE, SOFT_KEY_SET_RES_MESSAGE, SOFT_KEY_TEMPLATE_REQ_MESSAGE, SOFT_KEY_TEMPLATE_RES_MESSAGE, SPEED_DIAL_STAT_REQ_MESSAGE, SPEED_DIAL_STAT_RES_MESSAGE, ast_frame::src, START_MEDIA_TRANSMISSION_MESSAGE, start_rtp(), 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, ast_frame::subclass, t, TIME_DATE_REQ_MESSAGE, 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, VERBOSE_PREFIX_3, skinny_device::version_id, VERSION_REQ_MESSAGE, and VERSION_RES_MESSAGE.

Referenced by skinny_session().

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

static int has_voicemail struct skinny_line l  )  [static]
 

Definition at line 1298 of file chan_skinny.c.

References ast_app_has_voicemail(), and skinny_line::mailbox.

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

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

References ASTERISK_GPL_KEY.

03352 {
03353    return ASTERISK_GPL_KEY;
03354 }

int load_module void   ) 
 

Initialize the module.

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.

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

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

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

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

03246 {
03247    delete_devices();
03248    reload_config();
03249    restart_monitor();
03250    return 0;
03251 }

static int reload_config void   )  [static]
 

Definition at line 3067 of file chan_skinny.c.

References __ourip, accept_t, accept_thread(), 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(), capability, cfg, config, date_format, DEFAULT_SKINNY_BACKLOG, DEFAULT_SKINNY_PORT, devices, format, hp, keep_alive, ast_variable::lineno, LOG_ERROR, LOG_NOTICE, LOG_WARNING, skinny_device::name, ast_variable::name, skinny_device::next, ast_variable::next, option_verbose, ourhost, ourport, skinnysock, ast_variable::value, VERBOSE_PREFIX_2, and VERBOSE_PREFIX_3.

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

static skinny_req* req_alloc size_t  size  )  [static]
 

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

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

static int restart_monitor void   )  [static]
 

Definition at line 3001 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, LOG_WARNING, and monitor_thread.

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

static int skinny_answer struct ast_channel ast  )  [static]
 

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

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

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

Definition at line 1896 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, skinnydebug, 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.

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

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

Definition at line 1364 of file chan_skinny.c.

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

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

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

Definition at line 2102 of file chan_skinny.c.

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

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

static struct ast_rtp* skinny_get_rtp_peer struct ast_channel chan  )  [static]
 

Definition at line 1336 of file chan_skinny.c.

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

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

static struct ast_rtp* skinny_get_vrtp_peer struct ast_channel chan  )  [static]
 

Definition at line 1331 of file chan_skinny.c.

01332 {
01333    return NULL;
01334 }

static int skinny_hangup struct ast_channel ast  )  [static]
 

Definition at line 1982 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, skinnydebug, STIMULUS_LINE, ast_channel::tech_pvt, transmit_callstate(), transmit_lamp_indication(), transmit_ringer_mode(), transmit_speaker_mode(), transmit_tone(), skinny_line::type, and TYPE_LINE.

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

static int skinny_indicate struct ast_channel ast,
int  ind
[static]
 

Definition at line 2172 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, skinnydebug, ast_channel::tech_pvt, transmit_callinfo(), transmit_callstate(), transmit_diallednumber(), transmit_displaypromptstatus(), transmit_tone(), and VERBOSE_PREFIX_3.

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

static struct ast_channel* skinny_new struct skinny_subchannel sub,
int  state
[static]
 

Definition at line 2235 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_set_callerid(), 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, capability, skinny_line::capability, skinny_line::cid_name, 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, ast_channel::tech, ast_channel::tech_pvt, type, ast_channel::type, usecnt, usecnt_lock, and ast_channel::writeformat.

Referenced by handle_message(), and skinny_request().

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

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

Definition at line 1374 of file chan_skinny.c.

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

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

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

Definition at line 2064 of file chan_skinny.c.

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

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

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

Definition at line 1647 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, skinny_device::next, skinny_device::registered, skinny_device::session, skinnysession::sin, skinny_device::type, version_id, and skinny_device::version_id.

Referenced by handle_message().

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

static skinny_req* skinny_req_parse struct skinnysession s  )  [static]
 

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

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

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

Definition at line 3030 of file chan_skinny.c.

References ast_log(), AST_STATE_DOWN, ast_strlen_zero(), ast_verbose(), skinny_line::callwaiting, capability, 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.

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

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

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

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

static int skinny_senddigit struct ast_channel ast,
char  digit
[static]
 

Definition at line 2114 of file chan_skinny.c.

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

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

static void* skinny_session void *  data  )  [static]
 

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

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

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

References ast_channel::tech_pvt.

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

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

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

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

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

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

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

static void* skinny_ss void *  data  )  [static]
 

Definition at line 1690 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, ast_callerid::cid_ani, skinny_line::cid_name, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, skinny_line::dnd, ast_channel::exten, exten, firstdigittimeout, gendigittimeout, skinny_line::hidecallerid, ast_channel::language, skinny_line::lastcallerid, LOG_DEBUG, LOG_WARNING, matchdigittimeout, 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, skinnydebug, ast_channel::tech_pvt, transmit_tone(), and VERBOSE_PREFIX_3.

Referenced by handle_message().

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

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

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

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

static void start_rtp struct skinny_subchannel sub  )  [static]
 

Definition at line 1674 of file chan_skinny.c.

References ast_mutex_lock(), ast_mutex_unlock(), ast_rtp_fd(), ast_rtp_new(), ast_rtp_setnat(), and transmit_connect().

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

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

References ast_log(), CALL_INFO_MESSAGE, skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), and transmit_response().

Referenced by skinny_call(), and skinny_indicate().

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

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

Definition at line 1028 of file chan_skinny.c.

References ACTIVATE_CALL_PLANE_MESSAGE, ast_log(), CALL_STATE_MESSAGE, CLOSE_RECIEVE_CHANNEL_MESSAGE, skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_SPEAKEROFF, STOP_MEDIA_TRANSMISSION_MESSAGE, transmit_response(), and transmit_speaker_mode().

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

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

static void transmit_connect struct skinnysession s  )  [static]
 

Definition at line 1105 of file chan_skinny.c.

References ast_log(), skinny_line::capability, convert_cap(), skinny_req::data, skinnysession::device, skinny_req::e, htolel, skinny_req::len, skinny_device::lines, LOG_ERROR, OPEN_RECIEVE_CHANNEL_MESSAGE, req_alloc(), and transmit_response().

Referenced by start_rtp().

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

static void transmit_diallednumber struct skinnysession s,
char *  text,
int  instance,
int  callid
[static]
 

Definition at line 1278 of file chan_skinny.c.

References ast_log(), skinny_req::data, DIALLED_NUMBER_MESSAGE, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), and transmit_response().

Referenced by skinny_indicate().

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

static void transmit_displaymessage struct skinnysession s,
char *  text
[static]
 

Definition at line 1204 of file chan_skinny.c.

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

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

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

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

Definition at line 1230 of file chan_skinny.c.

References ast_log(), ast_verbose(), skinny_req::data, DISPLAY_NOTIFY_MESSAGE, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), skinnydebug, and transmit_response().

Referenced by handle_message().

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

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

Definition at line 1253 of file chan_skinny.c.

References ast_log(), ast_verbose(), skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), skinnydebug, and transmit_response().

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

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

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

Definition at line 1172 of file chan_skinny.c.

References ast_log(), skinny_req::data, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), SET_LAMP_MESSAGE, and transmit_response().

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

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

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

Definition at line 987 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, LOG_WARNING, and skinnydebug.

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

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

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

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

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

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

Definition at line 1013 of file chan_skinny.c.

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

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

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

static void transmit_tone struct skinnysession s,
int  tone
[static]
 

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

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

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

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 3291 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, monitor_thread, oh323_pvt::next, and skinny_session().

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

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

References usecnt.

03347 {
03348    return usecnt;
03349 }


Variable Documentation

struct in_addr __ourip [static]
 

Definition at line 682 of file chan_skinny.c.

pthread_t accept_t [static]
 

Definition at line 686 of file chan_skinny.c.

Referenced by reload_config().

char accountcode[AST_MAX_ACCOUNT_CODE] = "" [static]
 

Definition at line 705 of file chan_skinny.c.

struct ast_hostent ahp
 

Definition at line 683 of file chan_skinny.c.

int amaflags = 0 [static]
 

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

Referenced by build_device().

int callreturn = 0 [static]
 

Definition at line 698 of file chan_skinny.c.

int callwaiting = 0 [static]
 

Definition at line 697 of file chan_skinny.c.

int cancallforward = 0 [static]
 

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

char cid_num[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 690 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 1469 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 1472 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 1463 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 1466 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 687 of file chan_skinny.c.

ast_group_t cur_callergroup = 0 [static]
 

Definition at line 694 of file chan_skinny.c.

ast_group_t cur_pickupgroup = 0 [static]
 

Definition at line 695 of file chan_skinny.c.

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

Definition at line 88 of file chan_skinny.c.

Referenced by handle_message(), and reload_config().

char debug_usage[] [static]
 

Initial value:

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

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

int gendigittimeout = 8000 [static]
 

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

struct io_context* io [static]
 

Definition at line 774 of file chan_skinny.c.

int keep_alive = 120 [static]
 

Definition at line 87 of file chan_skinny.c.

Referenced by handle_message(), and reload_config().

char language[MAX_LANGUAGE] = "" [static]
 

Definition at line 688 of file chan_skinny.c.

char linelabel[AST_MAX_EXTENSION] = "" [static]
 

Definition at line 692 of file chan_skinny.c.

Referenced by build_device().

char mailbox[AST_MAX_EXTENSION] [static]
 

Definition at line 706 of file chan_skinny.c.

int matchdigittimeout = 3000 [static]
 

Definition at line 805 of file chan_skinny.c.

pthread_t monitor_thread = AST_PTHREADT_NULL [static]
 

Definition at line 796 of file chan_skinny.c.

char musicclass[MAX_MUSICCLASS] = "" [static]
 

Definition at line 689 of file chan_skinny.c.

int mwiblink = 0 [static]
 

Definition at line 700 of file chan_skinny.c.

Referenced by build_device().

int nat = 0 [static]
 

Definition at line 693 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 1459 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 773 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 1447 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 1451 of file chan_skinny.c.

struct ast_rtp_protocol skinny_rtp [static]
 

Definition at line 1357 of file chan_skinny.c.

const struct ast_channel_tech skinny_tech [static]
 

Definition at line 910 of file chan_skinny.c.

int skinnydebug = 1 [static]
 

Definition at line 676 of file chan_skinny.c.

Referenced by accept_thread(), do_housekeeping(), find_subchannel_by_name(), handle_message(), skinny_call(), skinny_do_debug(), skinny_hangup(), skinny_indicate(), skinny_no_debug(), skinny_ss(), transmit_displaymessage(), transmit_displaynotify(), transmit_displaypromptstatus(), and transmit_response().

int skinnysock = -1 [static]
 

Definition at line 684 of file chan_skinny.c.

Referenced by accept_thread(), and reload_config().

const char* soft_key_set_hack [static]
 

Definition at line 540 of file chan_skinny.c.

Referenced by handle_message().

soft_key_template_definition soft_key_template_default[]
 

Definition at line 511 of file chan_skinny.c.

pthread_t tcp_thread [static]
 

Definition at line 685 of file chan_skinny.c.

Referenced by accept_thread().

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

int transfer = 0 [static]
 

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

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

Definition at line 89 of file chan_skinny.c.

Referenced by skinny_register().


Generated on Sun Aug 6 15:06:34 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.2