Sat Mar 24 23:27:23 2007

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 const struct ast_channel_tech skinny_tech
static int skinnydebug = 1
static int skinnysock = -1
static const char * soft_key_set_hack
soft_key_template_definition soft_key_template_default []
static pthread_t tcp_thread
static const char tdesc [] = "Skinny Client Control Protocol (Skinny)"
static int threewaycalling = 0
static int transfer = 0
static const char type [] = "Skinny"
static int usecnt = 0
static char version_id [16] = "P002F202"


Detailed Description

Implementation of the Skinny protocol.

Author:
Jeremy McNamara & Florian Overkamp

Definition in file chan_skinny.c.


Define Documentation

#define ACTIVATE_CALL_PLANE_MESSAGE   0x0116
 

Definition at line 618 of file chan_skinny.c.

Referenced by transmit_callstate().

#define ALARM_MESSAGE   0x0020
 

Definition at line 183 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_REQ_MESSAGE   0x000E
 

Definition at line 181 of file chan_skinny.c.

Referenced by handle_message().

#define BUTTON_TEMPLATE_RES_MESSAGE   0x0097
 

Definition at line 320 of file chan_skinny.c.

Referenced by handle_message().

#define CALL_INFO_MESSAGE   0x008F
 

Definition at line 254 of file chan_skinny.c.

Referenced by transmit_callinfo().

#define CALL_STATE_MESSAGE   0x0111
 

Definition at line 597 of file chan_skinny.c.

Referenced by transmit_callstate().

#define CAPABILITIES_REQ_MESSAGE   0x009B
 

Definition at line 307 of file chan_skinny.c.

Referenced by handle_message().

#define CAPABILITIES_RES_MESSAGE   0x0010
 

Definition at line 154 of file chan_skinny.c.

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

#define DEFINETIMEDATE_MESSAGE   0x0094
 

Definition at line 282 of file chan_skinny.c.

#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.

#define KEEP_ALIVE_MESSAGE   0x0000
 

Definition at line 125 of file chan_skinny.c.

#define KEYPAD_BUTTON_MESSAGE   0x0003
 

Definition at line 140 of file chan_skinny.c.

#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.

#define LINE_STATE_REQ_MESSAGE   0x000B
 

Definition at line 174 of file chan_skinny.c.

#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.

#define ONHOOK_MESSAGE   0x0007
 

Definition at line 152 of file chan_skinny.c.

#define OPEN_RECIEVE_CHANNEL_ACK_MESSAGE   0x0022
 

Definition at line 185 of file chan_skinny.c.

#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 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.

#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 skinny_call(), skinny_hangup(), and transmit_callstate().

#define SKINNY_ONHOOK   2
 

Definition at line 718 of file chan_skinny.c.

Referenced by build_device(), 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 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 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.

#define SOFT_KEY_SET_RES_MESSAGE   0x0109
 

Definition at line 539 of file chan_skinny.c.

#define SOFT_KEY_TEMPLATE_REQ_MESSAGE   0x0028
 

Definition at line 195 of file chan_skinny.c.

#define SOFT_KEY_TEMPLATE_RES_MESSAGE   0x0108
 

Definition at line 504 of file chan_skinny.c.

#define SPEED_DIAL_STAT_REQ_MESSAGE   0x000A
 

Definition at line 169 of file chan_skinny.c.

#define SPEED_DIAL_STAT_RES_MESSAGE   0x0091
 

Definition at line 267 of file chan_skinny.c.

#define START_MEDIA_TRANSMISSION_MESSAGE   0x008A
 

Definition at line 230 of file chan_skinny.c.

#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.

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

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

02951 {
02952    int as;
02953    struct sockaddr_in sin;
02954    socklen_t sinlen;
02955    struct skinnysession *s;
02956    struct protoent *p;
02957    int arg = 1;
02958    pthread_attr_t attr;
02959 
02960    pthread_attr_init(&attr);
02961    pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
02962 
02963    for (;;) {
02964       sinlen = sizeof(sin);
02965       as = accept(skinnysock, (struct sockaddr *)&sin, &sinlen);
02966       if (as < 0) {
02967          ast_log(LOG_NOTICE, "Accept returned -1: %s\n", strerror(errno));
02968          continue;
02969       }
02970       p = getprotobyname("tcp");
02971       if(p) {
02972          if( setsockopt(as, p->p_proto, TCP_NODELAY, (char *)&arg, sizeof(arg) ) < 0 ) {
02973             ast_log(LOG_WARNING, "Failed to set Skinny tcp connection to TCP_NODELAY mode: %s\n", strerror(errno));
02974          }
02975       }
02976       s = malloc(sizeof(struct skinnysession));
02977       if (!s) {
02978          ast_log(LOG_WARNING, "Failed to allocate Skinny session: %s\n", strerror(errno));
02979          continue;
02980       } 
02981       memset(s, 0, sizeof(struct skinnysession));
02982       memcpy(&s->sin, &sin, sizeof(sin));
02983       ast_mutex_init(&s->lock);
02984       s->fd = as;
02985       ast_mutex_lock(&sessionlock);
02986       s->next = sessions;
02987       sessions = s;
02988       ast_mutex_unlock(&sessionlock);
02989       
02990       if (ast_pthread_create(&tcp_thread, NULL, skinny_session, s)) {
02991          destroy_session(s);
02992       }
02993    }
02994    if (skinnydebug) {
02995       ast_verbose("killing accept thread\n");
02996    }
02997    close(as);
02998    return 0;
02999 }

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_strlen_zero(), ast_true(), ast_verbose(), free, ast_variable::lineno, LOG_WARNING, malloc, MAX_SUBS, ast_variable::name, ast_variable::next, skinny_line::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 2143 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.

02143                                   {
02144     static char tmp[100];
02145 
02146     switch (ind) {
02147         case AST_CONTROL_HANGUP:
02148             return "Other end has hungup";
02149         case AST_CONTROL_RING:
02150             return "Local ring";
02151         case AST_CONTROL_RINGING:
02152             return "Remote end is ringing";
02153         case AST_CONTROL_ANSWER:
02154             return "Remote end has answered";
02155         case AST_CONTROL_BUSY:
02156             return "Remote end is busy";
02157         case AST_CONTROL_TAKEOFFHOOK:
02158             return "Make it go off hook";
02159         case AST_CONTROL_OFFHOOK:
02160             return "Line is off hook";
02161         case AST_CONTROL_CONGESTION:
02162             return "Congestion (circuits busy)";
02163         case AST_CONTROL_FLASH:
02164             return "Flash hook";
02165         case AST_CONTROL_WINK:
02166             return "Wink";
02167         case AST_CONTROL_OPTION:
02168             return "Set a low-level option";
02169         case AST_CONTROL_RADIO_KEY:
02170             return "Key Radio";
02171         case AST_CONTROL_RADIO_UNKEY:
02172             return "Un-Key Radio";
02173         case AST_CONTROL_PROGRESS:
02174             return "Remote end is making Progress";
02175         case AST_CONTROL_PROCEEDING:
02176             return "Remote end is proceeding";
02177         case AST_CONTROL_HOLD:
02178             return "Hold";
02179         case AST_CONTROL_UNHOLD:
02180             return "Unhold";
02181    case -1:
02182        return "Stop tone";
02183     }
02184     snprintf(tmp, 100, "UNKNOWN-%d", ind);
02185     return tmp;
02186 }

static int convert_cap int  capability  )  [static]
 

Definition at line 1007 of file chan_skinny.c.

Referenced by 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 3239 of file chan_skinny.c.

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

Referenced by reload().

03240 {
03241    struct skinny_device *d, *dlast;
03242    struct skinny_line *l, *llast;
03243    struct skinny_subchannel *sub, *slast;
03244    
03245    ast_mutex_lock(&devicelock);
03246    
03247    /* Delete all devices */
03248    for (d=devices;d;) {    
03249       /* Delete all lines for this device */
03250       for (l=d->lines;l;) {
03251          /* Delete all subchannels for this line */
03252          for (sub=l->sub;sub;) {
03253             slast = sub;
03254             sub = sub->next;
03255             ast_mutex_destroy(&slast->lock);
03256             free(slast);
03257          }
03258          llast = l;
03259          l = l->next;
03260          ast_mutex_destroy(&llast->lock);
03261          free(llast);
03262       }
03263       dlast = d;
03264       d = d->next;
03265       free(dlast);
03266    }
03267    devices=NULL;
03268    ast_mutex_unlock(&devicelock);
03269 }

char* description void   ) 
 

Provides a description of the module.

Returns:
a short description of your module

Definition at line 3382 of file chan_skinny.c.

03383 {
03384    return (char *) desc;
03385 }

static void destroy_session struct skinnysession s  )  [static]
 

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

02835 {
02836    struct skinnysession *cur, *prev = NULL;
02837    ast_mutex_lock(&sessionlock);
02838    cur = sessions;
02839    while(cur) {
02840       if (cur == s) {
02841          break;
02842       }
02843       prev = cur;
02844       cur = cur->next;
02845    }
02846    if (cur) {
02847       if (prev) {
02848          prev->next = cur->next;
02849       } else {
02850          sessions = cur->next;
02851       }
02852       if (s->fd > -1) {
02853          close(s->fd);
02854       }
02855       ast_mutex_destroy(&s->lock);
02856       free(s);
02857    } else {
02858       ast_log(LOG_WARNING, "Trying to delete nonexistent session %p?\n", s);
02859    }
02860    ast_mutex_unlock(&sessionlock);
02861 }

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

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

03002 {
03003    int res;
03004 
03005    /* This thread monitors all the interfaces which are not yet in use
03006       (and thus do not have a separate thread) indefinitely */
03007    /* From here on out, we die whenever asked */
03008    for(;;) {
03009       pthread_testcancel();
03010       /* Wait for sched or io */
03011       res = ast_sched_wait(sched);
03012       if ((res < 0) || (res > 1000)) {
03013          res = 1000;
03014       }
03015       res = ast_io_wait(io, res);
03016       ast_mutex_lock(&monlock);
03017       if (res >= 0) {
03018          ast_sched_runq(sched);
03019       }
03020       ast_mutex_unlock(&monlock);
03021    }
03022    /* Never reached */
03023    return NULL;
03024    
03025 }

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

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

02864 {  
02865    int res;  
02866    int dlen = 0;
02867    struct pollfd fds[1];  
02868  
02869    fds[0].fd = s->fd;
02870    fds[0].events = POLLIN;
02871    res = poll(fds, 1, -1);
02872  
02873    if (res < 0) {
02874       ast_log(LOG_WARNING, "Select returned error: %s\n", strerror(errno));
02875    } else if (res > 0) {
02876       memset(s->inbuf,0,sizeof(s->inbuf));
02877       res = read(s->fd, s->inbuf, 4);
02878       if (res != 4) {
02879          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
02880          return -1;
02881       }
02882       dlen = letohl(*(int *)s->inbuf);
02883       if (dlen < 0) {
02884          ast_log(LOG_WARNING, "Skinny Client sent invalid data.\n");
02885          return -1;
02886       }
02887       if (dlen+8 > sizeof(s->inbuf)) {
02888          dlen = sizeof(s->inbuf) - 8;
02889       }
02890       *(int *)s->inbuf = htolel(dlen);
02891       res = read(s->fd, s->inbuf+4, dlen+4);
02892       ast_mutex_unlock(&s->lock);
02893       if (res != (dlen+4)) {
02894          ast_log(LOG_WARNING, "Skinny Client sent less data than expected.\n");
02895          return -1;
02896       } 
02897    }  
02898    return res;  
02899 }   

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

Definition at line 2321 of file chan_skinny.c.

References ALARM_MESSAGE, ast_log(), ast_verbose(), button_defs, BUTTON_TEMPLATE_REQ_MESSAGE, BUTTON_TEMPLATE_RES_MESSAGE, CAPABILITIES_REQ_MESSAGE, skinny_req::data, register_ack_message::dateTemplate, skinny_req::e, register_rej_message::errMsg, find_subchannel_by_line(), free, htolel, IP_PORT_MESSAGE, register_ack_message::keepAlive, skinny_req::len, letohl, LOG_ERROR, LOG_WARNING, skinny_line::name, register_message::name, name, option_verbose, skinny_subchannel::parent, skinny_req::reg, skinny_req::regack, REGISTER_ACK_MESSAGE, REGISTER_MESSAGE, REGISTER_REJ_MESSAGE, skinny_req::regrej, register_ack_message::res, register_ack_message::res2, s, register_ack_message::secondaryKeepAlive, 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_DIALTONE, SKINNY_LAMP_OFF, SKINNY_LAMP_ON, SKINNY_MAX_PACKET, skinny_register(), 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, t, transmit_displaynotify(), transmit_lamp_indication(), transmit_response(), transmit_speaker_mode(), transmit_tone(), button_defs::type, UNREGISTER_MESSAGE, VERBOSE_PREFIX_3, version_res_message::version, skinny_req::version, VERSION_REQ_MESSAGE, and VERSION_RES_MESSAGE.

Referenced by skinny_session().

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

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

References ASTERISK_GPL_KEY.

03378 {
03379    return ASTERISK_GPL_KEY;
03380 }

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

References htolel.

03281 {
03282    int res = 0;
03283 
03284    for (; res < (sizeof(soft_key_template_default) / sizeof(soft_key_template_default[0])); res++) {
03285       soft_key_template_default[res].softKeyEvent = htolel(soft_key_template_default[res].softKeyEvent);
03286    }
03287    /* load and parse config */
03288    res = reload_config();
03289    
03290    ast_rtp_proto_register(&skinny_rtp);
03291    ast_cli_register(&cli_show_devices);
03292    ast_cli_register(&cli_show_lines);
03293    ast_cli_register(&cli_debug);
03294    ast_cli_register(&cli_no_debug);
03295    sched = sched_context_create();
03296    if (!sched) {
03297       ast_log(LOG_WARNING, "Unable to create schedule context\n");
03298    }
03299    io = io_context_create();
03300    if (!io) {
03301       ast_log(LOG_WARNING, "Unable to create I/O context\n");
03302    }
03303    /* And start the monitor for the first time */
03304    restart_monitor();
03305 
03306    /* Announce our presence to Asterisk */   
03307    if (!res) {
03308       /* Make sure we can register our skinny channel type */
03309       if (ast_channel_register(&skinny_tech)) {
03310          ast_log(LOG_ERROR, "Unable to register channel class %s\n", type);
03311          return -1;
03312       }
03313    }
03314    return res;
03315 }

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

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

03272 {
03273    delete_devices();
03274    reload_config();
03275    restart_monitor();
03276    return 0;
03277 }

static int reload_config void   )  [static]
 

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

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

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 3027 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.

03028 {
03029    /* If we're supposed to be stopped -- stay stopped */
03030    if (monitor_thread == AST_PTHREADT_STOP)
03031       return 0;
03032    if (ast_mutex_lock(&monlock)) {
03033       ast_log(LOG_WARNING, "Unable to lock monitor\n");
03034       return -1;
03035    }
03036    if (monitor_thread == pthread_self()) {
03037       ast_mutex_unlock(&monlock);
03038       ast_log(LOG_WARNING, "Cannot kill myself\n");
03039       return -1;
03040    }
03041    if (monitor_thread != AST_PTHREADT_NULL) {
03042       /* Wake up the thread */
03043       pthread_kill(monitor_thread, SIGURG);
03044    } else {
03045       /* Start a new monitor */
03046       if (ast_pthread_create(&monitor_thread, NULL, do_monitor, NULL) < 0) {
03047          ast_mutex_unlock(&monlock);
03048          ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
03049          return -1;
03050       }
03051    }
03052    ast_mutex_unlock(&monlock);
03053    return 0;
03054 }

static int skinny_answer struct ast_channel ast  )  [static]
 

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

02042 {
02043     int res = 0;
02044     struct skinny_subchannel *sub = ast->tech_pvt;
02045     struct skinny_line *l = sub->parent;
02046     struct skinnysession *s = l->parent->session;
02047 
02048     sub->cxmode = SKINNY_CX_SENDRECV;
02049     if (!sub->rtp) {
02050       start_rtp(sub);
02051     } 
02052     ast_verbose("skinny_answer(%s) on %s@%s-%d\n", ast->name, l->name, l->parent->name, sub->callid);
02053     if (ast->_state != AST_STATE_UP) {
02054    ast_setstate(ast, AST_STATE_UP);
02055     }
02056     transmit_tone(s, SKINNY_NOTONE);
02057     transmit_callstate(s, l->instance, SKINNY_CONNECTED, sub->callid);
02058     transmit_displaypromptstatus(s, "Connected", 0, l->instance, sub->callid);
02059     return res;
02060 }

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

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

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

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

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

02120 {
02121    struct skinny_subchannel *sub = newchan->tech_pvt;
02122       ast_log(LOG_NOTICE, "skinny_fixup(%s, %s)\n", oldchan->name, newchan->name);
02123    if (sub->owner != oldchan) {
02124       ast_log(LOG_WARNING, "old channel wasn't %p but was %p\n", oldchan, sub->owner);
02125       return -1;
02126    }
02127    sub->owner = newchan;
02128    return 0;
02129 }

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 1999 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.

02000 {
02001     struct skinny_subchannel *sub = ast->tech_pvt;
02002     struct skinny_line *l = sub->parent;
02003     struct skinnysession *s = l->parent->session;
02004 
02005     if (skinnydebug) {
02006         ast_verbose("skinny_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
02007     }
02008     if (!ast->tech_pvt) {
02009         ast_log(LOG_DEBUG, "Asked to hangup channel not connected\n");
02010         return 0;
02011     }
02012 
02013     if (l->parent->registered) {
02014    if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_OFFHOOK)) {
02015          sub->parent->hookstate = SKINNY_ONHOOK;
02016          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
02017          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
02018          transmit_speaker_mode(s, SKINNY_SPEAKEROFF); 
02019       } else if ((sub->parent->type = TYPE_LINE) && (sub->parent->hookstate == SKINNY_ONHOOK)) {
02020          transmit_callstate(s, l->instance, SKINNY_ONHOOK, sub->callid);
02021          transmit_speaker_mode(s, SKINNY_SPEAKEROFF); 
02022          transmit_ringer_mode(s, SKINNY_RING_OFF);
02023          transmit_tone(s, SKINNY_SILENCE);
02024          transmit_lamp_indication(s, STIMULUS_LINE, l->instance, SKINNY_LAMP_OFF);
02025          do_housekeeping(s);
02026       } 
02027     }
02028     ast_mutex_lock(&sub->lock);
02029     sub->owner = NULL;
02030     ast->tech_pvt = NULL;
02031     sub->alreadygone = 0;
02032     sub->outgoing = 0;
02033     if (sub->rtp) {
02034         ast_rtp_destroy(sub->rtp);
02035         sub->rtp = NULL;
02036     }
02037     ast_mutex_unlock(&sub->lock);
02038     return 0;
02039 }

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

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

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

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

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

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

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

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

02082 {
02083    struct ast_frame *fr;
02084    struct skinny_subchannel *sub = ast->tech_pvt;
02085    ast_mutex_lock(&sub->lock);
02086    fr = skinny_rtp_read(sub);
02087    ast_mutex_unlock(&sub->lock);
02088    return fr;
02089 }

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

02902 {
02903    skinny_req *req;
02904    
02905    req = malloc(SKINNY_MAX_PACKET);
02906    if (!req) {
02907       ast_log(LOG_ERROR, "Unable to allocate skinny_request, this is bad\n");
02908       return NULL;
02909    }
02910    memset(req, 0, sizeof(skinny_req));
02911    /* +8 to account for reserved and length fields */
02912    memcpy(req, s->inbuf, letohl(*(int*)(s->inbuf))+8); 
02913    if (letohl(req->e) < 0) {
02914       ast_log(LOG_ERROR, "Event Message is NULL from socket %d, This is bad\n", s->fd);
02915       free(req);
02916       return NULL;
02917    }
02918    return req;
02919 }

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

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

03057 {
03058    int oldformat;
03059    struct skinny_subchannel *sub;
03060    struct ast_channel *tmpc = NULL;
03061    char tmp[256];
03062    char *dest = data;
03063 
03064    oldformat = format;
03065    format &= capability;
03066    if (!format) {
03067       ast_log(LOG_NOTICE, "Asked to get a channel of unsupported format '%d'\n", format);
03068       return NULL;
03069    }
03070    strncpy(tmp, dest, sizeof(tmp) - 1);
03071    if (ast_strlen_zero(tmp)) {
03072       ast_log(LOG_NOTICE, "Skinny channels require a device\n");
03073       return NULL;
03074    }
03075    sub = find_subchannel_by_name(tmp);  
03076    if (!sub) {
03077       ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
03078       return NULL;
03079    }
03080       if (option_verbose > 2) {
03081          ast_verbose(VERBOSE_PREFIX_3 "skinny_request(%s)\n", tmp);
03082          ast_verbose(VERBOSE_PREFIX_3 "Skinny cw: %d, dnd: %d, so: %d, sno: %d\n", 
03083                      sub->parent->callwaiting, sub->parent->dnd, sub->owner ? 1 : 0, sub->next->owner ? 1: 0);
03084       }
03085    tmpc = skinny_new(sub->owner ? sub->next : sub, AST_STATE_DOWN);
03086    if (!tmpc) {
03087       ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
03088    }
03089    restart_monitor();
03090    return tmpc;
03091 }

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

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

02063 {
02064    /* Retrieve audio/etc from channel.  Assumes sub->lock is already held. */
02065    struct ast_frame *f;
02066    f = ast_rtp_read(sub->rtp);
02067    if (sub->owner) {
02068       /* We already hold the channel lock */
02069       if (f->frametype == AST_FRAME_VOICE) {
02070          if (f->subclass != sub->owner->nativeformats) {
02071             ast_log(LOG_DEBUG, "Oooh, format changed to %d\n", f->subclass);
02072             sub->owner->nativeformats = f->subclass;
02073             ast_set_read_format(sub->owner, sub->owner->readformat);
02074             ast_set_write_format(sub->owner, sub->owner->writeformat);
02075          }
02076       }
02077    }
02078    return f;
02079 }

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

Definition at line 2131 of file chan_skinny.c.

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

02132 {
02133 #if 0
02134    struct skinny_subchannel *sub = ast->tech_pvt;
02135    int tmp;
02136    /* not right */
02137    sprintf(tmp, "%d", digit);  
02138    transmit_tone(sub->parent->parent->session, digit);
02139 #endif
02140    return -1;
02141 }

static void* skinny_session void *  data  )  [static]
 

Definition at line 2921 of file chan_skinny.c.

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

Referenced by accept_thread(), and unload_module().

02922 {
02923    int res;
02924    skinny_req *req;
02925    struct skinnysession *s = data;
02926    char iabuf[INET_ADDRSTRLEN];
02927    
02928    ast_verbose(VERBOSE_PREFIX_3 "Starting Skinny session from %s\n",  ast_inet_ntoa(iabuf, sizeof(iabuf), s->sin.sin_addr));
02929    for (;;) {
02930       res = 0;
02931       res = get_input(s);
02932       if (res < 0) {
02933          break;
02934       }
02935       req = skinny_req_parse(s);
02936       if (!req) {
02937          return NULL;
02938       }
02939       res = handle_message(req, s);
02940       if (res < 0) {
02941          destroy_session(s);
02942          return NULL;
02943       } 
02944    }
02945    ast_log(LOG_NOTICE, "Skinny Session returned: %s\n", strerror(errno));
02946    destroy_session(s);
02947    return 0;
02948 }

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_setstate(), AST_STATE_RING, ast_strlen_zero(), ast_verbose(), ast_waitfordigit(), skinny_line::call_forward, skinny_line::callreturn, skinny_line::callwaiting, skinny_line::cancallforward, ast_channel::cid, ast_callerid::cid_ani, skinny_line::cid_name, ast_callerid::cid_name, ast_callerid::cid_num, skinny_line::cid_num, ast_channel::context, skinny_line::dnd, ast_channel::exten, exten, free, 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, strdup, skinny_line::sub, ast_channel::tech_pvt, transmit_tone(), and VERBOSE_PREFIX_3.

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                            if (!ast_strlen_zero(l->cid_num)) {
01745                                  if (!l->hidecallerid) {
01746                                        chan->cid.cid_num = strdup(l->cid_num);
01747                                     chan->cid.cid_ani = strdup(l->cid_num);
01748                               }
01749                               ast_setstate(chan, AST_STATE_RING);
01750                               res = ast_pbx_run(chan);
01751                               if (res) {
01752                                     ast_log(LOG_WARNING, "PBX exited non-zero\n");
01753                      transmit_tone(s, SKINNY_REORDER); 
01754                               }
01755                               return NULL;
01756                         }
01757             }
01758                   } else {
01759                      /* It's a match, but they just typed a digit, and there is an ambiguous match,
01760                            so just set the timeout to matchdigittimeout and wait some more */
01761                         timeout = matchdigittimeout;
01762               }
01763       } else if (res == 0) {
01764                   ast_log(LOG_DEBUG, "Not enough digits (and no ambiguous match)...\n");
01765             transmit_tone(s, SKINNY_REORDER); 
01766                ast_hangup(chan);
01767                return NULL;
01768          } else if (l->callwaiting && !strcmp(exten, "*70")) {
01769                   if (option_verbose > 2) {
01770                         ast_verbose(VERBOSE_PREFIX_3 "Disabling call waiting on %s\n", chan->name);
01771                   }
01772                /* Disable call waiting if enabled */
01773                l->callwaiting = 0;
01774                transmit_tone(s, SKINNY_DIALTONE);
01775          len = 0;
01776                memset(exten, 0, sizeof(exten));\
01777                timeout = firstdigittimeout;
01778           } else if (!strcmp(exten,ast_pickup_ext())) {
01779                /* Scan all channels and see if any there
01780                       * ringing channqels with that have call groups
01781                    * that equal this channels pickup group  
01782                    */
01783                   if (ast_pickup_call(chan)) {
01784                      ast_log(LOG_WARNING, "No call pickup possible...\n");
01785             transmit_tone(s, SKINNY_REORDER);
01786                   }
01787               ast_hangup(chan);
01788                   return NULL;
01789                } else if (!l->hidecallerid && !strcmp(exten, "*67")) {
01790                if (option_verbose > 2) {
01791                    ast_verbose(VERBOSE_PREFIX_3 "Disabling Caller*ID on %s\n", chan->name);
01792                   }
01793                /* Disable Caller*ID if enabled */
01794               l->hidecallerid = 1;
01795                if (chan->cid.cid_num) {
01796                         free(chan->cid.cid_num);
01797             }
01798                   chan->cid.cid_num = NULL;
01799             if (chan->cid.cid_name) {
01800                         free(chan->cid.cid_name);
01801             }
01802                chan->cid.cid_name = NULL;
01803                   transmit_tone(s, SKINNY_DIALTONE);
01804                len = 0;
01805                memset(exten, 0, sizeof(exten));
01806                   timeout = firstdigittimeout;
01807          } else if (l->callreturn && !strcmp(exten, "*69")) {
01808                res = 0;
01809                if (!ast_strlen_zero(l->lastcallerid)) {
01810                      res = ast_say_digit_str(chan, l->lastcallerid, "", chan->language);
01811                }
01812                if (!res) {
01813                      transmit_tone(s, SKINNY_DIALTONE);
01814          }
01815                break;
01816          } else if (!strcmp(exten, "*78")) {
01817                   /* Do not disturb */
01818                   if (option_verbose > 2) {
01819                         ast_verbose(VERBOSE_PREFIX_3 "Enabled DND on channel %s\n", chan->name);
01820                   }
01821                transmit_tone(s, SKINNY_DIALTONE);
01822                   l->dnd = 1;
01823                   getforward = 0;
01824                   memset(exten, 0, sizeof(exten));
01825                   len = 0;
01826          } else if (!strcmp(exten, "*79")) {
01827                /* Do not disturb */
01828                if (option_verbose > 2) {
01829                      ast_verbose(VERBOSE_PREFIX_3 "Disabled DND on channel %s\n", chan->name);
01830                   }
01831          transmit_tone(s, SKINNY_DIALTONE);
01832               l->dnd = 0;
01833                   getforward = 0;
01834                   memset(exten, 0, sizeof(exten));
01835                   len = 0;
01836          } else if (l->cancallforward && !strcmp(exten, "*72")) {
01837                transmit_tone(s, SKINNY_DIALTONE);
01838                getforward = 1;
01839                memset(exten, 0, sizeof(exten));
01840                len = 0;
01841             } else if (l->cancallforward && !strcmp(exten, "*73")) {
01842                if (option_verbose > 2) {
01843                   ast_verbose(VERBOSE_PREFIX_3 "Cancelling call forwarding on channel %s\n", chan->name);
01844                }
01845                transmit_tone(s, SKINNY_DIALTONE); 
01846                memset(l->call_forward, 0, sizeof(l->call_forward));
01847                getforward = 0;
01848                memset(exten, 0, sizeof(exten));
01849                len = 0;
01850             } else if (!strcmp(exten, ast_parking_ext()) && 
01851                         sub->next->owner &&
01852                         ast_bridged_channel(sub->next->owner)) {
01853                /* This is a three way call, the main call being a real channel, 
01854                         and we're parking the first call. */
01855                      ast_masq_park_call(ast_bridged_channel(sub->next->owner), chan, 0, NULL);
01856                if (option_verbose > 2) {
01857                         ast_verbose(VERBOSE_PREFIX_3 "Parking call to '%s'\n", chan->name);
01858                }
01859                break;
01860             } else if (!ast_strlen_zero(l->lastcallerid) && !strcmp(exten, "*60")) {
01861                if (option_verbose > 2) {
01862                      ast_verbose(VERBOSE_PREFIX_3 "Blacklisting number %s\n", l->lastcallerid);
01863                }
01864                   res = ast_db_put("blacklist", l->lastcallerid, "1");
01865                   if (!res) {
01866                         transmit_tone(s, SKINNY_DIALTONE);     
01867                   memset(exten, 0, sizeof(exten));
01868                         len = 0;
01869                }
01870             } else if (l->hidecallerid && !strcmp(exten, "*82")) {
01871                if (option_verbose > 2) {
01872                      ast_verbose(VERBOSE_PREFIX_3 "Enabling Caller*ID on %s\n", chan->name);
01873                }
01874                /* Enable Caller*ID if enabled */
01875                l->hidecallerid = 0;
01876                if (chan->cid.cid_num) {
01877                      free(chan->cid.cid_num);   
01878             }
01879                   if (!ast_strlen_zero(l->cid_num)) {
01880                      chan->cid.cid_num = strdup(l->cid_num);
01881             }
01882                if (chan->cid.cid_name) {
01883                         free(chan->cid.cid_name);
01884             }
01885                   if (!ast_strlen_zero(l->cid_name)) {
01886                         chan->cid.cid_name = strdup(l->cid_name); 
01887          }
01888                   transmit_tone(s, SKINNY_DIALTONE);
01889                   len = 0;
01890                   memset(exten, 0, sizeof(exten));
01891                timeout = firstdigittimeout;
01892             } else if (!ast_canmatch_extension(chan, chan->context, exten, 1, chan->cid.cid_num) &&
01893                            ((exten[0] != '*') || (!ast_strlen_zero(exten) > 2))) {
01894                   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);
01895                   transmit_tone(s, SKINNY_REORDER);   
01896          /* hang out for 3 seconds to let congestion play */
01897             ast_safe_sleep(chan, 3000); 
01898             break;
01899             }
01900             if (!timeout) {
01901                   timeout = gendigittimeout;
01902       }
01903          if (len && !ast_ignore_pattern(chan->context, exten)) {
01904          ast_indicate(chan, -1);
01905       }
01906       }  
01907    ast_hangup(chan);
01908    return NULL;
01909 }

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

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

02092 {
02093    struct skinny_subchannel *sub = ast->tech_pvt;
02094    int res = 0;
02095    if (frame->frametype != AST_FRAME_VOICE) {
02096       if (frame->frametype == AST_FRAME_IMAGE) {
02097          return 0;
02098       } else {
02099          ast_log(LOG_WARNING, "Can't send %d type frames with skinny_write\n", frame->frametype);
02100          return 0;
02101       }
02102    } else {
02103       if (!(frame->subclass & ast->nativeformats)) {
02104          ast_log(LOG_WARNING, "Asked to transmit frame type %d, while native formats is %d (read/write = %d/%d)\n",
02105             frame->subclass, ast->nativeformats, ast->readformat, ast->writeformat);
02106          return -1;
02107       }
02108    }
02109    if (sub) {
02110       ast_mutex_lock(&sub->lock);
02111       if (sub->rtp) {
02112          res =  ast_rtp_write(sub->rtp, frame);
02113       }
02114       ast_mutex_unlock(&sub->lock);
02115    }
02116    return res;
02117 }

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 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(), 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 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 3317 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, oh323_pvt::next, s, skinny_rtp, skinny_session(), and skinny_tech.

03318 {
03319 #if 0
03320    struct skinny_session *session, s;
03321    struct skinny_subchannel *sub;
03322    struct skinny_line *line = session;
03323 
03324    /* close all IP connections */
03325    if (!ast_mutex_lock(&devicelock)) {
03326       /* Terminate tcp listener thread */
03327    } else {
03328       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03329       return -1;
03330    }
03331    if (!ast_mutex_lock(&monlock)) {
03332       if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP)) {
03333          pthread_cancel(monitor_thread);
03334          pthread_kill(monitor_thread, SIGURG);
03335          pthread_join(monitor_thread, NULL);
03336       }
03337       monitor_thread = AST_PTHREADT_STOP;
03338       ast_mutex_unlock(&monlock);
03339    } else {
03340       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03341       return -1;
03342    }
03343    if (!ast_mutex_lock(&iflock)) {
03344       /* Destroy all the interfaces and free their memory */
03345       p = iflist;
03346       while(p) {
03347          pl = p;
03348          p = p->next;
03349          /* Free associated memory */
03350          ast_mutex_destroy(&pl->lock);
03351          free(pl);
03352       }
03353       iflist = NULL;
03354       ast_mutex_unlock(&iflock);
03355    } else {
03356       ast_log(LOG_WARNING, "Unable to lock the monitor\n");
03357       return -1;
03358    }
03359 
03360         ast_rtp_proto_register(&skinny_rtp);
03361    ast_channel_unregister(&skinny_tech);
03362         ast_cli_register(&cli_show_devices);
03363         ast_cli_register(&cli_show_lines);
03364         ast_cli_register(&cli_debug);
03365         ast_cli_register(&cli_no_debug);
03366 
03367    return 0;
03368 #endif
03369    return -1;
03370 }

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

03373 {
03374    return usecnt;
03375 }


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

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

const struct ast_channel_tech skinny_tech [static]
 

Definition at line 910 of file chan_skinny.c.

Referenced by 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.

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 Sat Mar 24 23:27:24 2007 for Asterisk - the Open Source PBX by  doxygen 1.4.6