Wed Aug 20 06:36:52 2008

Asterisk developer's documentation


chan_skinny.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2005, Digium, Inc.
00005  *
00006  * chan_skinny was developed by Jeremy McNamara & Florian Overkamp
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Implementation of the Skinny protocol
00022  * 
00023  * \author Jeremy McNamara & Florian Overkamp
00024  * \ingroup channel_drivers
00025  */
00026 
00027 
00028 #include <stdio.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <unistd.h>
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <netinet/tcp.h>
00035 #include <sys/ioctl.h>
00036 #include <net/if.h>
00037 #include <errno.h>
00038 #include <fcntl.h>
00039 #include <netdb.h>
00040 #include <arpa/inet.h>
00041 #include <sys/signal.h>
00042 #include <signal.h>
00043 #include <ctype.h>
00044 
00045 #include "asterisk.h"
00046 
00047 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 75449 $")
00048 
00049 #include "asterisk/lock.h"
00050 #include "asterisk/channel.h"
00051 #include "asterisk/config.h"
00052 #include "asterisk/logger.h"
00053 #include "asterisk/module.h"
00054 #include "asterisk/pbx.h"
00055 #include "asterisk/options.h"
00056 #include "asterisk/lock.h"
00057 #include "asterisk/sched.h"
00058 #include "asterisk/io.h"
00059 #include "asterisk/rtp.h"
00060 #include "asterisk/acl.h"
00061 #include "asterisk/callerid.h"
00062 #include "asterisk/cli.h"
00063 #include "asterisk/say.h"
00064 #include "asterisk/cdr.h"
00065 #include "asterisk/astdb.h"
00066 #include "asterisk/features.h"
00067 #include "asterisk/app.h"
00068 #include "asterisk/musiconhold.h"
00069 #include "asterisk/utils.h"
00070 #include "asterisk/dsp.h"
00071 
00072 /************************************************************************************/
00073 /*                         Skinny/Asterisk Protocol Settings                        */
00074 /************************************************************************************/
00075 static const char desc[] = "Skinny Client Control Protocol (Skinny)";
00076 static const char tdesc[] = "Skinny Client Control Protocol (Skinny)";
00077 static const char type[] = "Skinny";
00078 static const char config[] = "skinny.conf";
00079 
00080 /* Just about everybody seems to support ulaw, so make it a nice default */
00081 static int capability = AST_FORMAT_ULAW;
00082 
00083 #define DEFAULT_SKINNY_PORT   2000
00084 #define DEFAULT_SKINNY_BACKLOG  2
00085 #define SKINNY_MAX_PACKET  1000
00086 
00087 static int  keep_alive = 120;
00088 static char date_format[6] = "D-M-Y";
00089 static char version_id[16] = "P002F202";
00090 
00091 /* these should be in an include file, but dunno what to include */
00092 typedef unsigned char  UINT8;
00093 typedef unsigned short UINT16;
00094 typedef unsigned int   UINT32;
00095 
00096 #if __BYTE_ORDER == __LITTLE_ENDIAN
00097 #define letohl(x) (x)
00098 #define letohs(x) (x)
00099 #define htolel(x) (x)
00100 #define htoles(x) (x)
00101 #else
00102 #if defined(SOLARIS) || defined(__Darwin__) || defined(__NetBSD__)
00103 #define __bswap_16(x) \
00104      ((((x) & 0xff00) >> 8) | \
00105       (((x) & 0x00ff) << 8))
00106 #define __bswap_32(x) \
00107      ((((x) & 0xff000000) >> 24) | \
00108       (((x) & 0x00ff0000) >>  8) | \
00109       (((x) & 0x0000ff00) <<  8) | \
00110       (((x) & 0x000000ff) << 24))
00111 #else
00112 #include <bits/byteswap.h>
00113 #endif
00114 #define letohl(x) __bswap_32(x)
00115 #define letohs(x) __bswap_16(x)
00116 #define htolel(x) __bswap_32(x)
00117 #define htoles(x) __bswap_16(x)
00118 #endif
00119 
00120 
00121 /************************************************************************************/
00122 /*                                Protocol Messages                                 */
00123 /************************************************************************************/
00124 /* message types */
00125 #define  KEEP_ALIVE_MESSAGE 0x0000
00126 /* no additional struct */
00127 
00128 #define  REGISTER_MESSAGE 0x0001
00129 typedef struct register_message {
00130    char name[16];
00131    int userId;
00132    int instance;
00133    char ip[4];
00134    int type;
00135    int maxStreams;
00136 } register_message;
00137 
00138 #define IP_PORT_MESSAGE 0x0002
00139 
00140 #define KEYPAD_BUTTON_MESSAGE 0x0003
00141 typedef struct keypad_button_message {
00142    int button;
00143 } keypad_button_message;
00144 
00145 #define STIMULUS_MESSAGE 0x0005
00146 typedef struct stimulus_message {
00147    int stimulus;
00148    int stimulusInstance;
00149 } stimulus_message;
00150       
00151 #define OFFHOOK_MESSAGE 0x0006
00152 #define ONHOOK_MESSAGE 0x0007
00153 
00154 #define  CAPABILITIES_RES_MESSAGE 0x0010
00155 typedef struct station_capabilities {  
00156    int codec;
00157    int frames;
00158    union {
00159       char res[8];
00160       long rate;
00161    } payloads; 
00162 } station_capabilities;
00163 
00164 typedef struct capabilities_res_message {
00165    int count;
00166    struct station_capabilities caps[18];
00167 } capabilities_res_message;
00168 
00169 #define SPEED_DIAL_STAT_REQ_MESSAGE 0x000A
00170 typedef struct speed_dial_stat_req_message {
00171    int speedDialNumber;
00172 } speed_dial_stat_req_message;
00173 
00174 #define  LINE_STATE_REQ_MESSAGE 0x000B
00175 typedef struct line_state_req_message {
00176    int lineNumber;
00177 } line_state_req_message;
00178 
00179 #define  TIME_DATE_REQ_MESSAGE 0x000D
00180 #define  VERSION_REQ_MESSAGE 0x000F
00181 #define BUTTON_TEMPLATE_REQ_MESSAGE 0x000E
00182 #define SERVER_REQUEST_MESSAGE 0x0012
00183 #define ALARM_MESSAGE 0x0020
00184 
00185 #define OPEN_RECIEVE_CHANNEL_ACK_MESSAGE 0x0022 
00186 typedef struct open_recieve_channel_ack_message {
00187    int status;
00188    char ipAddr[4];
00189    int port;
00190    int passThruId;
00191 } open_recieve_channel_ack_message;
00192 
00193 #define  SOFT_KEY_SET_REQ_MESSAGE 0x0025
00194 #define UNREGISTER_MESSAGE 0x0027
00195 #define  SOFT_KEY_TEMPLATE_REQ_MESSAGE 0x0028
00196 
00197 #define  REGISTER_ACK_MESSAGE 0x0081
00198 typedef struct register_ack_message {
00199    int keepAlive;
00200    char dateTemplate[6];
00201    char res[2];
00202    int secondaryKeepAlive;
00203    char res2[4];
00204 } register_ack_message;
00205 
00206 #define  START_TONE_MESSAGE 0x0082
00207 typedef struct start_tone_message {
00208    int tone;
00209 } start_tone_message;
00210 
00211 #define STOP_TONE_MESSAGE 0x0083
00212 
00213 #define SET_RINGER_MESSAGE 0x0085
00214 typedef struct set_ringer_message {
00215    int ringerMode;
00216 } set_ringer_message;
00217 
00218 #define SET_LAMP_MESSAGE 0x0086
00219 typedef struct set_lamp_message {
00220    int stimulus;
00221    int stimulusInstance;
00222    int deviceStimulus;
00223 } set_lamp_message;
00224 
00225 #define SET_SPEAKER_MESSAGE 0x0088 
00226 typedef struct set_speaker_message {
00227    int mode;
00228 } set_speaker_message;
00229 
00230 #define START_MEDIA_TRANSMISSION_MESSAGE 0x008A
00231 typedef struct media_qualifier {
00232    int precedence;
00233    int vad;
00234    int packets;
00235    int bitRate;
00236 } media_qualifier;
00237 
00238 typedef struct start_media_transmission_message {
00239    int conferenceId;
00240    int passThruPartyId;
00241    char remoteIp[4];
00242    int remotePort;
00243    int packetSize;
00244    int payloadType;
00245    media_qualifier qualifier;
00246 } start_media_transmission_message;
00247 
00248 #define STOP_MEDIA_TRANSMISSION_MESSAGE 0x008B
00249 typedef struct stop_media_transmission_message {
00250    int conferenceId;
00251         int passThruPartyId;
00252 } stop_media_transmission_message;
00253 
00254 #define CALL_INFO_MESSAGE 0x008F
00255 typedef struct call_info_message {
00256    char callingPartyName[40];
00257    char callingParty[24];
00258    char calledPartyName[40];
00259    char calledParty[24];
00260    int  instance;
00261    int  reference;
00262    int  type;
00263    char originalCalledPartyName[40];
00264    char originalCalledParty[24];
00265 } call_info_message;
00266 
00267 #define SPEED_DIAL_STAT_RES_MESSAGE 0x0091
00268 typedef struct speed_dial_stat_res_message {
00269    int speedDialNumber;
00270    char speedDialDirNumber[24];
00271    char speedDialDisplayName[40];
00272 } speed_dial_stat_res_message;
00273 
00274 #define LINE_STAT_RES_MESSAGE 0x0092
00275 typedef struct line_stat_res_message {
00276    int  linenumber;
00277    char lineDirNumber[24];
00278    char lineDisplayName[42];
00279    int  space;
00280 } line_stat_res_message;
00281 
00282 #define DEFINETIMEDATE_MESSAGE 0x0094
00283 typedef struct definetimedate_message {
00284    int year;   /* since 1900 */
00285    int month;
00286    int dayofweek; /* monday = 1 */
00287    int day;
00288    int hour;
00289    int minute;
00290    int seconds;
00291    int milliseconds;
00292    int timestamp;
00293 } definetimedate_message;
00294  
00295 #define DISPLAYTEXT_MESSAGE 0x0099
00296 typedef struct displaytext_message {
00297    char text[40];
00298 } displaytext_message;
00299 
00300 #define CLEAR_DISPLAY_MESSAGE 0x009A
00301 
00302 #define  REGISTER_REJ_MESSAGE 0x009D
00303 typedef struct register_rej_message {
00304    char errMsg[33];
00305 } register_rej_message;
00306 
00307 #define CAPABILITIES_REQ_MESSAGE 0x009B
00308 
00309 #define SERVER_RES_MESSAGE 0x009E
00310 typedef struct server_identifier {
00311    char serverName[48];
00312 } server_identifier;
00313 
00314 typedef struct server_res_message {
00315    server_identifier server[5];
00316    int serverListenPort[5];
00317    int serverIpAddr[5];
00318 } server_res_message;
00319 
00320 #define BUTTON_TEMPLATE_RES_MESSAGE 0x0097
00321 
00322 typedef struct buttondefinition {
00323    UINT8 instanceNumber;
00324    UINT8 buttonDefinition;
00325 } button_definition;
00326 
00327 #define STIMULUS_REDIAL    0x01
00328 #define STIMULUS_SPEEDDIAL    0x02
00329 #define STIMULUS_HOLD      0x03
00330 #define STIMULUS_TRANSFER  0x04
00331 #define STIMULUS_FORWARDALL   0x05
00332 #define STIMULUS_FORWARDBUSY  0x06
00333 #define STIMULUS_FORWARDNOANSWER 0x07
00334 #define STIMULUS_DISPLAY   0x08
00335 #define STIMULUS_LINE      0x09
00336 #define STIMULUS_VOICEMAIL    0x0F
00337 #define STIMULUS_AUTOANSWER   0x11
00338 #define STIMULUS_CONFERENCE   0x7D
00339 #define STIMULUS_CALLPARK  0x7E
00340 #define STIMULUS_CALLPICKUP   0x7F
00341 #define STIMULUS_NONE      0xFF
00342 
00343 button_definition button_def_30vip[] = {
00344    { 1, STIMULUS_LINE },      /* Line 1 */
00345    { 2, STIMULUS_LINE },      /* Line 2 */
00346    { 3, STIMULUS_LINE },      /* Line 3 */
00347    { 4, STIMULUS_LINE },      /* Line 4 */
00348    { 1, STIMULUS_CALLPARK },  /* Call Park */
00349    { 0, STIMULUS_NONE },
00350    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00351    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00352    { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
00353    { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
00354    { 5, STIMULUS_SPEEDDIAL }, /* Speeddial 5 */
00355    { 6, STIMULUS_SPEEDDIAL }, /* Speeddial 6 */
00356    { 1, STIMULUS_VOICEMAIL }, /* Voicemail */
00357    { 1, STIMULUS_FORWARDALL },   /* Forward All */
00358    { 1, STIMULUS_CONFERENCE },   /* Conference */
00359    { 0, STIMULUS_NONE },
00360    { 0, STIMULUS_NONE },
00361    { 0, STIMULUS_NONE },
00362    { 0, STIMULUS_NONE },
00363    { 0, STIMULUS_NONE },
00364    { 7, STIMULUS_SPEEDDIAL }, /* Speeddial 7 */
00365    { 8, STIMULUS_SPEEDDIAL }, /* Speeddial 8 */
00366    { 9, STIMULUS_SPEEDDIAL }, /* Speeddial 9 */
00367    { 10, STIMULUS_SPEEDDIAL } /* Speeddial 10 */
00368 };
00369 
00370 button_definition button_def_12sp[] = {
00371    { 1, STIMULUS_LINE },      /* Line 1 */
00372    { 1, STIMULUS_LINE },      /* Line 1 */
00373    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00374    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00375    { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
00376    { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
00377    { 1, STIMULUS_VOICEMAIL }, /* Voicemail */
00378    { 5, STIMULUS_SPEEDDIAL }, /* Speeddial 5 */
00379    { 6, STIMULUS_SPEEDDIAL }, /* Speeddial 6 */
00380    { 7, STIMULUS_SPEEDDIAL }, /* Speeddial 7 */
00381    { 8, STIMULUS_SPEEDDIAL }, /* Speeddial 8 */
00382    { 9, STIMULUS_SPEEDDIAL }  /* Speeddial 9 */
00383 };
00384 
00385 button_definition button_def_7902[] = {
00386    { 1, STIMULUS_LINE },      /* Line 1 */
00387    { 1, STIMULUS_HOLD },      /* Hold */
00388    { 1, STIMULUS_TRANSFER },  
00389    { 1, STIMULUS_DISPLAY },
00390    { 1, STIMULUS_VOICEMAIL },
00391    { 1, STIMULUS_CONFERENCE },
00392    { 1, STIMULUS_FORWARDALL },
00393    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00394    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00395    { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
00396    { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
00397    { 1, STIMULUS_REDIAL }
00398 };
00399 
00400 button_definition button_def_7910[] = {
00401    { 1, STIMULUS_LINE },      /* Line 1 */
00402    { 1, STIMULUS_HOLD },      /* Hold */
00403    { 1, STIMULUS_TRANSFER },  
00404    { 1, STIMULUS_DISPLAY },
00405    { 1, STIMULUS_VOICEMAIL },
00406    { 1, STIMULUS_CONFERENCE },
00407    { 1, STIMULUS_FORWARDALL },
00408    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00409    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00410    { 1, STIMULUS_REDIAL }
00411 };
00412 
00413 button_definition button_def_7920[] = {
00414    { 1, STIMULUS_LINE },      /* Line 1 */
00415    { 2, STIMULUS_LINE },      /* Line 2 */
00416    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00417    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00418    { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
00419    { 4, STIMULUS_SPEEDDIAL }  /* Speeddial 4 */
00420 };
00421 
00422 button_definition button_def_7935[] = {
00423    { 1, STIMULUS_LINE },      /* Line 1 */
00424    { 2, STIMULUS_LINE }    /* Line 2 */
00425 };
00426 
00427 button_definition button_def_7940[] = {
00428    { 1, STIMULUS_LINE },      /* Line 1 */
00429    { 2, STIMULUS_LINE }    /* Line 2 */
00430 };
00431 
00432 button_definition button_def_7960[] = {
00433    { 1, STIMULUS_LINE },      /* Line 1 */
00434    { 2, STIMULUS_LINE },      /* Line 2 */
00435    { 3, STIMULUS_LINE },      /* Line 3 */
00436    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00437    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00438    { 3, STIMULUS_SPEEDDIAL }  /* Speeddial 3 */
00439 };
00440 
00441 button_definition button_def_7970[] = {
00442    { 1, STIMULUS_LINE },      /* Line 1 */
00443    { 2, STIMULUS_LINE },      /* Line 2 */
00444    { 3, STIMULUS_LINE },      /* Line 3 */
00445    { 1, STIMULUS_SPEEDDIAL }, /* Speeddial 1 */
00446    { 2, STIMULUS_SPEEDDIAL }, /* Speeddial 2 */
00447    { 3, STIMULUS_SPEEDDIAL }, /* Speeddial 3 */
00448    { 4, STIMULUS_SPEEDDIAL }, /* Speeddial 4 */
00449    { 5, STIMULUS_SPEEDDIAL }  /* Speeddial 5 */
00450 };
00451 
00452 button_definition button_def_none = { 0, STIMULUS_NONE };
00453 
00454 typedef struct button_defs {
00455    char *type;
00456    int num_buttons;
00457    button_definition *button_def;
00458 } button_defs_t;
00459 
00460 button_defs_t button_defs[] = {
00461    { "12SP",   12,   button_def_12sp }, /* First one is used if 
00462                         there's no match */
00463    { "30VIP",  26,   button_def_30vip },
00464    { "7902",   12,   button_def_7902 },
00465    { "7910",   10,   button_def_7910 },
00466    { "7920",   6, button_def_7920 },
00467    { "7935",   2, button_def_7935 },
00468    { "7940",   2, button_def_7940 },
00469    { "7960",   6, button_def_7960 },
00470    { "7970",   8, button_def_7970 },
00471    { NULL,     0, NULL }
00472 };
00473 
00474 typedef struct button_template_res_message {
00475    UINT32 buttonOffset;
00476    UINT32 buttonCount;
00477    UINT32 totalButtonCount;
00478    button_definition definition[42];
00479 } button_template_res_message;
00480 
00481 #define  VERSION_RES_MESSAGE 0x0098
00482 typedef struct version_res_message {
00483    char version[16];
00484 } version_res_message;
00485 
00486 #define  KEEP_ALIVE_ACK_MESSAGE 0x0100
00487 
00488 #define OPEN_RECIEVE_CHANNEL_MESSAGE 0x0105
00489 typedef struct open_recieve_channel_message {
00490    int conferenceId;
00491    int partyId;
00492    int packets;
00493    int capability;
00494    int echo;
00495    int bitrate;
00496 } open_recieve_channel_message;
00497 
00498 #define CLOSE_RECIEVE_CHANNEL_MESSAGE 0x0106
00499 typedef struct close_recieve_channel_message {
00500    int conferenceId;
00501    int partyId;
00502 } close_recieve_channel_message;
00503 
00504 #define  SOFT_KEY_TEMPLATE_RES_MESSAGE 0x0108
00505 
00506 typedef struct soft_key_template_definition {
00507    char softKeyLabel[16];
00508    int softKeyEvent;
00509 } soft_key_template_definition;
00510 
00511 soft_key_template_definition soft_key_template_default[] = {
00512    { "Redial",    1 },
00513    { "NewCall",      2 },
00514    { "Hold",      3 },
00515    { "Trnsfer",      4 },
00516    { "CFwdAll",      5 },
00517    { "CFwdBusy",     6 },
00518    { "CFwdNoAnswer", 7 },
00519    { "<<",        8 },
00520    { "EndCall",      9 },
00521    { "Resume",    10 },
00522    { "Answer",    11 },
00523    { "Info",      12 },
00524    { "Confrn",    13 },
00525    { "Park",      14 },
00526    { "Join",      15 },
00527    { "MeetMe",    16 },
00528    { "PickUp",    17 },
00529    { "GPickUp",      18 },
00530 };
00531 
00532 typedef struct soft_key_template {
00533    int softKeyOffset;
00534    int softKeyCount;
00535    int totalSoftKeyCount;
00536     soft_key_template_definition softKeyTemplateDefinition[32];
00537 } soft_key_template;
00538 
00539 #define  SOFT_KEY_SET_RES_MESSAGE 0x0109
00540 static const char *soft_key_set_hack = {
00541    "\x01\x02\x05\x03\x09\x0a\x0b\x10\x11\x12\x04\x0e\x0d\x00\x00\x00"
00542    "\x2d\x01\x2e\x01\x31\x01\x2f\x01\x35\x01\x36\x01\x37\x01\x3c\x01"
00543    "\x3d\x01\x3e\x01\x30\x01\x3a\x01\x39\x01\x00\x00\x00\x00\x00\x00"
00544    "\x03\x09\x04\x0e\x0d\x13\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00545    "\x2f\x01\x35\x01\x30\x01\x3a\x01\x39\x01\x3f\x01\x00\x00\x00\x00"
00546    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00547    "\x0a\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00548    "\x36\x01\x2e\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00549    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00550    "\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00551    "\x37\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00552    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00553    "\x01\x09\x05\x10\x11\x12\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00554    "\x2d\x01\x35\x01\x31\x01\x3c\x01\x3d\x01\x3e\x01\x00\x00\x00\x00"
00555    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00556    "\x00\x09\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00557    "\x00\x00\x35\x01\x30\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00558    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00559    "\x08\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00560    "\x34\x01\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00561    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00562    "\x00\x09\x0d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00563    "\x00\x00\x35\x01\x39\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00564    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00565    "\x00\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00566    "\x00\x00\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00567    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00568    "\x01\x09\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00569    "\x2d\x01\x35\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00570    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00571    "\x15\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00572    "\x41\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00573    "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
00574 };
00575 
00576 typedef struct soft_key_set_definition {
00577    UINT8  softKeyTemplateIndex[16];
00578    UINT16 softKeyInfoIndex[16];
00579 } soft_key_set_definition;
00580 
00581 typedef struct soft_key_sets {
00582    UINT32 softKeySetOffset;
00583    UINT32 softKeySetCount;
00584    UINT32 totalSoftKeySetCount;
00585    soft_key_set_definition softKeySetDefinition[16];
00586    UINT32 res;
00587 } soft_key_sets;
00588 
00589 #define SELECT_SOFT_KEYS_MESSAGE 0x0110
00590 typedef struct select_soft_keys_message {
00591    int instance;
00592    int reference;
00593    int softKeySetIndex;
00594    int validKeyMask;
00595 } select_soft_keys_message;
00596 
00597 #define CALL_STATE_MESSAGE 0x0111
00598 typedef struct call_state_message {
00599    int callState;
00600    int lineInstance;
00601    int callReference;
00602 } call_state_message;
00603 
00604 #define DISPLAY_PROMPT_STATUS_MESSAGE 0x0112
00605 typedef struct display_prompt_status_message {
00606    int messageTimeout;
00607    char promptMessage[32];
00608    int lineInstance;
00609    int callReference;
00610 } display_prompt_status_message;
00611 
00612 #define DISPLAY_NOTIFY_MESSAGE 0x0114
00613 typedef struct display_notify_message {
00614    int displayTimeout;
00615    char displayMessage[100];
00616 } display_notify_message;
00617 
00618 #define ACTIVATE_CALL_PLANE_MESSAGE 0x0116
00619 typedef struct activate_call_plane_message {
00620    int lineInstance;
00621 } activate_call_plane_message;
00622 
00623 #define DIALLED_NUMBER_MESSAGE 0x011D
00624 typedef struct dialled_number_message {
00625    char dialledNumber[24];
00626    int lineInstance;
00627    int callReference;
00628 } dialled_number_message;
00629 
00630 /* packet composition */
00631 typedef struct {
00632    int len;
00633    int res;
00634    int e;
00635    union {
00636       speed_dial_stat_req_message speeddialreq;
00637       register_message reg;
00638       register_ack_message regack;
00639       register_rej_message regrej;
00640       capabilities_res_message caps;
00641       version_res_message version;
00642       button_template_res_message buttontemplate;
00643       displaytext_message displaytext;
00644       display_prompt_status_message displaypromptstatus;
00645       definetimedate_message definetimedate;
00646       start_tone_message starttone;
00647       speed_dial_stat_res_message speeddial;
00648       line_state_req_message line;
00649       line_stat_res_message linestat;
00650       soft_key_sets softkeysets;
00651       soft_key_template softkeytemplate;
00652       server_res_message serverres;
00653       set_lamp_message setlamp;
00654       set_ringer_message setringer;
00655       call_state_message callstate;
00656       keypad_button_message keypad;
00657       select_soft_keys_message selectsoftkey;
00658       activate_call_plane_message activatecallplane;
00659       stimulus_message stimulus;
00660       set_speaker_message setspeaker;
00661       call_info_message callinfo;
00662       start_media_transmission_message startmedia;
00663       stop_media_transmission_message stopmedia;
00664       open_recieve_channel_message openrecievechannel;
00665       open_recieve_channel_ack_message openrecievechannelack;
00666       close_recieve_channel_message closerecievechannel;
00667       display_notify_message displaynotify;
00668       dialled_number_message diallednumber;
00669    } data;
00670 } skinny_req;
00671 
00672 /************************************************************************************/
00673 /*                            Asterisk specific globals                             */
00674 /************************************************************************************/
00675 
00676 static int skinnydebug = 1;   /* XXX for now, enable debugging default */
00677 
00678 /* a hostname, portnumber, socket and such is usefull for VoIP protocols */
00679 static struct sockaddr_in bindaddr;
00680 static char ourhost[256];
00681 static int ourport;
00682 static struct in_addr __ourip;
00683 struct ast_hostent ahp; struct hostent *hp;
00684 static int skinnysock  = -1;
00685 static pthread_t accept_t;
00686 static char context[AST_MAX_CONTEXT] = "default";
00687 static char language[MAX_LANGUAGE] = "";
00688 static char musicclass[MAX_MUSICCLASS] = "";
00689 static char cid_num[AST_MAX_EXTENSION] = "";
00690 static char cid_name[AST_MAX_EXTENSION] = "";
00691 static char linelabel[AST_MAX_EXTENSION] ="";
00692 static int nat = 0;
00693 static ast_group_t cur_callergroup = 0;
00694 static ast_group_t cur_pickupgroup = 0;
00695 static int immediate = 0;
00696 static int callwaiting = 0;
00697 static int callreturn = 0;
00698 static int threewaycalling = 0;
00699 static int mwiblink = 0;
00700 /* This is for flashhook transfers */
00701 static int transfer = 0;
00702 static int cancallforward = 0;
00703 /* static int busycount = 3;*/
00704 static char accountcode[AST_MAX_ACCOUNT_CODE] = "";
00705 static char mailbox[AST_MAX_EXTENSION];
00706 static int amaflags = 0;
00707 static int callnums = 1;
00708 
00709 #define SUB_REAL 0
00710 #define SUB_ALT  1
00711 #define MAX_SUBS 2
00712 
00713 #define SKINNY_SPEAKERON 1
00714 #define SKINNY_SPEAKEROFF 2
00715 
00716 #define SKINNY_OFFHOOK 1
00717 #define SKINNY_ONHOOK 2
00718 #define SKINNY_RINGOUT 3
00719 #define SKINNY_RINGIN 4
00720 #define SKINNY_CONNECTED 5
00721 #define SKINNY_BUSY 6
00722 #define SKINNY_CONGESTION 7
00723 #define SKINNY_HOLD 8
00724 #define SKINNY_CALLWAIT 9
00725 #define SKINNY_TRANSFER 10
00726 #define SKINNY_PARK 11
00727 #define SKINNY_PROGRESS 12
00728 #define SKINNY_INVALID 14
00729 
00730 #define SKINNY_SILENCE     0x00
00731 #define SKINNY_DIALTONE    0x21
00732 #define SKINNY_BUSYTONE    0x23
00733 #define SKINNY_ALERT    0x24
00734 #define SKINNY_REORDER     0x25
00735 #define SKINNY_CALLWAITTONE   0x2D
00736 #define SKINNY_NOTONE      0x7F
00737 
00738 #define SKINNY_LAMP_OFF 1
00739 #define SKINNY_LAMP_ON  2
00740 #define SKINNY_LAMP_WINK 3
00741 #define SKINNY_LAMP_FLASH 4
00742 #define SKINNY_LAMP_BLINK 5
00743