[svn-commits] russell: branch group/chan_unistim r88156 - in /team/group/chan_unistim: chan...

SVN commits to the Digium repositories svn-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 svn-commits mailing list