2f4b9c6a7986db5ea1a1ba7512d1730208462cb3
[asterisk/asterisk.git] / channels / chan_unistim.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * UNISTIM channel driver for asterisk
5  *
6  * Copyright (C) 2005 - 2007, Cedric Hans
7  *
8  * Cedric Hans <cedric.hans@mlkj.net>
9  *
10  * Asterisk 1.4 patch by Peter Be
11  *
12  * See http://www.asterisk.org for more information about
13  * the Asterisk project. Please do not directly contact
14  * any of the maintainers of this project for assistance;
15  * the project provides a web site, mailing lists and IRC
16  * channels for your use.
17  *
18  * This program is free software, distributed under the terms of
19  * the GNU General Public License Version 2. See the LICENSE file
20  * at the top of the source tree.
21  */
22
23 /*!
24  * \file
25  *
26  * \brief chan_unistim channel driver for Asterisk
27  * \author Cedric Hans <cedric.hans@mlkj.net>
28  *
29  * Unistim (Unified Networks IP Stimulus) channel driver
30  * for Nortel i2002, i2004 and i2050
31  *
32  * \ingroup channel_drivers
33  */
34
35 /*** MODULEINFO
36         <support_level>extended</support_level>
37  ***/
38
39 #include "asterisk.h"
40
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
42
43 #include <sys/stat.h>
44 #include <signal.h>
45
46 #if defined(__CYGWIN__)
47 /*
48  * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
49  * which is not included by default by sys/socket.h - in_pktinfo is defined in
50  * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
51  * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
52  *    This should be done in some common header, but for now this is the only file
53  * using iovec and in_pktinfo so it suffices to apply the fix here.
54  */
55 #ifdef HAVE_PKTINFO
56 #undef HAVE_PKTINFO
57 #endif
58 #endif /* __CYGWIN__ */
59
60 #include "asterisk/paths.h"     /* ast_config_AST_LOG_DIR used in (too ?) many places */
61 #include "asterisk/network.h"
62 #include "asterisk/channel.h"
63 #include "asterisk/config.h"
64 #include "asterisk/module.h"
65 #include "asterisk/pbx.h"
66 #include "asterisk/rtp_engine.h"
67 #include "asterisk/netsock2.h"
68 #include "asterisk/acl.h"
69 #include "asterisk/callerid.h"
70 #include "asterisk/cli.h"
71 #include "asterisk/app.h"
72 #include "asterisk/musiconhold.h"
73 #include "asterisk/causes.h"
74 #include "asterisk/indications.h"
75 #include "asterisk/pickup.h"
76 #include "asterisk/astobj2.h"
77 #include "asterisk/astdb.h"
78 #include "asterisk/features_config.h"
79 #include "asterisk/bridge.h"
80 #include "asterisk/stasis_channels.h"
81
82 #define DEFAULTCONTEXT    "default"
83 #define DEFAULTCALLERID  "Unknown"
84 #define DEFAULTCALLERNAME       " "
85 #define DEFAULTHEIGHT    3
86 #define USTM_LOG_DIR        "unistimHistory"
87 #define USTM_LANG_DIR       "unistimLang"
88
89 /*! Size of the transmit buffer */
90 #define MAX_BUF_SIZE        64
91 /*! Number of slots for the transmit queue */
92 #define MAX_BUF_NUMBER    50
93 /*! Number of digits displayed on screen */
94 #define MAX_SCREEN_NUMBER   15
95 /*! Try x times before removing the phone */
96 #define NB_MAX_RETRANSMIT       8
97 /*! Nb of milliseconds waited when no events are scheduled */
98 #define IDLE_WAIT              1000
99 /*! Wait x milliseconds before resending a packet */
100 #define RETRANSMIT_TIMER        2000
101 /*! How often the mailbox is checked for new messages */
102 #define TIMER_MWI              5000
103 /*! Timeout value for entered number being dialed */
104 #define DEFAULT_INTERDIGIT_TIMER        4000
105
106 /*! Not used */
107 #define DEFAULT_CODEC      0x00
108 #define SIZE_PAGE              4096
109 #define DEVICE_NAME_LEN  16
110 #define AST_CONFIG_MAX_PATH     255
111 #define MAX_ENTRY_LOG      30
112
113 #define SUB_REAL                0
114 #define SUB_RING                1
115 #define SUB_THREEWAY            2
116 #define SUB_ONHOLD              3
117
118 struct ast_format_cap *global_cap;
119
120 enum autoprovision {
121         AUTOPROVISIONING_NO = 0,
122         AUTOPROVISIONING_YES,
123         AUTOPROVISIONING_TN
124 };
125
126 enum autoprov_extn {
127         /*! Do not create an extension into the default dialplan */
128         EXTENSION_NONE = 0,
129         /*! Prompt user for an extension number and register it */
130         EXTENSION_ASK,
131         /*! Register an extension with the line=> value */
132         EXTENSION_LINE,
133         /*! Used with AUTOPROVISIONING_TN */
134         EXTENSION_TN
135 };
136 #define OUTPUT_HANDSET    0xC0
137 #define OUTPUT_HEADPHONE        0xC1
138 #define OUTPUT_SPEAKER    0xC2
139
140 #define VOLUME_LOW            0x01
141 #define VOLUME_LOW_SPEAKER      0x03
142 #define VOLUME_NORMAL      0x02
143 #define VOLUME_INSANELY_LOUD    0x07
144
145 #define MUTE_OFF                0x00
146 #define MUTE_ON          0xFF
147 #define MUTE_ON_DISCRET  0xCE
148
149 #define SIZE_HEADER          6
150 #define SIZE_MAC_ADDR      17
151 #define TEXT_LENGTH_MAX  24
152 #define TEXT_LINE0            0x00
153 #define TEXT_LINE1            0x20
154 #define TEXT_LINE2            0x40
155 #define TEXT_NORMAL          0x05
156 #define TEXT_INVERSE        0x25
157 #define STATUS_LENGTH_MAX       28
158
159 #define FAV_ICON_NONE              0x00
160 #define FAV_ICON_ONHOOK_BLACK      0x20
161 #define FAV_ICON_ONHOOK_WHITE      0x21
162 #define FAV_ICON_SPEAKER_ONHOOK_BLACK   0x22
163 #define FAV_ICON_SPEAKER_ONHOOK_WHITE   0x23
164 #define FAV_ICON_OFFHOOK_BLACK    0x24
165 #define FAV_ICON_OFFHOOK_WHITE    0x25
166 #define FAV_ICON_ONHOLD_BLACK      0x26
167 #define FAV_ICON_ONHOLD_WHITE      0x27
168 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK  0x28
169 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE  0x29
170 #define FAV_ICON_PHONE_BLACK        0x2A
171 #define FAV_ICON_PHONE_WHITE        0x2B
172 #define FAV_ICON_SPEAKER_ONHOLD_BLACK   0x2C
173 #define FAV_ICON_SPEAKER_ONHOLD_WHITE   0x2D
174 #define FAV_ICON_HEADPHONES          0x2E
175 #define FAV_ICON_HEADPHONES_ONHOLD      0x2F
176 #define FAV_ICON_HOME              0x30
177 #define FAV_ICON_CITY              0x31
178 #define FAV_ICON_SHARP            0x32
179 #define FAV_ICON_PAGER            0x33
180 #define FAV_ICON_CALL_CENTER        0x34
181 #define FAV_ICON_FAX                0x35
182 #define FAV_ICON_MAILBOX                0x36
183 #define FAV_ICON_REFLECT                0x37
184 #define FAV_ICON_COMPUTER              0x38
185 #define FAV_ICON_FORWARD                0x39
186 #define FAV_ICON_LOCKED          0x3A
187 #define FAV_ICON_TRASH            0x3B
188 #define FAV_ICON_INBOX            0x3C
189 #define FAV_ICON_OUTBOX          0x3D
190 #define FAV_ICON_MEETING                0x3E
191 #define FAV_ICON_BOX                0x3F
192
193 #define FAV_BLINK_FAST            0x20
194 #define FAV_BLINK_SLOW            0x40
195
196 #define FAV_MAX_LENGTH            0x0A
197
198 #define FAVNUM                    6
199 #define FAV_LINE_ICON         FAV_ICON_ONHOOK_BLACK
200
201 static void dummy(char *unused, ...)
202 {
203         return;
204 }
205
206 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
207  *  \note Values shown here match the defaults shown in unistim.conf.sample */
208 static struct ast_jb_conf default_jbconf =
209 {
210         .flags = 0,
211         .max_size = 200,
212         .resync_threshold = 1000,
213         .impl = "fixed",
214         .target_extra = 40,
215 };
216 static struct ast_jb_conf global_jbconf;
217
218
219 /* #define DUMP_PACKET 1 */
220 /* #define DEBUG_TIMER ast_verbose */
221
222 #define DEBUG_TIMER dummy
223 /*! Enable verbose output. can also be set with the CLI */
224 static int unistimdebug = 0;
225 static int unistim_port;
226 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
227 static int unistim_keepalive;
228 static int unistimsock = -1;
229
230 static struct {
231         unsigned int tos;
232         unsigned int tos_audio;
233         unsigned int cos;
234         unsigned int cos_audio;
235 } qos = { 0, 0, 0, 0 };
236
237 static struct io_context *io;
238 static struct ast_sched_context *sched;
239 static struct sockaddr_in public_ip = { 0, };
240 static unsigned char *buff; /*! Receive buffer address */
241 static int unistim_reloading = 0;
242 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
243
244 /*! This is the thread for the monitor which checks for input on the channels
245  * which are not currently in use.  */
246 static pthread_t monitor_thread = AST_PTHREADT_NULL;
247
248 /*! Protect the monitoring thread, so only one process can kill or start it, and not
249  *    when it's doing something critical. */
250 AST_MUTEX_DEFINE_STATIC(monlock);
251 /*! Protect the session list */
252 AST_MUTEX_DEFINE_STATIC(sessionlock);
253 /*! Protect the device list */
254 AST_MUTEX_DEFINE_STATIC(devicelock);
255
256 enum phone_state {
257         STATE_INIT,
258         STATE_AUTHDENY,
259         STATE_MAINPAGE,
260         STATE_EXTENSION,
261         STATE_DIALPAGE,
262         STATE_RINGING,
263         STATE_CALL,
264         STATE_SELECTOPTION,
265         STATE_SELECTCODEC,
266         STATE_SELECTLANGUAGE,
267         STATE_CLEANING,
268         STATE_HISTORY
269 };
270
271 enum handset_state {
272         STATE_ONHOOK,
273         STATE_OFFHOOK,
274 };
275
276 enum phone_key {
277         KEY_0 = 0x40,
278         KEY_1 = 0x41,
279         KEY_2 = 0x42,
280         KEY_3 = 0x43,
281         KEY_4 = 0x44,
282         KEY_5 = 0x45,
283         KEY_6 = 0x46,
284         KEY_7 = 0x47,
285         KEY_8 = 0x48,
286         KEY_9 = 0x49,
287         KEY_STAR = 0x4a,
288         KEY_SHARP = 0x4b,
289         KEY_UP = 0x4c,
290         KEY_DOWN = 0x4d,
291         KEY_RIGHT = 0x4e,
292         KEY_LEFT = 0x4f,
293         KEY_QUIT = 0x50,
294         KEY_COPY = 0x51,
295         KEY_FUNC1 = 0x54,
296         KEY_FUNC2 = 0x55,
297         KEY_FUNC3 = 0x56,
298         KEY_FUNC4 = 0x57,
299         KEY_ONHOLD = 0x5b,
300         KEY_HANGUP = 0x5c,
301         KEY_MUTE = 0x5d,
302         KEY_HEADPHN = 0x5e,
303         KEY_LOUDSPK = 0x5f,
304         KEY_FAV0 = 0x60,
305         KEY_FAV1 = 0x61,
306         KEY_FAV2 = 0x62,
307         KEY_FAV3 = 0x63,
308         KEY_FAV4 = 0x64,
309         KEY_FAV5 = 0x65,
310         KEY_COMPUTR = 0x7b,
311         KEY_CONF = 0x7c,
312         KEY_SNDHIST = 0x7d,
313         KEY_RCVHIST = 0x7e,
314         KEY_INDEX = 0x7f
315 };
316
317 enum charset {
318         LANG_DEFAULT,
319         ISO_8859_1,
320         ISO_8859_2,
321         ISO_8859_4,
322         ISO_8859_5,
323         ISO_2022_JP,
324 };
325
326 static const int dtmf_row[] = { 697,  770,  852,  941 };
327 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
328
329 struct wsabuf {
330         u_long len;
331         unsigned char *buf;
332 };
333
334 struct unistim_subchannel {
335         ast_mutex_t lock;
336         unsigned int subtype;           /*! SUB_REAL, SUB_RING, SUB_THREEWAY or SUB_ONHOLD */
337         struct ast_channel *owner;      /*! Asterisk channel used by the subchannel */
338         struct unistim_line *parent;    /*! Unistim line */
339         struct ast_rtp_instance *rtp;   /*! RTP handle */
340         int softkey;                    /*! Softkey assigned */
341         pthread_t ss_thread;            /*! unistim_ss thread handle */
342         int alreadygone;
343         char ringvolume;
344         char ringstyle;
345         int moh;                                        /*!< Music on hold in progress */
346         AST_LIST_ENTRY(unistim_subchannel) list;
347 };
348
349 /*!
350  * \todo Convert to stringfields
351  */
352 struct unistim_line {
353         ast_mutex_t lock;
354         char name[80]; /*! Like 200 */
355         char fullname[80]; /*! Like USTM/200\@black */
356         char exten[AST_MAX_EXTENSION]; /*! Extension where to start */
357         char cid_num[AST_MAX_EXTENSION]; /*! CallerID Number */
358         char mailbox[AST_MAX_EXTENSION]; /*! Mailbox for MWI */
359         char musicclass[MAX_MUSICCLASS]; /*! MusicOnHold class */
360         ast_group_t callgroup; /*! Call group */
361         ast_group_t pickupgroup; /*! Pickup group */
362         char accountcode[AST_MAX_ACCOUNT_CODE]; /*! Account code (for billing) */
363         int amaflags; /*! AMA flags (for billing) */
364         struct ast_format_cap *cap; /*! Codec supported */
365         char parkinglot[AST_MAX_CONTEXT]; /*! Parkinglot */
366         struct unistim_line *next;
367         struct unistim_device *parent;
368         AST_LIST_ENTRY(unistim_line) list;
369 };
370
371 /*!
372  * \brief A device containing one or more lines
373  */
374 static struct unistim_device {
375         ast_mutex_t lock;
376         int receiver_state;           /*!< state of the receiver (see ReceiverState) */
377         int size_phone_number;    /*!< size of the phone number */
378         char context[AST_MAX_EXTENSION]; /*!< Context to start in */
379         char phone_number[AST_MAX_EXTENSION];     /*!< the phone number entered by the user */
380         char redial_number[AST_MAX_EXTENSION];   /*!< the last phone number entered by the user */
381         char id[18];                        /*!< mac address of the current phone in ascii */
382         char name[DEVICE_NAME_LEN];     /*!< name of the device */
383         char softkeylabel[FAVNUM][11];       /*!< soft key label */
384         char softkeynumber[FAVNUM][AST_MAX_EXTENSION];      /*!< number dialed when the soft key is pressed */
385         char softkeyicon[FAVNUM];           /*!< icon number */
386         char softkeydevice[FAVNUM][16];      /*!< name of the device monitored */
387         struct unistim_subchannel *ssub[FAVNUM];
388         struct unistim_line *sline[FAVNUM];
389         struct unistim_device *sp[FAVNUM];   /*!< pointer to the device monitored by this soft key */
390         char language[MAX_LANGUAGE];    /*!< Language for asterisk sounds */
391         int height;                                                     /*!< The number of lines the phone can display */
392         char maintext0[25];                  /*!< when the phone is idle, display this string on line 0 */
393         char maintext1[25];                  /*!< when the phone is idle, display this string on line 1 */
394         char maintext2[25];                  /*!< when the phone is idle, display this string on line 2 */
395         char titledefault[13];    /*!< title (text before date/time) */
396         char datetimeformat;        /*!< format used for displaying time/date */
397         char contrast;                    /*!< contrast */
398         char country[3];                        /*!< country used for dial tone frequency */
399         struct ast_tone_zone *tz;              /*!< Tone zone for res_indications (ring, busy, congestion) */
400         char ringvolume;                        /*!< Ring volume */
401         char ringstyle;                  /*!< Ring melody */
402         char cwvolume;                  /*!< Ring volume on call waiting */
403         char cwstyle;                    /*!< Ring melody on call waiting */
404         int interdigit_timer;           /*!< Interdigit timer for dialing number by timeout */
405         time_t nextdial;                /*!< Timer used for dial by timeout */
406         int rtp_port;                      /*!< RTP port used by the phone */
407         int rtp_method;                  /*!< Select the unistim data used to establish a RTP session */
408         int status_method;                    /*!< Select the unistim packet used for sending status text */
409         char codec_number;                    /*!< The current codec used to make calls */
410         int missed_call;                        /*!< Number of call unanswered */
411         int callhistory;                        /*!< Allowed to record call history */
412         int sharp_dial;                         /*!< Execute Dial on '#' or not */
413         char lst_cid[TEXT_LENGTH_MAX];  /*!< Last callerID received */
414         char lst_cnm[TEXT_LENGTH_MAX];  /*!< Last callername recevied */
415         char call_forward[AST_MAX_EXTENSION];   /*!< Forward number */
416         int output;                                  /*!< Handset, headphone or speaker */
417         int previous_output;        /*!< Previous output */
418         int volume;                                  /*!< Default volume */
419         int selected;                           /*!< softkey selected */
420         int mute;                                      /*!< Mute mode */
421         int lastmsgssent;                                                   /*! Used by MWI */
422         time_t nextmsgcheck;                                            /*! Used by MWI */
423         int nat;                                        /*!< Used by the obscure ast_rtp_setnat */
424         enum autoprov_extn extension;   /*!< See ifdef EXTENSION for valid values */
425         char extension_number[11];      /*!< Extension number entered by the user */
426         char to_delete;                  /*!< Used in reload */
427         struct ast_silence_generator *silence_generator;
428         AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
429         AST_LIST_HEAD(,unistim_line) lines;
430         struct ast_ha *ha;
431         struct unistimsession *session;
432         struct unistim_device *next;
433 } *devices = NULL;
434
435 static struct unistimsession {
436         ast_mutex_t lock;
437         struct sockaddr_in sin;  /*!< IP address of the phone */
438         struct sockaddr_in sout;        /*!< IP address of server */
439         int timeout;                        /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
440         unsigned short seq_phone;       /*!< sequence number for the next packet (when we receive a request) */
441         unsigned short seq_server;      /*!< sequence number for the next packet (when we send a request) */
442         unsigned short last_seq_ack;    /*!< sequence number of the last ACK received */
443         unsigned long tick_next_ping;   /*!< time for the next ping */
444         int last_buf_available;  /*!< number of a free slot */
445         int nb_retransmit;                    /*!< number of retransmition */
446         int state;                                    /*!< state of the phone (see phone_state) */
447         int size_buff_entry;        /*!< size of the buffer used to enter datas */
448         char buff_entry[16];        /*!< Buffer for temporary datas */
449         char macaddr[18];                      /*!< mac adress of the phone (not always available) */
450         char firmware[8];                      /*!< firmware of the phone (not always available) */
451         struct wsabuf wsabufsend[MAX_BUF_NUMBER];      /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
452         unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE];        /*!< Buffer array used to keep the lastest non-acked paquets */
453         struct unistim_device *device;
454         struct unistimsession *next;
455 } *sessions = NULL;
456
457 /*! Store on screen phone menu item (label and handler function) */
458 struct unistim_menu_item {
459         char *label;
460         int state;
461         void (*handle_option)(struct unistimsession *);
462 };
463
464 /*! Language item for currently existed translations */
465 struct unistim_languages {
466         char *label;
467         char *lang_short;
468         int encoding;
469         struct ao2_container *trans;
470 };
471
472 /*!
473  * \page Unistim datagram formats
474  *
475  * Format of datagrams :
476  * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
477  * byte 2 : sequence number (high part)
478  * byte 3 : sequence number (low part)
479  * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
480  * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
481  */
482
483 static const unsigned char packet_rcv_discovery[] =
484         { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
485 static const unsigned char packet_send_discovery_ack[] =
486         { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
487
488 static const unsigned char packet_recv_firm_version[] =
489         { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
490 static const unsigned char packet_recv_it_type[] =
491         { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
492 static const unsigned char packet_recv_pressed_key[] =
493         { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
494 static const unsigned char packet_recv_pick_up[] =
495         { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
496 static const unsigned char packet_recv_hangup[] =
497         { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
498 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
499
500 /*! TransportAdapter */
501 static const unsigned char packet_recv_resume_connection_with_server[] =
502         { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
503 static const unsigned char packet_recv_mac_addr[] =
504         { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */  };
505
506 static const unsigned char packet_send_date_time3[] =
507         { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
508 /*Minutes */ 0x08, 0x32
509 };
510 static const unsigned char packet_send_date_time[] =
511         { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
512 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
513         0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
514                 0x05, 0x12, 0x00, 0x78
515 };
516
517 static const unsigned char packet_send_no_ring[] =
518         { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
519 static const unsigned char packet_send_s4[] =
520         { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
521 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
522         0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
523                 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
524         0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
525 };
526 static const unsigned char packet_send_call[] =
527         { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
528         0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
529                 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
530         0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
531                 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
532         /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
533                 0x16, 0x66
534 };
535 static const unsigned char packet_send_stream_based_tone_off[] =
536         { 0x16, 0x05, 0x1c, 0x00, 0x00 };
537
538 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
539 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
540 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
541 static const unsigned char packet_send_stream_based_tone_on[] =
542         { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
543 static const unsigned char packet_send_stream_based_tone_single_freq[] =
544         { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
545 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
546         { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
547 static const unsigned char packet_send_select_output[] =
548         { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
549 static const unsigned char packet_send_ring[] =
550         { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
551         0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18,     /* volume 00, 10, 20... */
552         0x20, 0x16, 0x04, 0x10, 0x00
553 };
554 static const unsigned char packet_send_end_call[] =
555         { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
556 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
557         0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
558 };
559 static const unsigned char packet_send_s9[] =
560         { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
561 0x00 };
562 static const unsigned char packet_send_rtp_packet_size[] =
563         { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
564 static const unsigned char packet_send_jitter_buffer_conf[] =
565         { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
566 /* early packet resync 2 bytes */ 0x3e, 0x80,
567         0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
568 };
569
570 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
571 static unsigned char packet_send_StreamBasedToneCad[] =
572   { 0x16, 0x0a, 0x1e, 0x00, duration on  0x0a, duration off  0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
573 static const unsigned char packet_send_open_audio_stream_rx[] =
574         { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
575 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
576         0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
577 };
578 static const unsigned char packet_send_open_audio_stream_tx[] =
579         { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
580 0x0e, 0x01, /* Local port */ 0x14, 0x50,
581         0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
582 };
583
584 static const unsigned char packet_send_open_audio_stream_rx3[] =
585         { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
586 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
587 /* RTCP Port */ 0x14,
588         0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
589                 0x69, 0x05
590 };
591 static const unsigned char packet_send_open_audio_stream_tx3[] =
592         { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
593 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
594         /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
595                 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
596 };
597
598 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
599 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
600 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05,   /*Day */
601         0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
602 };
603 static const unsigned char packet_send_Contrast[] =
604         { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
605 static const unsigned char packet_send_start_timer[] =
606         { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
607         /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
608 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
609 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 };      /* display an icon in front of the text zone */
610 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
611 static const unsigned char packet_send_set_pos_cursor[] =
612         { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
613
614 /*static unsigned char packet_send_MonthLabelsDownload[] =
615   { 0x17, 0x0a, 0x15,  Month (3 char)  0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
616 static const unsigned char packet_send_favorite[] =
617         { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
618 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
619         0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
620 };
621 static const unsigned char packet_send_title[] =
622         { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
623 0x20, 0x20, 0x20, 0x20 /*end_text */  };
624 static const unsigned char packet_send_text[] =
625         { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
626 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
627         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
628                 /*end_text */ 0x17, 0x04, 0x10, 0x87
629 };
630 static const unsigned char packet_send_status[] =
631         { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
632 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
633         0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20    /*end_text */
634 };
635 static const unsigned char packet_send_status2[] =
636         { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
637 0x20, 0x20, 0x20 /* end_text */  };
638
639 /* Multiple character set support */
640 /* ISO-8859-1 - Western European) */
641 static const unsigned char packet_send_charset_iso_8859_1[] =
642         { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
643 /* ISO-8859-2 - Central European) */
644 static const unsigned char packet_send_charset_iso_8859_2[] =
645         { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
646 /* ISO-8859-4 - Baltic) */
647 static const unsigned char packet_send_charset_iso_8859_4[] =
648         { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
649 /* ISO 8859-5 - cyrilic */
650 static const unsigned char packet_send_charset_iso_8859_5[] =
651         { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
652 /* Japaneese (ISO-2022-JP ?) */
653 static const unsigned char packet_send_charset_iso_2022_jp[] =
654         { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
655
656 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
657
658 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
659 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
660 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
661 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
662
663 static unsigned char packet_send_ping[] =
664         { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
665
666 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
667
668 static const char tdesc[] = "UNISTIM Channel Driver";
669 static const char channel_type[] = "USTM";
670
671 /*! Protos */
672 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
673 static int load_module(void);
674 static int reload(void);
675 static int unload_module(void);
676 static int reload_config(void);
677 static void unistim_set_owner(struct unistim_subchannel *sub, struct ast_channel *chan);
678 static void show_main_page(struct unistimsession *pte);
679 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
680         const char *dest, int *cause);
681 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
682 static int unistim_hangup(struct ast_channel *ast);
683 static int unistim_answer(struct ast_channel *ast);
684 static struct ast_frame *unistim_read(struct ast_channel *ast);
685 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
686 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
687         size_t datalen);
688 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
689 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
690 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
691         unsigned int duration);
692 static int unistim_sendtext(struct ast_channel *ast, const char *text);
693
694 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
695         char *line1);
696 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
697
698 static struct ast_channel_tech unistim_tech = {
699         .type = channel_type,
700         .description = tdesc,
701         .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
702         .requester = unistim_request,
703         .call = unistim_call,
704         .hangup = unistim_hangup,
705         .answer = unistim_answer,
706         .read = unistim_read,
707         .write = unistim_write,
708         .indicate = unistim_indicate,
709         .fixup = unistim_fixup,
710         .send_digit_begin = unistim_senddigit_begin,
711         .send_digit_end = unistim_senddigit_end,
712         .send_text = unistim_sendtext,
713 };
714
715 static void send_start_rtp(struct unistim_subchannel *);
716
717 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
718 static void key_favorite(struct unistimsession *, char);
719
720 static void handle_select_codec(struct unistimsession *);
721 static void handle_select_language(struct unistimsession *);
722 static int find_language(const char*);
723
724 static int unistim_free_sub(struct unistim_subchannel *);
725
726 static struct unistim_menu_item options_menu[] =
727 {
728         {"Change codec", STATE_SELECTCODEC, handle_select_codec},
729         {"Language", STATE_SELECTLANGUAGE, handle_select_language},
730         {NULL, 0, NULL}
731 };
732
733 static struct unistim_languages options_languages[] =
734 {
735         {"English", "en", ISO_8859_1, NULL},
736         {"French", "fr", ISO_8859_1, NULL},
737         {"Russian", "ru", ISO_8859_5, NULL},
738         {NULL, NULL, 0, NULL}
739 };
740
741 static char ustm_strcopy[1024];
742
743 struct ustm_lang_entry {
744         const char *str_orig;
745         const char *str_trans;
746 };
747
748 static int lang_hash_fn(const void *obj, const int flags)
749 {
750         const struct ustm_lang_entry *entry = obj;
751         return ast_str_hash(entry->str_orig);
752 }
753
754 static int lang_cmp_fn(void *obj, void *arg, int flags)
755 {
756         struct ustm_lang_entry *entry1 = obj;
757         struct ustm_lang_entry *entry2 = arg;
758
759         return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
760 }
761
762 static const char *ustmtext(const char *str, struct unistimsession *pte)
763 {
764         struct ustm_lang_entry *lang_entry;
765         struct ustm_lang_entry le_search;
766         struct unistim_languages *lang = NULL;
767         int size;
768
769         if (pte->device) {
770                 lang = &options_languages[find_language(pte->device->language)];
771         }
772         if (!lang) {
773                 return str;
774         }
775         /* Check if specified language exists */
776         if (!lang->trans) {
777                 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
778                 FILE *f;
779
780                 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
781                         ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
782                         return str;
783                 }
784                 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
785                          USTM_LANG_DIR, lang->lang_short);
786                 f = fopen(tmp, "r");
787                 if (!f) {
788                         ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
789                         return str;
790                 }
791                 while (fgets(tmp, sizeof(tmp), f)) {
792                         if (!(p = strchr(tmp, '\n'))) {
793                                 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
794                                 continue;
795                         }
796                         *p = '\0';
797                         if (!(p = strchr(tmp, '"'))) {
798                                 continue;
799                         }
800                         if (tmp == strstr(tmp, "msgid")) {
801                                 p_orig = ast_strdup(p + 1);
802                                 p = strchr(p_orig, '"');
803                         } else if (tmp == strstr(tmp, "msgstr")) {
804                                 p_trans = ast_strdup(p + 1);
805                                 p = strchr(p_trans, '"');
806                         } else {
807                                 continue;
808                         }
809                         *p = '\0';
810                         if (!p_trans || !p_orig) {
811                                 continue;
812                         }
813                         if (ast_strlen_zero(p_trans)) {
814                                 ast_free(p_trans);
815                                 ast_free(p_orig);
816                                 p_trans = NULL;
817                                 p_orig = NULL;
818                                 continue;
819                         }
820                         if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
821                                 fclose(f);
822                                 return str;
823                         }
824
825                         lang_entry->str_trans = p_trans;
826                         lang_entry->str_orig = p_orig;
827                         ao2_link(lang->trans, lang_entry);
828                         p_trans = NULL;
829                         p_orig = NULL;
830                 }
831
832                 fclose(f);
833         }
834
835         le_search.str_orig = str;
836         if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
837                 size = strlen(lang_entry->str_trans)+1;
838                 if (size > 1024) {
839                         size = 1024;
840                 }
841                 memcpy(ustm_strcopy, lang_entry->str_trans, size);
842                 ao2_ref(lang_entry, -1);
843                 return ustm_strcopy;
844         }
845
846         return str;
847 }
848
849 static void display_last_error(const char *sz_msg)
850 {
851         /* Display the error message */
852         ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
853 }
854
855 static unsigned int get_tick_count(void)
856 {
857         struct timeval now = ast_tvnow();
858
859         return (now.tv_sec * 1000) + (now.tv_usec / 1000);
860 }
861
862 /* Send data to a phone without retransmit nor buffering */
863 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
864                             const struct sockaddr_in *addr_ourip)
865 {
866 #ifdef HAVE_PKTINFO
867         struct iovec msg_iov;
868         struct msghdr msg;
869         char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
870         struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
871         struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
872
873         /* cast this to a non-const pointer, since the sendmsg() API
874          * does not provide read-only and write-only flavors of the
875          * structures used for its arguments, but in this case we know
876          * the data will not be modified
877          */
878         msg_iov.iov_base = (char *) data;
879         msg_iov.iov_len = size;
880
881         msg.msg_name = addr_to;  /* optional address */
882         msg.msg_namelen = sizeof(struct sockaddr_in);   /* size of address */
883         msg.msg_iov = &msg_iov;  /* scatter/gather array */
884         msg.msg_iovlen = 1;                  /* # elements in msg_iov */
885         msg.msg_control = ip_msg;       /* ancillary data */
886         msg.msg_controllen = sizeof(buffer);    /* ancillary data buffer len */
887         msg.msg_flags = 0;                    /* flags on received message */
888
889         ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
890         ip_msg->cmsg_level = IPPROTO_IP;
891         ip_msg->cmsg_type = IP_PKTINFO;
892         pki->ipi_ifindex = 0;      /* Interface index, 0 = use interface specified in routing table */
893         pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
894         /* pki->ipi_addr = ;   Header Destination address - ignored by kernel */
895
896 #ifdef DUMP_PACKET
897         if (unistimdebug) {
898                 int tmp;
899                 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
900                                         ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
901                                         ast_inet_ntoa(addr_to->sin_addr));
902                 for (tmp = 0; tmp < size; tmp++)
903                         ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
904                 ast_verb(0, "\n******************************************\n");
905
906         }
907 #endif
908
909         if (sendmsg(unistimsock, &msg, 0) == -1) {
910                 display_last_error("Error sending datas");
911         }
912 #else
913         if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
914                 == -1)
915                 display_last_error("Error sending datas");
916 #endif
917 }
918
919 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
920 {
921         unsigned int tick;
922         int buf_pos;
923         unsigned short seq = ntohs(++pte->seq_server);
924
925         ast_mutex_lock(&pte->lock);
926         buf_pos = pte->last_buf_available;
927
928         if (buf_pos >= MAX_BUF_NUMBER) {
929                 ast_log(LOG_WARNING, "Error : send queue overflow\n");
930                 ast_mutex_unlock(&pte->lock);
931                 return;
932         }
933         memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
934         pte->wsabufsend[buf_pos].len = size;
935         memcpy(pte->wsabufsend[buf_pos].buf, data, size);
936
937         tick = get_tick_count();
938         pte->timeout = tick + RETRANSMIT_TIMER;
939
940 /*#ifdef DUMP_PACKET */
941         if (unistimdebug) {
942                 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
943         }
944 /*#endif */
945         send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
946                                   &(pte->sout));
947         pte->last_buf_available++;
948         ast_mutex_unlock(&pte->lock);
949 }
950
951 static void send_ping(struct unistimsession *pte)
952 {
953         BUFFSEND;
954         if (unistimdebug) {
955                 ast_verb(6, "Sending ping\n");
956         }
957         pte->tick_next_ping = get_tick_count() + unistim_keepalive;
958         memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
959         send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
960 }
961
962 static int get_to_address(int fd, struct sockaddr_in *toAddr)
963 {
964 #ifdef HAVE_PKTINFO
965         int err;
966         struct msghdr msg;
967         struct {
968                 struct cmsghdr cm;
969                 int len;
970                 struct in_addr address;
971         } ip_msg;
972
973         /* Zero out the structures before we use them */
974         /* This sets several key values to NULL */
975         memset(&msg, 0, sizeof(msg));
976         memset(&ip_msg, 0, sizeof(ip_msg));
977
978         /* Initialize the message structure */
979         msg.msg_control = &ip_msg;
980         msg.msg_controllen = sizeof(ip_msg);
981         /* Get info about the incoming packet */
982         err = recvmsg(fd, &msg, MSG_PEEK);
983         if (err == -1) {
984                 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
985         }
986         memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
987         return err;
988 #else
989         memcpy(&toAddr, &public_ip, sizeof(&toAddr));
990         return 0;
991 #endif
992 }
993
994 /* Allocate memory & initialize structures for a new phone */
995 /* addr_from : ip address of the phone */
996 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
997 {
998         int tmp;
999         struct unistimsession *s;
1000
1001         if (!(s = ast_calloc(1, sizeof(*s))))
1002                 return NULL;
1003
1004         memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1005         get_to_address(unistimsock, &s->sout);
1006         s->sout.sin_family = AF_INET;
1007         if (unistimdebug) {
1008                 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1009                          ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1010         }
1011         ast_mutex_init(&s->lock);
1012         ast_mutex_lock(&sessionlock);
1013         s->next = sessions;
1014         sessions = s;
1015
1016         s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1017         s->state = STATE_INIT;
1018         s->tick_next_ping = get_tick_count() + unistim_keepalive;
1019         /* Initialize struct wsabuf  */
1020         for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1021                 s->wsabufsend[tmp].buf = s->buf[tmp];
1022         }
1023         ast_mutex_unlock(&sessionlock);
1024         return s;
1025 }
1026
1027 static void send_end_call(struct unistimsession *pte)
1028 {
1029         BUFFSEND;
1030         if (unistimdebug) {
1031                 ast_verb(0, "Sending end call\n");
1032         }
1033         memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1034         send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1035 }
1036
1037 static void set_ping_timer(struct unistimsession *pte)
1038 {
1039         unsigned int tick = 0;  /* XXX what is this for, anyways */
1040
1041         pte->timeout = pte->tick_next_ping;
1042         DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1043         return;
1044 }
1045
1046 /* Checking if our send queue is empty,
1047  * if true, setting up a timer for keepalive */
1048 static void check_send_queue(struct unistimsession *pte)
1049 {
1050         /* Check if our send queue contained only one element */
1051         if (pte->last_buf_available == 1) {
1052                 if (unistimdebug) {
1053                         ast_verb(6, "Our single packet was ACKed.\n");
1054                 }
1055                 pte->last_buf_available--;
1056                 set_ping_timer(pte);
1057                 return;
1058         }
1059         /* Check if this ACK catch up our latest packet */
1060         else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1061                 if (unistimdebug) {
1062                         ast_verb(6, "Our send queue is completely ACKed.\n");
1063                 }
1064                 pte->last_buf_available = 0;    /* Purge the send queue */
1065                 set_ping_timer(pte);
1066                 return;
1067         }
1068         if (unistimdebug) {
1069                 ast_verb(6, "We still have packets in our send queue\n");
1070         }
1071         return;
1072 }
1073
1074 static void send_start_timer(struct unistimsession *pte)
1075 {
1076         BUFFSEND;
1077         if (unistimdebug) {
1078                 ast_verb(0, "Sending start timer\n");
1079         }
1080         memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1081         send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1082 }
1083
1084 static void send_stop_timer(struct unistimsession *pte)
1085 {
1086         BUFFSEND;
1087         if (unistimdebug) {
1088                 ast_verb(0, "Sending stop timer\n");
1089         }
1090         memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1091         send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1092 }
1093
1094 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1095 {
1096         BUFFSEND;
1097         if (unistimdebug) {
1098                 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1099         }
1100         memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1101         buffsend[9] = pos;
1102         buffsend[10] = status;
1103         send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1104 }
1105
1106 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1107 {
1108         BUFFSEND;
1109         if (!tone1) {
1110                 if (unistimdebug) {
1111                         ast_verb(0, "Sending Stream Based Tone Off\n");
1112                 }
1113                 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1114                            sizeof(packet_send_stream_based_tone_off));
1115                 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1116                 return;
1117         }
1118         /* Since most of the world use a continuous tone, it's useless
1119            if (unistimdebug)
1120            ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1121            memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1122            send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1123         if (unistimdebug) {
1124                 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1125         }
1126         tone1 *= 8;
1127         if (!tone2) {
1128                 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1129                            sizeof(packet_send_stream_based_tone_single_freq));
1130                 buffsend[10] = (tone1 & 0xff00) >> 8;
1131                 buffsend[11] = (tone1 & 0x00ff);
1132                 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1133                                    pte);
1134         } else {
1135                 tone2 *= 8;
1136                 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1137                            sizeof(packet_send_stream_based_tone_dial_freq));
1138                 buffsend[10] = (tone1 & 0xff00) >> 8;
1139                 buffsend[11] = (tone1 & 0x00ff);
1140                 buffsend[12] = (tone2 & 0xff00) >> 8;
1141                 buffsend[13] = (tone2 & 0x00ff);
1142                 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1143                                    pte);
1144         }
1145
1146         if (unistimdebug) {
1147                 ast_verb(0, "Sending Stream Based Tone On\n");
1148         }
1149         memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1150                    sizeof(packet_send_stream_based_tone_on));
1151         send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1152 }
1153
1154 /* Positions for favorites
1155  |--------------------|
1156  |  5            2    | <-- not on screen in i2002
1157  |  4            1    |
1158  |  3            0    |
1159 */
1160
1161 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1162 static void
1163 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1164                          const char *text)
1165 {
1166         BUFFSEND;
1167         int i;
1168
1169         if (unistimdebug) {
1170                 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1171         }
1172         memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1173         buffsend[10] = pos;
1174         buffsend[24] = pos;
1175         buffsend[25] = status;
1176         i = strlen(ustmtext(text, pte));
1177         if (i > FAV_MAX_LENGTH) {
1178                 i = FAV_MAX_LENGTH;
1179         }
1180         memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1181         send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1182 }
1183
1184 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1185         send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1186         return;
1187 }
1188
1189 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1190         if (pte->device->selected != -1) {
1191                 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1192         }
1193         return;
1194 }
1195
1196 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1197 {
1198         if(d->height == 1 && num % 3 == 2) {
1199                 return 0;
1200         }
1201         return 1;
1202 }
1203
1204 static void refresh_all_favorite(struct unistimsession *pte)
1205 {
1206         unsigned char i = 0;
1207         char data[256];
1208         struct unistim_line *line;
1209         line = AST_LIST_FIRST(&pte->device->lines);
1210
1211         if (unistimdebug) {
1212                 ast_verb(0, "Refreshing all favorite\n");
1213         }
1214         for (i = 0; i < FAVNUM; i++) {
1215                 unsigned char status = pte->device->softkeyicon[i];
1216
1217                 if (!soft_key_visible(pte->device, i)) {
1218                         continue;
1219                 }
1220                 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1221                         if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1222                                 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1223                         }
1224                 }
1225
1226                 send_favorite_short(i, status, pte);
1227         }
1228 }
1229
1230 static int is_key_favorite(struct unistim_device *d, int fav)
1231 {
1232         if ((fav < 0) && (fav > 5)) {
1233                 return 0;
1234         }
1235         if (d->sline[fav]) {
1236                 return 0;
1237         }
1238         if (d->softkeynumber[fav][0] == '\0') {
1239                 return 0;
1240         }
1241         return 1;
1242 }
1243
1244 static int is_key_line(struct unistim_device *d, int fav)
1245 {
1246         if ((fav < 0) && (fav > 5)) {
1247                 return 0;
1248         }
1249         if (!d->sline[fav]) {
1250                 return 0;
1251         }
1252         if (is_key_favorite(d, fav)) {
1253                 return 0;
1254         }
1255         return 1;
1256 }
1257
1258 static int get_active_softkey(struct unistimsession *pte)
1259 {
1260         return pte->device->selected;
1261 }
1262
1263 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1264 {
1265         int i;
1266
1267         if (!is_key_line(pte->device, pte->device->selected)) {
1268                 pte->device->selected = -1;
1269         }
1270         for (i = 0; i < FAVNUM; i++) {
1271                 if (pte->device->selected != -1 && pte->device->selected != i) {
1272                         continue;
1273                 }
1274                 if (!soft_key_visible(pte->device, i)) {
1275                         continue;
1276                 }
1277                 if (pte->device->ssub[i]) {
1278                         continue;
1279                 }
1280                 if (is_key_line(pte->device, i)) {
1281                         if (name && strcmp(name, pte->device->sline[i]->name)) {
1282                                 continue;
1283                         }
1284                         if (unistimdebug) {
1285                                 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1286                         }
1287                         return i;
1288                 }
1289         }
1290         return -1;
1291 }
1292
1293
1294 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1295  * use FAV_ICON_*_BLACK constant in status parameters */
1296 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1297 {
1298         struct unistim_device *d = devices;
1299         int i;
1300         /* Update the current phone line softkey icon */
1301         if (pte->state != STATE_CLEANING) {
1302                 int softkeylinepos = get_active_softkey(pte);
1303                 if (softkeylinepos != -1) {
1304                         send_favorite_short(softkeylinepos, status, pte);
1305                 }
1306         }
1307         /* Notify other phones if we're in their bookmark */
1308         while (d) {
1309                 for (i = 0; i < FAVNUM; i++) {
1310                         if (d->sp[i] == pte->device) {  /* It's us ? */
1311                                 if (d->softkeyicon[i] != status) {      /* Avoid resending the same icon */
1312                                         d->softkeyicon[i] = status;
1313                                         if (d->session) {
1314                                                 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1315                                         }
1316                                 }
1317                         }
1318                 }
1319                 d = d->next;
1320         }
1321 }
1322
1323 static int register_extension(const struct unistimsession *pte)
1324 {
1325         struct unistim_line *line;
1326         line = AST_LIST_FIRST(&pte->device->lines);
1327         if (unistimdebug) {
1328                 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1329                                         pte->device->extension_number, pte->device->context,
1330                                         line->fullname);
1331         }
1332         return ast_add_extension(pte->device->context, 0,
1333                                                          pte->device->extension_number, 1, NULL, NULL, "Dial",
1334                                                          line->fullname, 0, "Unistim");
1335 }
1336
1337 static int unregister_extension(const struct unistimsession *pte)
1338 {
1339         if (unistimdebug) {
1340                 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1341                                         pte->device->extension_number, pte->device->context);
1342         }
1343         return ast_context_remove_extension(pte->device->context,
1344                                                                                 pte->device->extension_number, 1, "Unistim");
1345 }
1346
1347 /* Free memory allocated for a phone */
1348 static void close_client(struct unistimsession *s)
1349 {
1350         struct unistim_subchannel *sub = NULL;
1351         struct unistimsession *cur, *prev = NULL;
1352         ast_mutex_lock(&sessionlock);
1353         cur = sessions;
1354         /* Looking for the session in the linked chain */
1355         while (cur) {
1356                 if (cur == s) {
1357                         break;
1358                 }
1359                 prev = cur;
1360                 cur = cur->next;
1361         }
1362         if (cur) {                                    /* Session found ? */
1363                 if (cur->device) {            /* This session was registered ? */
1364                         s->state = STATE_CLEANING;
1365                         if (unistimdebug) {
1366                                 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1367                         }
1368                         change_favorite_icon(s, FAV_ICON_NONE);
1369                         ast_mutex_lock(&s->device->lock);
1370                         AST_LIST_LOCK(&s->device->subs);
1371                         AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1372                                 if (!sub) {
1373                                         continue;
1374                                 }
1375                                 if (sub->owner) {       /* Call in progress ? */
1376                                         if (unistimdebug) {
1377                                                 ast_verb(0, "Aborting call\n");
1378                                         }
1379                                         ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1380                                 } else {
1381                                         if (unistimdebug) {
1382                                                 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1383                                         }
1384                                         AST_LIST_REMOVE_CURRENT(list);
1385                                         unistim_free_sub(sub);
1386                                 }
1387                         }
1388                         AST_LIST_TRAVERSE_SAFE_END;
1389                         AST_LIST_UNLOCK(&s->device->subs);
1390
1391                         if (!ast_strlen_zero(s->device->extension_number)) {
1392                                 unregister_extension(s);
1393                         }
1394                         cur->device->session = NULL;
1395                         ast_mutex_unlock(&s->device->lock);
1396                 } else {
1397                         if (unistimdebug) {
1398                                 ast_verb(0, "Freeing an unregistered client\n");
1399                         }
1400                 }
1401                 if (prev) {
1402                         prev->next = cur->next;
1403                 } else {
1404                         sessions = cur->next;
1405                 }
1406                 ast_mutex_destroy(&s->lock);
1407                 ast_free(s);
1408         } else {
1409                 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1410         }
1411         ast_mutex_unlock(&sessionlock);
1412         return;
1413 }
1414
1415 /* Return 1 if the session chained link was modified */
1416 static int send_retransmit(struct unistimsession *pte)
1417 {
1418         int i;
1419
1420         ast_mutex_lock(&pte->lock);
1421         if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1422                 if (unistimdebug) {
1423                         ast_verb(0, "Too many retransmit - freeing client\n");
1424                 }
1425                 ast_mutex_unlock(&pte->lock);
1426                 close_client(pte);
1427                 return 1;
1428         }
1429         pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1430
1431         for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1432                  i < pte->last_buf_available; i++) {
1433                 if (i < 0) {
1434                         ast_log(LOG_WARNING,
1435                                         "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1436                                         pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1437                         continue;
1438                 }
1439
1440                 if (unistimdebug) {
1441                         unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1442                         unsigned short seq;
1443
1444                         seq = ntohs(sbuf[1]);
1445                         ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1446                                                 seq, pte->last_seq_ack);
1447                 }
1448                 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1449                                           &pte->sout);
1450         }
1451         ast_mutex_unlock(&pte->lock);
1452         return 0;
1453 }
1454
1455 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL  : no */
1456 static void
1457 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1458                  const char *text)
1459 {
1460         int i;
1461         BUFFSEND;
1462         if (!text) {
1463                 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1464                 return;
1465         }
1466         if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1467                 return;
1468         }
1469         if (unistimdebug) {
1470                 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1471         }
1472         memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1473         buffsend[10] = pos;
1474         buffsend[11] = inverse;
1475         i = strlen(text);
1476         if (i > TEXT_LENGTH_MAX) {
1477                 i = TEXT_LENGTH_MAX;
1478         }
1479         memcpy(buffsend + 12, text, i);
1480         send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1481 }
1482
1483 static void send_text_status(struct unistimsession *pte, const char *text)
1484 {
1485         BUFFSEND;
1486         int i;
1487         if (unistimdebug) {
1488                 ast_verb(0, "Sending status text\n");
1489         }
1490         if (pte->device) {
1491                 if (pte->device->status_method == 1) {  /* For new firmware and i2050 soft phone */
1492                         int n = strlen(text);
1493                         /* Must send individual button separately */
1494                         int j;
1495                         for (i = 0, j = 0; i < 4; i++, j += 7) {
1496                                 int pos = 0x08 + (i * 0x20);
1497                                 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1498                                            sizeof(packet_send_status2));
1499
1500                                 buffsend[9] = pos;
1501                                 memcpy(buffsend + 10, (j < n) ? (text + j) : "       ", 7);
1502                                 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1503                         }
1504                         return;
1505                 }
1506         }
1507
1508
1509         memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1510         i = strlen(text);
1511         if (i > STATUS_LENGTH_MAX) {
1512                 i = STATUS_LENGTH_MAX;
1513         }
1514         memcpy(buffsend + 10, text, i);
1515         send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1516
1517 }
1518
1519 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1520  * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1521  * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1522  * 18 = mute off, 19 mute on */
1523 static void send_led_update(struct unistimsession *pte, unsigned char led)
1524 {
1525         BUFFSEND;
1526         if (unistimdebug) {
1527                 ast_verb(0, "Sending led_update (%x)\n", led);
1528         }
1529         memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1530         buffsend[9] = led;
1531         send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1532 }
1533
1534 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1535  * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1536  * mute = MUTE_OFF, MUTE_ON */
1537 static void
1538 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1539                                  unsigned char mute)
1540 {
1541         BUFFSEND;
1542         if (unistimdebug) {
1543                 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1544                                         volume, mute);
1545         }
1546         memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1547                    sizeof(packet_send_select_output));
1548         buffsend[9] = output;
1549         if (output == OUTPUT_SPEAKER) {
1550                 volume = VOLUME_LOW_SPEAKER;
1551         } else {
1552                 volume = VOLUME_LOW;
1553         }
1554         buffsend[10] = volume;
1555         if (mute == MUTE_ON_DISCRET) {
1556                 buffsend[11] = MUTE_ON;
1557         } else {
1558                 buffsend[11] = mute;
1559         }
1560         send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1561         if (mute == MUTE_OFF) {
1562                 send_led_update(pte, 0x18);
1563         } else if (mute == MUTE_ON) {
1564                 send_led_update(pte, 0x19);
1565         }
1566         pte->device->mute = mute;
1567         if (output == OUTPUT_HANDSET) {
1568                 if (mute == MUTE_ON) {
1569                         change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1570                 } else {
1571                         change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1572                 }
1573                 send_led_update(pte, 0x08);
1574                 send_led_update(pte, 0x10);
1575         } else if (output == OUTPUT_HEADPHONE) {
1576                 if (mute == MUTE_ON) {
1577                         change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1578                 } else {
1579                         change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1580                 }
1581                 send_led_update(pte, 0x08);
1582                 send_led_update(pte, 0x11);
1583         } else if (output == OUTPUT_SPEAKER) {
1584                 send_led_update(pte, 0x10);
1585                 send_led_update(pte, 0x09);
1586                 if (pte->device->receiver_state == STATE_OFFHOOK) {
1587                         if (mute == MUTE_ON) {
1588                                 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1589                         } else {
1590                                 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1591                         }
1592                 } else {
1593                         if (mute == MUTE_ON) {
1594                                 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1595                         } else {
1596                                 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1597                         }
1598                 }
1599         } else {
1600                 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1601         }
1602         if (output != pte->device->output) {
1603                 pte->device->previous_output = pte->device->output;
1604         }
1605         pte->device->output = output;
1606 }
1607
1608 static void send_ring(struct unistimsession *pte, char volume, char style)
1609 {
1610         BUFFSEND;
1611         if (unistimdebug) {
1612                 ast_verb(0, "Sending ring packet\n");
1613         }
1614         memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1615         buffsend[24] = style + 0x10;
1616         buffsend[29] = volume * 0x10;
1617         send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1618 }
1619
1620 static void send_no_ring(struct unistimsession *pte)
1621 {
1622         BUFFSEND;
1623         if (unistimdebug) {
1624                 ast_verb(0, "Sending no ring packet\n");
1625         }
1626         memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1627         send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1628 }
1629
1630 static void send_texttitle(struct unistimsession *pte, const char *text)
1631 {
1632         BUFFSEND;
1633         int i;
1634         if (unistimdebug) {
1635                 ast_verb(0, "Sending title text\n");
1636         }
1637         memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1638         i = strlen(text);
1639         if (i > 12) {
1640                 i = 12;
1641         }
1642         memcpy(buffsend + 10, text, i);
1643         send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1644
1645 }
1646
1647 static void send_idle_clock(struct unistimsession *pte)
1648 {
1649         send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1650 }
1651
1652 static void send_date_time(struct unistimsession *pte)
1653 {
1654         BUFFSEND;
1655         struct timeval now = ast_tvnow();
1656         struct ast_tm atm = { 0, };
1657
1658         if (unistimdebug) {
1659                 ast_verb(0, "Sending Time & Date\n");
1660         }
1661         memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1662         ast_localtime(&now, &atm, NULL);
1663         buffsend[10] = (unsigned char) atm.tm_mon + 1;
1664         buffsend[11] = (unsigned char) atm.tm_mday;
1665         buffsend[12] = (unsigned char) atm.tm_hour;
1666         buffsend[13] = (unsigned char) atm.tm_min;
1667         send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1668 }
1669
1670 static void send_date_time2(struct unistimsession *pte)
1671 {
1672         BUFFSEND;
1673         struct timeval now = ast_tvnow();
1674         struct ast_tm atm = { 0, };
1675
1676         if (unistimdebug) {
1677                 ast_verb(0, "Sending Time & Date #2\n");
1678         }
1679         memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1680         ast_localtime(&now, &atm, NULL);
1681         if (pte->device) {
1682                 buffsend[9] = pte->device->datetimeformat;
1683         } else {
1684                 buffsend[9] = 61;
1685         }
1686         buffsend[14] = (unsigned char) atm.tm_mon + 1;
1687         buffsend[15] = (unsigned char) atm.tm_mday;
1688         buffsend[16] = (unsigned char) atm.tm_hour;
1689         buffsend[17] = (unsigned char) atm.tm_min;
1690         send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1691 }
1692
1693 static void send_date_time3(struct unistimsession *pte)
1694 {
1695         BUFFSEND;
1696         struct timeval now = ast_tvnow();
1697         struct ast_tm atm = { 0, };
1698
1699         if (unistimdebug) {
1700                 ast_verb(0, "Sending Time & Date #3\n");
1701         }
1702         memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1703         ast_localtime(&now, &atm, NULL);
1704         buffsend[10] = (unsigned char) atm.tm_mon + 1;
1705         buffsend[11] = (unsigned char) atm.tm_mday;
1706         buffsend[12] = (unsigned char) atm.tm_hour;
1707         buffsend[13] = (unsigned char) atm.tm_min;
1708         send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1709 }
1710
1711 static void send_blink_cursor(struct unistimsession *pte)
1712 {
1713         BUFFSEND;
1714         if (unistimdebug) {
1715                 ast_verb(0, "Sending set blink\n");
1716         }
1717         memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1718         send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1719         return;
1720 }
1721
1722 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1723 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1724 {
1725         BUFFSEND;
1726         if (unistimdebug) {
1727                 ast_verb(0, "Sending set cursor position\n");
1728         }
1729         memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1730                    sizeof(packet_send_set_pos_cursor));
1731         buffsend[11] = pos;
1732         send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1733         return;
1734 }
1735
1736 static void send_charset_update(struct unistimsession *pte, int charset)
1737 {
1738         const unsigned char* packet_send_charset;
1739         int packet_size;
1740         BUFFSEND;
1741         if (unistimdebug) {
1742                 ast_verb(0, "Sending set default charset\n");
1743         }
1744         if (charset == LANG_DEFAULT) {
1745                 charset = options_languages[find_language(pte->device->language)].encoding;
1746         }
1747         switch (charset) {
1748         case ISO_8859_2:
1749                 packet_send_charset = packet_send_charset_iso_8859_2;
1750                 packet_size = sizeof(packet_send_charset_iso_8859_2);
1751                 break;
1752         case ISO_8859_4:
1753                 packet_send_charset = packet_send_charset_iso_8859_4;
1754                 packet_size = sizeof(packet_send_charset_iso_8859_4);
1755                 break;
1756         case ISO_8859_5:
1757                 packet_send_charset = packet_send_charset_iso_8859_5;
1758                 packet_size = sizeof(packet_send_charset_iso_8859_5);
1759                 break;
1760         case ISO_2022_JP:
1761                 packet_send_charset = packet_send_charset_iso_2022_jp;
1762                 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1763                 break;
1764         case ISO_8859_1:
1765         default:
1766                 packet_send_charset = packet_send_charset_iso_8859_1;
1767                 packet_size = sizeof(packet_send_charset_iso_8859_1);
1768         }
1769         memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1770         send_client(SIZE_HEADER + packet_size, buffsend, pte);
1771         return;
1772 }
1773
1774 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1775 {
1776         BUFFSEND;
1777         if (unistimdebug) {
1778                 ast_verb(0, "ResumeConnectionWithServer received\n");
1779                 ast_verb(0, "Sending packet_send_query_mac_address\n");
1780         }
1781         memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1782                    sizeof(packet_send_query_mac_address));
1783         send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1784         return;
1785 }
1786
1787 static int unistim_register(struct unistimsession *s)
1788 {
1789         struct unistim_device *d;
1790
1791         ast_mutex_lock(&devicelock);
1792         d = devices;
1793         while (d) {
1794                 if (!strcasecmp(s->macaddr, d->id)) {
1795                         /* XXX Deal with IP authentication */
1796                         s->device = d;
1797                         d->session = s;
1798                         d->codec_number = DEFAULT_CODEC;
1799                         d->missed_call = 0;
1800                         d->receiver_state = STATE_ONHOOK;
1801                         break;
1802                 }
1803                 d = d->next;
1804         }
1805         ast_mutex_unlock(&devicelock);
1806
1807         if (!d) {
1808                 return 0;
1809         }
1810
1811         return 1;
1812 }
1813
1814 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1815 {
1816         struct ast_format_cap *tmp = src->cap;
1817         memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1818         src->cap = tmp;
1819         ast_format_cap_copy(src->cap, dst->cap);
1820 }
1821
1822 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1823 {
1824         if (!l) {
1825                 return NULL;
1826         }
1827         l->cap = ast_format_cap_destroy(l->cap);
1828         ast_free(l);
1829         return NULL;
1830 }
1831
1832 static struct unistim_line *unistim_line_alloc(void)
1833 {
1834         struct unistim_line *l;
1835         if (!(l = ast_calloc(1, sizeof(*l)))) {
1836                 return NULL;
1837         }
1838
1839         if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
1840                 ast_free(l);
1841                 return NULL;
1842         }
1843         return l;
1844 }
1845
1846 static int unistim_free_sub(struct unistim_subchannel *sub) {
1847         if (unistimdebug) {
1848                 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1849         }
1850         ast_mutex_destroy(&sub->lock);
1851         ast_free(sub);
1852         return 0;
1853 }
1854
1855 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1856 {
1857         struct unistim_subchannel *sub;
1858         if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1859                 return NULL;
1860         }
1861
1862         if (unistimdebug) {
1863                 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1864         }
1865         sub->ss_thread = AST_PTHREADT_NULL;
1866         sub->subtype = x;
1867         AST_LIST_LOCK(&d->subs);
1868         AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1869         AST_LIST_UNLOCK(&d->subs);
1870         ast_mutex_init(&sub->lock);
1871         return sub;
1872 }
1873
1874 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1875 {
1876         struct unistim_subchannel *s;
1877
1878         AST_LIST_LOCK(&d->subs);
1879         AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1880                 if (!s) {
1881                         continue;
1882                 }
1883                 if (s != sub) {
1884                         continue;
1885                 }
1886                 AST_LIST_REMOVE_CURRENT(list);
1887                 unistim_free_sub(sub);
1888         }
1889         AST_LIST_TRAVERSE_SAFE_END;
1890         AST_LIST_UNLOCK(&d->subs);
1891         return 0;
1892 }
1893
1894 static const char *subtype_tostr(const int type)
1895 {
1896         switch (type) {
1897         case SUB_REAL:
1898                 return "REAL";
1899         case SUB_ONHOLD:
1900                 return "ONHOLD";
1901         case SUB_RING:
1902                 return "RINGING";
1903         case SUB_THREEWAY:
1904                 return "THREEWAY";
1905         }
1906         return "UNKNOWN";
1907 }
1908
1909 static const char *ptestate_tostr(const int type)
1910 {
1911         switch (type) {
1912         case STATE_INIT:
1913                 return "INIT";
1914         case STATE_AUTHDENY:
1915                 return "AUTHDENY";
1916         case STATE_MAINPAGE:
1917                 return "MAINPAGE";
1918         case STATE_EXTENSION:
1919                 return "EXTENSION";
1920         case STATE_DIALPAGE:
1921                 return "DIALPAGE";
1922         case STATE_RINGING:
1923                 return "RINGING";
1924         case STATE_CALL:
1925                 return "CALL";
1926         case STATE_SELECTOPTION:
1927                 return "SELECTOPTION";
1928         case STATE_SELECTCODEC:
1929                 return "SELECTCODEC";
1930         case STATE_SELECTLANGUAGE:
1931                 return "SELECTLANGUAGE";
1932         case STATE_CLEANING:
1933                 return "CLEARING";
1934         case STATE_HISTORY:
1935                 return "HISTORY";
1936         }
1937         return "UNKNOWN";
1938 }
1939
1940 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1941 {
1942         BUFFSEND;
1943         int tmp, i = 0;
1944         char addrmac[19];
1945         int res = 0;
1946         for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1947                 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1948                 i += 2;
1949         }
1950         if (unistimdebug) {
1951                 ast_verb(0, "MAC Address received: %s\n", addrmac);
1952         }
1953         strcpy(pte->macaddr, addrmac);
1954         res = unistim_register(pte);
1955         if (!res) {
1956                 switch (autoprovisioning) {
1957                 case AUTOPROVISIONING_NO:
1958                         ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1959                         pte->state = STATE_AUTHDENY;
1960                         break;
1961                 case AUTOPROVISIONING_YES:
1962                         {
1963                                 struct unistim_device *d = NULL, *newd = NULL;
1964                                 struct unistim_line *newl = NULL, *l = NULL;
1965                                 if (unistimdebug) {
1966                                         ast_verb(0, "New phone, autoprovisioning on\n");
1967                                 }
1968                                 /* First : locate the [template] section */
1969                                 ast_mutex_lock(&devicelock);
1970                                 d = devices;
1971                                 while (d) {
1972                                         if (strcasecmp(d->name, "template")) {
1973                                                 d = d->next;
1974                                                 continue;
1975                                         }
1976                                         /* Found, cloning this entry */
1977                                         if (!(newd = ast_malloc(sizeof(*newd)))) {
1978                                                 ast_mutex_unlock(&devicelock);
1979                                                 return;
1980                                         }
1981                                         memcpy(newd, d, sizeof(*newd));
1982                                         ast_mutex_init(&newd->lock);
1983                                         newd->lines.first = NULL;
1984                                         newd->lines.last = NULL;
1985                                         AST_LIST_LOCK(&d->lines);
1986                                         AST_LIST_TRAVERSE(&d->lines, l, list) {
1987                                                 if (!(newl = unistim_line_alloc())) {
1988                                                         break;
1989                                                 }
1990                                                 unistim_line_copy(l, newl);
1991                                                 newl->parent = newd;
1992                                                 ast_copy_string(newl->name, l->name, sizeof(newl->name));
1993                                                 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1994                                                                  newl->name, newd->name);
1995                                                 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
1996
1997                                                 AST_LIST_LOCK(&newd->lines);
1998                                                 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
1999                                                 AST_LIST_UNLOCK(&newd->lines);
2000                                         }
2001                                         AST_LIST_UNLOCK(&d->lines);
2002                                         if (!newl) {
2003                                                 ast_free(newd);
2004                                                 ast_mutex_unlock(&devicelock);
2005                                         }
2006
2007                                         /* Ok, now updating some fields */
2008                                         ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2009                                         ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2010                                         if (newd->extension == EXTENSION_NONE) {
2011                                                 newd->extension = EXTENSION_ASK;
2012                                         }
2013
2014                                         newd->receiver_state = STATE_ONHOOK;
2015                                         newd->session = pte;
2016                                         newd->language[0] = '\0';
2017                                         newd->to_delete = -1;
2018                                         newd->next = NULL;
2019                                         pte->device = newd;
2020
2021                                         /* Go to the end of the linked chain */
2022                                         while (d->next) {
2023                                                 d = d->next;
2024                                         }
2025                                         d->next = newd;
2026                                         d = newd;
2027                                         break;
2028                                 }
2029                                 ast_mutex_unlock(&devicelock);
2030                                 if (!d) {
2031                                         ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2032                                         pte->state = STATE_AUTHDENY;
2033                                 }
2034                         }
2035                         break;
2036                 case AUTOPROVISIONING_TN:
2037                         pte->state = STATE_AUTHDENY;
2038                         break;
2039                 default:
2040                         ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2041                                         autoprovisioning);
2042                 }
2043         }
2044         if (pte->state != STATE_AUTHDENY) {
2045                 struct unistim_line *line;
2046                 struct unistim_subchannel *sub;
2047
2048                 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2049
2050                 AST_LIST_LOCK(&pte->device->subs);
2051                 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2052                         if (sub) {
2053                                 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2054                                 AST_LIST_REMOVE_CURRENT(list);
2055                                 ast_free(sub);
2056                         }
2057                 }
2058                 AST_LIST_TRAVERSE_SAFE_END;
2059                 AST_LIST_UNLOCK(&pte->device->subs);
2060
2061                 switch (pte->device->extension) {
2062                 case EXTENSION_NONE:
2063                         pte->state = STATE_MAINPAGE;
2064                         break;
2065                 case EXTENSION_ASK:
2066                         /* Checking if we already have an extension number */
2067                         if (ast_strlen_zero(pte->device->extension_number)) {
2068                                 pte->state = STATE_EXTENSION;
2069                         } else {
2070                                 /* Yes, because of a phone reboot. We don't ask again for the TN */
2071                                 if (register_extension(pte)) {
2072                                         pte->state = STATE_EXTENSION;
2073                                 } else {
2074                                         pte->state = STATE_MAINPAGE;
2075                                 }
2076                         }
2077                         break;
2078                 case EXTENSION_LINE:
2079                         line = AST_LIST_FIRST(&pte->device->lines);
2080                         ast_copy_string(pte->device->extension_number, line->name,
2081                                                         sizeof(pte->device->extension_number));
2082                         if (register_extension(pte)) {
2083                                 pte->state = STATE_EXTENSION;
2084                         } else {
2085                                 pte->state = STATE_MAINPAGE;
2086                         }
2087                         break;
2088                 case EXTENSION_TN:
2089                         /* If we are here, it's because of a phone reboot */
2090                         pte->state = STATE_MAINPAGE;
2091                         break;
2092                 default:
2093                         ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2094                                         pte->device->extension);
2095                         pte->state = STATE_AUTHDENY;
2096                         break;
2097                 }
2098         }
2099         if (pte->state == STATE_EXTENSION) {
2100                 if (pte->device->extension != EXTENSION_TN) {
2101                         pte->device->extension = EXTENSION_ASK;
2102                 }
2103                 pte->device->extension_number[0] = '\0';
2104         }
2105         if (unistimdebug) {
2106                 ast_verb(0, "\nSending S1\n");
2107         }
2108         memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2109         send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2110
2111         if (unistimdebug) {
2112                 ast_verb(0, "Sending query_basic_manager_04\n");
2113         }
2114         memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2115                    sizeof(packet_send_query_basic_manager_04));
2116         send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2117
2118         if (unistimdebug) {
2119                 ast_verb(0, "Sending query_basic_manager_10\n");
2120         }
2121         memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2122                    sizeof(packet_send_query_basic_manager_10));
2123         send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2124
2125         send_date_time(pte);
2126         return;
2127 }
2128
2129 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2130 {
2131         if (fwrite(&c, 1, 1, f) != 1) {
2132                 display_last_error("Unable to write history log header.");
2133                 return -1;
2134         }
2135         if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2136                 display_last_error("Unable to write history entry - date.");
2137                 return -1;
2138         }
2139         if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2140                 display_last_error("Unable to write history entry - callerid.");
2141                 return -1;
2142         }
2143         if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2144                 display_last_error("Unable to write history entry - callername.");
2145                 return -1;
2146         }
2147         return 0;
2148 }
2149
2150 static int write_history(struct unistimsession *pte, char way, char ismissed)
2151 {
2152         char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2153         char line1[TEXT_LENGTH_MAX + 1];
2154         char count = 0, *histbuf;
2155         int size;
2156         FILE *f, *f2;
2157         struct timeval now = ast_tvnow();
2158         struct ast_tm atm = { 0, };
2159
2160         if (!pte->device) {
2161                 return -1;
2162         }
2163         if (!pte->device->callhistory) {
2164                 return 0;
2165         }
2166         if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2167                 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2168                                 pte->device->name);
2169                 return -1;
2170         }
2171
2172         snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2173         if (ast_mkdir(tmp, 0770)) {
2174                 ast_log(LOG_WARNING, "Unable to create directory for history\n");
2175                 return -1;
2176         }
2177
2178         ast_localtime(&now, &atm, NULL);
2179         if (ismissed) {
2180                 if (way == 'i') {
2181                         ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2182                 } else {
2183                         ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2184                 }
2185         } else {
2186                 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2187         }
2188         snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2189                          atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2190                          atm.tm_min, atm.tm_sec, tmp2);
2191
2192         snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2193                          USTM_LOG_DIR, pte->device->name, way);
2194         if ((f = fopen(tmp, "r"))) {
2195                 struct stat bufstat;
2196
2197                 if (stat(tmp, &bufstat)) {
2198                         display_last_error("Unable to stat history log.");
2199                         fclose(f);
2200                         return -1;
2201                 }
2202                 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2203                 if (bufstat.st_size != size) {
2204                         ast_log(LOG_WARNING,
2205                                         "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2206                                         tmp, (int) bufstat.st_size, size);
2207                         fclose(f);
2208                         f = NULL;
2209                         count = 1;
2210                 }
2211         }
2212
2213         /* If we can't open the log file, we create a brand new one */
2214         if (!f) {
2215                 char c = 1;
2216                 int i;
2217
2218                 if ((errno != ENOENT) && (count == 0)) {
2219                         display_last_error("Unable to open history log.");
2220                         return -1;
2221                 }
2222                 f = fopen(tmp, "w");
2223                 if (!f) {
2224                         display_last_error("Unable to create history log.");
2225                         return -1;
2226                 }
2227                 if (write_entry_history(pte, f, c, line1)) {
2228                         fclose(f);
2229                         return -1;
2230                 }
2231                 memset(line1, ' ', TEXT_LENGTH_MAX);
2232                 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2233                         if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2234                                 display_last_error("Unable to write history entry - stuffing.");
2235                                 fclose(f);
2236                                 return -1;
2237                         }
2238                 }
2239                 if (fclose(f)) {
2240                         display_last_error("Unable to close history - creation.");
2241                 }
2242                 return 0;
2243         }
2244         /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2245         if (fread(&count, 1, 1, f) != 1) {
2246                 display_last_error("Unable to read history header.");
2247                 fclose(f);
2248                 return -1;
2249         }
2250         if (count > MAX_ENTRY_LOG) {
2251                 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2252                                 count, MAX_ENTRY_LOG);
2253                 fclose(f);
2254                 return -1;
2255         }
2256         snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2257                          USTM_LOG_DIR, pte->device->name, way);
2258         if (!(f2 = fopen(tmp2, "w"))) {
2259                 display_last_error("Unable to create temporary history log.");
2260                 fclose(f);
2261                 return -1;
2262         }
2263
2264         if (++count > MAX_ENTRY_LOG) {
2265                 count = MAX_ENTRY_LOG;
2266         }
2267         if (write_entry_history(pte, f2, count, line1)) {
2268                 fclose(f);
2269                 fclose(f2);
2270                 return -1;
2271         }
2272         size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2273         if (!(histbuf = ast_malloc(size))) {
2274                 fclose(f);
2275                 fclose(f2);
2276                 return -1;
2277         }
2278
2279         if (fread(histbuf, size, 1, f) != 1) {
2280                 ast_free(histbuf);
2281                 fclose(f);
2282                 fclose(f2);
2283                 display_last_error("Unable to read previous history entries.");
2284                 return -1;
2285         }
2286         if (fwrite(histbuf, size, 1, f2) != 1) {
2287                 ast_free(histbuf);
2288                 fclose(f);
2289                 fclose(f2);
2290                 display_last_error("Unable to write previous history entries.");
2291                 return -1;
2292         }
2293         ast_free(histbuf);
2294         if (fclose(f)) {
2295                 display_last_error("Unable to close history log.");
2296         }
2297         if (fclose(f2)) {
2298                 display_last_error("Unable to close temporary history log.");
2299         }
2300         if (unlink(tmp)) {
2301                 display_last_error("Unable to remove old history log.");
2302         }
2303         if (rename(tmp2, tmp)) {
2304                 display_last_error("Unable to rename new history log.");
2305         }
2306         return 0;
2307 }
2308
2309 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2310 {
2311         RAII_VAR(struct ast_channel *, chana, NULL, ast_channel_unref);
2312         RAII_VAR(struct ast_channel *, chanb, NULL, ast_channel_unref);
2313
2314         if (!p1->owner || !p2->owner) {
2315                 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2316                 return -1;
2317         }
2318         chana = ast_channel_ref(p1->owner);
2319         chanb = ast_channel_ref(p2->owner);
2320
2321         switch (ast_bridge_transfer_attended(chana, chanb)) {
2322         case AST_BRIDGE_TRANSFER_INVALID:
2323                 ast_log(LOG_WARNING, "Transfer failed. Invalid bridge setup\n");
2324                 break;
2325         case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
2326                 ast_log(LOG_WARNING, "Transfer not permitted\n");
2327                 break;
2328         case AST_BRIDGE_TRANSFER_FAIL:
2329                 ast_log(LOG_WARNING, "Transfer encountered internal error\n");
2330                 break;
2331         case AST_BRIDGE_TRANSFER_SUCCESS:
2332                 return 0;
2333         }
2334
2335         /* Control only reaches this point if transfer has failed */
2336         ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2337         ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2338         return -1;
2339 }
2340
2341 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2342 {
2343         char *data;
2344         int size;
2345
2346         if (type) {
2347                 data = pte->device->lst_cnm;
2348         } else {
2349                 data = pte->device->lst_cid;
2350         }
2351
2352         /* This is very nearly strncpy(), except that the remaining buffer
2353          * is padded with ' ', instead of '\0' */
2354         memset(data, ' ', TEXT_LENGTH_MAX);
2355         size = strlen(callerid);
2356         if (size > TEXT_LENGTH_MAX) {
2357                 size = TEXT_LENGTH_MAX;
2358         }
2359         memcpy(data, callerid, size);
2360 }
2361
2362 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2363 {
2364         struct unistim_subchannel *sub = NULL;
2365
2366         AST_LIST_LOCK(&device->subs);
2367         AST_LIST_TRAVERSE(&device->subs, sub, list) {
2368                 if (!sub) {
2369                         continue;
2370                 }
2371                 if (sub->subtype == type) {
2372                         break;
2373                 }
2374         }
2375         AST_LIST_UNLOCK(&device->subs);
2376
2377         return sub;
2378 }
2379
2380 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2381 {
2382         /* Silence our channel */
2383         if (!pte->device->silence_generator) {
2384                 pte->device->silence_generator =
2385                         ast_channel_start_silence_generator(sub->owner);
2386                 if (pte->device->silence_generator == NULL) {
2387                         ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2388                 } else if (unistimdebug) {
2389                         ast_verb(0, "Starting silence generator\n");
2390                 }
2391         }
2392
2393 }
2394
2395 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2396 {
2397         /* Stop the silence generator */
2398         if (pte->device->silence_generator) {
2399                 if (unistimdebug) {
2400                         ast_verb(0, "Stopping silence generator\n");
2401                 }
2402                 if (sub->owner) {
2403                         ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2404                 } else {
2405                         ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2406                 }
2407                 pte->device->silence_generator = NULL;
2408         }
2409 }
2410
2411 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2412 {
2413         if (!sub) {
2414                 return;
2415         }
2416         sub->moh = 1;
2417         sub->subtype = SUB_ONHOLD;
2418         send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2419         send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2420         send_stop_timer(pte);
2421         if (sub->owner) {
2422                 ast_queue_hold(sub->owner, NULL);
2423                 send_end_call(pte);
2424         }
2425         return;
2426 }
2427
2428 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2429 {
2430         struct unistim_subchannel *sub_real;
2431
2432         sub_real = get_sub(pte->device, SUB_REAL);
2433         if (sub_real) {
2434             sub_hold(pte, sub_real);
2435         }
2436
2437         sub->moh = 0;
2438         sub->subtype = SUB_REAL;
2439         send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2440         send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2441         send_start_timer(pte);
2442         if (sub->owner) {
2443                 ast_queue_unhold(sub->owner);
2444                 if (sub->rtp) {
2445                         send_start_rtp(sub);
2446                 }
2447         }
2448         return;
2449 }
2450
2451 static void close_call(struct unistimsession *pte)
2452 {
2453         struct unistim_subchannel *sub, *sub_transf;
2454
2455         sub = get_sub(pte->device, SUB_REAL);
2456         sub_transf = get_sub(pte->device, SUB_THREEWAY);
2457         send_stop_timer(pte);
2458         if (!sub) {
2459                 ast_log(LOG_WARNING, "Close call without sub\n");
2460                 return;
2461         }
2462         send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2463         if (sub->owner) {
2464                 sub->alreadygone = 1;
2465                 if (sub_transf) {
2466                         sub_transf->alreadygone = 1;
2467                         if (attempt_transfer(sub, sub_transf) < 0) {
2468                                 ast_verb(0, "attempt_transfer failed.\n");
2469                         }
2470                 } else {
2471                         ast_queue_hangup(sub->owner);
2472                 }
2473         } else {
2474                 if (sub_transf) {
2475                         if (sub_transf->owner) {
2476                                 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2477                         } else {
2478                                 ast_log(LOG_WARNING, "threeway sub without owner\n");
2479                         }
2480                 } else {
2481                         ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2482                                                 pte->device->name, sub->softkey);
2483                 }
2484         }
2485         change_callerid(pte, 0, pte->device->redial_number);
2486         change_callerid(pte, 1, "");
2487         write_history(pte, 'o', pte->device->missed_call);
2488         pte->device->missed_call = 0;
2489         show_main_page(pte);
2490         return;
2491 }
2492
2493 static void ignore_call(struct unistimsession *pte)
2494 {
2495         send_no_ring(pte);
2496         return;
2497 }
2498
2499 static void discard_call(struct unistimsession *pte)
2500 {
2501         struct unistim_subchannel* sub;
2502         sub = get_sub(pte->device, SUB_RING);
2503         if (!sub) {
2504             return;
2505         }
2506
2507         ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2508         return;
2509 }
2510
2511 static void *unistim_ss(void *data)
2512 {
2513         struct ast_channel *chan = data;
2514         struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2515         struct unistim_line *l = sub->parent;
2516         struct unistimsession *s = l->parent->session;
2517         int res;
2518
2519         ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2520         ast_channel_lock(chan);
2521         ast_channel_exten_set(chan, s->device->phone_number);
2522         ast_setstate(chan, AST_STATE_RING);
2523         ast_channel_unlock(chan);
2524         ast_copy_string(s->device->redial_number, s->device->phone_number,
2525                                         sizeof(s->device->redial_number));
2526         res = ast_pbx_run(chan);
2527         if (res) {
2528                 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2529                 send_tone(s, 1000, 0);
2530         }
2531         return NULL;
2532 }
2533
2534 static int find_rtp_port(struct unistim_subchannel *s)
2535 {
2536         struct unistim_subchannel *sub = NULL;
2537         int rtp_start = s->parent->parent->rtp_port;
2538         struct ast_sockaddr us_tmp;
2539         struct sockaddr_in us = { 0, };
2540
2541         AST_LIST_LOCK(&s->parent->parent->subs);
2542         AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2543                 if (!sub) {
2544                         continue;
2545                 }
2546                 if (sub->rtp) {
2547                         ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2548                         ast_sockaddr_to_sin(&us_tmp, &us);
2549                         if (htons(us.sin_port)) {
2550                                 rtp_start = htons(us.sin_port) + 1;
2551                                 break;
2552                         }
2553                 }
2554         }
2555         AST_LIST_UNLOCK(&s->parent->parent->subs);
2556         return rtp_start;
2557 }
2558
2559 static void send_start_rtp(struct unistim_subchannel *sub)
2560 {
2561         BUFFSEND;
2562
2563         int codec;
2564         struct sockaddr_in public = { 0, };
2565         struct sockaddr_in us = { 0, };
2566         struct sockaddr_in sin = { 0, };
2567         struct ast_sockaddr us_tmp;
2568         struct ast_sockaddr sin_tmp;
2569         struct unistimsession *pte;
2570
2571         ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2572         ast_sockaddr_to_sin(&us_tmp, &us);
2573         ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2574         ast_sockaddr_to_sin(&sin_tmp, &sin);
2575
2576         /* Setting up RTP of the phone */
2577         if (public_ip.sin_family == 0) {  /* NAT IP override ?   */
2578                 memcpy(&public, &us, sizeof(public));   /* No defined, using IP from recvmsg  */
2579         } else {
2580                 memcpy(&public, &public_ip, sizeof(public));    /* override  */
2581         }
2582         if (unistimdebug) {
2583                 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2584                          ast_inet_ntoa(us.sin_addr),
2585                          htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2586                 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2587                                         ast_inet_ntoa(public.sin_addr));
2588         }
2589
2590         pte = sub->parent->parent->session;
2591         codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2592         if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2593                 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2594                 if (unistimdebug) {
2595                         ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2596                 }
2597                 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2598                            sizeof(packet_send_rtp_packet_size));
2599                 buffsend[10] = (int) codec & 0xffffffffLL;
2600                 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2601         }
2602         if (unistimdebug) {
2603                 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2604         }
2605         memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2606                    sizeof(packet_send_jitter_buffer_conf));
2607         send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2608         if (pte->device->rtp_method != 0) {
2609                 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2610
2611                 if (unistimdebug) {
2612                         ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2613                 }
2614                 if (pte->device->rtp_method == 3) {
2615                         memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2616                                    sizeof(packet_send_open_audio_stream_tx3));
2617                 } else {
2618                         memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2619                                    sizeof(packet_send_open_audio_stream_tx));
2620                 }
2621                 if (pte->device->rtp_method != 2) {
2622                         memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2623                         buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2624                         buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2625                         buffsend[23] = (rtcpsin_port & 0x00ff);
2626                         buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2627                         buffsend[25] = (us.sin_port & 0xff00) >> 8;
2628                         buffsend[24] = (us.sin_port & 0x00ff);
2629                         buffsend[27] = (rtcpsin_port & 0x00ff);
2630                         buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2631                 } else {
2632                         memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2633                         buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2634                         buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2635                         buffsend[20] = (us.sin_port & 0xff00) >> 8;
2636                         buffsend[19] = (us.sin_port & 0x00ff);
2637                 }
2638                 buffsend[11] = codec; /* rx */
2639                 buffsend[12] = codec; /* tx */
2640                 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2641
2642                 if (unistimdebug) {
2643                         ast_verb(0, "Sending OpenAudioStreamRX\n");
2644                 }
2645                 if (pte->device->rtp_method == 3) {
2646                         memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2647                                    sizeof(packet_send_open_audio_stream_rx3));
2648                 } else {
2649                         memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2650                                    sizeof(packet_send_open_audio_stream_rx));
2651                 }
2652                 if (pte->device->rtp_method != 2) {
2653                         memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2654                         buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2655                         buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2656                         buffsend[23] = (rtcpsin_port & 0x00ff);
2657                         buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2658                         buffsend[25] = (us.sin_port & 0xff00) >> 8;
2659                         buffsend[24] = (us.sin_port & 0x00ff);
2660                         buffsend[27] = (rtcpsin_port & 0x00ff);
2661                         buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2662                 } else {
2663                         memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2664                         buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2665                         buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2666                         buffsend[20] = (us.sin_port & 0xff00) >> 8;
2667                         buffsend[19] = (us.sin_port & 0x00ff);
2668                 }
2669                 buffsend[11] = codec; /* rx */
2670                 buffsend[12] = codec; /* tx */
2671                 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2672         } else {
2673                 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2674
2675                 if (unistimdebug) {
2676                         ast_verb(0, "Sending packet_send_call default method\n");
2677                 }
2678
2679                 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2680                 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2681                 /* Destination port when sending RTP */
2682                 buffsend[49] = (us.sin_port & 0x00ff);
2683                 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2684                 /* Destination port when sending RTCP */
2685                 buffsend[52] = (rtcpsin_port & 0x00ff);
2686                 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2687                 /* Codec */
2688                 buffsend[40] = codec;
2689                 buffsend[41] = codec;
2690                 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2691                         buffsend[42] = 1;       /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2692                 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2693                         buffsend[42] = 1;       /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2694                 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2695                         buffsend[42] = 2;       /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2696                 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2697                         buffsend[42] = 2;       /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2698                 } else {
2699                         ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2700                                         ast_getformatname(ast_channel_readformat(sub->owner)));
2701                 }
2702                 /* Source port for transmit RTP and Destination port for receiving RTP */
2703                 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2704                 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2705                 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2706                 buffsend[48] = (rtcpsin_port & 0x00ff);
2707                 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2708         }
2709 }
2710
2711 static void start_rtp(struct unistim_subchannel *sub)
2712 {
2713         struct sockaddr_in sin = { 0, };
2714         struct sockaddr_in sout = { 0, };
2715         struct ast_sockaddr sin_tmp;
2716         struct ast_sockaddr sout_tmp;
2717
2718         /* Sanity checks */
2719         if (!sub) {
2720                 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2721                 return;
2722         }
2723         if (!sub->parent) {
2724                 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2725                 return;
2726         }
2727         if (!sub->parent->parent) {
2728                 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2729                 return;
2730         }
2731         if (!sub->parent->parent->session) {
2732                 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2733                 return;
2734         }
2735         if (!sub->owner) {
2736                 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2737                 return;
2738         }
2739         sout = sub->parent->parent->session->sout;
2740         ast_mutex_lock(&sub->lock);
2741         /* Allocate the RTP */
2742         if (unistimdebug) {
2743                 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2744         }
2745         ast_sockaddr_from_sin(&sout_tmp, &sout);
2746         sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2747         if (!sub->rtp) {
2748                 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2749                                 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2750                 ast_mutex_unlock(&sub->lock);
2751                 return;
2752         }
2753         ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2754         ast_rtp_instance_set_channel_id(sub->rtp, ast_channel_uniqueid(sub->owner));
2755         ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2756         ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2757         ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2758         ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2759
2760         /* Create the RTP connection */
2761         sin.sin_family = AF_INET;
2762         /* Setting up RTP for our side */
2763         memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2764                    sizeof(sin.sin_addr));
2765
2766         sin.sin_port = htons(find_rtp_port(sub));
2767         ast_sockaddr_from_sin(&sin_tmp, &sin);
2768         ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2769         if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2770                 struct ast_format tmpfmt;
2771                 char tmp[256];
2772                 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2773                 ast_log(LOG_WARNING,
2774                                 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2775                                 ast_getformatname(ast_channel_readformat(sub->owner)),
2776                                 ast_getformatname(&tmpfmt),
2777                                 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2778
2779                 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2780                 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2781         }
2782         send_start_rtp(sub);
2783         ast_mutex_unlock(&sub->lock);
2784 }
2785
2786 static void send_dial_tone(struct unistimsession *pte)
2787 {
2788         struct ast_tone_zone_sound *ts = NULL;
2789         struct ast_tone_zone_part tone_data;
2790         char *s = NULL;
2791         char *ind;
2792
2793         if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2794                 ind = ast_strdupa(ts->data);
2795                 s = strsep(&ind, ",");
2796                 ast_tone_zone_part_parse(s, &tone_data);
2797                 if (tone_data.modulate) {
2798                         tone_data.freq2 = 0;
2799                 }
2800                 send_tone(pte, tone_data.freq1, tone_data.freq2);
2801                 if (unistimdebug) {
2802                         ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2803                                                         pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2804                 }
2805                 ts = ast_tone_zone_sound_unref(ts);
2806         }
2807 }
2808
2809 static void show_phone_number(struct unistimsession *pte)
2810 {
2811         char tmp[TEXT_LENGTH_MAX + 1];
2812         const char *tmp_number = ustmtext("Number:", pte);
2813         int line, tmp_copy, offset = 0, i;
2814
2815         pte->device->phone_number[pte->device->size_phone_number] = '\0';
2816         if  (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2817                 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2818                 if (offset > strlen(tmp_number)) {
2819                         offset = strlen(tmp_number);
2820                 }
2821                 tmp_copy = strlen(tmp_number) - offset + 1;
2822                 if (tmp_copy > sizeof(tmp)) {
2823                         tmp_copy = sizeof(tmp);
2824                 }
2825                 memcpy(tmp, tmp_number + offset, tmp_copy);
2826         } else {
2827                 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2828         }
2829
2830         offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2831         if (pte->device->size_phone_number) {
2832                 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2833         }
2834         offset = strlen(tmp);
2835
2836         for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2837                 tmp[i] = '.';
2838         }
2839         tmp[i] = '\0';
2840
2841         line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2842         send_text(line, TEXT_NORMAL, pte, tmp);
2843         send_blink_cursor(pte);
2844         send_cursor_pos(pte, (unsigned char) (line + offset));
2845         send_led_update(pte, 0);
2846 }
2847
2848 static void handle_dial_page(struct unistimsession *pte)
2849 {
2850         pte->state = STATE_DIALPAGE;
2851         if (pte->device->call_forward[0] == -1) {
2852                 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2853                 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2854                 send_text_status(pte, ustmtext("Fwd    Cancel BackSp Erase", pte));
2855                 if (pte->device->call_forward[1] != 0) {
2856                         ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2857                                                         sizeof(pte->device->phone_number));
2858                         show_phone_number(pte);
2859                         send_led_update(pte, 0);
2860                         return;
2861                 }
2862         } else {
2863                 if ((pte->device->output == OUTPUT_HANDSET) &&
2864                         (pte->device->receiver_state == STATE_ONHOOK)) {
2865                         send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2866                 } else {
2867                         send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2868                 }
2869                 send_dial_tone(pte);
2870
2871                 if (pte->device->height > 1) {
2872                         send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2873                         send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2874                 }
2875                 if (ast_strlen_zero(pte->device->redial_number)) {
2876                         send_text_status(pte, ustmtext("Call          BackSp Erase", pte));
2877                 } else {
2878                         send_text_status(pte, ustmtext("Call   Redial BackSp Erase", pte));
2879                 }
2880         }
2881
2882         pte->device->size_phone_number = 0;
2883         pte->device->phone_number[0] = 0;
2884         show_phone_number(pte);
2885         change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2886         send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2887         pte->device->missed_call = 0;
2888         send_led_update(pte, 0);
2889         pte->device->lastmsgssent = -1;
2890         return;
2891 }
2892
2893 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2894 {
2895         struct ast_rtp_instance *rtp;
2896         int fds;
2897
2898         if (unistimdebug) {
2899                 ast_verb(0, "Swapping %p and %p\n", a, b);
2900         }
2901         if ((!a->owner) || (!b->owner)) {
2902                 ast_log(LOG_WARNING,
2903                                 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2904                                 a, a->owner, b, b->owner);
2905                 return;
2906         }
2907         rtp = a->rtp;
2908         a->rtp = b->rtp;
2909         b->rtp = rtp;
2910
2911         fds = ast_channel_fd(a->owner, 0);
2912         ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2913         ast_channel_internal_fd_set(b->owner, 0, fds);
2914
2915         fds = ast_channel_fd(a->owner, 1);
2916         ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2917         ast_channel_internal_fd_set(b->owner, 1, fds);
2918 }
2919
2920 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2921 static void transfer_call_step1(struct unistimsession *pte)
2922 {
2923         struct unistim_subchannel *sub /*, *sub_trans */;
2924         struct unistim_device *d = pte->device;
2925
2926         sub = get_sub(d, SUB_REAL);
2927         /* sub_trans = get_sub(d, SUB_THREEWAY); */
2928
2929         if (!sub || !sub->owner) {
2930                 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2931                 return;
2932         }
2933         /* Start music on hold if appropriate */
2934         if (sub->moh) {
2935                 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2936         } else {
2937                 ast_queue_hold(sub->owner, sub->parent->musicclass);
2938                 sub->moh = 1;
2939                 sub->subtype = SUB_THREEWAY;
2940         }
2941         sub_start_silence(pte, sub);
2942         handle_dial_page(pte);
2943 }
2944
2945 static void transfer_cancel_step2(struct unistimsession *pte)
2946 {
2947         struct unistim_subchannel *sub, *sub_trans;
2948         struct unistim_device *d = pte->device;
2949
2950         sub = get_sub(d, SUB_REAL);
2951         sub_trans = get_sub(d, SUB_THREEWAY);
2952
2953         if (!sub || !sub->owner) {
2954                 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2955                 return;
2956         }
2957         if (sub_trans) {
2958                 if (unistimdebug) {
2959                         ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2960                 }
2961                 if (sub->owner) {
2962                         swap_subs(sub, sub_trans);
2963                         ast_queue_unhold(sub_trans->owner);
2964                         sub_trans->moh = 0;
2965                         sub_trans->subtype = SUB_REAL;
2966                         sub->subtype = SUB_THREEWAY;
2967                         ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2968                 } else {
2969                         ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2970                 }
2971                 return;
2972         }
2973 }
2974
2975 /* From phone to PBX */
2976 static void handle_call_outgoing(struct unistimsession *s)
2977 {
2978         struct ast_channel *c;
2979         struct unistim_subchannel *sub;
2980         int softkey;
2981
2982         s->state = STATE_CALL;
2983
2984         sub = get_sub(s->device, SUB_THREEWAY);
2985         if (sub) {
2986                 /* If sub for threway call created than we use transfer behaviuor */
2987                 struct unistim_subchannel *sub_trans = NULL;
2988                 struct unistim_device *d = s->device;
2989
2990                 sub_trans = get_sub(d, SUB_REAL);
2991                 if (sub_trans) {
2992                         ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
2993                         return;
2994                 }
2995                 if (!sub->owner) {
2996                         ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
2997                         return;
2998                 }
2999
3000                 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3001                 if (!sub_trans) {
3002                         ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3003                         return;
3004                 }
3005                 sub_trans->parent = sub->parent;
3006                 sub_stop_silence(s, sub);
3007                 send_tone(s, 0, 0);
3008                 /* Make new channel */
3009                 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3010                 if (!c) {
3011                         ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3012                         return;
3013                 }
3014                 /* Swap things around between the three-way and real call */
3015                 swap_subs(sub, sub_trans);
3016                 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3017                 if (s->device->height == 1) {
3018                         send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3019                 } else {
3020                         send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3021                         send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3022                         send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3023                 }
3024                 send_text_status(s, ustmtext("TransfrCancel", s));
3025
3026                 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3027                         ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3028                         sub->ss_thread = AST_PTHREADT_NULL;
3029                         ast_hangup(c);
3030                         return;
3031                 }
3032                 if (unistimdebug) {
3033                         ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3034                                  sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
3035                 }
3036                 return;
3037         }
3038
3039         softkey = get_avail_softkey(s, NULL);
3040         if (softkey == -1) {
3041                 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
3042                 return;
3043         }
3044         sub = get_sub(s->device, SUB_REAL);
3045         if (sub) { /* have already call assigned */
3046                 sub_hold(s, sub); /* Need to put on hold */
3047         }
3048         if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
3049                 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
3050                 return;
3051         }
3052         sub->parent = s->device->sline[softkey];
3053         s->device->ssub[softkey] = sub;
3054         sub->softkey = softkey;
3055
3056         if (unistimdebug) {
3057                 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
3058         }
3059         send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3060         s->device->selected = -1;
3061         if (!sub->owner) {                    /* A call is already in progress ? */
3062                 RAII_VAR(struct ast_features_pickup_config *, pickup_cfg, NULL, ao2_cleanup);
3063                 const char *pickupexten;
3064
3065                 c = unistim_new(sub, AST_STATE_DOWN, NULL);   /* No, starting a new one */
3066                 if (!sub->rtp) { /* Need to start RTP before calling ast_pbx_run */
3067                         start_rtp(sub);
3068                 }
3069                 if (c) {
3070                         ast_channel_lock(c);
3071                         pickup_cfg = ast_get_chan_features_pickup_config(c);
3072                         if (!pickup_cfg) {
3073                                 ast_log(LOG_ERROR, "Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
3074                                 pickupexten = "";
3075                         } else {
3076                                 pickupexten = ast_strdupa(pickup_cfg->pickupexten);
3077                         }
3078                         ast_channel_unlock(c);
3079                 }
3080                 if (c && !strcmp(s->device->phone_number, pickupexten)) {
3081                         if (unistimdebug) {
3082                                 ast_verb(0, "Try to pickup in unistim_new\n");
3083                         }
3084                         send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
3085                         send_text_status(s, ustmtext("       Transf        Hangup", s));
3086                         send_start_timer(s);
3087                         if (ast_pickup_call(c)) {
3088                                 ast_log(LOG_NOTICE, "Nothing to pick up\n");
3089                                 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
3090                         } else {
3091                                 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
3092                         }
3093                         ast_hangup(c);
3094                         c = NULL;
3095                 } else if (c) {
3096                         send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3097                         send_tone(s, 0, 0); /* Dialing empty number should also stop dial tone */
3098                         if (s->device->height == 1) {
3099                                 if (strlen(s->device->phone_number) > 0) {
3100                                         send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3101                                 } else {
3102                                         send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
3103                                 }
3104                         } else {
3105                                 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
3106                                 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3107                                 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3108                         }
3109                         send_text_status(s, ustmtext("                     Hangup", s));
3110
3111                         /* start switch */
3112                         if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3113                                 ast_log(LOG_WARNING, "Unable to create switch thread\n");
3114                                 sub->ss_thread = AST_PTHREADT_NULL;
3115                                 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
3116                         }
3117                 } else
3118                         ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
3119                                         sub->parent->name, s->device->name);
3120         } else {
3121                 ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
3122         }
3123         return;
3124 }
3125
3126 /* From PBX to phone */
3127 static void handle_call_incoming(struct unistimsession *s)
3128 {
3129         struct unistim_subchannel *sub = NULL;
3130         int i;
3131
3132         s->state = STATE_CALL;
3133         s->device->missed_call = 0;
3134         send_no_ring(s);
3135         sub = get_sub(s->device, SUB_RING); /* Put other SUB_REAL call on hold */
3136         if (!sub) {
3137                 ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
3138                 return;
3139         }
3140         /* Change icons for all ringing keys */
3141         for (i = 0; i < FAVNUM; i++) {
3142                 if (!s->device->ssub[i]) { /* No sub assigned - skip */
3143                         continue;
3144                 }
3145                 if (s->device->ssub[i]->subtype == SUB_REAL) {
3146                         sub_hold(s, s->device->ssub[i]);
3147                 }
3148                 if (s->device->ssub[i] != sub) {
3149                         continue;
3150                 }
3151                 if (sub->softkey == i) { /* If softkey assigned at this moment - do not erase */
3152                         continue;
3153                 }
3154                 if (sub->softkey < 0) { /* If softkey not defined - first one used */
3155                         sub->softkey = i;
3156                         continue;
3157                 }
3158                 send_favorite_short(i, FAV_LINE_ICON, s);
3159                 s->device->ssub[i] = NULL;
3160         }
3161         if (sub->softkey < 0) {
3162                 ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
3163                 return;
3164         }
3165         send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3166         sub->parent = s->device->sline[sub->softkey];
3167         sub->subtype = SUB_REAL;
3168         if (unistimdebug) {
3169                 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
3170                                         s->device->name);
3171         }
3172         if (sub->owner) {
3173                 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
3174         }
3175         send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
3176         send_text_status(s, ustmtext("       Transf        Hangup", s));
3177         send_start_timer(s);
3178
3179         if ((s->device->output == OUTPUT_HANDSET) &&
3180                 (s->device->receiver_state == STATE_ONHOOK)) {
3181                 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
3182         } else {
3183                 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3184         }
3185         write_history(s, 'i', 0);
3186         return;
3187 }
3188
3189 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
3190 {
3191         struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
3192         struct unistim_subchannel *sub;
3193         int row, col;
3194
3195         sub = get_sub(pte->device, SUB_REAL);
3196         if (!sub || !sub->owner || sub->alreadygone) {
3197                 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
3198                 return -1;
3199         }
3200
3201         /* Send DTMF indication _before_ playing sounds */
3202         ast_queue_frame(sub->owner, &f);
3203
3204         if (unistimdebug) {
3205                 ast_verb(0, "Send Digit %c\n", digit);
3206         }
3207         row = (digit - '1') % 3;
3208         col = (digit - '1' - row) / 3;
3209         if (digit >= '1' && digit <='9') {
3210                 send_tone(pte, dtmf_row[row], dtmf_col[col]);
3211         } else if (digit >= 'A' && digit <= 'D') {
3212                 send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
3213         } else if (digit == '*') {
3214                 send_tone(pte, dtmf_row[3], dtmf_col[0]);
3215         } else if (digit == '0') {
3216                 send_tone(pte, dtmf_row[3], dtmf_col[1]);
3217         } else if (digit == '#') {
3218                 send_tone(pte, dtmf_row[3], dtmf_col[2]);
3219         } else {
3220                 send_tone(pte, 500, 2000);
3221         }
3222         usleep(150000);                  /* XXX Less than perfect, blocking an important thread is not a good idea */
3223         send_tone(pte, 0, 0);
3224         return 0;
3225 }
3226
3227 static void handle_key_fav(struct unistimsession *pte, char keycode)
3228 {
3229         int keynum = keycode - KEY_FAV0;
3230         struct unistim_subchannel *sub;
3231
3232         sub = get_sub(pte->device, SUB_REAL);
3233
3234         /* Make an action on selected favorite key */
3235         if (!pte->device->ssub[keynum]) { /* Key have no assigned call */
3236                 send_favorite_selected(FAV_LINE_ICON, pte);
3237                 if (is_key_line(pte->device, keynum)) {
3238                         if (unistimdebug) {
3239                                 ast_verb(0, "Handle line w/o sub - dialpage\n");
3240                         }
3241                         pte->device->selected = keynum;
3242                         sub_hold(pte, sub); /* Put active call on hold */
3243                         send_stop_timer(pte);
3244                         handle_dial_page(pte);
3245                 } else if (is_key_favorite(pte->device, keynum)) {
3246                         /* Put active call on hold in handle_call_outgoing function, after preparation and
3247                          checking if lines available for calling */
3248                         if (unistimdebug) {
3249                                 ast_verb(0, "Handle favorite w/o sub - dialing\n");
3250                         }
3251                         if ((pte->device->output == OUTPUT_HANDSET) &&
3252                                 (pte->device->receiver_state == STATE_ONHOOK)) {
3253                                 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3254                         } else {
3255                                 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3256                         }
3257                         key_favorite(pte, keycode);
3258                 }
3259         } else {
3260                 sub = pte->device->ssub[keynum];
3261                 /* Favicon have assigned sub, activate it and put current on hold */
3262                 if (sub->subtype == SUB_REAL) {
3263                         sub_hold(pte, sub);
3264                         show_main_page(pte);
3265                 } else if (sub->subtype == SUB_RING) {
3266                         sub->softkey = keynum;
3267                         handle_call_incoming(pte);
3268                 } else if (sub->subtype == SUB_ONHOLD) {
3269                         if (pte->state == STATE_DIALPAGE){
3270                                 send_tone(pte, 0, 0);
3271                         }
3272                         send_callerid_screen(pte, sub);
3273                         sub_unhold(pte, sub);
3274                         pte->state = STATE_CALL;
3275                 }
3276         }
3277 }
3278
3279 static void key_call(struct unistimsession *pte, char keycode)
3280 {
3281         struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
3282         struct unistim_subchannel *sub_3way = get_sub(pte->device, SUB_THREEWAY);
3283
3284         if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3285                 if (keycode == KEY_SHARP) {
3286                         keycode = '#';
3287                 } else if (keycode == KEY_STAR) {
3288                         keycode = '*';
3289                 } else {
3290                         keycode -= 0x10;
3291                 }
3292                 unistim_do_senddigit(pte, keycode);
3293                 return;
3294         }
3295         switch (keycode) {
3296         case KEY_FUNC1:
3297                 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3298                         if (sub_3way) {
3299                                 close_call(pte);
3300                         }
3301                 }
3302                 break;
3303         case KEY_FUNC2:
3304                 if (sub_3way) {
3305                         transfer_cancel_step2(pte);
3306                 } else if (ast_channel_state(sub->owner) == AST_STATE_UP) {
3307                         transfer_call_step1(pte);
3308                 }
3309                 break;
3310         case KEY_HANGUP:
3311         case KEY_FUNC4:
3312                 if (!sub_3way) {
3313                         close_call(pte);
3314                 }
3315                 break;
3316         case KEY_FAV0:
3317         case KEY_FAV1:
3318         case KEY_FAV2:
3319         case KEY_FAV3:
3320         case KEY_FAV4:
3321         case KEY_FAV5:
3322                 handle_key_fav(pte, keycode);
3323                 break;
3324         case KEY_HEADPHN:
3325                 if (pte->device->output == OUTPUT_HEADPHONE) {
3326                         send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3327                 } else {
3328                         send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
3329                 }
3330                 break;
3331         case KEY_LOUDSPK:
3332                 if (pte->device->output != OUTPUT_SPEAKER)
3333                         send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3334                 else
3335                         send_select_output(pte, pte->device->previous_output, pte->device->volume,
3336                                                          MUTE_OFF);
3337                 break;
3338         case KEY_MUTE:
3339                 if (!sub || !sub->owner) {
3340                         ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
3341                         return;
3342                 }
3343                 if (!sub->moh) {
3344                         if (pte->device->mute == MUTE_ON) {
3345                                 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3346                         } else {
3347                                 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
3348                         }
3349                         break;
3350                 }
3351                 break;
3352         case KEY_ONHOLD:
3353                 if (!sub) {
3354                         if(pte->device->ssub[pte->device->selected]) {
3355                                 sub_hold(pte, pte->device->ssub[pte->device->selected]);
3356                         }
3357                 } else {
3358                         sub_hold(pte, sub);
3359                 }
3360                 break;
3361         }
3362         return;
3363 }
3364
3365 static void key_ringing(struct unistimsession *pte, char keycode)
3366 {
3367         switch (keycode) {
3368         case KEY_FAV0:
3369         case KEY_FAV1:
3370         case KEY_FAV2:
3371         case KEY_FAV3:
3372         case KEY_FAV4:
3373         case KEY_FAV5:
3374                 handle_key_fav(pte, keycode);
3375                 break;
3376         case KEY_FUNC3:
3377                 ignore_call(pte);
3378                 break;
3379         case KEY_HANGUP:
3380         case KEY_FUNC4:
3381                 discard_call(pte);
3382                 break;
3383         case KEY_LOUDSPK:
3384                 pte->device->output = OUTPUT_SPEAKER;
3385                 handle_call_incoming(pte);
3386                 break;
3387         case KEY_HEADPHN:
3388                 pte->device->output = OUTPUT_HEADPHONE;
3389                 handle_call_incoming(pte);
3390                 break;
3391         case KEY_FUNC1:
3392                 handle_call_incoming(pte);
3393                 break;
3394         }
3395         return;
3396 }
3397
3398 static void key_favorite(struct unistimsession *pte, char keycode)
3399 {
3400         int fav = keycode - KEY_FAV0;
3401         if (!is_key_favorite(pte->device, fav)) {
3402                 ast_log(LOG_WARNING, "It's not a favorite key\n");
3403                 return;
3404         }
3405         ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
3406                                         sizeof(pte->device->phone_number));
3407         handle_call_outgoing(pte);
3408         return;
3409 }
3410
3411 static void key_dial_page(struct unistimsession *pte, char keycode)
3412 {
3413         struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
3414
3415         pte->device->nextdial = 0;
3416         if (keycode == KEY_FUNC3) {
3417                 if (pte->device->size_phone_number <= 1) {
3418                         keycode = KEY_FUNC4;
3419                 } else {
3420                         pte->device->size_phone_number -= 2;
3421                         keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
3422                 }
3423         }
3424         if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
3425                 keycode = KEY_FUNC1;
3426         }
3427         if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3428                 int i = pte->device->size_phone_number;
3429
3430                 if (pte->device->size_phone_number == 0) {
3431                         send_tone(pte, 0, 0);
3432                 }
3433                 if (keycode == KEY_SHARP) {
3434                         keycode = '#';
3435                 } else if (keycode == KEY_STAR) {
3436                         keycode = '*';
3437                 } else {
3438                         keycode -= 0x10;
3439                 }
3440                 pte->device->phone_number[i] = keycode;
3441                 pte->device->size_phone_number++;
3442                 pte->device->phone_number[i + 1] = 0;
3443                 show_phone_number(pte);
3444
3445                 if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
3446                         !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
3447                     keycode = KEY_FUNC1;
3448                 } else {
3449                         if (pte->device->interdigit_timer) {
3450                                 pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
3451                         }
3452                 }
3453         }
3454         if (keycode == KEY_FUNC4) {
3455                 pte->device->size_phone_number = 0;
3456                 show_phone_number(pte);
3457                 return;
3458         }
3459
3460         if (pte->device->call_forward[0] == -1) {
3461                 if (keycode == KEY_FUNC1) {
3462                         ast_copy_string(pte->device->call_forward, pte->device->phone_number,
3463                                                         sizeof(pte->device->call_forward));
3464                         show_main_page(pte);
3465                 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
3466                         pte->device->call_forward[0] = '\0';
3467                         send_led_update(pte, 0x08);
3468                         send_led_update(pte, 0x10);
3469                         show_main_page(pte);
3470                 }
3471                 return;
3472         }
3473         switch (keycode) {
3474         case KEY_FUNC2:
3475                 if (ast_strlen_zero(pte->device->redial_number)) {
3476                         break;
3477                 }
3478                 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
3479                                                 sizeof(pte->device->phone_number));
3480         case KEY_FUNC1:
3481                 handle_call_outgoing(pte);
3482                 break;
3483         case KEY_HANGUP:
3484                 if (sub && sub->owner) {
3485                         sub_stop_silence(pte, sub);
3486                         send_tone(pte, 0, 0);
3487                         ast_queue_unhold(sub->owner);
3488                         sub->moh = 0;
3489                         sub->subtype = SUB_REAL;
3490                         pte->state = STATE_CALL;
3491
3492                         send_text_status(pte, ustmtext("       Transf        Hangup", pte));
3493                         send_callerid_screen(pte, sub);
3494                 } else {
3495                         send_led_update(pte, 0x08);
3496                         send_led_update(pte, 0x10);
3497                         show_main_page(pte);
3498                 }
3499                 break;
3500         case KEY_FAV0:
3501         case KEY_FAV1:
3502         case KEY_FAV2:
3503         case KEY_FAV3:
3504         case KEY_FAV4:
3505         case KEY_FAV5:
3506                 send_favorite_selected(FAV_LINE_ICON, pte);
3507                 pte->device->selected = -1;
3508                 handle_key_fav(pte, keycode);
3509                 break;
3510         case KEY_LOUDSPK:
3511                 if (pte->device->output == OUTPUT_SPEAKER) {
3512                         if (pte->device->receiver_state == STATE_OFFHOOK) {
3513                                 send_select_output(pte, pte->device->previous_output, pte->device->volume,
3514                                                                  MUTE_OFF);
3515                         } else {
3516                                 show_main_page(pte);
3517                         }
3518                 } else {
3519                         send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
3520                 }
3521                 break;
3522         case KEY_HEADPHN:
3523                 if (pte->device->output == OUTPUT_HEADPHONE) {
3524                         if (pte->device->receiver_state == STATE_OFFHOOK) {
3525                                 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
3526