Fri Sep 29 11:13:24 2006

Asterisk developer's documentation


chan_skinny.c File Reference

Implementation of the Skinny protocol. More...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <signal.h>
#include <ctype.h>
#include "asterisk.h"
#include "asterisk/lock.h"
#include "asterisk/channel.h"
#include "asterisk/config.h"
#include "asterisk/logger.h"
#include "asterisk/module.h"
#include "asterisk/pbx.h"
#include "asterisk/options.h"
#include "asterisk/sched.h"
#include "asterisk/io.h"
#include "asterisk/rtp.h"
#include "asterisk/acl.h"
#include "asterisk/callerid.h"
#include "asterisk/cli.h"
#include "asterisk/say.h"
#include "asterisk/cdr.h"
#include "asterisk/astdb.h"
#include "asterisk/features.h"
#include "asterisk/app.h"
#include "asterisk/musiconhold.h"
#include "asterisk/utils.h"
#include "asterisk/dsp.h"

Include dependency graph for chan_skinny.c:

Go to the source code of this file.

Data Structures

struct  activate_call_plane_message
struct  button_defs
struct  button_template_res_message
struct  buttondefinition
struct  call_info_message
struct  call_state_message
struct  capabilities_res_message
struct  close_recieve_channel_message
struct  definetimedate_message
struct  dialled_number_message
struct  display_notify_message
struct  display_prompt_status_message
struct  displaytext_message
struct  keypad_button_message
struct  line_stat_res_message
struct  line_state_req_message
struct  media_qualifier
struct  open_recieve_channel_ack_message
struct  open_recieve_channel_message
struct  register_ack_message
struct  register_message
struct  register_rej_message
struct  select_soft_keys_message
struct  server_identifier
struct  server_res_message
struct  set_lamp_message
struct  set_ringer_message
struct  set_speaker_message
struct  skinny_device
struct  skinny_line
struct  skinny_paging_device
struct  skinny_req
struct  skinny_subchannel
struct  skinnysession
struct  soft_key_set_definition
struct  soft_key_sets
struct  soft_key_template
struct  soft_key_template_definition
struct  speed_dial_stat_req_message
struct  speed_dial_stat_res_message
struct  start_media_transmission_message
struct  start_tone_message
struct  station_capabilities
struct  stimulus_message
struct  stop_media_transmission_message
struct  version_res_message

Defines

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116
#define ALARM_MESSAGE   0x0020
#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E
#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097
#define CALL_INFO_MESSAGE   0x008F
#define CALL_STATE_MESSAGE   0x0111
#define CAPABILITIES_REQ_MESSAGE   0x009B
#define CAPABILITIES_RES_MESSAGE   0x0010
#define CLEAR_DISPLAY_MESSAGE   0x009A
#define CLOSE_RECIEVE_CHANNEL_MESSAGE   0x0106
#define DEFAULT_SKINNY_BACKLOG   2
#define DEFAULT_SKINNY_PORT   2000
#define DEFINETIMEDATE_MESSAGE   0x0094
#define DIALLED_NUMBER_MESSAGE   0x011D
#define DISPLAY_NOTIFY_MESSAGE   0x0114
#define DISPLAY_PROMPT_STATUS_MESSAGE   0x0112
#define DISPLAYTEXT_MESSAGE   0x0099
#define htolel(x)   (x)
#define htoles(x)   (x)
#define IP_PORT_MESSAGE   0x0002
#define KEEP_ALIVE_ACK_MESSAGE   0x0100
#define KEEP_ALIVE_MESSAGE   0x0000
#define KEYPAD_BUTTON_MESSAGE   0x0003
#define letohl(x)   (x)
#define letohs(x)   (x)
#define LINE_STAT_RES_MESSAGE   0x0092
#define LINE_STATE_REQ_MESSAGE   0x000B
#define MAX_SUBS   2
#define OFFHOOK_MESSAGE   0x0006
#define ONHOOK_MESSAGE   0x0007
#define OPEN_RECIEVE_CHANNEL_ACK_MESSAGE   0x0022
#define OPEN_RECIEVE_CHANNEL_MESSAGE   0x0105
#define REGISTER_ACK_MESSAGE   0x0081
#define REGISTER_MESSAGE   0x0001
#define REGISTER_REJ_MESSAGE   0x009D
#define SELECT_SOFT_KEYS_MESSAGE   0x0110
#define SERVER_REQUEST_MESSAGE   0x0012
#define SERVER_RES_MESSAGE   0x009E
#define SET_LAMP_MESSAGE   0x0086
#define SET_RINGER_MESSAGE   0x0085
#define SET_SPEAKER_MESSAGE   0x0088
#define SKINNY_ALERT   0x24
#define SKINNY_BUSY   6
#define SKINNY_BUSYTONE   0x23
#define SKINNY_CALLWAIT   9
#define SKINNY_CALLWAITTONE   0x2D
#define SKINNY_CONGESTION   7
#define SKINNY_CONNECTED   5
#define SKINNY_CX_CONF   3
#define SKINNY_CX_CONFERENCE   3
#define SKINNY_CX_INACTIVE   4
#define SKINNY_CX_MUTE   4
#define SKINNY_CX_RECVONLY   1
#define SKINNY_CX_SENDONLY   0
#define SKINNY_CX_SENDRECV   2
#define SKINNY_DIALTONE   0x21
#define SKINNY_HOLD   8
#define SKINNY_INVALID   14
#define SKINNY_LAMP_BLINK   5
#define SKINNY_LAMP_FLASH   4
#define SKINNY_LAMP_OFF   1
#define SKINNY_LAMP_ON   2
#define SKINNY_LAMP_WINK   3
#define SKINNY_MAX_PACKET   1000
#define SKINNY_NOTONE   0x7F
#define SKINNY_OFFHOOK   1
#define SKINNY_ONHOOK   2
#define SKINNY_PARK   11
#define SKINNY_PROGRESS   12
#define SKINNY_REORDER   0x25
#define SKINNY_RING_FEATURE   4
#define SKINNY_RING_INSIDE   2
#define SKINNY_RING_OFF   1
#define SKINNY_RING_OUTSIDE   3
#define SKINNY_RINGIN   4
#define SKINNY_RINGOUT   3
#define SKINNY_SILENCE   0x00
#define SKINNY_SPEAKEROFF   2
#define SKINNY_SPEAKERON   1
#define SKINNY_TRANSFER   10
#define SOFT_KEY_SET_REQ_MESSAGE   0x0025
#define SOFT_KEY_SET_RES_MESSAGE   0x0109
#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028
#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108
#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A
#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091
#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A
#define START_TONE_MESSAGE   0x0082
#define STIMULUS_AUTOANSWER   0x11
#define STIMULUS_CALLPARK   0x7E
#define STIMULUS_CALLPICKUP   0x7F
#define STIMULUS_CONFERENCE   0x7D
#define STIMULUS_DISPLAY   0x08
#define STIMULUS_FORWARDALL   0x05
#define STIMULUS_FORWARDBUSY   0x06
#define STIMULUS_FORWARDNOANSWER   0x07
#define STIMULUS_HOLD   0x03
#define STIMULUS_LINE   0x09
#define STIMULUS_MESSAGE   0x0005
#define STIMULUS_NONE   0xFF
#define STIMULUS_REDIAL   0x01
#define STIMULUS_SPEEDDIAL   0x02
#define STIMULUS_TRANSFER   0x04
#define STIMULUS_VOICEMAIL   0x0F
#define STOP_MEDIA_TRANSMISSION_MESSAGE   0x008B
#define STOP_TONE_MESSAGE   0x0083
#define SUB_ALT   1
#define SUB_REAL   0
#define TIME_DATE_REQ_MESSAGE   0x000D
#define TYPE_LINE   2
#define TYPE_TRUNK   1
#define UNREGISTER_MESSAGE   0x0027
#define VERSION_REQ_MESSAGE   0x000F
#define VERSION_RES_MESSAGE   0x0098

Typedefs

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

Functions

static void * accept_thread (void *ignore)
 AST_MUTEX_DEFINE_STATIC (devicelock)
 AST_MUTEX_DEFINE_STATIC (sessionlock)
 AST_MUTEX_DEFINE_STATIC (netlock)
 AST_MUTEX_DEFINE_STATIC (monlock)
 AST_MUTEX_DEFINE_STATIC (usecnt_lock)
static struct skinny_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 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 do_housekeeping(), and 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 do_housekeeping(), and 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 buttondefinition button_definition

typedef struct button_defs button_defs_t

typedef unsigned short UINT16

Definition at line 93 of file chan_skinny.c.

typedef unsigned int UINT32

Definition at line 94 of file chan_skinny.c.

typedef unsigned char UINT8

Definition at line 92 of file chan_skinny.c.


Function Documentation

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

Definition at line 2929 of file chan_skinny.c.

References ast_log(), ast_mutex_init(), ast_mutex_lock(), ast_mutex_unlock(), ast_pthread_create, ast_verbose(), destroy_session(), LOG_NOTICE, LOG_WARNING, malloc, s, sessions, and skinny_session().

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

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 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(), DEFAULT_SKINNY_PORT, free, ast_variable::lineno, LOG_ERROR, LOG_WARNING, malloc, MAX_SUBS, ast_variable::name, ast_variable::next, SKINNY_CX_INACTIVE, SKINNY_ONHOOK, 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 3218 of file chan_skinny.c.

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

Referenced by reload().

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

char* description ( void   ) 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 3361 of file chan_skinny.c.

References desc.

03362 {
03363    return (char *) desc;
03364 }

static void destroy_session ( struct skinnysession s  )  [static]

Definition at line 2817 of file chan_skinny.c.

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

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

static void do_housekeeping ( struct skinnysession s  )  [static]

Definition at line 1304 of file chan_skinny.c.

References ast_app_messagecount(), ast_verbose(), find_subchannel_by_line(), has_voicemail(), skinny_line::instance, skinny_line::mailbox, skinny_line::mwiblink, skinny_device::name, skinny_line::name, skinny_line::parent, skinny_subchannel::parent, s, SKINNY_LAMP_BLINK, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, STIMULUS_VOICEMAIL, skinny_line::sub, 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 2980 of file chan_skinny.c.

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

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

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

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

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

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

Definition at line 2304 of file chan_skinny.c.

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

Referenced by skinny_session().

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

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

References ASTERISK_GPL_KEY.

03357 {
03358    return ASTERISK_GPL_KEY;
03359 }

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

References ast_channel_register(), ast_cli_register(), ast_log(), ast_rtp_proto_register(), cli_debug, cli_no_debug, cli_show_devices, cli_show_lines, htolel, io, io_context_create(), LOG_ERROR, LOG_WARNING, reload_config(), restart_monitor(), sched_context_create(), skinny_rtp, skinny_tech, soft_key_template_default, and type.

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

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

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

03251 {
03252    delete_devices();
03253    reload_config();
03254    restart_monitor();
03255    return 0;
03256 }

static int reload_config ( void   )  [static]

Definition at line 3072 of file chan_skinny.c.

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

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

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

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

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

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, s, skinny_device::session, SKINNY_CONNECTED, SKINNY_CX_SENDRECV, SKINNY_NOTONE, start_rtp(), skinny_line::sub, 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, 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, and RESULT_SUCCESS.

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, s, skinny_device::session, SKINNY_LAMP_OFF, SKINNY_OFFHOOK, SKINNY_ONHOOK, SKINNY_RING_OFF, SKINNY_SILENCE, SKINNY_SPEAKEROFF, STIMULUS_LINE, skinny_line::sub, 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, s, skinny_device::session, SKINNY_ALERT, SKINNY_BUSY, SKINNY_BUSYTONE, SKINNY_CONGESTION, SKINNY_PROGRESS, SKINNY_REORDER, SKINNY_RINGOUT, SKINNY_SILENCE, skinny_line::sub, 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_setstate(), AST_STATE_DOWN, AST_STATE_RING, ast_strlen_zero(), ast_update_use_count(), ast_verbose(), skinny_line::call_forward, ast_channel::call_forward, skinny_line::callgroup, ast_channel::callgroup, skinny_subchannel::callid, skinny_line::capability, ast_channel::cid, ast_callerid::cid_name, skinny_line::cid_name, ast_callerid::cid_num, skinny_line::cid_num, skinny_line::context, ast_channel::context, skinny_line::exten, ast_channel::exten, ast_channel::fds, fmt, ast_channel::language, skinny_line::language, LOG_WARNING, skinny_device::name, skinny_line::name, ast_channel::name, ast_channel::nativeformats, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_line::pickupgroup, ast_channel::pickupgroup, ast_channel::priority, ast_channel::rawreadformat, ast_channel::rawwriteformat, ast_channel::readformat, ast_channel::rings, skinny_subchannel::rtp, skinny_tech, strdup, skinny_line::sub, ast_channel::tech, ast_channel::tech_pvt, ast_channel::type, 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 
02283       if (!ast_strlen_zero(l->cid_num))
02284          tmp->cid.cid_num = strdup(l->cid_num);
02285       if (!ast_strlen_zero(l->cid_name))
02286          tmp->cid.cid_name = strdup(l->cid_name);
02287 
02288       tmp->priority = 1;
02289       tmp->adsicpe = AST_ADSI_UNAVAILABLE;
02290 
02291       if (state != AST_STATE_DOWN) {
02292          if (ast_pbx_start(tmp)) {
02293             ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
02294             ast_hangup(tmp);
02295             tmp = NULL;
02296          }
02297       }
02298    } else {
02299       ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
02300     }
02301     return tmp;
02302 }

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, and RESULT_SUCCESS.

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, devices, skinny_device::ha, skinny_device::id, letohl, register_message::name, skinny_device::next, skinny_req::reg, skinny_device::registered, s, skinny_device::session, register_message::type, skinny_device::type, 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 2880 of file chan_skinny.c.

References ast_log(), skinny_req::e, free, letohl, LOG_ERROR, malloc, s, and SKINNY_MAX_PACKET.

Referenced by skinny_session().

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

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

Definition at line 3035 of file chan_skinny.c.

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

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

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

References ast_inet_ntoa(), ast_log(), ast_verbose(), destroy_session(), get_input(), handle_message(), LOG_NOTICE, s, skinny_req_parse(), and VERBOSE_PREFIX_3.

Referenced by accept_thread(), and unload_module().

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

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, skinny_line::cid_name, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, skinny_line::dnd, ast_channel::exten, exten, skinny_line::hidecallerid, ast_channel::language, skinny_line::lastcallerid, LOG_DEBUG, LOG_WARNING, ast_channel::name, skinny_device::name, skinny_line::name, skinny_subchannel::next, option_verbose, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, s, skinny_device::session, SKINNY_DIALTONE, SKINNY_REORDER, SKINNY_SILENCE, skinny_line::sub, 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                      NULL);
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(), ast_channel::fds, io, skinny_subchannel::lock, skinny_subchannel::nat, skinny_subchannel::owner, skinny_line::parent, skinny_subchannel::parent, skinny_subchannel::rtp, sched, skinny_device::session, 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, call_info_message::calledParty, call_info_message::calledPartyName, skinny_req::callinfo, call_info_message::callingParty, call_info_message::callingPartyName, skinny_req::data, skinny_req::e, htolel, call_info_message::instance, skinny_req::len, LOG_ERROR, call_info_message::reference, req_alloc(), s, transmit_response(), and call_info_message::type.

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, call_state_message::callReference, call_state_message::callState, skinny_req::callstate, CLOSE_RECIEVE_CHANNEL_MESSAGE, skinny_req::data, skinny_req::e, htolel, skinny_req::len, call_state_message::lineInstance, LOG_ERROR, req_alloc(), s, 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(), open_recieve_channel_message::bitrate, skinny_line::capability, open_recieve_channel_message::capability, open_recieve_channel_message::conferenceId, convert_cap(), skinny_req::data, skinny_req::e, open_recieve_channel_message::echo, htolel, skinny_req::len, LOG_ERROR, OPEN_RECIEVE_CHANNEL_MESSAGE, skinny_req::openrecievechannel, open_recieve_channel_message::packets, open_recieve_channel_message::partyId, req_alloc(), s, 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(), dialled_number_message::callReference, skinny_req::data, DIALLED_NUMBER_MESSAGE, dialled_number_message::dialledNumber, skinny_req::diallednumber, skinny_req::e, htolel, skinny_req::len, dialled_number_message::lineInstance, LOG_ERROR, req_alloc(), s, 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, skinny_req::displaytext, DISPLAYTEXT_MESSAGE, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), s, displaytext_message::text, 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, display_notify_message::displayMessage, skinny_req::displaynotify, display_notify_message::displayTimeout, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), s, 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(), display_prompt_status_message::callReference, skinny_req::data, DISPLAY_PROMPT_STATUS_MESSAGE, skinny_req::displaypromptstatus, skinny_req::e, htolel, skinny_req::len, display_prompt_status_message::lineInstance, LOG_ERROR, display_prompt_status_message::messageTimeout, display_prompt_status_message::promptMessage, req_alloc(), s, 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, set_lamp_message::deviceStimulus, skinny_req::e, htolel, skinny_req::len, LOG_ERROR, req_alloc(), s, SET_LAMP_MESSAGE, skinny_req::setlamp, set_lamp_message::stimulus, set_lamp_message::stimulusInstance, and transmit_response().

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

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, skinny_req::len, letohl, LOG_WARNING, and s.

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::ringerMode, s, SET_RINGER_MESSAGE, skinny_req::setringer, 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, set_speaker_message::mode, req_alloc(), s, SET_SPEAKER_MESSAGE, skinny_req::setspeaker, 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(), s, START_TONE_MESSAGE, skinny_req::starttone, STOP_TONE_MESSAGE, start_tone_message::tone, and transmit_response().

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

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 3296 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(), cli_debug, cli_no_debug, cli_show_devices, cli_show_lines, free, iflist, LOG_WARNING, monitor_thread, oh323_pvt::next, s, skinny_rtp, skinny_session(), and skinny_tech.

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

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

References usecnt.

03352 {
03353    return usecnt;
03354 }


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.

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.

Referenced by ast_dnsmgr_lookup(), ast_find_ourip(), ast_get_ip_or_srv(), ast_sip_ouraddrfor(), check_via(), create_addr(), festival_exec(), iax2_register(), launch_netscript(), parse_ok_contact(), parse_register_contact(), process_sdp(), refresh_list(), reload_config(), rpt_exec(), rtp_do_debug_ip(), set_destination(), sip_devicestate(), and sip_do_debug_ip().

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.

Referenced by handle_message().

button_defs_t button_defs[]

Definition at line 460 of file chan_skinny.c.

Referenced by handle_message().

int callnums = 1 [static]

Definition at line 708 of file chan_skinny.c.

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.

Referenced by load_module(), and unload_module().

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.

Referenced by load_module(), and unload_module().

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.

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

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.

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.

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.

Referenced by load_module(), and unload_module().

struct ast_channel_tech skinny_tech [static]

Definition at line 910 of file chan_skinny.c.

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

int skinnydebug = 1 [static]

Definition at line 676 of file chan_skinny.c.

int skinnysock = -1 [static]

Definition at line 684 of file chan_skinny.c.

const char* soft_key_set_hack [static]

Definition at line 540 of file chan_skinny.c.

soft_key_template_definition soft_key_template_default[]

Definition at line 511 of file chan_skinny.c.

Referenced by handle_message(), and load_module().

pthread_t tcp_thread [static]

Definition at line 685 of file chan_skinny.c.

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

Definition at line 76 of file chan_skinny.c.

int threewaycalling = 0 [static]

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


Generated on Fri Sep 29 11:13:25 2006 for Asterisk - the Open Source PBX by  doxygen 1.4.7