[asterisk-commits] russell: branch group/chan_unistim r88156 - in /team/group/chan_unistim: chan...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Thu Nov 1 15:27:46 CDT 2007
Author: russell
Date: Thu Nov 1 15:27:46 2007
New Revision: 88156
URL: http://svn.digium.com/view/asterisk?view=rev&rev=88156
Log:
Initial import of the code from issue #8864
Added:
team/group/chan_unistim/channels/chan_unistim.c (with props)
team/group/chan_unistim/configs/unistim.conf.sample (with props)
team/group/chan_unistim/doc/unistim.txt (with props)
Added: team/group/chan_unistim/channels/chan_unistim.c
URL: http://svn.digium.com/view/asterisk/team/group/chan_unistim/channels/chan_unistim.c?view=auto&rev=88156
==============================================================================
--- team/group/chan_unistim/channels/chan_unistim.c (added)
+++ team/group/chan_unistim/channels/chan_unistim.c Thu Nov 1 15:27:46 2007
@@ -1,0 +1,5568 @@
+/*
+ * Asterisk -- An open source telephony toolkit.
+ *
+ * UNISTIM channel driver for asterisk
+ *
+ * Copyright (C) 2005 - 2007, Cedric Hans
+ *
+ * Cedric Hans <cedric.hans at mlkj.net>
+ *
+ * Asterisk 1.4 patch by Peter Be
+ *
+ * See http://www.asterisk.org for more information about
+ * the Asterisk project. Please do not directly contact
+ * any of the maintainers of this project for assistance;
+ * the project provides a web site, mailing lists and IRC
+ * channels for your use.
+ *
+ * This program is free software, distributed under the terms of
+ * the GNU General Public License Version 2. See the LICENSE file
+ * at the top of the source tree.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59
+ * Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+/*!
+ * \file
+ *
+ * \brief chan_unistim channel driver for Asterisk
+ * \author Cedric Hans <cedric.hans at mlkj.net>
+ *
+ * Unistim (Unified Networks IP Stimulus) channel driver
+ * for Nortel i2002, i2004 and i2050
+ *
+ * \ingroup channel_drivers
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#include <signal.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#include "asterisk/lock.h"
+#include "asterisk/channel.h"
+#include "asterisk/config.h"
+#include "asterisk/logger.h"
+#include "asterisk/module.h"
+#include "asterisk/pbx.h"
+#include "asterisk/options.h"
+#include "asterisk/lock.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/causes.h"
+#include "asterisk/indications.h"
+#include "asterisk/dsp.h"
+#include "asterisk/devicestate.h"
+#include "asterisk/stringfields.h"
+#include "asterisk/abstract_jb.h"
+
+/* IP_PKTINFO is not portable. It's used to retrieve our IP.
+ Comment the next line if your running *BSD */
+#define HAVE_PKTINFO 1
+
+/* Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
+#define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
+
+#define DEFAULTCONTEXT "default"
+#define DEFAULTCALLERID "Unknown"
+#define DEFAULTCALLERNAME " "
+#define USTM_LOG_DIR "unistimHistory"
+
+#define MAX_BUF_SIZE 64 /* Size of the transmit buffer */
+#define MAX_BUF_NUMBER 50 /* Number of slots for the transmit queue */
+#define NB_MAX_RETRANSMIT 8 /* Try x times before removing the phone */
+#define IDLE_WAIT 1000 /* Nb of milliseconds waited when no events are scheduled */
+#define RETRANSMIT_TIMER 2000 /* Wait x milliseconds before resending a packet */
+#define TIMER_MWI 10000 /* How often the mailbox is checked for new messages */
+#define DEFAULT_CODEC 0x00 /* Not used */
+#define SIZE_PAGE 4096
+#define MAXINT (unsigned int)(-1)
+#define DEVICE_NAME_LEN 16
+#define AST_CONFIG_MAX_PATH 255
+#define MAX_ENTRY_LOG 30
+
+#define SUB_REAL 0
+#define SUB_THREEWAY 1
+#define MAX_SUBS 2
+
+enum autoprovision {
+ AUTOPROVISIONING_NO = 0,
+ AUTOPROVISIONING_YES,
+ AUTOPROVISIONING_DB,
+ AUTOPROVISIONING_TN
+};
+
+enum autoprov_extn {
+ EXTENSION_NONE = 0, /* Do not create an extension into the default dialplan */
+ EXTENSION_ASK, /* Prompt user for an extension number and register it */
+ EXTENSION_LINE, /* Register an extension with the line=> value */
+ EXTENSION_TN /* Used with AUTOPROVISIONING_TN */
+};
+#define OUTPUT_HANDSET 0xC0
+#define OUTPUT_HEADPHONE 0xC1
+#define OUTPUT_SPEAKER 0xC2
+
+#define VOLUME_LOW 0x01
+#define VOLUME_LOW_SPEAKER 0x03
+#define VOLUME_NORMAL 0x02
+#define VOLUME_INSANELY_LOUD 0x07
+
+#define MUTE_OFF 0x00
+#define MUTE_ON 0xFF
+#define MUTE_ON_DISCRET 0xCE
+
+#define SIZE_HEADER 6
+#define SIZE_MAC_ADDR 17
+#define TEXT_LENGTH_MAX 24
+#define TEXT_LINE0 0x00
+#define TEXT_LINE1 0x20
+#define TEXT_LINE2 0x40
+#define TEXT_NORMAL 0x05
+#define TEXT_INVERSE 0x25
+#define STATUS_LENGTH_MAX 28
+
+#define FAV_ICON_NONE 0x00
+#define FAV_ICON_ONHOOK_BLACK 0x20
+#define FAV_ICON_ONHOOK_WHITE 0x21
+#define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
+#define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
+#define FAV_ICON_OFFHOOK_BLACK 0x24
+#define FAV_ICON_OFFHOOK_WHITE 0x25
+#define FAV_ICON_ONHOLD_BLACK 0x26
+#define FAV_ICON_ONHOLD_WHITE 0x27
+#define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
+#define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
+#define FAV_ICON_PHONE_BLACK 0x2A
+#define FAV_ICON_PHONE_WHITE 0x2B
+#define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
+#define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
+#define FAV_ICON_HEADPHONES 0x2E
+#define FAV_ICON_HEADPHONES_ONHOLD 0x2F
+#define FAV_ICON_HOME 0x30
+#define FAV_ICON_CITY 0x31
+#define FAV_ICON_SHARP 0x32
+#define FAV_ICON_PAGER 0x33
+#define FAV_ICON_CALL_CENTER 0x34
+#define FAV_ICON_FAX 0x35
+#define FAV_ICON_MAILBOX 0x36
+#define FAV_ICON_REFLECT 0x37
+#define FAV_ICON_COMPUTER 0x38
+#define FAV_ICON_FORWARD 0x39
+#define FAV_ICON_LOCKED 0x3A
+#define FAV_ICON_TRASH 0x3B
+#define FAV_ICON_INBOX 0x3C
+#define FAV_ICON_OUTBOX 0x3D
+#define FAV_ICON_MEETING 0x3E
+#define FAV_ICON_BOX 0x3F
+
+#define FAV_BLINK_FAST 0x20
+#define FAV_BLINK_SLOW 0x40
+
+#define FAV_MAX_LENGTH 0x0A
+
+static void dummy(char *dummy, ...)
+{
+ return;
+}
+
+/* #define DUMP_PACKET 1 */
+/* #define DEBUG_TIMER ast_verbose */
+
+#define DEBUG_TIMER dummy
+static int unistimdebug = 0; /* Enable verbose output. can also be set with the CLI */
+static int unistim_reload(int fd, int argc, char *argv[]);
+static int unistim_port;
+static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
+static int unistim_keepalive;
+static int unistimsock = -1;
+static struct io_context *io;
+static struct sched_context *sched;
+static struct sockaddr_in public_ip = { 0, };
+static struct sockaddr_in addr_from; /* give the IP address for the last packet received */
+static unsigned int size_addr_from = sizeof(addr_from); /* size of the sockaddr_in (in WSARecvFrom) */
+static unsigned char *buff; /* Receive buffer address */
+static unsigned char flag = 0; /* Used for test */
+static int unistim_reloading = 0;
+AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
+AST_MUTEX_DEFINE_STATIC(usecnt_lock);
+static int usecnt = 0;
+/* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
+
+/* This is the thread for the monitor which checks for input on the channels
+ * which are not currently in use. */
+static pthread_t monitor_thread = AST_PTHREADT_NULL;
+
+/* Protect the monitoring thread, so only one process can kill or start it, and not
+ * when it's doing something critical. */
+AST_MUTEX_DEFINE_STATIC(monlock);
+/* Protect the session list */
+AST_MUTEX_DEFINE_STATIC(sessionlock);
+/* Protect the device list */
+AST_MUTEX_DEFINE_STATIC(devicelock);
+
+enum PhoneState {
+ STATE_INIT,
+ STATE_AUTHDENY,
+ STATE_MAINPAGE,
+ STATE_EXTENSION,
+ STATE_DIALPAGE,
+ STATE_RINGING,
+ STATE_CALL,
+ STATE_SELECTCODEC,
+ STATE_CLEANING,
+ STATE_HISTORY
+};
+
+enum HandsetState {
+ STATE_ONHOOK,
+ STATE_OFFHOOK,
+};
+
+enum PhoneKey {
+ KEY_0 = 0x40,
+ KEY_1 = 0x41,
+ KEY_2 = 0x42,
+ KEY_3 = 0x43,
+ KEY_4 = 0x44,
+ KEY_5 = 0x45,
+ KEY_6 = 0x46,
+ KEY_7 = 0x47,
+ KEY_8 = 0x48,
+ KEY_9 = 0x49,
+ KEY_STAR = 0x4a,
+ KEY_SHARP = 0x4b,
+ KEY_UP = 0x4c,
+ KEY_DOWN = 0x4d,
+ KEY_RIGHT = 0x4e,
+ KEY_LEFT = 0x4f,
+ KEY_QUIT = 0x50,
+ KEY_COPY = 0x51,
+ KEY_FUNC1 = 0x54,
+ KEY_FUNC2 = 0x55,
+ KEY_FUNC3 = 0x56,
+ KEY_FUNC4 = 0x57,
+ KEY_ONHOLD = 0x5b,
+ KEY_HANGUP = 0x5c,
+ KEY_MUTE = 0x5d,
+ KEY_HEADPHN = 0x5e,
+ KEY_LOUDSPK = 0x5f,
+ KEY_FAV0 = 0x60,
+ KEY_FAV1 = 0x61,
+ KEY_FAV2 = 0x62,
+ KEY_FAV3 = 0x63,
+ KEY_FAV4 = 0x64,
+ KEY_FAV5 = 0x65,
+ KEY_COMPUTR = 0x7b,
+ KEY_CONF = 0x7c,
+ KEY_SNDHIST = 0x7d,
+ KEY_RCVHIST = 0x7e,
+ KEY_INDEX = 0x7f
+};
+
+struct tone_zone_unistim {
+ char country[3];
+ int freq1;
+ int freq2;
+};
+
+static const struct tone_zone_unistim frequency[] = {
+ {"us", 350, 440},
+ {"fr", 440, 0},
+ {"au", 413, 438},
+ {"nl", 425, 0},
+ {"uk", 350, 440},
+ {"fi", 425, 0},
+ {"es", 425, 0},
+ {"jp", 400, 0},
+ {"no", 425, 0},
+ {"at", 420, 0},
+ {"nz", 400, 0},
+ {"tw", 350, 440},
+ {"cl", 400, 0},
+ {"se", 425, 0},
+ {"be", 425, 0},
+ {"sg", 425, 0},
+ {"il", 414, 0},
+ {"br", 425, 0},
+ {"hu", 425, 0},
+ {"lt", 425, 0},
+ {"pl", 425, 0},
+ {"za", 400, 0},
+ {"pt", 425, 0},
+ {"ee", 425, 0},
+ {"mx", 425, 0},
+ {"in", 400, 0},
+ {"de", 425, 0},
+ {"ch", 425, 0},
+ {"dk", 425, 0},
+ {"cn", 450, 0},
+ {"--", 0, 0}
+};
+
+typedef struct __WSABUF {
+ u_long len;
+ unsigned char *buf;
+} WSABUF, *LPWSABUF;
+
+typedef struct _SYSTEMTIME {
+ unsigned short wYear;
+ unsigned short wMonth;
+ unsigned short wDayOfWeek;
+ unsigned short wDay;
+ unsigned short wHour;
+ unsigned short wMinute;
+ unsigned short wSecond;
+ unsigned short wMilliseconds;
+} SYSTEMTIME;
+
+struct unistim_subchannel {
+ ast_mutex_t lock;
+ unsigned int subtype; /* SUBS_REAL or SUBS_THREEWAY */
+ struct ast_channel *owner; /* Asterisk channel used by the subchannel */
+ struct unistim_line *parent; /* Unistim line */
+ struct ast_rtp *rtp; /* RTP Handle */
+ int alreadygone;
+ char ringvolume;
+ char ringstyle;
+};
+
+struct unistim_line {
+ ast_mutex_t lock;
+ char name[80]; /* Like 200 */
+ char fullname[80]; /* Like USTM/200 at black */
+ struct unistim_subchannel *subs[MAX_SUBS]; /* pointer to our current connection, channel... */
+ char exten[AST_MAX_EXTENSION]; /* Extention where to start */
+ char context[AST_MAX_EXTENSION]; /* Context */
+ char language[MAX_LANGUAGE]; /* Language for asterisk sounds */
+ char cid_num[AST_MAX_EXTENSION]; /* Caller*ID */
+ char mailbox[AST_MAX_EXTENSION]; /* Mailbox to check - used by MWI */
+ int lastmsgssent; /* Used by MWI */
+ time_t nextmsgcheck; /* Used by MWI */
+ char musicclass[MAX_MUSICCLASS]; /* Music On Hold */
+ unsigned int callgroup; /* Call Group - untested */
+ unsigned int pickupgroup; /* Call Group - untested */
+ char accountcode[80]; /* Billing stuff */
+ int amaflags; /* Billing stuff */
+ int capability; /* Codec supported */
+ struct unistim_line *next;
+ struct unistim_device *parent;
+};
+
+static struct unistim_device {
+ /* A device containing one or more lines */
+ int receiver_state; /* state of the receiver (see ReceiverState) */
+ int size_phone_number; /* size of the phone number */
+ char phone_number[16]; /* the phone number entered by the user */
+ char redial_number[16]; /* the last phone number entered by the user */
+ int phone_current; /* Number of the current phone */
+ int pos_fav; /* Position of the displayed favorites (used for scrolling) */
+ char id[18]; /* mac address of the current phone in ascii */
+ char name[DEVICE_NAME_LEN]; /* name of the device */
+ int softkeylinepos; /* position of the line softkey (default 0) */
+ char softkeylabel[6][11]; /* soft key label */
+ char softkeynumber[6][16]; /* number dialed when the soft key is pressed */
+ char softkeyicon[6]; /* icon number */
+ char softkeydevice[6][16]; /* name of the device monitored */
+ struct unistim_device *sp[6]; /* pointer to the device monitored by this soft key */
+ char maintext0[25]; /* when the phone is idle, display this string on line 0 */
+ char maintext1[25]; /* when the phone is idle, display this string on line 1 */
+ char maintext2[25]; /* when the phone is idle, display this string on line 2 */
+ char titledefault[13]; /* title (text before date/time) */
+ char datetimeformat; /* format used for displaying time/date */
+ char contrast; /* contrast */
+ char country[3]; /* country used for dial tone frequency */
+ struct ind_tone_zone *tz; /* Tone zone for res_indications (ring, busy, congestion) */
+ char ringvolume; /* Ring volume */
+ char ringstyle; /* Ring melody */
+ int rtp_port; /* RTP port used by the phone */
+ int rtp_method; /* Select the unistim data used to establish a RTP session */
+ int status_method; /* Select the unistim packet used for sending status text */
+ char codec_number; /* The current codec used to make calls */
+ int missed_call; /* Number of call unanswered */
+ int callhistory; /* Allowed to record call history */
+ char lst_cid[TEXT_LENGTH_MAX]; /* Last callerID received */
+ char lst_cnm[TEXT_LENGTH_MAX]; /* Last callername recevied */
+ char call_forward[AST_MAX_EXTENSION]; /* Forward number */
+ int output; /* Handset, headphone or speaker */
+ int previous_output; /* Previous output */
+ int volume; /* Default volume */
+ int mute; /* Mute mode */
+ int moh; /* Music on hold in progress */
+ int nat; /* Used by the obscure ast_rtp_setnat */
+ enum autoprov_extn extension; /* See ifdef EXTENSION for valid values */
+ char extension_number[11]; /* Extension number entered by the user */
+ char to_delete; /* Used in reload */
+ time_t start_call_timestamp; /* timestamp for the length calculation of the call */
+ struct ast_silence_generator *silence_generator;
+ struct unistim_line *lines;
+ struct ast_ha *ha;
+ struct unistimsession *session;
+ struct unistim_device *next;
+} *devices = NULL;
+
+static struct unistimsession {
+ ast_mutex_t lock;
+ struct sockaddr_in sin; /* IP address of the phone */
+ struct sockaddr_in sout; /* IP address of server */
+ int timeout; /* time-out in ticks : resend packet if no ack was received before the timeout occured */
+ unsigned short seq_phone; /* sequence number for the next packet (when we receive a request) */
+ unsigned short seq_server; /* sequence number for the next packet (when we send a request) */
+ unsigned short last_seq_ack; /* sequence number of the last ACK received */
+ unsigned long tick_next_ping; /* time for the next ping */
+ int last_buf_available; /* number of a free slot */
+ int nb_retransmit; /* number of retransmition */
+ int state; /* state of the phone (see PhoneState) */
+ int size_buff_entry; /* size of the buffer used to enter datas */
+ char buff_entry[16]; /* Buffer for temporary datas */
+ char macaddr[18]; /* mac adress of the phone (not always available) */
+ WSABUF wsabufsend[MAX_BUF_NUMBER]; /* Size of each paquet stored in the buffer array & pointer to this buffer */
+ unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /* Buffer array used to keep the lastest non-acked paquets */
+ struct unistim_device *device;
+ struct unistimsession *next;
+} *sessions = NULL;
+
+/* Format of datagrams :
+bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
+byte 2 : sequence number (high part)
+byte 3 : sequence number (low part)
+byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
+byte 5 : direction, 1 = server to phone, 2 = phone to server
+arguments */
+
+const static unsigned char PacketRcvDiscovery[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
+static unsigned char PacketSendDiscoveryACK[] =
+ { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
+
+const static unsigned char PacketRecvFirmVersion[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
+const static unsigned char PacketRecvPressedKey[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
+const static unsigned char PacketRecvPickUp[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
+const static unsigned char PacketRecvHangUp[] =
+ { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
+const static unsigned char PacketRecvR2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
+
+/* TransportAdapter */
+const static unsigned char PacketRecvResumeConnectionWithServer[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
+const static unsigned char PacketRecvMacAddr[] =
+ { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07, 0x31, 0x38 /*MacAddr */ };
+
+const static unsigned char PacketSendDateTime3[] =
+ { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
+/*Minutes */ 0x08, 0x32
+};
+const static unsigned char PacketSendDateTime[] =
+ { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
+0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
+ 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
+ 0x05, 0x12, 0x00, 0x78
+};
+
+const static unsigned char PacketSendNoRing[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
+const static unsigned char PacketSendS4[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
+0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
+ 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
+ 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
+ 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
+};
+const static unsigned char PacketSendCall[] =
+ { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
+ 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
+ 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
+ 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
+ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
+ /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
+ 0x16, 0x66
+};
+const static unsigned char PacketSendStreamBasedToneOff[] =
+ { 0x16, 0x05, 0x1c, 0x00, 0x00 };
+
+/* const static unsigned char PacketSendMute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
+const static unsigned char PacketSendCloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
+const static unsigned char PacketSendCloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
+const static unsigned char PacketSendStreamBasedToneOn[] =
+ { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
+const static unsigned char PacketSendStreamBasedToneSingleFreq[] =
+ { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
+const static unsigned char PacketSendStreamBasedToneDualFreq[] =
+ { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
+const static unsigned char PacketSendSelectOutput[] =
+ { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
+const static unsigned char PacketSendRing[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
+ 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
+ 0x20, 0x16, 0x04, 0x10, 0x00
+};
+const static unsigned char PacketSendEndCall[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
+0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
+ 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
+};
+const static unsigned char PacketSendS9[] =
+ { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
+0x00 };
+const static unsigned char PacketSendRTPpacketSize[] =
+ { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
+const static unsigned char PacketSendJitterBufferConf[] =
+ { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
+/* early packet resync 2 bytes */ 0x3e, 0x80,
+ 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
+};
+
+/* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
+static unsigned char PacketSendStreamBasedToneCad[] =
+ { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
+const static unsigned char PacketSendOpenAudioStreamRX[] =
+ { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
+0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
+ 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+const static unsigned char PacketSendOpenAudioStreamTX[] =
+ { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
+0x0e, 0x01, /* Local port */ 0x14, 0x50,
+ 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+
+const static unsigned char PacketSendOpenAudioStreamRX3[] =
+ { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
+0x06, 0x81, /* RTP Port */ 0x14, 0x50,
+/* RTCP Port */ 0x14,
+ 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
+ 0x69, 0x05
+};
+const static unsigned char PacketSendOpenAudioStreamTX3[] =
+ { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
+0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
+ /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
+ /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
+};
+
+const static unsigned char PacketSendArrow[] = { 0x17, 0x04, 0x04, 0x00 };
+const static unsigned char PacketSendBlinkCursor[] = { 0x17, 0x04, 0x10, 0x86 };
+const static unsigned char PacketSendDateTime2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
+ 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
+};
+const static unsigned char PacketSendContrast[] =
+ { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
+const static unsigned char PacketSendStartTimer[] =
+ { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
+0x65 };
+const static unsigned char PacketSendStopTimer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
+const static unsigned char PacketSendIcon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
+const static unsigned char PacketSendS7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
+const static unsigned char PacketSendSetPosCursor[] =
+ { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
+
+/*static unsigned char PacketSendMonthLabelsDownload[] =
+ { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
+const static unsigned char PacketSendFavorite[] =
+ { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
+ 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
+};
+const static unsigned char PacketSendTitle[] =
+ { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20 /*end_text */ };
+const static unsigned char PacketSendText[] =
+ { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ /*end_text */ 0x17, 0x04, 0x10, 0x87
+};
+const static unsigned char PacketSendStatus[] =
+ { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
+ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
+};
+const static unsigned char PacketSendStatus2[] =
+ { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
+0x20, 0x20, 0x20 /* end_text */ };
+
+const static unsigned char PacketSendLedUpdate[] = { 0x19, 0x04, 0x00, 0x00 };
+
+const static unsigned char PacketSendQueryBasicManager04[] = { 0x1a, 0x04, 0x01, 0x04 };
+const static unsigned char PacketSendQueryMacAddress[] = { 0x1a, 0x04, 0x01, 0x08 };
+const static unsigned char PacketSendQueryBasicManager10[] = { 0x1a, 0x04, 0x01, 0x10 };
+const static unsigned char PacketSendS1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
+
+static unsigned char PacketSendPing[] =
+ { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
+
+#define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
+
+const static char desc[] = "UNISTIM for Asterisk";
+const static char tdesc[] = "UNISTIM Channel Driver";
+const static char type[] = "USTM";
+
+/* Protos */
+static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state);
+static int load_module(void);
+static int reload(void);
+static int unload_module(void);
+static int reload_config(void);
+static void ShowMainPage(struct unistimsession *pte);
+static struct ast_channel *unistim_request(const char *type, int format, void *data,
+ int *cause);
+static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
+static int unistim_hangup(struct ast_channel *ast);
+static int unistim_answer(struct ast_channel *ast);
+static struct ast_frame *unistim_read(struct ast_channel *ast);
+static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
+static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
+ size_t datalen);
+static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
+static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
+static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration);
+static int unistim_sendtext(struct ast_channel *ast, const char *text);
+
+int WriteEntryHistory(struct unistimsession *pte, FILE * f, char c, char *line1);
+void ChangeCallerID(struct unistimsession *pte, int type, char *callerid);
+int usecount(void);
+char *key(void);
+char *description(void);
+
+
+static const struct ast_channel_tech unistim_tech = {
+ .type = type,
+ .description = tdesc,
+ .capabilities = CAPABILITY,
+ .properties = AST_CHAN_TP_WANTSJITTER,
+ .requester = unistim_request,
+ .call = unistim_call,
+ .hangup = unistim_hangup,
+ .answer = unistim_answer,
+ .read = unistim_read,
+ .write = unistim_write,
+ .indicate = unistim_indicate,
+ .fixup = unistim_fixup,
+ .send_digit_begin = unistim_senddigit_begin,
+ .send_digit_end = unistim_senddigit_end,
+ .send_text = unistim_sendtext,
+/* .bridge = ast_rtp_bridge, */
+};
+
+static void DisplayLastError(const char *szMessage)
+{
+ int dwLastError;
+ char *lpMsgBuf;
+ time_t cur_time = time(0);
+
+ dwLastError = errno;
+ lpMsgBuf = strerror(dwLastError);
+
+ /* Display the error message */
+ ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), szMessage, dwLastError,
+ lpMsgBuf);
+}
+
+static void GetLocalTime(SYSTEMTIME * systime)
+{
+ struct tm *stm;
+ time_t cur_time = time(0);
+
+ if ((stm = localtime(&cur_time)) == 0) {
+ DisplayLastError("Error in localtime()");
+ return;
+ }
+ systime->wYear = stm->tm_year;
+ systime->wMonth = stm->tm_mon + 1;
+ systime->wDayOfWeek = stm->tm_wday;
+ systime->wDay = stm->tm_mday;
+ systime->wHour = stm->tm_hour;
+ systime->wMinute = stm->tm_min;
+ systime->wSecond = stm->tm_sec;
+ systime->wMilliseconds = 0;
+ return;
+}
+
+static unsigned int GetTickCount(void)
+{
+ struct timeval tv;
+
+ if (gettimeofday(&tv, NULL) == -1)
+ DisplayLastError("Error in gettimeofday");
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+
+/* Send data to a phone without retransmit nor buffering */
+static void
+SendRawClient(int size, unsigned char *data, struct sockaddr_in *addr_to,
+ const struct sockaddr_in *addr_ourip)
+{
+#ifdef HAVE_PKTINFO
+ struct iovec msg_iov;
+ struct msghdr msg;
+ char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
+ struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
+ struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
+
+ msg_iov.iov_base = data;
+ msg_iov.iov_len = size;
+
+ msg.msg_name = addr_to; /* optional address */
+ msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
+ msg.msg_iov = &msg_iov; /* scatter/gather array */
+ msg.msg_iovlen = 1; /* # elements in msg_iov */
+ msg.msg_control = ip_msg; /* ancillary data */
+ msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
+ msg.msg_flags = 0; /* flags on received message */
+
+ ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
+ ip_msg->cmsg_level = SOL_IP;
+ ip_msg->cmsg_type = IP_PKTINFO;
+ pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
+ pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
+ /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
+
+#ifdef DUMP_PACKET
+ if (unistimdebug) {
+ int tmp;
+ char iabuf[INET_ADDRSTRLEN];
+ char iabuf2[INET_ADDRSTRLEN];
+ ast_verbose("\n**> From %s sending %d bytes to %s ***\n",
+ ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
+ ast_inet_ntoa(addr_to->sin_addr));
+ for (tmp = 0; tmp < size; tmp++)
+ ast_verbose("%.2x ", (unsigned char) data[tmp]);
+ ast_verbose("\n******************************************\n");
+
+ }
+#endif
+
+ if (sendmsg(unistimsock, &msg, 0) == -1)
+ DisplayLastError("Error sending datas");
+#else
+ if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
+ == -1)
+ DisplayLastError("Error sending datas");
+#endif
+}
+
+static void SendClient(int size, const unsigned char *data, struct unistimsession *pte)
+{
+ unsigned int tick;
+ int buf_pos;
+ unsigned short *sdata = (unsigned short *) data;
+
+ ast_mutex_lock(&pte->lock);
+ buf_pos = pte->last_buf_available;
+
+ if (buf_pos >= MAX_BUF_NUMBER) {
+ ast_log(LOG_WARNING, "Error : send queue overflow\n");
+ ast_mutex_unlock(&pte->lock);
+ return;
+ }
+ sdata[1] = ntohs(++(pte->seq_server));
+ pte->wsabufsend[buf_pos].len = size;
+ memcpy(pte->wsabufsend[buf_pos].buf, data, size);
+
+ tick = GetTickCount();
+ pte->timeout = tick + RETRANSMIT_TIMER;
+
+/*#ifdef DUMP_PACKET */
+ if ((unistimdebug) && (option_verbose > 5)) {
+ ast_verbose("Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server,
+ buf_pos);
+ }
+/*#endif */
+ SendRawClient(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
+ &(pte->sout));
+ pte->last_buf_available++;
+ ast_mutex_unlock(&pte->lock);
+}
+
+static void SendPing(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("Sending ping\n");
+ pte->tick_next_ping = GetTickCount() + unistim_keepalive;
+ memcpy(buffsend + SIZE_HEADER, PacketSendPing, sizeof(PacketSendPing));
+ SendClient(SIZE_HEADER + sizeof(PacketSendPing), buffsend, pte);
+}
+
+static int getToAddress(int fd, struct sockaddr_in *toAddr)
+{
+#ifdef HAVE_PKTINFO
+ int err;
+ struct msghdr msg;
+ struct {
+ struct cmsghdr cm;
+ int len;
+ struct in_addr address;
+ } ip_msg;
+
+ /* Zero out the structures before we use them */
+ /* This sets several key values to NULL */
+ memset(&msg, 0, sizeof(msg));
+ memset(&ip_msg, 0, sizeof(ip_msg));
+
+ /* Initialize the message structure */
+ msg.msg_control = &ip_msg;
+ msg.msg_controllen = sizeof(ip_msg);
+ /* Get info about the incoming packet */
+ err = recvmsg(fd, &msg, MSG_PEEK);
+ if (err == -1)
+ ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
+ memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
+ return err;
+#else
+ memcpy(&toAddr, &public_ip, sizeof(&toAddr));
+ return 0;
+#endif
+}
+
+/* Allocate memory & initialize structures for a new phone */
+/* addr_from : ip address of the phone */
+static struct unistimsession *CreateClient(const struct sockaddr_in *addr_from)
+{
+ int tmp;
+ struct unistimsession *s;
+
+ if (!(s = ast_calloc(1, sizeof(*s))))
+ return NULL;
+
+ memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
+ getToAddress(unistimsock, &s->sout);
+ if (unistimdebug) {
+
+
+ ast_verbose
+ ("Creating a new entry for the phone from %s received via server ip %s\n",
+ ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
+ }
+ ast_mutex_init(&s->lock);
+ ast_mutex_lock(&sessionlock);
+ s->next = sessions;
+ sessions = s;
+
+ s->timeout = GetTickCount() + RETRANSMIT_TIMER;
+ s->seq_phone = (short) 0x0000;
+ s->seq_server = (short) 0x0000;
+ s->last_seq_ack = (short) 0x000;
+ s->last_buf_available = 0;
+ s->nb_retransmit = 0;
+ s->state = STATE_INIT;
+ s->tick_next_ping = GetTickCount() + unistim_keepalive;
+ /* Initialize WSABUF */
+ for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
+ s->wsabufsend[tmp].buf = s->buf[tmp];
+ }
+ ast_mutex_unlock(&sessionlock);
+ return s;
+}
+
+static void SendEndCall(struct unistimsession *pte)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verbose("Sending end call\n");
+ memcpy(buffsend + SIZE_HEADER, PacketSendEndCall, sizeof(PacketSendEndCall));
+ SendClient(SIZE_HEADER + sizeof(PacketSendEndCall), buffsend, pte);
+}
+
+static void SetPingTimer(struct unistimsession *pte)
+{
+ unsigned int tick;
+
+ pte->timeout = pte->tick_next_ping;
+ DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
+ return;
+}
+
+/* Checking if our send queue is empty,
+ * if true, setting up a timer for keepalive */
+static void CheckSendQueue(struct unistimsession *pte)
+{
+ /* Check if our send queue contained only one element */
+ if (pte->last_buf_available == 1) {
+ if ((unistimdebug) && (option_verbose > 5))
+ ast_verbose("Our single packet was ACKed.\n");
+ pte->last_buf_available--;
+ SetPingTimer(pte);
+ return;
+ }
+ /* Check if this ACK catch up our latest packet */
+ else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
[... 4858 lines stripped ...]
More information about the asterisk-commits
mailing list