Wed Jan 8 2020 09:49:45

Asterisk developer's documentation


chan_unistim.c
Go to the documentation of this file.
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: 413586 $")
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/event.h"
67 #include "asterisk/rtp_engine.h"
68 #include "asterisk/netsock.h"
69 #include "asterisk/acl.h"
70 #include "asterisk/callerid.h"
71 #include "asterisk/cli.h"
72 #include "asterisk/app.h"
73 #include "asterisk/musiconhold.h"
74 #include "asterisk/causes.h"
75 #include "asterisk/indications.h"
76 
77 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
78 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
79 
80 #define DEFAULTCONTEXT "default"
81 #define DEFAULTCALLERID "Unknown"
82 #define DEFAULTCALLERNAME " "
83 #define DEFAULTHEIGHT 3
84 #define USTM_LOG_DIR "unistimHistory"
85 
86 /*! Size of the transmit buffer */
87 #define MAX_BUF_SIZE 64
88 /*! Number of slots for the transmit queue */
89 #define MAX_BUF_NUMBER 50
90 /*! Try x times before removing the phone */
91 #define NB_MAX_RETRANSMIT 8
92 /*! Nb of milliseconds waited when no events are scheduled */
93 #define IDLE_WAIT 1000
94 /*! Wait x milliseconds before resending a packet */
95 #define RETRANSMIT_TIMER 2000
96 /*! How often the mailbox is checked for new messages */
97 #define TIMER_MWI 10000
98 /*! Not used */
99 #define DEFAULT_CODEC 0x00
100 #define SIZE_PAGE 4096
101 #define DEVICE_NAME_LEN 16
102 #define AST_CONFIG_MAX_PATH 255
103 #define MAX_ENTRY_LOG 30
104 
105 #define SUB_REAL 0
106 #define SUB_THREEWAY 1
107 #define MAX_SUBS 2
108 
114 };
115 
117  /*! Do not create an extension into the default dialplan */
119  /*! Prompt user for an extension number and register it */
121  /*! Register an extension with the line=> value */
123  /*! Used with AUTOPROVISIONING_TN */
125 };
126 #define OUTPUT_HANDSET 0xC0
127 #define OUTPUT_HEADPHONE 0xC1
128 #define OUTPUT_SPEAKER 0xC2
129 
130 #define VOLUME_LOW 0x01
131 #define VOLUME_LOW_SPEAKER 0x03
132 #define VOLUME_NORMAL 0x02
133 #define VOLUME_INSANELY_LOUD 0x07
134 
135 #define MUTE_OFF 0x00
136 #define MUTE_ON 0xFF
137 #define MUTE_ON_DISCRET 0xCE
138 
139 #define SIZE_HEADER 6
140 #define SIZE_MAC_ADDR 17
141 #define TEXT_LENGTH_MAX 24
142 #define TEXT_LINE0 0x00
143 #define TEXT_LINE1 0x20
144 #define TEXT_LINE2 0x40
145 #define TEXT_NORMAL 0x05
146 #define TEXT_INVERSE 0x25
147 #define STATUS_LENGTH_MAX 28
148 
149 #define FAV_ICON_NONE 0x00
150 #define FAV_ICON_ONHOOK_BLACK 0x20
151 #define FAV_ICON_ONHOOK_WHITE 0x21
152 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
153 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
154 #define FAV_ICON_OFFHOOK_BLACK 0x24
155 #define FAV_ICON_OFFHOOK_WHITE 0x25
156 #define FAV_ICON_ONHOLD_BLACK 0x26
157 #define FAV_ICON_ONHOLD_WHITE 0x27
158 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
159 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
160 #define FAV_ICON_PHONE_BLACK 0x2A
161 #define FAV_ICON_PHONE_WHITE 0x2B
162 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
163 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
164 #define FAV_ICON_HEADPHONES 0x2E
165 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
166 #define FAV_ICON_HOME 0x30
167 #define FAV_ICON_CITY 0x31
168 #define FAV_ICON_SHARP 0x32
169 #define FAV_ICON_PAGER 0x33
170 #define FAV_ICON_CALL_CENTER 0x34
171 #define FAV_ICON_FAX 0x35
172 #define FAV_ICON_MAILBOX 0x36
173 #define FAV_ICON_REFLECT 0x37
174 #define FAV_ICON_COMPUTER 0x38
175 #define FAV_ICON_FORWARD 0x39
176 #define FAV_ICON_LOCKED 0x3A
177 #define FAV_ICON_TRASH 0x3B
178 #define FAV_ICON_INBOX 0x3C
179 #define FAV_ICON_OUTBOX 0x3D
180 #define FAV_ICON_MEETING 0x3E
181 #define FAV_ICON_BOX 0x3F
182 
183 #define FAV_BLINK_FAST 0x20
184 #define FAV_BLINK_SLOW 0x40
185 
186 #define FAV_MAX_LENGTH 0x0A
187 
188 static void dummy(char *unused, ...)
189 {
190  return;
191 }
192 
193 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
194  * \note Values shown here match the defaults shown in unistim.conf.sample */
196 {
197  .flags = 0,
198  .max_size = 200,
199  .resync_threshold = 1000,
200  .impl = "fixed",
201  .target_extra = 40,
202 };
204 
205 
206 /* #define DUMP_PACKET 1 */
207 /* #define DEBUG_TIMER ast_verbose */
208 
209 #define DEBUG_TIMER dummy
210 /*! Enable verbose output. can also be set with the CLI */
211 static int unistimdebug = 0;
212 static int unistim_port;
214 static int unistim_keepalive;
215 static int unistimsock = -1;
216 
217 static struct {
218  unsigned int tos;
219  unsigned int tos_audio;
220  unsigned int cos;
221  unsigned int cos_audio;
222 } qos = { 0, 0, 0, 0 };
223 
224 static struct io_context *io;
225 static struct sched_context *sched;
226 static struct sockaddr_in public_ip = { 0, };
227 /*! give the IP address for the last packet received */
228 static struct sockaddr_in address_from;
229 /*! size of the sockaddr_in (in WSARecvFrom) */
230 static unsigned int size_addr_from = sizeof(address_from);
231 /*! Receive buffer address */
232 static unsigned char *buff;
233 static int unistim_reloading = 0;
236 static int usecnt = 0;
237 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
238 
239 /*! This is the thread for the monitor which checks for input on the channels
240  * which are not currently in use. */
242 
243 /*! Protect the monitoring thread, so only one process can kill or start it, and not
244  * when it's doing something critical. */
246 /*! Protect the session list */
248 /*! Protect the device list */
250 
262 };
263 
267 };
268 
269 enum phone_key {
270  KEY_0 = 0x40,
271  KEY_1 = 0x41,
272  KEY_2 = 0x42,
273  KEY_3 = 0x43,
274  KEY_4 = 0x44,
275  KEY_5 = 0x45,
276  KEY_6 = 0x46,
277  KEY_7 = 0x47,
278  KEY_8 = 0x48,
279  KEY_9 = 0x49,
280  KEY_STAR = 0x4a,
281  KEY_SHARP = 0x4b,
282  KEY_UP = 0x4c,
283  KEY_DOWN = 0x4d,
284  KEY_RIGHT = 0x4e,
285  KEY_LEFT = 0x4f,
286  KEY_QUIT = 0x50,
287  KEY_COPY = 0x51,
288  KEY_FUNC1 = 0x54,
289  KEY_FUNC2 = 0x55,
290  KEY_FUNC3 = 0x56,
291  KEY_FUNC4 = 0x57,
292  KEY_ONHOLD = 0x5b,
293  KEY_HANGUP = 0x5c,
294  KEY_MUTE = 0x5d,
295  KEY_HEADPHN = 0x5e,
296  KEY_LOUDSPK = 0x5f,
297  KEY_FAV0 = 0x60,
298  KEY_FAV1 = 0x61,
299  KEY_FAV2 = 0x62,
300  KEY_FAV3 = 0x63,
301  KEY_FAV4 = 0x64,
302  KEY_FAV5 = 0x65,
303  KEY_COMPUTR = 0x7b,
304  KEY_CONF = 0x7c,
305  KEY_SNDHIST = 0x7d,
306  KEY_RCVHIST = 0x7e,
307  KEY_INDEX = 0x7f
308 };
309 
311  char country[3];
312  int freq1;
313  int freq2;
314 };
315 
316 static const struct tone_zone_unistim frequency[] = {
317  {"us", 350, 440},
318  {"fr", 440, 0},
319  {"au", 413, 438},
320  {"nl", 425, 0},
321  {"uk", 350, 440},
322  {"fi", 425, 0},
323  {"es", 425, 0},
324  {"jp", 400, 0},
325  {"no", 425, 0},
326  {"at", 420, 0},
327  {"nz", 400, 0},
328  {"tw", 350, 440},
329  {"cl", 400, 0},
330  {"se", 425, 0},
331  {"be", 425, 0},
332  {"sg", 425, 0},
333  {"il", 414, 0},
334  {"br", 425, 0},
335  {"hu", 425, 0},
336  {"lt", 425, 0},
337  {"pl", 425, 0},
338  {"za", 400, 0},
339  {"pt", 425, 0},
340  {"ee", 425, 0},
341  {"mx", 425, 0},
342  {"in", 400, 0},
343  {"de", 425, 0},
344  {"ch", 425, 0},
345  {"dk", 425, 0},
346  {"cn", 450, 0},
347  {"--", 0, 0}
348 };
349 
350 struct wsabuf {
351  u_long len;
352  unsigned char *buf;
353 };
354 
355 struct systemtime {
356  unsigned short w_year;
357  unsigned short w_month;
358  unsigned short w_day_of_week;
359  unsigned short w_day;
360  unsigned short w_hour;
361  unsigned short w_minute;
362  unsigned short w_second;
363  unsigned short w_milliseconds;
364 };
365 
368  /*! SUBS_REAL or SUBS_THREEWAY */
369  unsigned int subtype;
370  /*! Asterisk channel used by the subchannel */
372  /*! Unistim line */
374  /*! RTP handle */
378  char ringstyle;
379 };
380 
381 /*!
382  * \todo Convert to stringfields
383  */
384 struct unistim_line {
386  /*! Like 200 */
387  char name[80];
388  /*! Like USTM/200\@black */
389  char fullname[80];
390  /*! pointer to our current connection, channel... */
392  /*! Extension where to start */
394  /*! Context to start in */
396  /*! Language for asterisk sounds */
398  /*! CallerID Number */
400  /*! Mailbox for MWI */
402  /*! Used by MWI */
404  /*! Used by MWI */
405  time_t nextmsgcheck;
406  /*! MusicOnHold class */
408  /*! Call group */
409  unsigned int callgroup;
410  /*! Pickup group */
411  unsigned int pickupgroup;
412  /*! Account code (for billing) */
413  char accountcode[80];
414  /*! AMA flags (for billing) */
415  int amaflags;
416  /*! Codec supported */
418  /*! Parkinglot */
422 };
423 
424 /*!
425  * \brief A device containing one or more lines
426  */
427 static struct unistim_device {
428  int receiver_state; /*!< state of the receiver (see ReceiverState) */
429  int size_phone_number; /*!< size of the phone number */
430  char phone_number[16]; /*!< the phone number entered by the user */
431  char redial_number[16]; /*!< the last phone number entered by the user */
432  int phone_current; /*!< Number of the current phone */
433  int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
434  char id[18]; /*!< mac address of the current phone in ascii */
435  char name[DEVICE_NAME_LEN]; /*!< name of the device */
436  int softkeylinepos; /*!< position of the line softkey (default 0) */
437  char softkeylabel[6][11]; /*!< soft key label */
438  char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
439  char softkeyicon[6]; /*!< icon number */
440  char softkeydevice[6][16]; /*!< name of the device monitored */
441  struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
442  int height; /*!< The number of lines the phone can display */
443  char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
444  char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
445  char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
446  char titledefault[13]; /*!< title (text before date/time) */
447  char datetimeformat; /*!< format used for displaying time/date */
448  char contrast; /*!< contrast */
449  char country[3]; /*!< country used for dial tone frequency */
450  struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
451  char ringvolume; /*!< Ring volume */
452  char ringstyle; /*!< Ring melody */
453  int rtp_port; /*!< RTP port used by the phone */
454  int rtp_method; /*!< Select the unistim data used to establish a RTP session */
455  int status_method; /*!< Select the unistim packet used for sending status text */
456  char codec_number; /*!< The current codec used to make calls */
457  int missed_call; /*!< Number of call unanswered */
458  int callhistory; /*!< Allowed to record call history */
459  char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
460  char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
461  char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
462  int output; /*!< Handset, headphone or speaker */
463  int previous_output; /*!< Previous output */
464  int volume; /*!< Default volume */
465  int mute; /*!< Mute mode */
466  int moh; /*!< Music on hold in progress */
467  int nat; /*!< Used by the obscure ast_rtp_setnat */
468  enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
469  char extension_number[11]; /*!< Extension number entered by the user */
470  char to_delete; /*!< Used in reload */
471  time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
474  struct ast_ha *ha;
477 } *devices = NULL;
478 
479 static struct unistimsession {
481  struct sockaddr_in sin; /*!< IP address of the phone */
482  struct sockaddr_in sout; /*!< IP address of server */
483  int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
484  unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
485  unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
486  unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
487  unsigned long tick_next_ping; /*!< time for the next ping */
488  int last_buf_available; /*!< number of a free slot */
489  int nb_retransmit; /*!< number of retransmition */
490  int state; /*!< state of the phone (see phone_state) */
491  int size_buff_entry; /*!< size of the buffer used to enter datas */
492  char buff_entry[16]; /*!< Buffer for temporary datas */
493  char macaddr[18]; /*!< mac adress of the phone (not always available) */
494  struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
495  unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
498 } *sessions = NULL;
499 
500 /*!
501  * \page Unistim datagram formats
502  *
503  * Format of datagrams :
504  * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
505  * byte 2 : sequence number (high part)
506  * byte 3 : sequence number (low part)
507  * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
508  * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
509  */
510 
511 static const unsigned char packet_rcv_discovery[] =
512  { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
513 static const unsigned char packet_send_discovery_ack[] =
514  { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
515 
516 static const unsigned char packet_recv_firm_version[] =
517  { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
518 static const unsigned char packet_recv_pressed_key[] =
519  { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
520 static const unsigned char packet_recv_pick_up[] =
521  { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
522 static const unsigned char packet_recv_hangup[] =
523  { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
524 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
525 
526 /*! TransportAdapter */
527 static const unsigned char packet_recv_resume_connection_with_server[] =
528  { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
529 static const unsigned char packet_recv_mac_addr[] =
530  { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
531 
532 static const unsigned char packet_send_date_time3[] =
533  { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
534 /*Minutes */ 0x08, 0x32
535 };
536 static const unsigned char packet_send_date_time[] =
537  { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
538 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
539  0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
540  0x05, 0x12, 0x00, 0x78
541 };
542 
543 static const unsigned char packet_send_no_ring[] =
544  { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
545 static const unsigned char packet_send_s4[] =
546  { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
547 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
548  0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
549  0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
550  0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
551 };
552 static const unsigned char packet_send_call[] =
553  { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
554  0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
555  0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
556  0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
557  0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
558  /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
559  0x16, 0x66
560 };
561 static const unsigned char packet_send_stream_based_tone_off[] =
562  { 0x16, 0x05, 0x1c, 0x00, 0x00 };
563 
564 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
565 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
566 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
567 static const unsigned char packet_send_stream_based_tone_on[] =
568  { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
569 static const unsigned char packet_send_stream_based_tone_single_freq[] =
570  { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
571 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
572  { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
573 static const unsigned char packet_send_select_output[] =
574  { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
575 static const unsigned char packet_send_ring[] =
576  { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
577  0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
578  0x20, 0x16, 0x04, 0x10, 0x00
579 };
580 static const unsigned char packet_send_end_call[] =
581  { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
582 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
583  0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
584 };
585 static const unsigned char packet_send_s9[] =
586  { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
587 0x00 };
588 static const unsigned char packet_send_rtp_packet_size[] =
589  { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
590 static const unsigned char packet_send_jitter_buffer_conf[] =
591  { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
592 /* early packet resync 2 bytes */ 0x3e, 0x80,
593  0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
594 };
595 
596 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
597 static unsigned char packet_send_StreamBasedToneCad[] =
598  { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
599 static const unsigned char packet_send_open_audio_stream_rx[] =
600  { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
601 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
602  0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
603 };
604 static const unsigned char packet_send_open_audio_stream_tx[] =
605  { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
606 0x0e, 0x01, /* Local port */ 0x14, 0x50,
607  0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
608 };
609 
610 static const unsigned char packet_send_open_audio_stream_rx3[] =
611  { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
612 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
613 /* RTCP Port */ 0x14,
614  0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
615  0x69, 0x05
616 };
617 static const unsigned char packet_send_open_audio_stream_tx3[] =
618  { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
619 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
620  /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
621  /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
622 };
623 
624 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
625 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
626 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
627  0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
628 };
629 static const unsigned char packet_send_Contrast[] =
630  { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
631 static const unsigned char packet_send_StartTimer[] =
632  { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
633 0x65 };
634 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
635 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
636 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
637 static const unsigned char packet_send_set_pos_cursor[] =
638  { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
639 
640 /*static unsigned char packet_send_MonthLabelsDownload[] =
641  { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
642 static const unsigned char packet_send_favorite[] =
643  { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
644 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
645  0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
646 };
647 static const unsigned char packet_send_title[] =
648  { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
649 0x20, 0x20, 0x20, 0x20 /*end_text */ };
650 static const unsigned char packet_send_text[] =
651  { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
652 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
653  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
654  /*end_text */ 0x17, 0x04, 0x10, 0x87
655 };
656 static const unsigned char packet_send_status[] =
657  { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
658 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
659  0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
660 };
661 static const unsigned char packet_send_status2[] =
662  { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
663 0x20, 0x20, 0x20 /* end_text */ };
664 
665 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
666 
667 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
668 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
669 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
670 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
671 
672 static unsigned char packet_send_ping[] =
673  { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
674 
675 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
676 
677 static const char tdesc[] = "UNISTIM Channel Driver";
678 static const char channel_type[] = "USTM";
679 
680 /*! Protos */
681 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
682 static int load_module(void);
683 static int reload(void);
684 static int unload_module(void);
685 static int reload_config(void);
686 static void show_main_page(struct unistimsession *pte);
687 static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor,
688  void *data, int *cause);
689 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
690 static int unistim_hangup(struct ast_channel *ast);
691 static int unistim_answer(struct ast_channel *ast);
692 static struct ast_frame *unistim_read(struct ast_channel *ast);
693 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
694 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
695  size_t datalen);
696 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
697 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
698 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
699  unsigned int duration);
700 static int unistim_sendtext(struct ast_channel *ast, const char *text);
701 
702 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
703  char *line1);
704 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
705 
706 static const struct ast_channel_tech unistim_tech = {
707  .type = channel_type,
708  .description = tdesc,
709  .capabilities = CAPABILITY,
711  .requester = unistim_request,
712  .call = unistim_call,
713  .hangup = unistim_hangup,
714  .answer = unistim_answer,
715  .read = unistim_read,
716  .write = unistim_write,
717  .indicate = unistim_indicate,
718  .fixup = unistim_fixup,
719  .send_digit_begin = unistim_senddigit_begin,
720  .send_digit_end = unistim_senddigit_end,
721  .send_text = unistim_sendtext,
722  .bridge = ast_rtp_instance_bridge,
723 };
724 
725 static void display_last_error(const char *sz_msg)
726 {
727  time_t cur_time;
728 
729  time(&cur_time);
730 
731  /* Display the error message */
732  ast_log(LOG_WARNING, "%s %s : (%d) %s\n", ctime(&cur_time), sz_msg, errno,
733  strerror(errno));
734 }
735 
736 static unsigned int get_tick_count(void)
737 {
738  struct timeval now = ast_tvnow();
739 
740  return (now.tv_sec * 1000) + (now.tv_usec / 1000);
741 }
742 
743 /* Send data to a phone without retransmit nor buffering */
744 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
745  const struct sockaddr_in *addr_ourip)
746 {
747 #ifdef HAVE_PKTINFO
748  struct iovec msg_iov;
749  struct msghdr msg;
750  char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
751  struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
752  struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
753 
754  /* cast this to a non-const pointer, since the sendmsg() API
755  * does not provide read-only and write-only flavors of the
756  * structures used for its arguments, but in this case we know
757  * the data will not be modified
758  */
759  msg_iov.iov_base = (char *) data;
760  msg_iov.iov_len = size;
761 
762  msg.msg_name = addr_to; /* optional address */
763  msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
764  msg.msg_iov = &msg_iov; /* scatter/gather array */
765  msg.msg_iovlen = 1; /* # elements in msg_iov */
766  msg.msg_control = ip_msg; /* ancillary data */
767  msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
768  msg.msg_flags = 0; /* flags on received message */
769 
770  ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
771  ip_msg->cmsg_level = IPPROTO_IP;
772  ip_msg->cmsg_type = IP_PKTINFO;
773  pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
774  pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
775  /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
776 
777 #ifdef DUMP_PACKET
778  if (unistimdebug) {
779  int tmp;
780  char iabuf[INET_ADDRSTRLEN];
781  char iabuf2[INET_ADDRSTRLEN];
782  ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
783  ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
784  ast_inet_ntoa(addr_to->sin_addr));
785  for (tmp = 0; tmp < size; tmp++)
786  ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
787  ast_verb(0, "\n******************************************\n");
788 
789  }
790 #endif
791 
792  if (sendmsg(unistimsock, &msg, 0) == -1)
793  display_last_error("Error sending datas");
794 #else
795  if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
796  == -1)
797  display_last_error("Error sending datas");
798 #endif
799 }
800 
801 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
802 {
803  unsigned int tick;
804  int buf_pos;
805  unsigned short seq = ntohs(++pte->seq_server);
806 
807  ast_mutex_lock(&pte->lock);
808  buf_pos = pte->last_buf_available;
809 
810  if (buf_pos >= MAX_BUF_NUMBER) {
811  ast_log(LOG_WARNING, "Error : send queue overflow\n");
812  ast_mutex_unlock(&pte->lock);
813  return;
814  }
815  memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
816  pte->wsabufsend[buf_pos].len = size;
817  memcpy(pte->wsabufsend[buf_pos].buf, data, size);
818 
819  tick = get_tick_count();
820  pte->timeout = tick + RETRANSMIT_TIMER;
821 
822 /*#ifdef DUMP_PACKET */
823  if (unistimdebug)
824  ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", (unsigned)pte->seq_server, buf_pos);
825 /*#endif */
826  send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
827  &(pte->sout));
828  pte->last_buf_available++;
829  ast_mutex_unlock(&pte->lock);
830 }
831 
832 static void send_ping(struct unistimsession *pte)
833 {
834  BUFFSEND;
835  if (unistimdebug)
836  ast_verb(6, "Sending ping\n");
838  memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
839  send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
840 }
841 
842 static int get_to_address(int fd, struct sockaddr_in *toAddr)
843 {
844 #ifdef HAVE_PKTINFO
845  int err;
846  struct msghdr msg;
847  struct {
848  struct cmsghdr cm;
849  int len;
850  struct in_addr address;
851  } ip_msg;
852 
853  /* Zero out the structures before we use them */
854  /* This sets several key values to NULL */
855  memset(&msg, 0, sizeof(msg));
856  memset(&ip_msg, 0, sizeof(ip_msg));
857 
858  /* Initialize the message structure */
859  msg.msg_control = &ip_msg;
860  msg.msg_controllen = sizeof(ip_msg);
861  /* Get info about the incoming packet */
862  err = recvmsg(fd, &msg, MSG_PEEK);
863  if (err == -1)
864  ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
865  memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
866  return err;
867 #else
868  memcpy(&toAddr, &public_ip, sizeof(&toAddr));
869  return 0;
870 #endif
871 }
872 
873 /* Allocate memory & initialize structures for a new phone */
874 /* addr_from : ip address of the phone */
875 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
876 {
877  int tmp;
878  struct unistimsession *s;
879 
880  if (!(s = ast_calloc(1, sizeof(*s))))
881  return NULL;
882 
883  memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
884  get_to_address(unistimsock, &s->sout);
885  s->sout.sin_family = AF_INET;
886  if (unistimdebug) {
887  ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
888  ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
889  }
890  ast_mutex_init(&s->lock);
892  s->next = sessions;
893  sessions = s;
894 
896  s->seq_phone = (short) 0x0000;
897  s->seq_server = (short) 0x0000;
898  s->last_seq_ack = (short) 0x000;
899  s->last_buf_available = 0;
900  s->nb_retransmit = 0;
901  s->state = STATE_INIT;
903  /* Initialize struct wsabuf */
904  for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
905  s->wsabufsend[tmp].buf = s->buf[tmp];
906  }
908  return s;
909 }
910 
911 static void send_end_call(struct unistimsession *pte)
912 {
913  BUFFSEND;
914  if (unistimdebug)
915  ast_verb(0, "Sending end call\n");
916  memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
917  send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
918 }
919 
920 static void set_ping_timer(struct unistimsession *pte)
921 {
922  unsigned int tick = 0; /* XXX what is this for, anyways */
923 
924  pte->timeout = pte->tick_next_ping;
925  DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
926  return;
927 }
928 
929 /* Checking if our send queue is empty,
930  * if true, setting up a timer for keepalive */
931 static void check_send_queue(struct unistimsession *pte)
932 {
933  /* Check if our send queue contained only one element */
934  if (pte->last_buf_available == 1) {
935  if (unistimdebug)
936  ast_verb(6, "Our single packet was ACKed.\n");
937  pte->last_buf_available--;
938  set_ping_timer(pte);
939  return;
940  }
941  /* Check if this ACK catch up our latest packet */
942  else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
943  if (unistimdebug)
944  ast_verb(6, "Our send queue is completely ACKed.\n");
945  pte->last_buf_available = 0; /* Purge the send queue */
946  set_ping_timer(pte);
947  return;
948  }
949  if (unistimdebug)
950  ast_verb(6, "We still have packets in our send queue\n");
951  return;
952 }
953 
954 static void send_start_timer(struct unistimsession *pte)
955 {
956  BUFFSEND;
957  if (unistimdebug)
958  ast_verb(0, "Sending start timer\n");
959  memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
960  send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
961 }
962 
963 static void send_stop_timer(struct unistimsession *pte)
964 {
965  BUFFSEND;
966  if (unistimdebug)
967  ast_verb(0, "Sending stop timer\n");
968  memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
969  send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
970 }
971 
972 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
973 {
974  BUFFSEND;
975  if (unistimdebug)
976  ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, (unsigned)status);
977  memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
978  buffsend[9] = pos;
979  buffsend[10] = status;
980  send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
981 }
982 
983 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
984 {
985  BUFFSEND;
986  if (!tone1) {
987  if (unistimdebug)
988  ast_verb(0, "Sending Stream Based Tone Off\n");
989  memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
990  sizeof(packet_send_stream_based_tone_off));
991  send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
992  return;
993  }
994  /* Since most of the world use a continuous tone, it's useless
995  if (unistimdebug)
996  ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
997  memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
998  send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
999  if (unistimdebug)
1000  ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1001  tone1 *= 8;
1002  if (!tone2) {
1003  memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1004  sizeof(packet_send_stream_based_tone_single_freq));
1005  buffsend[10] = (tone1 & 0xff00) >> 8;
1006  buffsend[11] = (tone1 & 0x00ff);
1007  send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1008  pte);
1009  } else {
1010  tone2 *= 8;
1011  memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1012  sizeof(packet_send_stream_based_tone_dial_freq));
1013  buffsend[10] = (tone1 & 0xff00) >> 8;
1014  buffsend[11] = (tone1 & 0x00ff);
1015  buffsend[12] = (tone2 & 0xff00) >> 8;
1016  buffsend[13] = (tone2 & 0x00ff);
1017  send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1018  pte);
1019  }
1020 
1021  if (unistimdebug)
1022  ast_verb(0, "Sending Stream Based Tone On\n");
1023  memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1024  sizeof(packet_send_stream_based_tone_on));
1025  send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1026 }
1027 
1028 /* Positions for favorites
1029  |--------------------|
1030  | 5 2 |
1031  | 4 1 |
1032  | 3 0 |
1033 */
1034 
1035 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1036 static void
1037 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1038  const char *text)
1039 {
1040  BUFFSEND;
1041  int i;
1042 
1043  if (unistimdebug)
1044  ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, (unsigned)status);
1045  memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1046  buffsend[10] = pos;
1047  buffsend[24] = pos;
1048  buffsend[25] = status;
1049  i = strlen(text);
1050  if (i > FAV_MAX_LENGTH)
1051  i = FAV_MAX_LENGTH;
1052  memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
1053  send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1054 }
1055 
1056 static void refresh_all_favorite(struct unistimsession *pte)
1057 {
1058  int i = 0;
1059 
1060  if (unistimdebug)
1061  ast_verb(0, "Refreshing all favorite\n");
1062  for (i = 0; i < 6; i++) {
1063  if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
1064  (pte->device->softkeylinepos != i))
1065  send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
1066  pte->device->softkeylabel[i]);
1067  else
1068  send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
1069  pte->device->softkeylabel[i]);
1070 
1071  }
1072 }
1073 
1074 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1075  * use FAV_ICON_*_BLACK constant in status parameters */
1076 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1077 {
1078  struct unistim_device *d = devices;
1079  int i;
1080  /* Update the current phone */
1081  if (pte->state != STATE_CLEANING)
1082  send_favorite(pte->device->softkeylinepos, status, pte,
1083  pte->device->softkeylabel[pte->device->softkeylinepos]);
1084  /* Notify other phones if we're in their bookmark */
1085  while (d) {
1086  for (i = 0; i < 6; i++) {
1087  if (d->sp[i] == pte->device) { /* It's us ? */
1088  if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1089  d->softkeyicon[i] = status;
1090  if (d->session)
1091  send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1092  }
1093  }
1094  }
1095  d = d->next;
1096  }
1097 }
1098 
1099 static int RegisterExtension(const struct unistimsession *pte)
1100 {
1101  if (unistimdebug)
1102  ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1103  pte->device->extension_number, pte->device->lines->context,
1104  pte->device->lines->fullname);
1105  return ast_add_extension(pte->device->lines->context, 0,
1106  pte->device->extension_number, 1, NULL, NULL, "Dial",
1107  pte->device->lines->fullname, 0, "Unistim");
1108 }
1109 
1110 static int UnregisterExtension(const struct unistimsession *pte)
1111 {
1112  if (unistimdebug)
1113  ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1114  pte->device->extension_number, pte->device->lines->context);
1116  pte->device->extension_number, 1, "Unistim");
1117 }
1118 
1119 /* Free memory allocated for a phone */
1120 static void close_client(struct unistimsession *s)
1121 {
1122  struct unistim_subchannel *sub;
1123  struct unistimsession *cur, *prev = NULL;
1125  cur = sessions;
1126  /* Looking for the session in the linked chain */
1127  while (cur) {
1128  if (cur == s)
1129  break;
1130  prev = cur;
1131  cur = cur->next;
1132  }
1133  if (cur) { /* Session found ? */
1134  if (cur->device) { /* This session was registered ? */
1135  s->state = STATE_CLEANING;
1136  if (unistimdebug)
1137  ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
1138  s, s->device, s->device->lines,
1139  s->device->lines->subs[SUB_REAL]);
1141  sub = s->device->lines->subs[SUB_REAL];
1142  if (sub) {
1143  if (sub->owner) { /* Call in progress ? */
1144  if (unistimdebug)
1145  ast_verb(0, "Aborting call\n");
1147  }
1148  } else
1149  ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
1152  cur->device->session = NULL;
1153  } else {
1154  if (unistimdebug)
1155  ast_verb(0, "Freeing an unregistered client\n");
1156  }
1157  if (prev)
1158  prev->next = cur->next;
1159  else
1160  sessions = cur->next;
1161  ast_mutex_destroy(&s->lock);
1162  ast_free(s);
1163  } else
1164  ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1166  return;
1167 }
1168 
1169 /* Return 1 if the session chained link was modified */
1170 static int send_retransmit(struct unistimsession *pte)
1171 {
1172  int i;
1173 
1174  ast_mutex_lock(&pte->lock);
1175  if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1176  if (unistimdebug)
1177  ast_verb(0, "Too many retransmit - freeing client\n");
1178  ast_mutex_unlock(&pte->lock);
1179  close_client(pte);
1180  return 1;
1181  }
1183 
1184  for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1185  i < pte->last_buf_available; i++) {
1186  if (i < 0) {
1188  "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1189  pte->last_buf_available, (unsigned)pte->seq_server, (unsigned)pte->last_seq_ack);
1190  continue;
1191  }
1192 
1193  if (unistimdebug) {
1194  unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1195  unsigned short seq;
1196 
1197  seq = ntohs(sbuf[1]);
1198  ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1199  (unsigned)seq, (unsigned)pte->last_seq_ack);
1200  }
1201  send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1202  &pte->sout);
1203  }
1204  ast_mutex_unlock(&pte->lock);
1205  return 0;
1206 }
1207 
1208 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1209 static void
1210 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1211  const char *text)
1212 {
1213  int i;
1214  BUFFSEND;
1215  if (unistimdebug)
1216  ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1217  memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1218  buffsend[10] = pos;
1219  buffsend[11] = inverse;
1220  i = strlen(text);
1221  if (i > TEXT_LENGTH_MAX)
1222  i = TEXT_LENGTH_MAX;
1223  memcpy(buffsend + 12, text, i);
1224  send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1225 }
1226 
1227 static void send_text_status(struct unistimsession *pte, const char *text)
1228 {
1229  BUFFSEND;
1230  int i;
1231  if (unistimdebug)
1232  ast_verb(0, "Sending status text\n");
1233  if (pte->device) {
1234  if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1235  int n = strlen(text);
1236  /* Must send individual button separately */
1237  int j;
1238  for (i = 0, j = 0; i < 4; i++, j += 7) {
1239  int pos = 0x08 + (i * 0x20);
1240  memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1241  sizeof(packet_send_status2));
1242 
1243  buffsend[9] = pos;
1244  memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1245  send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1246  }
1247  return;
1248  }
1249  }
1250 
1251 
1252  memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1253  i = strlen(text);
1254  if (i > STATUS_LENGTH_MAX)
1255  i = STATUS_LENGTH_MAX;
1256  memcpy(buffsend + 10, text, i);
1257  send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1258 
1259 }
1260 
1261 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1262  * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1263  * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1264  * 18 = mute off, 19 mute on */
1265 static void send_led_update(struct unistimsession *pte, unsigned char led)
1266 {
1267  BUFFSEND;
1268  if (unistimdebug)
1269  ast_verb(0, "Sending led_update (%x)\n", (unsigned)led);
1270  memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1271  buffsend[9] = led;
1272  send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1273 }
1274 
1275 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1276  * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1277  * mute = MUTE_OFF, MUTE_ON */
1278 static void
1279 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1280  unsigned char mute)
1281 {
1282  BUFFSEND;
1283  if (unistimdebug)
1284  ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", (unsigned)output,
1285  (unsigned)volume, (unsigned)mute);
1286  memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1287  sizeof(packet_send_select_output));
1288  buffsend[9] = output;
1289  if (output == OUTPUT_SPEAKER)
1290  volume = VOLUME_LOW_SPEAKER;
1291  else
1292  volume = VOLUME_LOW;
1293  buffsend[10] = volume;
1294  if (mute == MUTE_ON_DISCRET)
1295  buffsend[11] = MUTE_ON;
1296  else
1297  buffsend[11] = mute;
1298  send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1299  if (mute == MUTE_OFF)
1300  send_led_update(pte, 0x18);
1301  else if (mute == MUTE_ON)
1302  send_led_update(pte, 0x19);
1303  pte->device->mute = mute;
1304  if (output == OUTPUT_HANDSET) {
1305  if (mute == MUTE_ON)
1307  else
1309  send_led_update(pte, 0x08);
1310  send_led_update(pte, 0x10);
1311  } else if (output == OUTPUT_HEADPHONE) {
1312  if (mute == MUTE_ON)
1314  else
1316  send_led_update(pte, 0x08);
1317  send_led_update(pte, 0x11);
1318  } else if (output == OUTPUT_SPEAKER) {
1319  send_led_update(pte, 0x10);
1320  send_led_update(pte, 0x09);
1321  if (pte->device->receiver_state == STATE_OFFHOOK) {
1322  if (mute == MUTE_ON)
1324  else
1326  } else {
1327  if (mute == MUTE_ON)
1329  else
1331  }
1332  } else
1333  ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1334  if (output != pte->device->output)
1335  pte->device->previous_output = pte->device->output;
1336  pte->device->output = output;
1337 }
1338 
1339 static void send_ring(struct unistimsession *pte, char volume, char style)
1340 {
1341  BUFFSEND;
1342  if (unistimdebug)
1343  ast_verb(0, "Sending ring packet\n");
1344  memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1345  buffsend[24] = style + 0x10;
1346  buffsend[29] = volume * 0x10;
1347  send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1348 }
1349 
1350 static void send_no_ring(struct unistimsession *pte)
1351 {
1352  BUFFSEND;
1353  if (unistimdebug)
1354  ast_verb(0, "Sending no ring packet\n");
1355  memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1356  send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1357 }
1358 
1359 static void send_texttitle(struct unistimsession *pte, const char *text)
1360 {
1361  BUFFSEND;
1362  int i;
1363  if (unistimdebug)
1364  ast_verb(0, "Sending title text\n");
1365  memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1366  i = strlen(text);
1367  if (i > 12)
1368  i = 12;
1369  memcpy(buffsend + 10, text, i);
1370  send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1371 
1372 }
1373 
1374 static void send_date_time(struct unistimsession *pte)
1375 {
1376  BUFFSEND;
1377  struct timeval now = ast_tvnow();
1378  struct ast_tm atm = { 0, };
1379 
1380  if (unistimdebug)
1381  ast_verb(0, "Sending Time & Date\n");
1382  memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1383  ast_localtime(&now, &atm, NULL);
1384  buffsend[10] = (unsigned char) atm.tm_mon + 1;
1385  buffsend[11] = (unsigned char) atm.tm_mday;
1386  buffsend[12] = (unsigned char) atm.tm_hour;
1387  buffsend[13] = (unsigned char) atm.tm_min;
1388  send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1389 }
1390 
1391 static void send_date_time2(struct unistimsession *pte)
1392 {
1393  BUFFSEND;
1394  struct timeval now = ast_tvnow();
1395  struct ast_tm atm = { 0, };
1396 
1397  if (unistimdebug)
1398  ast_verb(0, "Sending Time & Date #2\n");
1399  memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1400  ast_localtime(&now, &atm, NULL);
1401  if (pte->device)
1402  buffsend[9] = pte->device->datetimeformat;
1403  else
1404  buffsend[9] = 61;
1405  buffsend[14] = (unsigned char) atm.tm_mon + 1;
1406  buffsend[15] = (unsigned char) atm.tm_mday;
1407  buffsend[16] = (unsigned char) atm.tm_hour;
1408  buffsend[17] = (unsigned char) atm.tm_min;
1409  send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1410 }
1411 
1412 static void send_date_time3(struct unistimsession *pte)
1413 {
1414  BUFFSEND;
1415  struct timeval now = ast_tvnow();
1416  struct ast_tm atm = { 0, };
1417 
1418  if (unistimdebug)
1419  ast_verb(0, "Sending Time & Date #3\n");
1420  memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1421  ast_localtime(&now, &atm, NULL);
1422  buffsend[10] = (unsigned char) atm.tm_mon + 1;
1423  buffsend[11] = (unsigned char) atm.tm_mday;
1424  buffsend[12] = (unsigned char) atm.tm_hour;
1425  buffsend[13] = (unsigned char) atm.tm_min;
1426  send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1427 }
1428 
1429 static void send_blink_cursor(struct unistimsession *pte)
1430 {
1431  BUFFSEND;
1432  if (unistimdebug)
1433  ast_verb(0, "Sending set blink\n");
1434  memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1435  send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1436  return;
1437 }
1438 
1439 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1440 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1441 {
1442  BUFFSEND;
1443  if (unistimdebug)
1444  ast_verb(0, "Sending set cursor position\n");
1445  memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1446  sizeof(packet_send_set_pos_cursor));
1447  buffsend[11] = pos;
1448  send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1449  return;
1450 }
1451 
1453 {
1454  BUFFSEND;
1455  if (unistimdebug) {
1456  ast_verb(0, "ResumeConnectionWithServer received\n");
1457  ast_verb(0, "Sending packet_send_query_mac_address\n");
1458  }
1459  memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1460  sizeof(packet_send_query_mac_address));
1461  send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1462  return;
1463 }
1464 
1465 static int unistim_register(struct unistimsession *s)
1466 {
1467  struct unistim_device *d;
1468 
1470  d = devices;
1471  while (d) {
1472  if (!strcasecmp(s->macaddr, d->id)) {
1473  /* XXX Deal with IP authentication */
1474  s->device = d;
1475  d->session = s;
1477  d->pos_fav = 0;
1478  d->missed_call = 0;
1480  break;
1481  }
1482  d = d->next;
1483  }
1485 
1486  if (!d)
1487  return 0;
1488 
1489  return 1;
1490 }
1491 
1492 static int alloc_sub(struct unistim_line *l, int x)
1493 {
1494  struct unistim_subchannel *sub;
1495  if (!(sub = ast_calloc(1, sizeof(*sub))))
1496  return 0;
1497 
1498  if (unistimdebug)
1499  ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
1500  sub->parent = l;
1501  sub->subtype = x;
1502  l->subs[x] = sub;
1503  ast_mutex_init(&sub->lock);
1504  return 1;
1505 }
1506 
1507 static int unalloc_sub(struct unistim_line *p, int x)
1508 {
1509  if (!x) {
1510  ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
1511  p->parent->name);
1512  return -1;
1513  }
1514  if (unistimdebug)
1515  ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
1516  p->parent->name);
1517  ast_mutex_destroy(&p->lock);
1518  ast_free(p->subs[x]);
1519  p->subs[x] = 0;
1520  return 0;
1521 }
1522 
1523 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1524 {
1525  BUFFSEND;
1526  int tmp, i = 0;
1527  char addrmac[19];
1528  int res = 0;
1529  for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1530  sprintf(&addrmac[i], "%.2x", (unsigned) buf[tmp]);
1531  i += 2;
1532  }
1533  if (unistimdebug) {
1534  ast_verb(0, "Mac Address received : %s\n", addrmac);
1535  }
1536  strcpy(pte->macaddr, addrmac);
1537  res = unistim_register(pte);
1538  if (!res) {
1539  switch (autoprovisioning) {
1540  case AUTOPROVISIONING_NO:
1541  ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1542  pte->state = STATE_AUTHDENY;
1543  break;
1544  case AUTOPROVISIONING_YES:
1545  {
1546  struct unistim_device *d, *newd;
1547  struct unistim_line *newl;
1548  if (unistimdebug)
1549  ast_verb(0, "New phone, autoprovisioning on\n");
1550  /* First : locate the [template] section */
1552  d = devices;
1553  while (d) {
1554  if (!strcasecmp(d->name, "template")) {
1555  /* Found, cloning this entry */
1556  if (!(newd = ast_malloc(sizeof(*newd)))) {
1558  return;
1559  }
1560 
1561  memcpy(newd, d, sizeof(*newd));
1562  if (!(newl = ast_malloc(sizeof(*newl)))) {
1563  ast_free(newd);
1565  return;
1566  }
1567 
1568  memcpy(newl, d->lines, sizeof(*newl));
1569  if (!alloc_sub(newl, SUB_REAL)) {
1570  ast_free(newd);
1571  ast_free(newl);
1573  return;
1574  }
1575  /* Ok, now updating some fields */
1576  ast_copy_string(newd->id, addrmac, sizeof(newd->id));
1577  ast_copy_string(newd->name, addrmac, sizeof(newd->name));
1578  if (newd->extension == EXTENSION_NONE)
1579  newd->extension = EXTENSION_ASK;
1580  newd->lines = newl;
1581  newd->receiver_state = STATE_ONHOOK;
1582  newd->session = pte;
1583  newd->to_delete = -1;
1584  pte->device = newd;
1585  newd->next = NULL;
1586  newl->parent = newd;
1587  strcpy(newl->name, d->lines->name);
1588  snprintf(d->lines->name, sizeof(d->lines->name), "%d",
1589  atoi(d->lines->name) + 1);
1590  snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1591  newl->name, newd->name);
1592  /* Go to the end of the linked chain */
1593  while (d->next) {
1594  d = d->next;
1595  }
1596  d->next = newd;
1597  d = newd;
1598  break;
1599  }
1600  d = d->next;
1601  }
1603  if (!d) {
1604  ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
1605  pte->state = STATE_AUTHDENY;
1606  }
1607  }
1608  break;
1609  case AUTOPROVISIONING_TN:
1610  pte->state = STATE_AUTHDENY;
1611  break;
1612  case AUTOPROVISIONING_DB:
1614  "Autoprovisioning with database is not yet functional\n");
1615  break;
1616  default:
1617  ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %u\n",
1618  autoprovisioning);
1619  }
1620  }
1621  if (pte->state != STATE_AUTHDENY) {
1622  ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
1623  switch (pte->device->extension) {
1624  case EXTENSION_NONE:
1625  pte->state = STATE_MAINPAGE;
1626  break;
1627  case EXTENSION_ASK:
1628  /* Checking if we already have an extension number */
1630  pte->state = STATE_EXTENSION;
1631  else {
1632  /* Yes, because of a phone reboot. We don't ask again for the TN */
1633  if (RegisterExtension(pte))
1634  pte->state = STATE_EXTENSION;
1635  else
1636  pte->state = STATE_MAINPAGE;
1637  }
1638  break;
1639  case EXTENSION_LINE:
1641  sizeof(pte->device->extension_number));
1642  if (RegisterExtension(pte))
1643  pte->state = STATE_EXTENSION;
1644  else
1645  pte->state = STATE_MAINPAGE;
1646  break;
1647  case EXTENSION_TN:
1648  /* If we are here, it's because of a phone reboot */
1649  pte->state = STATE_MAINPAGE;
1650  break;
1651  default:
1652  ast_log(LOG_WARNING, "Internal error, extension value unknown : %u\n",
1653  pte->device->extension);
1654  pte->state = STATE_AUTHDENY;
1655  break;
1656  }
1657  }
1658  if (pte->state == STATE_EXTENSION) {
1659  if (pte->device->extension != EXTENSION_TN)
1660  pte->device->extension = EXTENSION_ASK;
1661  pte->device->extension_number[0] = '\0';
1662  }
1663  if (unistimdebug)
1664  ast_verb(0, "\nSending S1\n");
1665  memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
1666  send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
1667 
1668  if (unistimdebug)
1669  ast_verb(0, "Sending query_basic_manager_04\n");
1670  memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
1671  sizeof(packet_send_query_basic_manager_04));
1672  send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
1673 
1674  if (unistimdebug)
1675  ast_verb(0, "Sending query_basic_manager_10\n");
1676  memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
1677  sizeof(packet_send_query_basic_manager_10));
1678  send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
1679 
1680  send_date_time(pte);
1681  return;
1682 }
1683 
1684 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
1685 {
1686  if (fwrite(&c, 1, 1, f) != 1) {
1687  display_last_error("Unable to write history log header.");
1688  return -1;
1689  }
1690  if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1691  display_last_error("Unable to write history entry - date.");
1692  return -1;
1693  }
1694  if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
1695  display_last_error("Unable to write history entry - callerid.");
1696  return -1;
1697  }
1698  if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
1699  display_last_error("Unable to write history entry - callername.");
1700  return -1;
1701  }
1702  return 0;
1703 }
1704 
1705 static int write_history(struct unistimsession *pte, char way, char ismissed)
1706 {
1707  char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
1708  char line1[TEXT_LENGTH_MAX + 1];
1709  char count = 0, *histbuf;
1710  int size;
1711  FILE *f, *f2;
1712  struct timeval now = ast_tvnow();
1713  struct ast_tm atm = { 0, };
1714 
1715  if (!pte->device)
1716  return -1;
1717  if (!pte->device->callhistory)
1718  return 0;
1719  if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
1720  ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
1721  pte->device->name);
1722  return -1;
1723  }
1724 
1725  snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
1726  if (ast_mkdir(tmp, 0770)) {
1727  if (errno != EEXIST) {
1728  display_last_error("Unable to create directory for history");
1729  return -1;
1730  }
1731  }
1732 
1733  ast_localtime(&now, &atm, NULL);
1734  if (ismissed) {
1735  if (way == 'i')
1736  strcpy(tmp2, "Miss");
1737  else
1738  strcpy(tmp2, "Fail");
1739  } else
1740  strcpy(tmp2, "Answ");
1741  snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
1742  atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
1743  atm.tm_min, atm.tm_sec, tmp2);
1744 
1745  snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
1746  USTM_LOG_DIR, pte->device->name, way);
1747  if ((f = fopen(tmp, "r"))) {
1748  struct stat bufstat;
1749 
1750  if (stat(tmp, &bufstat)) {
1751  display_last_error("Unable to stat history log.");
1752  fclose(f);
1753  return -1;
1754  }
1755  size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
1756  if (bufstat.st_size != size) {
1758  "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1759  tmp, (int) bufstat.st_size, size);
1760  fclose(f);
1761  f = NULL;
1762  count = 1;
1763  }
1764  }
1765 
1766  /* If we can't open the log file, we create a brand new one */
1767  if (!f) {
1768  char c = 1;
1769  int i;
1770 
1771  if ((errno != ENOENT) && (count == 0)) {
1772  display_last_error("Unable to open history log.");
1773  return -1;
1774  }
1775  f = fopen(tmp, "w");
1776  if (!f) {
1777  display_last_error("Unable to create history log.");
1778  return -1;
1779  }
1780  if (write_entry_history(pte, f, c, line1)) {
1781  fclose(f);
1782  return -1;
1783  }
1784  memset(line1, ' ', TEXT_LENGTH_MAX);
1785  for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
1786  if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
1787  display_last_error("Unable to write history entry - stuffing.");
1788  fclose(f);
1789  return -1;
1790  }
1791  }
1792  if (fclose(f))
1793  display_last_error("Unable to close history - creation.");
1794  return 0;
1795  }
1796  /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1797  if (fread(&count, 1, 1, f) != 1) {
1798  display_last_error("Unable to read history header.");
1799  fclose(f);
1800  return -1;
1801  }
1802  if (count > MAX_ENTRY_LOG) {
1803  ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
1804  count, MAX_ENTRY_LOG);
1805  fclose(f);
1806  return -1;
1807  }
1808  snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
1809  USTM_LOG_DIR, pte->device->name, way);
1810  if (!(f2 = fopen(tmp2, "w"))) {
1811  display_last_error("Unable to create temporary history log.");
1812  fclose(f);
1813  return -1;
1814  }
1815 
1816  if (++count > MAX_ENTRY_LOG)
1817  count = MAX_ENTRY_LOG;
1818 
1819  if (write_entry_history(pte, f2, count, line1)) {
1820  fclose(f);
1821  fclose(f2);
1822  return -1;
1823  }
1824 
1825  size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
1826  if (!(histbuf = ast_malloc(size))) {
1827  fclose(f);
1828  fclose(f2);
1829  return -1;
1830  }
1831 
1832  if (fread(histbuf, size, 1, f) != 1) {
1833  ast_free(histbuf);
1834  fclose(f);
1835  fclose(f2);
1836  display_last_error("Unable to read previous history entries.");
1837  return -1;
1838  }
1839  if (fwrite(histbuf, size, 1, f2) != 1) {
1840  ast_free(histbuf);
1841  fclose(f);
1842  fclose(f2);
1843  display_last_error("Unable to write previous history entries.");
1844  return -1;
1845  }
1846  ast_free(histbuf);
1847  if (fclose(f))
1848  display_last_error("Unable to close history log.");
1849  if (fclose(f2))
1850  display_last_error("Unable to close temporary history log.");
1851  if (unlink(tmp))
1852  display_last_error("Unable to remove old history log.");
1853  if (rename(tmp2, tmp))
1854  display_last_error("Unable to rename new history log.");
1855  return 0;
1856 }
1857 
1858 static void cancel_dial(struct unistimsession *pte)
1859 {
1860  send_no_ring(pte);
1861  pte->device->missed_call++;
1862  write_history(pte, 'i', 1);
1863  show_main_page(pte);
1864  return;
1865 }
1866 
1867 static void swap_subs(struct unistim_line *p, int a, int b)
1868 {
1869 /* struct ast_channel *towner; */
1870  struct ast_rtp_instance *rtp;
1871  int fds;
1872 
1873  if (unistimdebug)
1874  ast_verb(0, "Swapping %d and %d\n", a, b);
1875 
1876  if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
1878  "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1879  a, p->subs[a]->owner, b, p->subs[b]->owner);
1880  return;
1881  }
1882  rtp = p->subs[a]->rtp;
1883  p->subs[a]->rtp = p->subs[b]->rtp;
1884  p->subs[b]->rtp = rtp;
1885 
1886  fds = p->subs[a]->owner->fds[0];
1887  p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
1888  p->subs[b]->owner->fds[0] = fds;
1889 
1890  fds = p->subs[a]->owner->fds[1];
1891  p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
1892  p->subs[b]->owner->fds[1] = fds;
1893 }
1894 
1895 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
1896 {
1897  int res = 0;
1898  struct ast_channel
1899  *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
1900  NULL, *peerb = NULL, *peerc = NULL;
1901 
1902  if (!p1->owner || !p2->owner) {
1903  ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
1904  return -1;
1905  }
1906  chana = p1->owner;
1907  chanb = p2->owner;
1908  bridgea = ast_bridged_channel(chana);
1909  bridgeb = ast_bridged_channel(chanb);
1910 
1911  if (bridgea) {
1912  peera = chana;
1913  peerb = chanb;
1914  peerc = bridgea;
1915  } else if (bridgeb) {
1916  peera = chanb;
1917  peerb = chana;
1918  peerc = bridgeb;
1919  }
1920 
1921  if (peera && peerb && peerc && (peerb != peerc)) {
1922  /*ast_quiet_chan(peera);
1923  ast_quiet_chan(peerb);
1924  ast_quiet_chan(peerc);
1925  ast_quiet_chan(peerd); */
1926 
1927  if (ast_channel_masquerade(peerb, peerc)) {
1928  ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
1929  peerc->name);
1930  res = -1;
1931  }
1932  return res;
1933  } else {
1935  "Transfer attempted with no appropriate bridged calls to transfer\n");
1936  if (chana)
1938  if (chanb)
1940  return -1;
1941  }
1942  return 0;
1943 }
1944 
1945 void change_callerid(struct unistimsession *pte, int type, char *callerid)
1946 {
1947  char *data;
1948  int size;
1949 
1950  if (type)
1951  data = pte->device->lst_cnm;
1952  else
1953  data = pte->device->lst_cid;
1954 
1955  /* This is very nearly strncpy(), except that the remaining buffer
1956  * is padded with ' ', instead of '\0' */
1957  memset(data, ' ', TEXT_LENGTH_MAX);
1958  size = strlen(callerid);
1959  if (size > TEXT_LENGTH_MAX)
1960  size = TEXT_LENGTH_MAX;
1961  memcpy(data, callerid, size);
1962 }
1963 
1964 static void close_call(struct unistimsession *pte)
1965 {
1966  struct unistim_subchannel *sub;
1967  struct unistim_line *l = pte->device->lines;
1968 
1969  sub = pte->device->lines->subs[SUB_REAL];
1970  send_stop_timer(pte);
1971  if (sub->owner) {
1972  sub->alreadygone = 1;
1973  if (l->subs[SUB_THREEWAY]) {
1974  l->subs[SUB_THREEWAY]->alreadygone = 1;
1975  if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
1976  ast_verb(0, "attempt_transfer failed.\n");
1977  } else
1978  ast_queue_hangup(sub->owner);
1979  } else {
1980  if (l->subs[SUB_THREEWAY]) {
1981  if (l->subs[SUB_THREEWAY]->owner)
1983  else
1984  ast_log(LOG_WARNING, "threeway sub without owner\n");
1985  } else
1986  ast_verb(0, "USTM(%s@%s-%u) channel already destroyed\n", sub->parent->name,
1987  sub->parent->parent->name, sub->subtype);
1988  }
1989  change_callerid(pte, 0, pte->device->redial_number);
1990  change_callerid(pte, 1, "");
1991  write_history(pte, 'o', pte->device->missed_call);
1992  pte->device->missed_call = 0;
1993  show_main_page(pte);
1994  return;
1995 }
1996 
1997 static void IgnoreCall(struct unistimsession *pte)
1998 {
1999  send_no_ring(pte);
2000  return;
2001 }
2002 
2003 static void *unistim_ss(void *data)
2004 {
2005  struct ast_channel *chan = data;
2006  struct unistim_subchannel *sub = chan->tech_pvt;
2007  struct unistim_line *l = sub->parent;
2008  struct unistimsession *s = l->parent->session;
2009  int res;
2010 
2011  ast_verb(3, "Starting switch on '%s@%s-%u' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
2012  ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
2014  sizeof(s->device->redial_number));
2016  res = ast_pbx_run(chan);
2017  if (res) {
2018  ast_log(LOG_WARNING, "PBX exited non-zero\n");
2019  send_tone(s, 1000, 0);;
2020  }
2021  return NULL;
2022 }
2023 
2024 static void start_rtp(struct unistim_subchannel *sub)
2025 {
2026  BUFFSEND;
2027  struct sockaddr_in us = { 0, };
2028  struct sockaddr_in public = { 0, };
2029  struct sockaddr_in sin = { 0, };
2030  format_t codec;
2031  struct sockaddr_in sout = { 0, };
2032  struct ast_sockaddr us_tmp;
2033  struct ast_sockaddr sin_tmp;
2034  struct ast_sockaddr sout_tmp;
2035 
2036  /* Sanity checks */
2037  if (!sub) {
2038  ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2039  return;
2040  }
2041  if (!sub->parent) {
2042  ast_log(LOG_WARNING, "start_rtp with a null line !\n");
2043  return;
2044  }
2045  if (!sub->parent->parent) {
2046  ast_log(LOG_WARNING, "start_rtp with a null device !\n");
2047  return;
2048  }
2049  if (!sub->parent->parent->session) {
2050  ast_log(LOG_WARNING, "start_rtp with a null session !\n");
2051  return;
2052  }
2053  sout = sub->parent->parent->session->sout;
2054 
2055  ast_mutex_lock(&sub->lock);
2056  /* Allocate the RTP */
2057  if (unistimdebug)
2058  ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2059  ast_sockaddr_from_sin(&sout_tmp, &sout);
2060  sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2061  if (!sub->rtp) {
2062  ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2063  strerror(errno), ast_inet_ntoa(sout.sin_addr));
2064  ast_mutex_unlock(&sub->lock);
2065  return;
2066  }
2068  if (sub->owner) {
2069  sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
2070  sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
2071  }
2072  ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2074 
2075  /* Create the RTP connection */
2076  ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2077  ast_sockaddr_to_sin(&us_tmp, &us);
2078  sin.sin_family = AF_INET;
2079  /* Setting up RTP for our side */
2080  memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2081  sizeof(sin.sin_addr));
2082  sin.sin_port = htons(sub->parent->parent->rtp_port);
2083  ast_sockaddr_from_sin(&sin_tmp, &sin);
2084  ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2085  if (!(sub->owner->nativeformats & sub->owner->readformat)) {
2086  format_t fmt;
2087  char tmp[256];
2088  fmt = ast_best_codec(sub->owner->nativeformats);
2090  "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2092  ast_getformatname(fmt),
2093  ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
2094  sub->owner->readformat = fmt;
2095  sub->owner->writeformat = fmt;
2096  }
2098  /* Setting up RTP of the phone */
2099  if (public_ip.sin_family == 0) /* NAT IP override ? */
2100  memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2101  else
2102  memcpy(&public, &public_ip, sizeof(public)); /* override */
2103  if (unistimdebug) {
2104  ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2105  ast_inet_ntoa(us.sin_addr),
2106  htons(us.sin_port), ast_getformatname(sub->owner->readformat));
2107  ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2108  ast_inet_ntoa(public.sin_addr));
2109  }
2110  if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
2111  (sub->owner->readformat == AST_FORMAT_ALAW)) {
2112  if (unistimdebug)
2113  ast_verb(0, "Sending packet_send_rtp_packet_size for codec %s\n", ast_getformatname(codec));
2114  memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2115  sizeof(packet_send_rtp_packet_size));
2116  buffsend[10] = (int) codec & 0xffffffffLL;
2117  send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
2118  sub->parent->parent->session);
2119  }
2120  if (unistimdebug)
2121  ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2122  memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2123  sizeof(packet_send_jitter_buffer_conf));
2124  send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
2125  sub->parent->parent->session);
2126  if (sub->parent->parent->rtp_method != 0) {
2127  uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2128 
2129  if (unistimdebug)
2130  ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
2131  sub->parent->parent->rtp_method);
2132  if (sub->parent->parent->rtp_method == 3)
2133  memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2134  sizeof(packet_send_open_audio_stream_tx3));
2135  else
2136  memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2137  sizeof(packet_send_open_audio_stream_tx));
2138  if (sub->parent->parent->rtp_method != 2) {
2139  memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2140  buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2141  buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2142  buffsend[23] = (rtcpsin_port & 0x00ff);
2143  buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2144  buffsend[25] = (us.sin_port & 0xff00) >> 8;
2145  buffsend[24] = (us.sin_port & 0x00ff);
2146  buffsend[27] = (rtcpsin_port & 0x00ff);
2147  buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2148  } else {
2149  memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2150  buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2151  buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2152  buffsend[20] = (us.sin_port & 0xff00) >> 8;
2153  buffsend[19] = (us.sin_port & 0x00ff);
2154  }
2155  buffsend[11] = codec; /* rx */
2156  buffsend[12] = codec; /* tx */
2157  send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
2158  sub->parent->parent->session);
2159 
2160  if (unistimdebug)
2161  ast_verb(0, "Sending OpenAudioStreamRX\n");
2162  if (sub->parent->parent->rtp_method == 3)
2163  memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2164  sizeof(packet_send_open_audio_stream_rx3));
2165  else
2166  memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2167  sizeof(packet_send_open_audio_stream_rx));
2168  if (sub->parent->parent->rtp_method != 2) {
2169  memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2170  buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2171  buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2172  buffsend[23] = (rtcpsin_port & 0x00ff);
2173  buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2174  buffsend[25] = (us.sin_port & 0xff00) >> 8;
2175  buffsend[24] = (us.sin_port & 0x00ff);
2176  buffsend[27] = (rtcpsin_port & 0x00ff);
2177  buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2178  } else {
2179  memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2180  buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2181  buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2182  buffsend[20] = (us.sin_port & 0xff00) >> 8;
2183  buffsend[19] = (us.sin_port & 0x00ff);
2184  }
2185  buffsend[11] = codec; /* rx */
2186  buffsend[12] = codec; /* tx */
2187  send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
2188  sub->parent->parent->session);
2189  } else {
2190  uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2191 
2192  if (unistimdebug)
2193  ast_verb(0, "Sending packet_send_call default method\n");
2194 
2195  memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2196  memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2197  /* Destination port when sending RTP */
2198  buffsend[49] = (us.sin_port & 0x00ff);
2199  buffsend[50] = (us.sin_port & 0xff00) >> 8;
2200  /* Destination port when sending RTCP */
2201  buffsend[52] = (rtcpsin_port & 0x00ff);
2202  buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2203  /* Codec */
2204  buffsend[40] = codec;
2205  buffsend[41] = codec;
2206  if (sub->owner->readformat == AST_FORMAT_ULAW)
2207  buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2208  else if (sub->owner->readformat == AST_FORMAT_ALAW)
2209  buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2210  else if (sub->owner->readformat == AST_FORMAT_G723_1)
2211  buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2212  else if (sub->owner->readformat == AST_FORMAT_G729A)
2213  buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2214  else
2215  ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2217  /* Source port for transmit RTP and Destination port for receiving RTP */
2218  buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2219  buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2220  buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2221  buffsend[48] = (rtcpsin_port & 0x00ff);
2222  send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
2223  sub->parent->parent->session);
2224  }
2225  ast_mutex_unlock(&sub->lock);
2226 }
2227 
2228 static void SendDialTone(struct unistimsession *pte)
2229 {
2230  int i;
2231  /* No country defined ? Using US tone */
2232  if (ast_strlen_zero(pte->device->country)) {
2233  if (unistimdebug)
2234  ast_verb(0, "No country defined, using US tone\n");
2235  send_tone(pte, 350, 440);
2236  return;
2237  }
2238  if (strlen(pte->device->country) != 2) {
2239  if (unistimdebug)
2240  ast_verb(0, "Country code != 2 char, using US tone\n");
2241  send_tone(pte, 350, 440);
2242  return;
2243  }
2244  i = 0;
2245  while (frequency[i].freq1) {
2246  if ((frequency[i].country[0] == pte->device->country[0]) &&
2247  (frequency[i].country[1] == pte->device->country[1])) {
2248  if (unistimdebug)
2249  ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2250  frequency[i].country, frequency[i].freq1, frequency[i].freq2);
2251  send_tone(pte, frequency[i].freq1, frequency[i].freq2);
2252  }
2253  i++;
2254  }
2255 }
2256 
2257 static void handle_dial_page(struct unistimsession *pte)
2258 {
2259  pte->state = STATE_DIALPAGE;
2260  if (pte->device->call_forward[0] == -1) {
2261  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2262  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
2263  send_text_status(pte, "ForwardCancel BackSpcErase");
2264  if (pte->device->call_forward[1] != 0) {
2265  char tmp[TEXT_LENGTH_MAX + 1];
2266 
2268  sizeof(pte->device->phone_number));
2269  pte->device->size_phone_number = strlen(pte->device->phone_number);
2270  if (pte->device->size_phone_number > 15)
2271  pte->device->size_phone_number = 15;
2272  strcpy(tmp, "Number : ...............");
2273  memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
2274 
2275  if (pte->device->height == 1) {
2276  send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
2277  send_blink_cursor(pte);
2278  send_cursor_pos(pte,
2279  (unsigned char) (TEXT_LINE0 + 0x09 +
2280  pte->device->size_phone_number));
2281  } else {
2282  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
2283  send_blink_cursor(pte);
2284  send_cursor_pos(pte,
2285  (unsigned char) (TEXT_LINE2 + 0x09 +
2286  pte->device->size_phone_number));
2287  }
2288 
2289  send_led_update(pte, 0);
2290  return;
2291  }
2292  } else {
2293  if ((pte->device->output == OUTPUT_HANDSET) &&
2294  (pte->device->receiver_state == STATE_ONHOOK))
2296  else
2297  send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2298  SendDialTone(pte);
2299 
2300  if (pte->device->height > 1) {
2301  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
2302  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
2303  }
2304  send_text_status(pte, "Call Redial BackSpcErase");
2305  }
2306 
2307  if (pte->device->height == 1) {
2308  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2309  send_blink_cursor(pte);
2310  send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2311  } else {
2312  send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2313  send_blink_cursor(pte);
2314  send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2315  }
2316  pte->device->size_phone_number = 0;
2317  pte->device->phone_number[0] = 0;
2320  pte->device->missed_call = 0;
2321  send_led_update(pte, 0);
2322  return;
2323 }
2324 
2325 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2326 static void TransferCallStep1(struct unistimsession *pte)
2327 {
2328  struct unistim_subchannel *sub;
2329  struct unistim_line *p = pte->device->lines;
2330 
2331  sub = p->subs[SUB_REAL];
2332 
2333  if (!sub->owner) {
2334  ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2335  return;
2336  }
2337  if (p->subs[SUB_THREEWAY]) {
2338  if (unistimdebug)
2339  ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2340  if (p->subs[SUB_THREEWAY]->owner)
2342  else
2343  ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
2344  return;
2345  }
2346  /* Start music on hold if appropriate */
2347  if (pte->device->moh)
2348  ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2349  else {
2350  if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
2352  pte->device->lines->musicclass, NULL);
2353  pte->device->moh = 1;
2354  } else {
2355  ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2356  return;
2357  }
2358  }
2359  /* Silence our channel */
2360  if (!pte->device->silence_generator) {
2361  pte->device->silence_generator =
2363  if (pte->device->silence_generator == NULL)
2364  ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2365  else if (unistimdebug)
2366  ast_verb(0, "Starting silence generator\n");
2367  }
2368  handle_dial_page(pte);
2369 }
2370 
2371 /* From phone to PBX */
2372 static void HandleCallOutgoing(struct unistimsession *s)
2373 {
2374  struct ast_channel *c;
2375  struct unistim_subchannel *sub;
2376  pthread_t t;
2377  s->state = STATE_CALL;
2378  sub = s->device->lines->subs[SUB_REAL];
2379  if (!sub) {
2380  ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2381  return;
2382  }
2383  if (!sub->owner) { /* A call is already in progress ? */
2384  c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
2385  if (c) {
2386  /* Need to start RTP before calling ast_pbx_run */
2387  if (!sub->rtp)
2388  start_rtp(sub);
2390 
2391  if (s->device->height == 1) {
2393  } else {
2394  send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
2396  send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2397  }
2398  send_text_status(s, "Hangup");
2399 
2400  /* start switch */
2401  if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
2402  display_last_error("Unable to create switch thread");
2404  }
2405  } else
2406  ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
2407  sub->parent->name, s->device->name);
2408  } else { /* We already have a call, so we switch in a threeway call */
2409 
2410  if (s->device->moh) {
2411  struct unistim_subchannel *subchannel;
2412  struct unistim_line *p = s->device->lines;
2413  subchannel = p->subs[SUB_REAL];
2414 
2415  if (!subchannel->owner) {
2416  ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2417  return;
2418  }
2419  if (p->subs[SUB_THREEWAY]) {
2421  "Can't transfer while an another transfer is taking place\n");
2422  return;
2423  }
2424  if (!alloc_sub(p, SUB_THREEWAY)) {
2425  ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
2426  return;
2427  }
2428  /* Stop the silence generator */
2429  if (s->device->silence_generator) {
2430  if (unistimdebug)
2431  ast_verb(0, "Stopping silence generator\n");
2434  s->device->silence_generator = NULL;
2435  }
2436  send_tone(s, 0, 0);
2437  /* Make new channel */
2438  c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
2439  if (!c) {
2440  ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
2441  return;
2442  }
2443  /* Swap things around between the three-way and real call */
2446 
2447  if (s->device->height == 1) {
2449  } else {
2450  send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
2452  send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
2453  }
2454  send_text_status(s, "TransfrCancel");
2455 
2456  if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
2457  ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
2458  ast_hangup(c);
2459  return;
2460  }
2461  if (unistimdebug)
2462  ast_verb(0, "Started three way call on channel %p (%s) subchan %u\n",
2464  p->subs[SUB_THREEWAY]->subtype);
2465  } else
2466  ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
2467  }
2468  return;
2469 }
2470 
2471 /* From PBX to phone */
2472 static void HandleCallIncoming(struct unistimsession *s)
2473 {
2474  struct unistim_subchannel *sub;
2475  s->state = STATE_CALL;
2476  s->device->missed_call = 0;
2477  send_no_ring(s);
2478  sub = s->device->lines->subs[SUB_REAL];
2479  if (!sub) {
2480  ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
2481  return;
2482  } else if (unistimdebug)
2483  ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
2484  s->device->name);
2485  start_rtp(sub);
2486  if (!sub->rtp)
2487  ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
2488  s->device->name);
2490  send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
2491  send_text_status(s, "Hangup Transf");
2492  send_start_timer(s);
2493 
2494  if ((s->device->output == OUTPUT_HANDSET) &&
2497  else
2499  s->device->start_call_timestamp = time(0);
2500  write_history(s, 'i', 0);
2501  return;
2502 }
2503 
2504 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
2505 {
2506  struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
2507  struct unistim_subchannel *sub;
2508  sub = pte->device->lines->subs[SUB_REAL];
2509  if (!sub->owner || sub->alreadygone) {
2510  ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
2511  return -1;
2512  }
2513 
2514  /* Send DTMF indication _before_ playing sounds */
2515  ast_queue_frame(sub->owner, &f);
2516 
2517  if (unistimdebug)
2518  ast_verb(0, "Send Digit %c\n", digit);
2519  switch (digit) {
2520  case '0':
2521  send_tone(pte, 941, 1336);
2522  break;
2523  case '1':
2524  send_tone(pte, 697, 1209);
2525  break;
2526  case '2':
2527  send_tone(pte, 697, 1336);
2528  break;
2529  case '3':
2530  send_tone(pte, 697, 1477);
2531  break;
2532  case '4':
2533  send_tone(pte, 770, 1209);
2534  break;
2535  case '5':
2536  send_tone(pte, 770, 1336);
2537  break;
2538  case '6':
2539  send_tone(pte, 770, 1477);
2540  break;
2541  case '7':
2542  send_tone(pte, 852, 1209);
2543  break;
2544  case '8':
2545  send_tone(pte, 852, 1336);
2546  break;
2547  case '9':
2548  send_tone(pte, 852, 1477);
2549  break;
2550  case 'A':
2551  send_tone(pte, 697, 1633);
2552  break;
2553  case 'B':
2554  send_tone(pte, 770, 1633);
2555  break;
2556  case 'C':
2557  send_tone(pte, 852, 1633);
2558  break;
2559  case 'D':
2560  send_tone(pte, 941, 1633);
2561  break;
2562  case '*':
2563  send_tone(pte, 941, 1209);
2564  break;
2565  case '#':
2566  send_tone(pte, 941, 1477);
2567  break;
2568  default:
2569  send_tone(pte, 500, 2000);
2570  }
2571  usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2572  send_tone(pte, 0, 0);
2573  return 0;
2574 }
2575 
2576 static void key_call(struct unistimsession *pte, char keycode)
2577 {
2578  if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2579  if (keycode == KEY_SHARP)
2580  keycode = '#';
2581  else if (keycode == KEY_STAR)
2582  keycode = '*';
2583  else
2584  keycode -= 0x10;
2585  unistim_do_senddigit(pte, keycode);
2586  return;
2587  }
2588  switch (keycode) {
2589  case KEY_HANGUP:
2590  case KEY_FUNC1:
2591  close_call(pte);
2592  break;
2593  case KEY_FUNC2:
2594  TransferCallStep1(pte);
2595  break;
2596  case KEY_HEADPHN:
2597  if (pte->device->output == OUTPUT_HEADPHONE)
2599  else
2601  break;
2602  case KEY_LOUDSPK:
2603  if (pte->device->output != OUTPUT_SPEAKER)
2605  else
2607  MUTE_OFF);
2608  break;
2609  case KEY_MUTE:
2610  if (!pte->device->moh) {
2611  if (pte->device->mute == MUTE_ON)
2612  send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2613  else
2614  send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2615  break;
2616  }
2617  case KEY_ONHOLD:
2618  {
2619  struct unistim_subchannel *sub;
2620  struct ast_channel *bridgepeer = NULL;
2621  sub = pte->device->lines->subs[SUB_REAL];
2622  if (!sub->owner) {
2623  ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2624  return;
2625  }
2626  if ((bridgepeer = ast_bridged_channel(sub->owner))) {
2627  if (pte->device->moh) {
2628  ast_moh_stop(bridgepeer);
2629  pte->device->moh = 0;
2630  send_select_output(pte, pte->device->output, pte->device->volume,
2631  MUTE_OFF);
2632  } else {
2633  ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
2634  pte->device->moh = 1;
2635  send_select_output(pte, pte->device->output, pte->device->volume,
2636  MUTE_ON);
2637  }
2638  } else
2640  "Unable to find peer subchannel for music on hold\n");
2641  break;
2642  }
2643  }
2644  return;
2645 }
2646 
2647 static void key_ringing(struct unistimsession *pte, char keycode)
2648 {
2649  if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
2650  HandleCallIncoming(pte);
2651  return;
2652  }
2653  switch (keycode) {
2654  case KEY_HANGUP:
2655  case KEY_FUNC4:
2656  IgnoreCall(pte);
2657  break;
2658  case KEY_FUNC1:
2659  HandleCallIncoming(pte);
2660  break;
2661  }
2662  return;
2663 }
2664 
2665 static void Keyfavorite(struct unistimsession *pte, char keycode)
2666 {
2667  int fav;
2668 
2669  if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
2670  ast_log(LOG_WARNING, "It's not a favorite key\n");
2671  return;
2672  }
2673  if (keycode == KEY_FAV0)
2674  return;
2675  fav = keycode - KEY_FAV0;
2676  if (pte->device->softkeyicon[fav] == 0)
2677  return;
2679  sizeof(pte->device->phone_number));
2680  HandleCallOutgoing(pte);
2681  return;
2682 }
2683 
2684 static void key_dial_page(struct unistimsession *pte, char keycode)
2685 {
2686  if (keycode == KEY_FUNC3) {
2687  if (pte->device->size_phone_number <= 1)
2688  keycode = KEY_FUNC4;
2689  else {
2690  pte->device->size_phone_number -= 2;
2691  keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
2692  }
2693  }
2694  if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
2695  char tmpbuf[] = "Number : ...............";
2696  unsigned int i = 0; /* changed to unsigned due to weird gcc 4.8.1 compiler complaint */
2697 
2698  if (pte->device->size_phone_number >= 15)
2699  return;
2700  if (pte->device->size_phone_number == 0)
2701  send_tone(pte, 0, 0);
2702  while (i < pte->device->size_phone_number) {
2703  tmpbuf[i + 9] = pte->device->phone_number[i];
2704  i++;
2705  }
2706  if (keycode == KEY_SHARP)
2707  keycode = '#';
2708  else if (keycode == KEY_STAR)
2709  keycode = '*';
2710  else
2711  keycode -= 0x10;
2712  tmpbuf[i + 9] = keycode;
2713  pte->device->phone_number[i] = keycode;
2714  pte->device->size_phone_number++;
2715  pte->device->phone_number[i + 1] = 0;
2716  if (pte->device->height == 1) {
2717  send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
2718  } else {
2719  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2720  }
2721  send_blink_cursor(pte);
2722  send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
2723  return;
2724  }
2725  if (keycode == KEY_FUNC4) {
2726 
2727  pte->device->size_phone_number = 0;
2728  if (pte->device->height == 1) {
2729  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
2730  send_blink_cursor(pte);
2731  send_cursor_pos(pte, TEXT_LINE0 + 0x09);
2732  } else {
2733  send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
2734  send_blink_cursor(pte);
2735  send_cursor_pos(pte, TEXT_LINE2 + 0x09);
2736  }
2737  return;
2738  }
2739 
2740  if (pte->device->call_forward[0] == -1) {
2741  if (keycode == KEY_FUNC1) {
2743  sizeof(pte->device->call_forward));
2744  show_main_page(pte);
2745  } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
2746  pte->device->call_forward[0] = '\0';
2747  show_main_page(pte);
2748  }
2749  return;
2750  }
2751  switch (keycode) {
2752  case KEY_FUNC2:
2754  break;
2756  sizeof(pte->device->phone_number));
2757  case KEY_FUNC1:
2758  HandleCallOutgoing(pte);
2759  break;
2760  case KEY_HANGUP:
2761  if (pte->device->lines->subs[SUB_REAL]->owner) {
2762  /* Stop the silence generator */
2763  if (pte->device->silence_generator) {
2764  if (unistimdebug)
2765  ast_verb(0, "Stopping silence generator\n");
2767  owner, pte->device->silence_generator);
2768  pte->device->silence_generator = NULL;
2769  }
2770  send_tone(pte, 0, 0);
2772  pte->device->moh = 0;
2773  pte->state = STATE_CALL;
2774 
2775  if (pte->device->height == 1) {
2776  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
2777  } else {
2778  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
2779  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
2780  send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
2781  }
2782  send_text_status(pte, "Hangup Transf");
2783  } else
2784  show_main_page(pte);
2785  break;
2786  case KEY_FAV1:
2787  case KEY_FAV2:
2788  case KEY_FAV3:
2789  case KEY_FAV4:
2790  case KEY_FAV5:
2791  Keyfavorite(pte, keycode);
2792  break;
2793  case KEY_LOUDSPK:
2794  if (pte->device->output == OUTPUT_SPEAKER) {
2795  if (pte->device->receiver_state == STATE_OFFHOOK)
2797  MUTE_OFF);
2798  else
2799  show_main_page(pte);
2800  } else
2802  break;
2803  case KEY_HEADPHN:
2804  if (pte->device->output == OUTPUT_HEADPHONE) {
2805  if (pte->device->receiver_state == STATE_OFFHOOK)
2807  else
2808  show_main_page(pte);
2809  } else
2811  break;
2812  }
2813  return;
2814 }
2815 
2816 #define SELECTCODEC_START_ENTRY_POS 15
2817 #define SELECTCODEC_MAX_LENGTH 2
2818 #define SELECTCODEC_MSG "Codec number : .."
2819 static void HandleSelectCodec(struct unistimsession *pte)
2820 {
2821  char buf[30], buf2[5];
2822 
2823  pte->state = STATE_SELECTCODEC;
2824  strcpy(buf, "Using codec ");
2825  sprintf(buf2, "%d", pte->device->codec_number);
2826  strcat(buf, buf2);
2827  strcat(buf, " (G711u=0,");
2828 
2829  send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
2830  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
2832  send_blink_cursor(pte);
2834  pte->size_buff_entry = 0;
2835  send_text_status(pte, "Select BackSpcErase Cancel");
2836  return;
2837 }
2838 
2839 static void key_select_codec(struct unistimsession *pte, char keycode)
2840 {
2841  if (keycode == KEY_FUNC2) {
2842  if (pte->size_buff_entry <= 1)
2843  keycode = KEY_FUNC3;
2844  else {
2845  pte->size_buff_entry -= 2;
2846  keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2847  }
2848  }
2849  if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2850  char tmpbuf[] = SELECTCODEC_MSG;
2851  int i = 0;
2852 
2854  return;
2855 
2856  while (i < pte->size_buff_entry) {
2857  tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
2858  i++;
2859  }
2860  tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
2861  pte->buff_entry[i] = keycode - 0x10;
2862  pte->size_buff_entry++;
2863  send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
2864  send_blink_cursor(pte);
2865  send_cursor_pos(pte,
2866  (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
2867  return;
2868  }
2869 
2870  switch (keycode) {
2871  case KEY_FUNC1:
2872  if (pte->size_buff_entry == 1)
2873  pte->device->codec_number = pte->buff_entry[0] - 48;
2874  else if (pte->size_buff_entry == 2)
2875  pte->device->codec_number =
2876  ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
2877  show_main_page(pte);
2878  break;
2879  case KEY_FUNC3:
2880  pte->size_buff_entry = 0;
2882  send_blink_cursor(pte);
2884  break;
2885  case KEY_HANGUP:
2886  case KEY_FUNC4:
2887  show_main_page(pte);
2888  break;
2889  }
2890  return;
2891 }
2892 
2893 #define SELECTEXTENSION_START_ENTRY_POS 0
2894 #define SELECTEXTENSION_MAX_LENGTH 10
2895 #define SELECTEXTENSION_MSG ".........."
2896 static void ShowExtensionPage(struct unistimsession *pte)
2897 {
2898  pte->state = STATE_EXTENSION;
2899 
2900  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
2901  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
2903  send_blink_cursor(pte);
2905  send_text_status(pte, "Enter BackSpcErase");
2906  pte->size_buff_entry = 0;
2907  return;
2908 }
2909 
2910 static void key_select_extension(struct unistimsession *pte, char keycode)
2911 {
2912  if (keycode == KEY_FUNC2) {
2913  if (pte->size_buff_entry <= 1)
2914  keycode = KEY_FUNC3;
2915  else {
2916  pte->size_buff_entry -= 2;
2917  keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
2918  }
2919  }
2920  if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
2921  char tmpbuf[] = SELECTEXTENSION_MSG;
2922  int i = 0;
2923 
2925  return;
2926 
2927  while (i < pte->size_buff_entry) {
2928  tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
2929  i++;
2930  }
2931  tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
2932  pte->buff_entry[i] = keycode - 0x10;
2933  pte->size_buff_entry++;
2934  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
2935  send_blink_cursor(pte);
2936  send_cursor_pos(pte,
2937  (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
2938  i));
2939  return;
2940  }
2941 
2942  switch (keycode) {
2943  case KEY_FUNC1:
2944  if (pte->size_buff_entry < 1)
2945  return;
2946  if (autoprovisioning == AUTOPROVISIONING_TN) {
2947  struct unistim_device *d;
2948 
2949  /* First step : looking for this TN in our device list */
2951  d = devices;
2952  pte->buff_entry[pte->size_buff_entry] = '\0';
2953  while (d) {
2954  if (d->id[0] == 'T') { /* It's a TN device ? */
2955  /* It's the TN we're looking for ? */
2956  if (!strcmp((d->id) + 1, pte->buff_entry)) {
2957  pte->device = d;
2958  d->session = pte;
2960  d->pos_fav = 0;
2961  d->missed_call = 0;
2963  strcpy(d->id, pte->macaddr);
2964  pte->device->extension_number[0] = 'T';
2965  pte->device->extension = EXTENSION_TN;
2967  pte->buff_entry, pte->size_buff_entry + 1);
2969  show_main_page(pte);
2970  refresh_all_favorite(pte);
2971  return;
2972  }
2973  }
2974  d = d->next;
2975  }
2977  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
2978  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2979  send_cursor_pos(pte,
2980  (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
2981  pte->size_buff_entry));
2982  send_blink_cursor(pte);
2983  } else {
2985  pte->size_buff_entry + 1);
2986  if (RegisterExtension(pte)) {
2987  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
2988  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
2989  send_cursor_pos(pte,
2990  (unsigned char) (TEXT_LINE2 +
2992  pte->size_buff_entry));
2993  send_blink_cursor(pte);
2994  } else
2995  show_main_page(pte);
2996  }
2997  break;
2998  case KEY_FUNC3:
2999  pte->size_buff_entry = 0;
3001  send_blink_cursor(pte);
3003  break;
3004  }
3005  return;
3006 }
3007 
3008 static int ReformatNumber(char *number)
3009 {
3010  int pos = 0, i = 0, size = strlen(number);
3011 
3012  for (; i < size; i++) {
3013  if ((number[i] >= '0') && (number[i] <= '9')) {
3014  if (i == pos) {
3015  pos++;
3016  continue;
3017  }
3018  number[pos] = number[i];
3019  pos++;
3020  }
3021  }
3022  number[pos] = 0;
3023  return pos;
3024 }
3025 
3026 static void show_entry_history(struct unistimsession *pte, FILE ** f)
3027 {
3028  char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
3029  func3[10];
3030 
3031  if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3032  display_last_error("Can't read history date entry");
3033  fclose(*f);
3034  return;
3035  }
3036  line[sizeof(line) - 1] = '\0';
3037  send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
3038  if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3039  display_last_error("Can't read callerid entry");
3040  fclose(*f);
3041  return;
3042  }
3043  line[sizeof(line) - 1] = '\0';
3044  ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
3045  send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
3046  if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3047  display_last_error("Can't read callername entry");
3048  fclose(*f);
3049  return;
3050  }
3051  line[sizeof(line) - 1] = '\0';
3052  send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
3053  fclose(*f);
3054 
3055  snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
3056  pte->buff_entry[1]);
3057  send_texttitle(pte, line);
3058 
3059  if (pte->buff_entry[2] == 1)
3060  strcpy(func1, " ");
3061  else
3062  strcpy(func1, "Prvious");
3063  if (pte->buff_entry[2] >= pte->buff_entry[1])
3064  strcpy(func2, " ");
3065  else
3066  strcpy(func2, "Next ");
3067  if (ReformatNumber(pte->device->lst_cid))
3068  strcpy(func3, "Redial ");
3069  else
3070  strcpy(func3, " ");
3071  snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
3072  send_text_status(pte, status);
3073 }
3074 
3075 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
3076 {
3077  char tmp[AST_CONFIG_MAX_PATH];
3078  char count;
3079 
3080  snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
3081  USTM_LOG_DIR, pte->device->name, way);
3082  *f = fopen(tmp, "r");
3083  if (!*f) {
3084  display_last_error("Unable to open history file");
3085  return 0;
3086  }
3087  if (fread(&count, 1, 1, *f) != 1) {
3088  display_last_error("Unable to read history header - display.");
3089  fclose(*f);
3090  return 0;
3091  }
3092  if (count > MAX_ENTRY_LOG) {
3093  ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
3094  count, MAX_ENTRY_LOG);
3095  fclose(*f);
3096  return 0;
3097  }
3098  return count;
3099 }
3100 
3101 static void show_history(struct unistimsession *pte, char way)
3102 {
3103  FILE *f;
3104  char count;
3105 
3106  if (!pte->device)
3107  return;
3108  if (!pte->device->callhistory)
3109  return;
3110  count = OpenHistory(pte, way, &f);
3111  if (!count)
3112  return;
3113  pte->buff_entry[0] = way;
3114  pte->buff_entry[1] = count;
3115  pte->buff_entry[2] = 1;
3116  show_entry_history(pte, &f);
3117  pte->state = STATE_HISTORY;
3118 }
3119 
3120 static void show_main_page(struct unistimsession *pte)
3121 {
3122  char tmpbuf[TEXT_LENGTH_MAX + 1];
3123 
3124 
3125  if ((pte->device->extension == EXTENSION_ASK) &&
3127  ShowExtensionPage(pte);
3128  return;
3129  }
3130 
3131  pte->state = STATE_MAINPAGE;
3132 
3133  send_tone(pte, 0, 0);
3135  pte->device->lines->lastmsgssent = 0;
3137  pte->device->softkeylabel[pte->device->softkeylinepos]);
3138  if (!ast_strlen_zero(pte->device->call_forward)) {
3139  if (pte->device->height == 1) {
3140  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Forwarding ON");
3141  } else {
3142  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
3144  }
3146  send_text_status(pte, "Dial Redial NoForwd");
3147  } else {
3148  if ((pte->device->extension == EXTENSION_ASK) ||
3149  (pte->device->extension == EXTENSION_TN))
3150  send_text_status(pte, "Dial Redial ForwardUnregis");
3151  else
3152  send_text_status(pte, "Dial Redial Forward");
3153 
3155  if (pte->device->missed_call == 0)
3157  else {
3158  sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
3159  send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
3161  }
3162  }
3163  if (ast_strlen_zero(pte->device->maintext2)) {
3164  strcpy(tmpbuf, "IP : ");
3165  strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
3166  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
3167  } else
3169  send_texttitle(pte, pte->device->titledefault);
3171 }
3172 
3173 static void key_main_page(struct unistimsession *pte, char keycode)
3174 {
3175  if (pte->device->missed_call) {
3177  pte->device->missed_call = 0;
3178  }
3179  if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3180  handle_dial_page(pte);
3181  key_dial_page(pte, keycode);
3182  return;
3183  }
3184  switch (keycode) {
3185  case KEY_FUNC1:
3186  handle_dial_page(pte);
3187  break;
3188  case KEY_FUNC2:
3190  break;
3191  if ((pte->device->output == OUTPUT_HANDSET) &&
3192  (pte->device->receiver_state == STATE_ONHOOK))
3194  else
3195  send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3196 
3198  sizeof(pte->device->phone_number));
3199  HandleCallOutgoing(pte);
3200  break;
3201  case KEY_FUNC3:
3202  if (!ast_strlen_zero(pte->device->call_forward)) {
3203  /* Cancel call forwarding */
3204  memmove(pte->device->call_forward + 1, pte->device->call_forward,
3205  sizeof(pte->device->call_forward) - 1);
3206  pte->device->call_forward[0] = '\0';
3208  pte->device->output = OUTPUT_HANDSET; /* Seems to be reseted somewhere */
3209  show_main_page(pte);
3210  break;
3211  }
3212  pte->device->call_forward[0] = -1;
3213  handle_dial_page(pte);
3214  break;
3215  case KEY_FUNC4:
3216  if (pte->device->extension == EXTENSION_ASK) {
3217  UnregisterExtension(pte);
3218  pte->device->extension_number[0] = '\0';
3219  ShowExtensionPage(pte);
3220  } else if (pte->device->extension == EXTENSION_TN) {
3222  strcpy(pte->device->id, pte->device->extension_number);
3223  pte->buff_entry[0] = '\0';
3224  pte->size_buff_entry = 0;
3225  pte->device->session = NULL;
3226  pte->device = NULL;
3228  ShowExtensionPage(pte);
3229  }
3230  break;
3231  case KEY_FAV0:
3232  handle_dial_page(pte);
3233  break;
3234  case KEY_FAV1:
3235  case KEY_FAV2:
3236  case KEY_FAV3:
3237  case KEY_FAV4:
3238  case KEY_FAV5:
3239  if ((pte->device->output == OUTPUT_HANDSET) &&
3240  (pte->device->receiver_state == STATE_ONHOOK))
3242  else
3243  send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
3244  Keyfavorite(pte, keycode);
3245  break;
3246  case KEY_CONF:
3247  HandleSelectCodec(pte);
3248  break;
3249  case KEY_LOUDSPK:
3251  handle_dial_page(pte);
3252  break;
3253  case KEY_HEADPHN:
3255  handle_dial_page(pte);
3256  break;
3257  case KEY_SNDHIST:
3258  show_history(pte, 'o');
3259  break;
3260  case KEY_RCVHIST:
3261  show_history(pte, 'i');
3262  break;
3263  }
3264  return;
3265 }
3266 
3267 static void key_history(struct unistimsession *pte, char keycode)
3268 {
3269  FILE *f;
3270  char count;
3271  long offset;
3272 
3273  switch (keycode) {
3274  case KEY_UP:
3275  case KEY_LEFT:
3276  case KEY_FUNC1:
3277  if (pte->buff_entry[2] <= 1)
3278  return;
3279  pte->buff_entry[2]--;
3280  count = OpenHistory(pte, pte->buff_entry[0], &f);
3281  if (!count)
3282  return;
3283  offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3284  if (fseek(f, offset, SEEK_CUR)) {
3285  display_last_error("Unable to seek history entry.");
3286  fclose(f);
3287  return;
3288  }
3289  show_entry_history(pte, &f);
3290  break;
3291  case KEY_DOWN:
3292  case KEY_RIGHT:
3293  case KEY_FUNC2:
3294  if (pte->buff_entry[2] >= pte->buff_entry[1])
3295  return;
3296  pte->buff_entry[2]++;
3297  count = OpenHistory(pte, pte->buff_entry[0], &f);
3298  if (!count)
3299  return;
3300  offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
3301  if (fseek(f, offset, SEEK_CUR)) {
3302  display_last_error("Unable to seek history entry.");
3303  fclose(f);
3304  return;
3305  }
3306  show_entry_history(pte, &f);
3307  break;
3308  case KEY_FUNC3:
3309  if (!ReformatNumber(pte->device->lst_cid))
3310  break;
3312  sizeof(pte->device->redial_number));
3313  key_main_page(pte, KEY_FUNC2);
3314  break;
3315  case KEY_FUNC4:
3316  case KEY_HANGUP:
3317  show_main_page(pte);
3318  break;
3319  case KEY_SNDHIST:
3320  if (pte->buff_entry[0] == 'i')
3321  show_history(pte, 'o');
3322  else
3323  show_main_page(pte);
3324  break;
3325  case KEY_RCVHIST:
3326  if (pte->buff_entry[0] == 'i')
3327  show_main_page(pte);
3328  else
3329  show_history(pte, 'i');
3330  break;
3331  }
3332  return;
3333 }
3334 
3335 static void init_phone_step2(struct unistimsession *pte)
3336 {
3337  BUFFSEND;
3338  if (unistimdebug)
3339  ast_verb(0, "Sending S4\n");
3340  memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
3341  send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
3342  send_date_time2(pte);
3343  send_date_time3(pte);
3344  if (unistimdebug)
3345  ast_verb(0, "Sending S7\n");
3346  memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3347  send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3348  if (unistimdebug)
3349  ast_verb(0, "Sending Contrast\n");
3350  memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
3351  if (pte->device != NULL)
3352  buffsend[9] = pte->device->contrast;
3353  send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
3354 
3355  if (unistimdebug)
3356  ast_verb(0, "Sending S9\n");
3357  memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
3358  send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
3359  send_no_ring(pte);
3360 
3361  if (unistimdebug)
3362  ast_verb(0, "Sending S7\n");
3363  memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
3364  send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
3365  send_led_update(pte, 0);
3366  send_ping(pte);
3367  if (pte->state < STATE_MAINPAGE) {
3368  if (autoprovisioning == AUTOPROVISIONING_TN) {
3369  ShowExtensionPage(pte);
3370  return;
3371  } else {
3372  int i;
3373  char tmp[30];
3374 
3375  for (i = 1; i < 6; i++)
3376  send_favorite(i, 0, pte, "");
3377  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
3378  send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
3379  strcpy(tmp, "MAC = ");
3380  strcat(tmp, pte->macaddr);
3381  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
3382  send_text_status(pte, "");
3383  send_texttitle(pte, "UNISTIM for*");
3384  return;
3385  }
3386  }
3387  show_main_page(pte);
3388  refresh_all_favorite(pte);
3389  if (unistimdebug)
3390  ast_verb(0, "Sending arrow\n");
3391  memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
3392  send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
3393  return;
3394 }
3395 
3396 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
3397 {
3398  char tmpbuf[255];
3399  if (memcmp
3400  (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
3401  sizeof(packet_recv_resume_connection_with_server)) == 0) {
3403  return;
3404  }
3405  if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
3406  0) {
3407  buf[size] = 0;
3408  if (unistimdebug)
3409  ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
3410  init_phone_step2(pte);
3411  return;
3412  }
3413  if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
3414  rcv_mac_addr(pte, buf);
3415  return;
3416  }
3417  if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
3418  if (unistimdebug)
3419  ast_verb(0, "R2 received\n");
3420  return;
3421  }
3422 
3423  if (pte->state < STATE_MAINPAGE) {
3424  if (unistimdebug)
3425  ast_verb(0, "Request not authorized in this state\n");
3426  return;
3427  }
3428  if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
3429  char keycode = buf[13];
3430 
3431  if (unistimdebug)
3432  ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", (unsigned)keycode,
3433  pte->state);
3434 
3435  switch (pte->state) {
3436  case STATE_INIT:
3437  if (unistimdebug)
3438  ast_verb(0, "No keys allowed in the init state\n");
3439  break;
3440  case STATE_AUTHDENY:
3441  if (unistimdebug)
3442  ast_verb(0, "No keys allowed in authdeny state\n");
3443  break;
3444  case STATE_MAINPAGE:
3445  key_main_page(pte, keycode);
3446  break;
3447  case STATE_DIALPAGE:
3448  key_dial_page(pte, keycode);
3449  break;
3450  case STATE_RINGING:
3451  key_ringing(pte, keycode);
3452  break;
3453  case STATE_CALL:
3454  key_call(pte, keycode);
3455  break;
3456  case STATE_EXTENSION:
3457  key_select_extension(pte, keycode);
3458  break;
3459  case STATE_SELECTCODEC:
3460  key_select_codec(pte, keycode);
3461  break;
3462  case STATE_HISTORY:
3463  key_history(pte, keycode);
3464  break;
3465  default:
3466  ast_log(LOG_WARNING, "Key : Unknown state\n");
3467  }
3468  return;
3469  }
3470  if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
3471  if (unistimdebug)
3472  ast_verb(0, "Handset off hook\n");
3473  if (!pte->device) /* We are not yet registered (asking for a TN in AUTOPROVISIONING_TN) */
3474  return;
3476  if (pte->device->output == OUTPUT_HEADPHONE)
3478  else
3480  if (pte->state == STATE_RINGING)
3481  HandleCallIncoming(pte);
3482  else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
3484  else if (pte->state == STATE_EXTENSION) /* We must have a TN before calling */
3485  return;
3486  else {
3488  handle_dial_page(pte);
3489  }
3490  return;
3491  }
3492  if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
3493  if (unistimdebug)
3494  ast_verb(0, "Handset on hook\n");
3495  if (!pte->device)
3496  return;
3498  if (pte->state == STATE_CALL)
3499  close_call(pte);
3500  else if (pte->device->lines->subs[SUB_REAL]->owner)
3501  close_call(pte);
3502  else if (pte->state == STATE_EXTENSION)
3503  return;
3504  else
3505  show_main_page(pte);
3506  return;
3507  }
3508  strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
3509  strcat(tmpbuf, " Unknown request packet\n");
3510  if (unistimdebug)
3511  ast_debug(1, "%s", tmpbuf);
3512  return;
3513 }
3514 
3515 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
3516  struct sockaddr_in *addr_from)
3517 {
3518  unsigned short *sbuf = (unsigned short *) buf;
3519  unsigned short seq;
3520  char tmpbuf[255];
3521 
3522  strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
3523 
3524  if (size < 10) {
3525  if (size == 0) {
3526  ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
3527  } else {
3528  ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
3529  }
3530  return;
3531  }
3532  if (sbuf[0] == 0xffff) { /* Starting with 0xffff ? *//* Yes, discovery packet ? */
3533  if (size != sizeof(packet_rcv_discovery)) {
3534  ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
3535  } else {
3536  if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
3537  if (unistimdebug)
3538  ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
3539  if (pte) { /* A session was already active for this IP ? */
3540  if (pte->state == STATE_INIT) { /* Yes, but it's a dupe */
3541  if (unistimdebug)
3542  ast_verb(1, "Duplicated Discovery packet\n");
3543  send_raw_client(sizeof(packet_send_discovery_ack),
3544  packet_send_discovery_ack, addr_from, &pte->sout);
3545  pte->seq_phone = (short) 0x0000; /* reset sequence number */
3546  } else { /* No, probably a reboot, phone side */
3547  close_client(pte); /* Cleanup the previous session */
3548  if (create_client(addr_from))
3549  send_raw_client(sizeof(packet_send_discovery_ack),
3550  packet_send_discovery_ack, addr_from, &pte->sout);
3551  }
3552  } else {
3553  /* Creating new entry in our phone list */
3554  if ((pte = create_client(addr_from)))
3555  send_raw_client(sizeof(packet_send_discovery_ack),
3556  packet_send_discovery_ack, addr_from, &pte->sout);
3557  }
3558  return;
3559  }
3560  ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
3561  }
3562  return;
3563  }
3564  if (!pte) {
3565  if (unistimdebug)
3566  ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n",
3567  tmpbuf);
3568  return;
3569  }
3570 
3571  if (sbuf[0] != 0) { /* Starting with something else than 0x0000 ? */
3572  ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
3573  return;
3574  }
3575  if (buf[5] != 2) {
3576  ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
3577  (unsigned)buf[5]);
3578  return;
3579  }
3580  seq = ntohs(sbuf[1]);
3581  if (buf[4] == 1) {
3582  ast_mutex_lock(&pte->lock);
3583  if (unistimdebug)
3584  ast_verb(6, "ACK received for packet #0x%.4x\n", (unsigned)seq);
3585  pte->nb_retransmit = 0;
3586 
3587  if ((pte->last_seq_ack) + 1 == seq) {
3588  pte->last_seq_ack++;
3589  check_send_queue(pte);
3590  ast_mutex_unlock(&pte->lock);
3591  return;
3592  }
3593  if (pte->last_seq_ack > seq) {
3594  if (pte->last_seq_ack == 0xffff) {
3595  ast_verb(0, "ACK at 0xffff, restarting counter.\n");
3596  pte->last_seq_ack = 0;
3597  } else
3599  "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
3600  tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
3601  ast_mutex_unlock(&pte->lock);
3602  return;
3603  }
3604  if (pte->seq_server < seq) {
3606  "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
3607  tmpbuf, (unsigned)pte->seq_server);
3608  ast_mutex_unlock(&pte->lock);
3609  return;
3610  }
3611  if (unistimdebug)
3612  ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
3613  tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
3614  pte->last_seq_ack = seq;
3615  check_send_queue(pte);
3616  ast_mutex_unlock(&pte->lock);
3617  return;
3618  }
3619  if (buf[4] == 2) {
3620  if (unistimdebug)
3621  ast_verb(0, "Request received\n");
3622  if (pte->seq_phone == seq) {
3623  /* Send ACK */
3624  buf[4] = 1;
3625  buf[5] = 1;
3626  send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
3627  pte->seq_phone++;
3628 
3629  process_request(size, buf, pte);
3630  return;
3631  }
3632  if (pte->seq_phone > seq) {
3634  "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
3635  tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
3636  /* BUG ? pte->device->seq_phone = seq; */
3637  /* Send ACK */
3638  buf[4] = 1;
3639  buf[5] = 1;
3640  send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
3641  return;
3642  }
3644  "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
3645  tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
3646  return;
3647  }
3648  if (buf[4] == 0) {
3649  ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, (unsigned)seq);
3650  if (pte->last_seq_ack > seq) {
3652  "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
3653  tmpbuf, (unsigned)pte->last_seq_ack);
3654  return;
3655  }
3656  if (pte->seq_server < seq) {
3658  "%s Error : received a request for a non-existent packet : #0x%.4x\n",
3659  tmpbuf, (unsigned)pte->seq_server);
3660  return;
3661  }
3662  send_retransmit(pte);
3663  return;
3664  }
3665  ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
3666  tmpbuf, (unsigned)buf[4]);
3667  return;
3668 }
3669 
3670 static struct unistimsession *channel_to_session(struct ast_channel *ast)
3671 {
3672  struct unistim_subchannel *sub;
3673  if (!ast) {
3674  ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
3675  return NULL;
3676  }
3677  if (!ast->tech_pvt) {
3678  ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
3679  return NULL;
3680  }
3681  sub = ast->tech_pvt;
3682 
3683  if (!sub->parent) {
3684  ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
3685  return NULL;
3686  }
3687  if (!sub->parent->parent) {
3688  ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
3689  return NULL;
3690  }
3691  if (!sub->parent->parent->session) {
3692  ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
3693  return NULL;
3694  }
3695  return sub->parent->parent->session;
3696 }
3697 
3698 /*--- unistim_call: Initiate UNISTIM call from PBX ---*/
3699 /* used from the dial() application */
3700 static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
3701 {
3702  int res = 0;
3703  struct unistim_subchannel *sub;
3704  struct unistimsession *session;
3705 
3706  session = channel_to_session(ast);
3707  if (!session) {
3708  ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
3709  return -1;
3710  }
3711 
3712  sub = ast->tech_pvt;
3713  if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
3714  ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
3715  ast->name);
3716  return -1;
3717  }
3718 
3719  if (unistimdebug)
3720  ast_verb(3, "unistim_call(%s)\n", ast->name);
3721 
3722  session->state = STATE_RINGING;
3723  Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
3724 
3725  if (sub->owner) {
3726  if (sub->owner->connected.id.number.valid
3727  && sub->owner->connected.id.number.str) {
3728  if (session->device->height == 1) {
3730  } else {
3732  }
3733  change_callerid(session, 0, sub->owner->connected.id.number.str);
3734  } else {
3735  if (session->device->height == 1) {
3737  } else {
3739  }
3740  change_callerid(session, 0, DEFAULTCALLERID);
3741  }
3742  if (sub->owner->connected.id.name.valid
3743  && sub->owner->connected.id.name.str) {
3745  change_callerid(session, 1, sub->owner->connected.id.name.str);
3746  } else {
3748  change_callerid(session, 1, DEFAULTCALLERNAME);
3749  }
3750  }
3751  send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
3752  send_text_status(session, "Accept Ignore");
3753 
3754  if (sub->ringstyle == -1)
3755  send_ring(session, session->device->ringvolume, session->device->ringstyle);
3756  else {
3757  if (sub->ringvolume == -1)
3758  send_ring(session, session->device->ringvolume, sub->ringstyle);
3759  else
3760  send_ring(session, sub->ringvolume, sub->ringstyle);
3761  }
3763 
3766  return res;
3767 }
3768 
3769 /*--- unistim_hangup: Hangup UNISTIM call */
3770 static int unistim_hangup(struct ast_channel *ast)
3771 {
3772  struct unistim_subchannel *sub;
3773  struct unistim_line *l;
3774  struct unistimsession *s;
3775 
3776  s = channel_to_session(ast);
3777  sub = ast->tech_pvt;
3778  if (!s) {
3779  ast_debug(1, "Asked to hangup channel not connected\n");
3780  ast_mutex_lock(&sub->lock);
3781  sub->owner = NULL;
3782  ast->tech_pvt = NULL;
3783  sub->alreadygone = 0;
3784  ast_mutex_unlock(&sub->lock);
3785  if (sub->rtp) {
3786  if (unistimdebug)
3787  ast_verb(0, "Destroying RTP session\n");
3789  sub->rtp = NULL;
3790  }
3791  return 0;
3792  }
3793  l = sub->parent;
3794  if (unistimdebug)
3795  ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
3796 
3797  if ((l->subs[SUB_THREEWAY]) && (sub->subtype == SUB_REAL)) {
3798  if (unistimdebug)
3799  ast_verb(0, "Real call disconnected while talking to threeway\n");
3800  sub->owner = NULL;
3801  ast->tech_pvt = NULL;
3802  return 0;
3803  }
3804  if ((l->subs[SUB_REAL]->owner) && (sub->subtype == SUB_THREEWAY) &&
3805  (sub->alreadygone == 0)) {
3806  if (unistimdebug)
3807  ast_verb(0, "threeway call disconnected, switching to real call\n");
3808  send_text(TEXT_LINE0, TEXT_NORMAL, s, "Three way call canceled,");
3809  send_text(TEXT_LINE1, TEXT_NORMAL, s, "switching back to");
3810  send_text(TEXT_LINE2, TEXT_NORMAL, s, "previous call.");
3811  send_text_status(s, "Hangup Transf");
3814  l->parent->moh = 0;
3815  ast_mutex_lock(&sub->lock);
3816  sub->owner = NULL;
3817  ast->tech_pvt = NULL;
3818  ast_mutex_unlock(&sub->lock);
3820  return 0;
3821  }
3822  ast_mutex_lock(&sub->lock);
3823  sub->owner = NULL;
3824  ast->tech_pvt = NULL;
3825  sub->alreadygone = 0;
3826  ast_mutex_unlock(&sub->lock);
3827  if (!s) {
3828  if (unistimdebug)
3829  ast_verb(0, "Asked to hangup channel not connected (no session)\n");
3830  if (sub->rtp) {
3831  if (unistimdebug)
3832  ast_verb(0, "Destroying RTP session\n");
3834  sub->rtp = NULL;
3835  }
3836  return 0;
3837  }
3838  if (sub->subtype == SUB_REAL) {
3839  /* Stop the silence generator */
3840  if (s->device->silence_generator) {
3841  if (unistimdebug)
3842  ast_verb(0, "Stopping silence generator\n");
3843  if (sub->owner)
3846  else
3848  "Trying to stop silence generator on a null channel !\n");
3849  s->device->silence_generator = NULL;
3850  }
3851  }
3852  l->parent->moh = 0;
3853  send_no_ring(s);
3854  send_end_call(s);
3855  if (sub->rtp) {
3856  if (unistimdebug)
3857  ast_verb(0, "Destroying RTP session\n");
3859  sub->rtp = NULL;
3860  } else if (unistimdebug)
3861  ast_verb(0, "No RTP session to destroy\n");
3862  if (l->subs[SUB_THREEWAY]) {
3863  if (unistimdebug)
3864  ast_verb(0, "Cleaning other subchannels\n");
3866  }
3867  if (s->state == STATE_RINGING)
3868  cancel_dial(s);
3869  else if (s->state == STATE_CALL)
3870  close_call(s);
3871 
3872  return 0;
3873 }
3874 
3875 /*--- unistim_answer: Answer UNISTIM call */
3876 static int unistim_answer(struct ast_channel *ast)
3877 {
3878  int res = 0;
3879  struct unistim_subchannel *sub;
3880  struct unistim_line *l;
3881  struct unistimsession *s;
3882 
3883  s = channel_to_session(ast);
3884  if (!s) {
3885  ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
3886  return -1;
3887  }
3888  sub = ast->tech_pvt;
3889  l = sub->parent;
3890 
3891  if ((!sub->rtp) && (!l->subs[SUB_THREEWAY]))
3892  start_rtp(sub);
3893  if (unistimdebug)
3894  ast_verb(0, "unistim_answer(%s) on %s@%s-%u\n", ast->name, l->name,
3895  l->parent->name, sub->subtype);
3896  send_text(TEXT_LINE2, TEXT_NORMAL, l->parent->session, "is now on-line");
3897  if (l->subs[SUB_THREEWAY])
3898  send_text_status(l->parent->session, "Transf Cancel");
3899  else
3900  send_text_status(l->parent->session, "Hangup Transf");
3902  if (ast->_state != AST_STATE_UP)
3903  ast_setstate(ast, AST_STATE_UP);
3904  return res;
3905 }
3906 
3907 /*--- unistimsock_read: Read data from UNISTIM socket ---*/
3908 /* Successful messages is connected to UNISTIM call and forwarded to parsing() */
3909 static int unistimsock_read(int *id, int fd, short events, void *ignore)
3910 {
3911  struct sockaddr_in addr_from = { 0, };
3912  struct unistimsession *cur = NULL;
3913  int found = 0;
3914  int tmp = 0;
3915  int dw_num_bytes_rcvd;
3916 #ifdef DUMP_PACKET
3917  int dw_num_bytes_rcvdd;
3918  char iabuf[INET_ADDRSTRLEN];
3919 #endif
3920 
3921  dw_num_bytes_rcvd =
3922  recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
3923  &size_addr_from);
3924  if (dw_num_bytes_rcvd == -1) {
3925  if (errno == EAGAIN)
3926  ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
3927  else if (errno != ECONNREFUSED)
3928  ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
3929  return 1;
3930  }
3931 
3932  /* Looking in the phone list if we already have a registration for him */
3934  cur = sessions;
3935  while (cur) {
3936  if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
3937  found = 1;
3938  break;
3939  }
3940  tmp++;
3941  cur = cur->next;
3942  }
3944 
3945 #ifdef DUMP_PACKET
3946  if (unistimdebug)
3947  ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
3948  dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
3949  for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
3950  dw_num_bytes_rcvdd++)
3951  ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
3952  ast_verb(0, "\n******************************************\n");
3953 #endif
3954 
3955  if (!found) {
3956  if (unistimdebug)
3957  ast_verb(0, "Received a packet from an unknown source\n");
3958  parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
3959 
3960  } else
3961  parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
3962 
3963  return 1;
3964 }
3965 
3966 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
3967  const struct unistim_subchannel *sub)
3968 {
3969  /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
3970  struct ast_frame *f;
3971 
3972  if (!ast) {
3973  ast_log(LOG_WARNING, "Channel NULL while reading\n");
3974  return &ast_null_frame;
3975  }
3976 
3977  if (!sub->rtp) {
3978  ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %u\n",
3979  sub->subtype);
3980  return &ast_null_frame;
3981  }
3982 
3983  switch (ast->fdno) {
3984  case 0:
3985  f = ast_rtp_instance_read(sub->rtp, 0); /* RTP Audio */
3986  break;
3987  case 1:
3988  f = ast_rtp_instance_read(sub->rtp, 1); /* RTCP Control Channel */
3989  break;
3990  default:
3991  f = &ast_null_frame;
3992  }
3993 
3994  if (sub->owner) {
3995  /* We already hold the channel lock */
3996  if (f->frametype == AST_FRAME_VOICE) {
3997  if (f->subclass.codec != sub->owner->nativeformats) {
3998  ast_debug(1,
3999  "Oooh, format changed from %s to %s\n",
4002 
4003  sub->owner->nativeformats = f->subclass.codec;
4006  }
4007  }
4008  }
4009 
4010  return f;
4011 }
4012 
4013 static struct ast_frame *unistim_read(struct ast_channel *ast)
4014 {
4015  struct ast_frame *fr;
4016  struct unistim_subchannel *sub = ast->tech_pvt;
4017 
4018  ast_mutex_lock(&sub->lock);
4019  fr = unistim_rtp_read(ast, sub);
4020  ast_mutex_unlock(&sub->lock);
4021 
4022  return fr;
4023 }
4024 
4025 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
4026 {
4027  struct unistim_subchannel *sub = ast->tech_pvt;
4028  int res = 0;
4029 
4030  if (frame->frametype != AST_FRAME_VOICE) {
4031  if (frame->frametype == AST_FRAME_IMAGE)
4032  return 0;
4033  else {
4034  ast_log(LOG_WARNING, "Can't send %u type frames with unistim_write\n",
4035  frame->frametype);
4036  return 0;
4037  }
4038  } else {
4039  if (!(frame->subclass.codec & ast->nativeformats)) {
4040  char tmp[256];
4042  "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
4044  ast_getformatname_multiple(tmp, sizeof(tmp), ast->nativeformats),
4047  return -1;
4048  }
4049  }
4050 
4051  if (sub) {
4052  ast_mutex_lock(&sub->lock);
4053  if (sub->rtp) {
4054  res = ast_rtp_instance_write(sub->rtp, frame);
4055  }
4056  ast_mutex_unlock(&sub->lock);
4057  }
4058 
4059  return res;
4060 }
4061 
4062 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
4063 {
4064  struct unistim_subchannel *p = newchan->tech_pvt;
4065  struct unistim_line *l = p->parent;
4066 
4067  ast_mutex_lock(&p->lock);
4068 
4069  ast_debug(1, "New owner for channel USTM/%s@%s-%u is %s\n", l->name,
4070  l->parent->name, p->subtype, newchan->name);
4071 
4072  if (p->owner != oldchan) {
4073  ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
4074  oldchan->name, oldchan, p->owner->name, p->owner);
4075  ast_mutex_unlock(&p->lock);
4076  return -1;
4077  }
4078 
4079  p->owner = newchan;
4080 
4081  ast_mutex_unlock(&p->lock);
4082 
4083  return 0;
4084 
4085 }
4086 
4087 static char *control2str(int ind)
4088 {
4089  switch (ind) {
4090  case AST_CONTROL_HANGUP:
4091  return "Other end has hungup";
4092  case AST_CONTROL_RING:
4093  return "Local ring";
4094  case AST_CONTROL_RINGING:
4095  return "Remote end is ringing";
4096  case AST_CONTROL_ANSWER:
4097  return "Remote end has answered";
4098  case AST_CONTROL_BUSY:
4099  return "Remote end is busy";
4101  return "Make it go off hook";
4102  case AST_CONTROL_OFFHOOK:
4103  return "Line is off hook";
4105  return "Congestion (circuits busy)";
4106  case AST_CONTROL_FLASH:
4107  return "Flash hook";
4108  case AST_CONTROL_WINK:
4109  return "Wink";
4110  case AST_CONTROL_OPTION:
4111  return "Set a low-level option";
4112  case AST_CONTROL_RADIO_KEY:
4113  return "Key Radio";
4115  return "Un-Key Radio";
4116  case -1:
4117  return "Stop tone";
4118  }
4119  return "UNKNOWN";
4120 }
4121 
4122 static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
4123  const char *indication)
4124 {
4125  struct ast_tone_zone_sound *ts = NULL;
4126 
4127  if ((ts = ast_get_indication_tone(tz, indication))) {
4128  ast_playtones_start(ast, 0, ts->data, 1);
4129  ts = ast_tone_zone_sound_unref(ts);
4130  } else {
4131  ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
4132  }
4133 }
4134 
4135 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
4136  size_t datalen)
4137 {
4138  struct unistim_subchannel *sub;
4139  struct unistim_line *l;
4140  struct unistimsession *s;
4141 
4142  if (unistimdebug) {
4143  ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
4144  control2str(ind), ast->name);
4145  }
4146 
4147  s = channel_to_session(ast);
4148  if (!s)
4149  return -1;
4150 
4151  sub = ast->tech_pvt;
4152  l = sub->parent;
4153 
4154  switch (ind) {
4155  case AST_CONTROL_RINGING:
4156  if (ast->_state != AST_STATE_UP) {
4157  send_text(TEXT_LINE2, TEXT_NORMAL, s, "Ringing...");
4158  in_band_indication(ast, l->parent->tz, "ring");
4159  s->device->missed_call = -1;
4160  break;
4161  }
4162  return -1;
4163  case AST_CONTROL_BUSY:
4164  if (ast->_state != AST_STATE_UP) {
4165  sub->alreadygone = 1;
4166  send_text(TEXT_LINE2, TEXT_NORMAL, s, "Busy");
4167  in_band_indication(ast, l->parent->tz, "busy");
4168  s->device->missed_call = -1;
4169  break;
4170  }
4171  return -1;
4173  /* Overlapped dialing is not currently supported for UNIStim. Treat an indication
4174  * of incomplete as congestion
4175  */
4177  if (ast->_state != AST_STATE_UP) {
4178  sub->alreadygone = 1;
4179  send_text(TEXT_LINE2, TEXT_NORMAL, s, "Congestion");
4180  in_band_indication(ast, l->parent->tz, "congestion");
4181  s->device->missed_call = -1;
4182  break;
4183  }
4184  return -1;
4185  case AST_CONTROL_HOLD:
4186  ast_moh_start(ast, data, NULL);
4187  break;
4188  case AST_CONTROL_UNHOLD:
4189  ast_moh_stop(ast);
4190  break;
4191  case AST_CONTROL_PROGRESS:
4192  case AST_CONTROL_SRCUPDATE:
4193  break;
4194  case -1:
4195  ast_playtones_stop(ast);
4196  s->device->missed_call = 0;
4197  break;
4200  break;
4201  default:
4202  ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
4203  return -1;
4204  }
4205 
4206  return 0;
4207 }
4208 
4209 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
4210 {
4211  struct unistim_line *l;
4212  struct unistim_device *d;
4213  char line[256];
4214  char *at;
4215  char *device;
4216 
4217  ast_copy_string(line, dest, sizeof(line));
4218  at = strchr(line, '@');
4219  if (!at) {
4220  ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
4221  return NULL;
4222  }
4223  *at = '\0';
4224  at++;
4225  device = at;
4227  d = devices;
4228  at = strchr(device, '/'); /* Extra options ? */
4229  if (at)
4230  *at = '\0';
4231  while (d) {
4232  if (!strcasecmp(d->name, device)) {
4233  if (unistimdebug)
4234  ast_verb(0, "Found device: %s\n", d->name);
4235  /* Found the device */
4236  l = d->lines;
4237  while (l) {
4238  /* Search for the right line */
4239  if (!strcasecmp(l->name, line)) {
4240  l->subs[SUB_REAL]->ringvolume = -1;
4241  l->subs[SUB_REAL]->ringstyle = -1;
4242  if (at) { /* Other options ? */
4243  at++; /* Skip slash */
4244  if (*at == 'r') { /* distinctive ring */
4245  at++;
4246  if ((*at < '0') || (*at > '7')) /* ring style */
4247  ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
4248  else {
4249  char ring_volume = -1;
4250  char ring_style = *at - '0';
4251  at++;
4252  if ((*at >= '0') && (*at <= '3')) /* ring volume */
4253  ring_volume = *at - '0';
4254  if (unistimdebug)
4255  ast_verb(0, "Distinctive ring : style #%d volume %d\n",
4256  ring_style, ring_volume);
4257  l->subs[SUB_REAL]->ringvolume = ring_volume;
4258  l->subs[SUB_REAL]->ringstyle = ring_style;
4259  }
4260  }
4261  }
4263  return l->subs[SUB_REAL];
4264  }
4265  l = l->next;
4266  }
4267  }
4268  d = d->next;
4269  }
4270  /* Device not found */
4272 
4273  return NULL;
4274 }
4275 
4276 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
4277 {
4278  struct unistimsession *pte = channel_to_session(ast);
4279 
4280  if (!pte)
4281  return -1;
4282 
4283  return unistim_do_senddigit(pte, digit);
4284 }
4285 
4286 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
4287 {
4288  struct unistimsession *pte = channel_to_session(ast);
4289  struct ast_frame f = { 0, };
4290  struct unistim_subchannel *sub;
4291 
4292  sub = pte->device->lines->subs[SUB_REAL];
4293 
4294  if (!sub->owner || sub->alreadygone) {
4295  ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
4296  return -1;
4297  }
4298 
4299  if (unistimdebug)
4300  ast_verb(0, "Send Digit off %c\n", digit);
4301 
4302  if (!pte)
4303  return -1;
4304 
4305  send_tone(pte, 0, 0);
4307  f.subclass.integer = digit;
4308  f.src = "unistim";
4309  ast_queue_frame(sub->owner, &f);
4310 
4311  return 0;
4312 }
4313 
4314 /*--- unistim_sendtext: Display a text on the phone screen ---*/
4315 /* Called from PBX core text message functions */
4316 static int unistim_sendtext(struct ast_channel *ast, const char *text)
4317 {
4318  struct unistimsession *pte = channel_to_session(ast);
4319  int size;
4320  char tmp[TEXT_LENGTH_MAX + 1];
4321 
4322  if (unistimdebug)
4323  ast_verb(0, "unistim_sendtext called\n");
4324 
4325  if (!text) {
4326  ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
4327  return 1;
4328  }
4329 
4330  size = strlen(text);
4331  if (text[0] == '@') {
4332  int pos = 0, i = 1, tok = 0, sz = 0;
4333  char label[11];
4334  char number[16];
4335  char icon = '\0';
4336  char cur = '\0';
4337 
4338  memset(label, 0, 11);
4339  memset(number, 0, 16);
4340  while (text[i]) {
4341  cur = text[i++];
4342  switch (tok) {
4343  case 0:
4344  if ((cur < '0') && (cur > '5')) {
4346  "sendtext failed : position must be a number beetween 0 and 5\n");
4347  return 1;
4348  }
4349  pos = cur - '0';
4350  tok = 1;
4351  continue;
4352  case 1:
4353  if (cur != '@') {
4354  ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
4355  return 1;
4356  }
4357  tok = 2;
4358  continue;
4359  case 2:
4360  if ((cur < '3') && (cur > '6')) {
4362  "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
4363  return 1;
4364  }
4365  icon = (cur - '0') * 10;
4366  tok = 3;
4367  continue;
4368  case 3:
4369  if ((cur < '0') && (cur > '9')) {
4371  "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
4372  return 1;
4373  }
4374  icon += (cur - '0');
4375  tok = 4;
4376  continue;
4377  case 4:
4378  if (cur != '@') {
4380  "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
4381  return 1;
4382  }
4383  tok = 5;
4384  continue;
4385  case 5:
4386  if (cur == '@') {
4387  tok = 6;
4388  sz = 0;
4389  continue;
4390  }
4391  if (sz > 10)
4392  continue;
4393  label[sz] = cur;
4394  sz++;
4395  continue;
4396  case 6:
4397  if (sz > 15) {
4399  "sendtext failed : extension too long = %d (15 car max)\n",
4400  sz);
4401  return 1;
4402  }
4403  number[sz] = cur;
4404  sz++;
4405  continue;
4406  }
4407  }
4408  if (tok != 6) {
4409  ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
4410  return 1;
4411  }
4412  if (!pte->device) {
4413  ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
4414  return 1;
4415  }
4416  strcpy(pte->device->softkeylabel[pos], label);
4417  strcpy(pte->device->softkeynumber[pos], number);
4418  pte->device->softkeyicon[pos] = icon;
4419  send_favorite(pos, icon, pte, label);
4420  return 0;
4421  }
4422 
4423  if (size <= TEXT_LENGTH_MAX * 2) {
4424  if (pte->device->height == 1) {
4425  send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
4426  } else {
4427  send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Message :");
4428  send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
4429  }
4430  if (size <= TEXT_LENGTH_MAX) {
4431  send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
4432  return 0;
4433  }
4434  memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
4435  tmp[sizeof(tmp) - 1] = '\0';
4436  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
4437  return 0;
4438  }
4439  send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
4440  memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
4441  tmp[sizeof(tmp) - 1] = '\0';
4442  send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
4443  memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
4444  tmp[sizeof(tmp) - 1] = '\0';
4445  send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
4446  return 0;
4447 }
4448 
4449 /*--- unistim_send_mwi_to_peer: Send message waiting indication ---*/
4450 static int unistim_send_mwi_to_peer(struct unistimsession *s, unsigned int tick)
4451 {
4452  struct ast_event *event;
4453  int new;
4454  char *mailbox, *context;
4455  struct unistim_line *peer = s->device->lines;
4456 
4457  context = mailbox = ast_strdupa(peer->mailbox);
4458  strsep(&context, "@");
4459  if (ast_strlen_zero(context))
4460  context = "default";
4461 
4466 
4467  if (event) {
4469  ast_event_destroy(event);
4470  } else { /* Fall back on checking the mailbox directly */
4471  new = ast_app_has_voicemail(peer->mailbox, "INBOX");
4472  }
4473 
4474  peer->nextmsgcheck = tick + TIMER_MWI;
4475 
4476  /* Return now if it's the same thing we told them last time */
4477  if (new == peer->lastmsgssent) {
4478  return 0;
4479  }
4480 
4481  peer->lastmsgssent = new;
4482  if (new == 0) {
4483  send_led_update(s, 0);
4484  } else {
4485  send_led_update(s, 1);
4486  }
4487 
4488  return 0;
4489 }
4490 
4491 /*--- unistim_new: Initiate a call in the UNISTIM channel */
4492 /* called from unistim_request (calls from the pbx ) */
4493 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
4494 {
4495  struct ast_channel *tmp;
4496  struct unistim_line *l;
4497  int fmt;
4498 
4499  if (!sub) {
4500  ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
4501  return NULL;
4502  }
4503  if (!sub->parent) {
4504  ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
4505  return NULL;
4506  }
4507  l = sub->parent;
4508  tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
4509  l->context, linkedid, l->amaflags, "%s@%s-%u", l->name, l->parent->name, sub->subtype);
4510  if (unistimdebug)
4511  ast_verb(0, "unistim_new sub=%u (%p) chan=%p\n", sub->subtype, sub, tmp);
4512  if (!tmp) {
4513  ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
4514  return NULL;
4515  }
4516 
4517  tmp->nativeformats = l->capability;
4518  if (!tmp->nativeformats)
4519  tmp->nativeformats = CAPABILITY;
4520  fmt = ast_best_codec(tmp->nativeformats);
4521  if (unistimdebug) {
4522  char tmp1[256], tmp2[256], tmp3[256];
4523  ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
4524  ast_getformatname(fmt),
4525  ast_getformatname_multiple(tmp1, sizeof(tmp1), tmp->nativeformats),
4526  ast_getformatname_multiple(tmp2, sizeof(tmp2), l->capability),
4527  ast_getformatname_multiple(tmp3, sizeof(tmp3), CAPABILITY));
4528  }
4529  if ((sub->rtp) && (sub->subtype == 0)) {
4530  if (unistimdebug)
4531  ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
4532  tmp->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
4533  tmp->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
4534  }
4535  if (sub->rtp)
4537 
4538 /* tmp->type = type; */
4539  ast_setstate(tmp, state);
4540  if (state == AST_STATE_RING)
4541  tmp->rings = 1;
4543  tmp->writeformat = fmt;
4544  tmp->rawwriteformat = fmt;
4545  tmp->readformat = fmt;
4546  tmp->rawreadformat = fmt;
4547  tmp->tech_pvt = sub;
4548  tmp->tech = &unistim_tech;
4549  if (!ast_strlen_zero(l->language))
4551  sub->owner = tmp;
4553  usecnt++;
4556  tmp->callgroup = l->callgroup;
4557  tmp->pickupgroup = l->pickupgroup;
4558  ast_string_field_set(tmp, call_forward, l->parent->call_forward);
4559  if (!ast_strlen_zero(l->cid_num)) {
4560  char *name, *loc, *instr;
4561  instr = ast_strdup(l->cid_num);
4562  if (instr) {
4563  ast_callerid_parse(instr, &name, &loc);
4564  tmp->caller.id.number.valid = 1;
4565  ast_free(tmp->caller.id.number.str);
4566  tmp->caller.id.number.str = ast_strdup(loc);
4567  tmp->caller.id.name.valid = 1;
4568  ast_free(tmp->caller.id.name.str);
4569  tmp->caller.id.name.str = ast_strdup(name);
4570  ast_free(instr);
4571  }
4572  }
4573  tmp->priority = 1;
4574  if (state != AST_STATE_DOWN) {
4575  if (unistimdebug)
4576  ast_verb(0, "Starting pbx in unistim_new\n");
4577  if (ast_pbx_start(tmp)) {
4578  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
4579  ast_hangup(tmp);
4580  tmp = NULL;
4581  }
4582  }
4583 
4584  return tmp;
4585 }
4586 
4587 static void *do_monitor(void *data)
4588 {
4589  struct unistimsession *cur = NULL;
4590  unsigned int dw_timeout = 0;
4591  unsigned int tick;
4592  int res;
4593  int reloading;
4594 
4595  /* Add an I/O event to our UDP socket */
4596  if (unistimsock > -1)
4597  ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
4598 
4599  /* This thread monitors our UDP socket and timers */
4600  for (;;) {
4601  /* This loop is executed at least every IDLE_WAITus (1s) or every time a packet is received */
4602  /* Looking for the smallest time-out value */
4603  tick = get_tick_count();
4604  dw_timeout = UINT_MAX;
4606  cur = sessions;
4607  DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
4608  while (cur) {
4609  DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
4610  cur->timeout);
4611  /* Check if we have miss something */
4612  if (cur->timeout <= tick) {
4613  DEBUG_TIMER("Event for session %p\n", cur);
4614  /* If the queue is empty, send a ping */
4615  if (cur->last_buf_available == 0)
4616  send_ping(cur);
4617  else {
4618  if (send_retransmit(cur)) {
4619  DEBUG_TIMER("The chained link was modified, restarting...\n");
4620  cur = sessions;
4621  dw_timeout = UINT_MAX;
4622  continue;
4623  }
4624  }
4625  }
4626  if (dw_timeout > cur->timeout - tick)
4627  dw_timeout = cur->timeout - tick;
4628  /* Checking if the phone is logged on for a new MWI */
4629  if (cur->device) {
4630  if ((!ast_strlen_zero(cur->device->lines->mailbox)) &&
4631  ((tick >= cur->device->lines->nextmsgcheck))) {
4632  DEBUG_TIMER("Checking mailbox for MWI\n");
4633  unistim_send_mwi_to_peer(cur, tick);
4634  break;
4635  }
4636  }
4637  cur = cur->next;
4638  }
4640  DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
4641  res = dw_timeout;
4642  /* We should not wait more than IDLE_WAIT */
4643  if ((res < 0) || (res > IDLE_WAIT))
4644  res = IDLE_WAIT;
4645  /* Wait for UDP messages for a maximum of res us */
4646  res = ast_io_wait(io, res); /* This function will call unistimsock_read if a packet is received */
4647  /* Check for a reload request */
4649  reloading = unistim_reloading;
4650  unistim_reloading = 0;
4652  if (reloading) {
4653  ast_verb(1, "Reloading unistim.conf...\n");
4654  reload_config();
4655  }
4656  pthread_testcancel();
4657  }
4658  /* Never reached */
4659  return NULL;
4660 }
4661 
4662 /*--- restart_monitor: Start the channel monitor thread ---*/
4663 static int restart_monitor(void)
4664 {
4665  pthread_attr_t attr;
4666  /* If we're supposed to be stopped -- stay stopped */
4667  if (monitor_thread == AST_PTHREADT_STOP)
4668  return 0;
4669  if (ast_mutex_lock(&monlock)) {
4670  ast_log(LOG_WARNING, "Unable to lock monitor\n");
4671  return -1;
4672  }
4673  if (monitor_thread == pthread_self()) {
4675  ast_log(LOG_WARNING, "Cannot kill myself\n");
4676  return -1;
4677  }
4678  if (monitor_thread != AST_PTHREADT_NULL) {
4679  /* Wake up the thread */
4680  pthread_kill(monitor_thread, SIGURG);
4681  } else {
4682  pthread_attr_init(&attr);
4683  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
4684  /* Start a new monitor */
4685  if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
4687  ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
4688  return -1;
4689  }
4690  }
4692  return 0;
4693 }
4694 
4695 /*--- unistim_request: PBX interface function ---*/
4696 /* UNISTIM calls initiated by the PBX arrive here */
4697 static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor, void *data,
4698  int *cause)
4699 {
4700  format_t oldformat;
4701  struct unistim_subchannel *sub;
4702  struct ast_channel *tmpc = NULL;
4703  char tmp[256];
4704  char *dest = data;
4705 
4706  oldformat = format;
4707  format &= CAPABILITY;
4709  "Asked to get a channel of format %s while capability is %s result : %s\n",
4710  ast_getformatname(oldformat),
4711  ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY),
4712  ast_getformatname(format));
4713  if (!format) {
4715  "Asked to get a channel of unsupported format %s while capability is %s\n",
4716  ast_getformatname(oldformat), ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY));
4717  return NULL;
4718  }
4719 
4720  ast_copy_string(tmp, dest, sizeof(tmp));
4721  if (ast_strlen_zero(tmp)) {
4722  ast_log(LOG_NOTICE, "Unistim channels require a device\n");
4723  return NULL;
4724  }
4725 
4726  sub = find_subchannel_by_name(tmp);
4727  if (!sub) {
4728  ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
4729  *cause = AST_CAUSE_CONGESTION;
4730  return NULL;
4731  }
4732 
4733  ast_verb(3, "unistim_request(%s)\n", tmp);
4734  /* Busy ? */
4735  if (sub->owner) {
4736  if (unistimdebug)
4737  ast_verb(0, "Can't create channel : Busy !\n");
4738  *cause = AST_CAUSE_BUSY;
4739  return NULL;
4740  }
4741  sub->parent->capability = format;
4742  tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
4743  if (!tmpc)
4744  ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
4745  if (unistimdebug)
4746  ast_verb(0, "unistim_request owner = %p\n", sub->owner);
4747  restart_monitor();
4748 
4749  /* and finish */
4750  return tmpc;
4751 }
4752 
4753 static char *unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4754 {
4755  struct unistim_device *device = devices;
4756  struct unistim_line *line;
4757  struct unistim_subchannel *sub;
4758  struct unistimsession *s;
4759  int i;
4760  struct ast_channel *tmp;
4761 
4762  switch (cmd) {
4763  case CLI_INIT:
4764  e->command = "unistim show info";
4765  e->usage =
4766  "Usage: unistim show info\n"
4767  " Dump internal structures.\n";
4768  return NULL;
4769 
4770  case CLI_GENERATE:
4771  return NULL; /* no completion */
4772  }
4773 
4774  if (a->argc != e->args)
4775  return CLI_SHOWUSAGE;
4776 
4777  ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
4778  while (device) {
4779  ast_cli(a->fd, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
4780  device->name, device->id, device->lines, device->ha, device->session,
4781  device);
4782  line = device->lines;
4783  while (line) {
4784  ast_cli(a->fd,
4785  "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " device=%p line=%p\n",
4786  line->name, line->fullname, line->exten, line->cid_num,
4787  line->capability, line->parent, line);
4788  for (i = 0; i < MAX_SUBS; i++) {
4789  sub = line->subs[i];
4790  if (!sub)
4791  continue;
4792  if (!sub->owner)
4793  tmp = (void *) -42;
4794  else
4795  tmp = sub->owner->_bridge;
4796  if (sub->subtype != i)
4797  ast_cli(a->fd, "Warning ! subchannel->subs[%d] have a subtype=%u\n", i,
4798  sub->subtype);
4799  ast_cli(a->fd,
4800  "-->subtype=%u chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
4801  sub->subtype, sub->owner, sub->rtp, tmp, sub->parent,
4802  sub->alreadygone);
4803  }
4804  line = line->next;
4805  }
4806  device = device->next;
4807  }
4808  ast_cli(a->fd, "\nSessions:\n");
4810  s = sessions;
4811  while (s) {
4812  ast_cli(a->fd,
4813  "sin=%s timeout=%d state=%d macaddr=%s device=%p session=%p\n",
4814  ast_inet_ntoa(s->sin.sin_addr), s->timeout, s->state, s->macaddr,
4815  s->device, s);
4816  s = s->next;
4817  }
4819 
4820  return CLI_SUCCESS;
4821 }
4822 
4823 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4824 {
4825  BUFFSEND;
4826  struct unistim_subchannel *sub;
4827  int i, j = 0, len;
4828  unsigned char c, cc;
4829  char tmp[256];
4830 
4831  switch (cmd) {
4832  case CLI_INIT:
4833  e->command = "unistim send packet";
4834  e->usage =
4835  "Usage: unistim send packet USTM/line@name hexa\n"
4836  " unistim send packet USTM/1000@hans 19040004\n";
4837  return NULL;
4838 
4839  case CLI_GENERATE:
4840  return NULL; /* no completion */
4841  }
4842 
4843  if (a->argc < 5)
4844  return CLI_SHOWUSAGE;
4845 
4846  if (strlen(a->argv[3]) < 9)
4847  return CLI_SHOWUSAGE;
4848 
4849  len = strlen(a->argv[4]);
4850  if (len % 2)
4851  return CLI_SHOWUSAGE;
4852 
4853  ast_copy_string(tmp, a->argv[3] + 5, sizeof(tmp));
4854  sub = find_subchannel_by_name(tmp);
4855  if (!sub) {
4856  ast_cli(a->fd, "Can't find '%s'\n", tmp);
4857  return CLI_SUCCESS;
4858  }
4859  if (!sub->parent->parent->session) {
4860  ast_cli(a->fd, "'%s' is not connected\n", tmp);
4861  return CLI_SUCCESS;
4862  }
4863  ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->parent->parent->session);
4864  for (i = 0; i < len; i++) {
4865  c = a->argv[4][i];
4866  if (c >= 'a')
4867  c -= 'a' - 10;
4868  else
4869  c -= '0';
4870  i++;
4871  cc = a->argv[4][i];
4872  if (cc >= 'a')
4873  cc -= 'a' - 10;
4874  else
4875  cc -= '0';
4876  tmp[j++] = (c << 4) | cc;
4877  }
4878  memcpy(buffsend + SIZE_HEADER, tmp, j);
4879  send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
4880  return CLI_SUCCESS;
4881 }
4882 
4883 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4884 {
4885  switch (cmd) {
4886  case CLI_INIT:
4887  e->command = "unistim set debug {on|off}";
4888  e->usage =
4889  "Usage: unistim set debug\n"
4890  " Display debug messages.\n";
4891  return NULL;
4892 
4893  case CLI_GENERATE:
4894  return NULL; /* no completion */
4895  }
4896 
4897  if (a->argc != e->args)
4898  return CLI_SHOWUSAGE;
4899 
4900  if (!strcasecmp(a->argv[3], "on")) {
4901  unistimdebug = 1;
4902  ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
4903  } else if (!strcasecmp(a->argv[3], "off")) {
4904  unistimdebug = 0;
4905  ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
4906  } else
4907  return CLI_SHOWUSAGE;
4908 
4909  return CLI_SUCCESS;
4910 }
4911 
4912 /*! \brief --- unistim_reload: Force reload of module from cli ---
4913  * Runs in the asterisk main thread, so don't do anything useful
4914  * but setting a flag and waiting for do_monitor to do the job
4915  * in our thread */
4916 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
4917 {
4918  switch (cmd) {
4919  case CLI_INIT:
4920  e->command = "unistim reload";
4921  e->usage =
4922  "Usage: unistim reload\n"
4923  " Reloads UNISTIM configuration from unistim.conf\n";
4924  return NULL;
4925 
4926  case CLI_GENERATE:
4927  return NULL; /* no completion */
4928  }
4929 
4930  if (e && a && a->argc != e->args)
4931  return CLI_SHOWUSAGE;
4932 
4933  if (unistimdebug)
4934  ast_verb(0, "reload unistim\n");
4935 
4937  if (!unistim_reloading)
4938  unistim_reloading = 1;
4940 
4941  restart_monitor();
4942 
4943  return CLI_SUCCESS;
4944 }
4945 
4946 static struct ast_cli_entry unistim_cli[] = {
4947  AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
4948  AST_CLI_DEFINE(unistim_info, "Show UNISTIM info"),
4949  AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
4950  AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
4951 };
4952 
4953 static void unquote(char *out, const char *src, int maxlen)
4954 {
4955  int len = strlen(src);
4956  if (!len)
4957  return;
4958  if ((len > 1) && src[0] == '\"') {
4959  /* This is a quoted string */
4960  src++;
4961  /* Don't take more than what's there */
4962  len--;
4963  if (maxlen > len - 1)
4964  maxlen = len - 1;
4965  memcpy(out, src, maxlen);
4966  ((char *) out)[maxlen] = '\0';
4967  } else
4968  memcpy(out, src, maxlen);
4969  return;
4970 }
4971 
4972 static int ParseBookmark(const char *text, struct unistim_device *d)
4973 {
4974  char line[256];
4975  char *at;
4976  char *number;
4977  char *icon;
4978  int p;
4979  int len = strlen(text);
4980 
4981  ast_copy_string(line, text, sizeof(line));
4982  /* Position specified ? */
4983  if ((len > 2) && (line[1] == '@')) {
4984  p = line[0];
4985  if ((p >= '0') && (p <= '5'))
4986  p -= '0';
4987  else {
4989  "Invalid position for bookmark : must be between 0 and 5\n");
4990  return 0;
4991  }
4992  if (d->softkeyicon[p] != 0) {
4993  ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used\n:", p);
4994  return 0;
4995  }
4996  memmove(line, line + 2, sizeof(line) - 2);
4997  } else {
4998  /* No position specified, looking for a free slot */
4999  for (p = 0; p <= 5; p++) {
5000  if (!d->softkeyicon[p])
5001  break;
5002  }
5003  if (p > 5) {
5004  ast_log(LOG_WARNING, "No more free bookmark position\n");
5005  return 0;
5006  }
5007  }
5008  at = strchr(line, '@');
5009  if (!at) {
5010  ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
5011  return 0;
5012  }
5013  *at = '\0';
5014  at++;
5015  number = at;
5016  at = strchr(at, '@');
5017  if (ast_strlen_zero(number)) {
5018  ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
5019  return 0;
5020  }
5021  if (ast_strlen_zero(line)) {
5022  ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
5023  return 0;
5024  }
5025 
5026  at = strchr(number, '@');
5027  if (!at)
5028  d->softkeyicon[p] = FAV_ICON_SHARP; /* default icon */
5029  else {
5030  *at = '\0';
5031  at++;
5032  icon = at;
5033  if (ast_strlen_zero(icon)) {
5034  ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
5035  return 0;
5036  }
5037  if (strncmp(icon, "USTM/", 5))
5038  d->softkeyicon[p] = atoi(icon);
5039  else {
5040  d->softkeyicon[p] = 1;
5041  ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
5042  }
5043  }
5044  ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
5045  ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
5046  if (unistimdebug)
5047  ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
5048  p, d->softkeylabel[p], d->softkeynumber[p], (unsigned)d->softkeyicon[p]);
5049  return 1;
5050 }
5051 
5052 /* Looking for dynamic icons entries in bookmarks */
5053 static void finish_bookmark(void)
5054 {
5055  struct unistim_device *d = devices;
5056  int i;
5057  while (d) {
5058  for (i = 0; i < 6; i++) {
5059  if (d->softkeyicon[i] == 1) { /* Something for us */
5060  struct unistim_device *d2 = devices;
5061  while (d2) {
5062  if (!strcmp(d->softkeydevice[i], d2->name)) {
5063  d->sp[i] = d2;
5064  d->softkeyicon[i] = 0;
5065  break;
5066  }
5067  d2 = d2->next;
5068  }
5069  if (d->sp[i] == NULL)
5070  ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
5071  d->softkeydevice[i]);
5072  }
5073  }
5074  d = d->next;
5075  }
5076 }
5077 
5078 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
5079 {
5080  struct unistim_device *d;
5081  struct unistim_line *l = NULL;
5082  int create = 1;
5083  int nbsoftkey, dateformat, timeformat, callhistory;
5084  char linelabel[AST_MAX_EXTENSION];
5085  char context[AST_MAX_EXTENSION];
5086  char ringvolume, ringstyle;
5087 
5088  /* First, we need to know if we already have this name in our list */
5089  /* Get a lock for the device chained list */
5091  d = devices;
5092  while (d) {
5093  if (!strcmp(d->name, cat)) {
5094  /* Yep, we alreay have this one */
5095  if (unistimsock < 0) {
5096  /* It's a dupe */
5097  ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
5099  return NULL;
5100  }
5101  /* we're reloading right now */
5102  create = 0;
5103  l = d->lines;
5104  break;
5105  }
5106  d = d->next;
5107  }
5109  if (create) {
5110  if (!(d = ast_calloc(1, sizeof(*d))))
5111  return NULL;
5112 
5113  if (!(l = ast_calloc(1, sizeof(*l)))) {
5114  ast_free(d);
5115  return NULL;
5116  }
5117  ast_copy_string(d->name, cat, sizeof(d->name));
5118  d->contrast = -1;
5119  d->output = OUTPUT_HANDSET;
5121  d->volume = VOLUME_LOW;
5122  d->mute = MUTE_OFF;
5123  d->height = DEFAULTHEIGHT;
5124  }
5125  ast_copy_string(context, DEFAULTCONTEXT, sizeof(context));
5126  linelabel[0] = '\0';
5127  dateformat = 1;
5128  timeformat = 1;
5129  ringvolume = 2;
5130  callhistory = 1;
5131  ringstyle = 3;
5132  nbsoftkey = 0;
5133  while (v) {
5134  if (!strcasecmp(v->name, "rtp_port"))
5135  d->rtp_port = atoi(v->value);
5136  else if (!strcasecmp(v->name, "rtp_method"))
5137  d->rtp_method = atoi(v->value);
5138  else if (!strcasecmp(v->name, "status_method"))
5139  d->status_method = atoi(v->value);
5140  else if (!strcasecmp(v->name, "device"))
5141  ast_copy_string(d->id, v->value, sizeof(d->id));
5142  else if (!strcasecmp(v->name, "tn"))
5144  else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny"))
5145  d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
5146  else if (!strcasecmp(v->name, "context"))
5147  ast_copy_string(context, v->value, sizeof(context));
5148  else if (!strcasecmp(v->name, "maintext0"))
5149  unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
5150  else if (!strcasecmp(v->name, "maintext1"))
5151  unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
5152  else if (!strcasecmp(v->name, "maintext2"))
5153  unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
5154  else if (!strcasecmp(v->name, "titledefault"))
5155  unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
5156  else if (!strcasecmp(v->name, "dateformat"))
5157  dateformat = atoi(v->value);
5158  else if (!strcasecmp(v->name, "timeformat"))
5159  timeformat = atoi(v->value);
5160  else if (!strcasecmp(v->name, "contrast")) {
5161  d->contrast = atoi(v->value);
5162  if ((d->contrast < 0) || (d->contrast > 15)) {
5163  ast_log(LOG_WARNING, "contrast must be beetween 0 and 15\n");
5164  d->contrast = 8;
5165  }
5166  } else if (!strcasecmp(v->name, "nat"))
5167  d->nat = ast_true(v->value);
5168  else if (!strcasecmp(v->name, "ringvolume"))
5169  ringvolume = atoi(v->value);
5170  else if (!strcasecmp(v->name, "ringstyle"))
5171  ringstyle = atoi(v->value);
5172  else if (!strcasecmp(v->name, "callhistory"))
5173  callhistory = atoi(v->value);
5174  else if (!strcasecmp(v->name, "callerid")) {
5175  if (!strcasecmp(v->value, "asreceived"))
5176  l->cid_num[0] = '\0';
5177  else
5178  ast_copy_string(l->cid_num, v->value, sizeof(l->cid_num));
5179  } else if (!strcasecmp(v->name, "language"))
5180  ast_copy_string(l->language, v->value, sizeof(l->language));
5181  else if (!strcasecmp(v->name, "country"))
5182  ast_copy_string(d->country, v->value, sizeof(d->country));
5183  else if (!strcasecmp(v->name, "accountcode"))
5184  ast_copy_string(l->accountcode, v->value, sizeof(l->accountcode));
5185  else if (!strcasecmp(v->name, "amaflags")) {
5186  int y;
5187  y = ast_cdr_amaflags2int(v->value);
5188  if (y < 0)
5189  ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
5190  v->lineno);
5191  else
5192  l->amaflags = y;
5193  } else if (!strcasecmp(v->name, "musiconhold"))
5194  ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass));
5195  else if (!strcasecmp(v->name, "callgroup"))
5196  l->callgroup = ast_get_group(v->value);
5197  else if (!strcasecmp(v->name, "pickupgroup"))
5198  l->pickupgroup = ast_get_group(v->value);
5199  else if (!strcasecmp(v->name, "mailbox"))
5200  ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
5201  else if (!strcasecmp(v->name, "parkinglot"))
5202  ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
5203  else if (!strcasecmp(v->name, "linelabel"))
5204  unquote(linelabel, v->value, sizeof(linelabel) - 1);
5205  else if (!strcasecmp(v->name, "extension")) {
5206  if (!strcasecmp(v->value, "none"))
5208  else if (!strcasecmp(v->value, "ask"))
5209  d->extension = EXTENSION_ASK;
5210  else if (!strcasecmp(v->value, "line"))
5212  else
5213  ast_log(LOG_WARNING, "Unknown extension option.\n");
5214  } else if (!strcasecmp(v->name, "bookmark")) {
5215  if (nbsoftkey > 5)
5217  "More than 6 softkeys defined. Ignoring new entries.\n");
5218  else {
5219  if (ParseBookmark(v->value, d))
5220  nbsoftkey++;
5221  }
5222  } else if (!strcasecmp(v->name, "line")) {
5223  int len = strlen(linelabel);
5224 
5225  if (nbsoftkey) {
5227  "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
5228  if (create) {
5229  ast_free(d);
5230  ast_free(l);
5231  }
5232  return NULL;
5233  }
5234  if (create) {
5235  ast_mutex_init(&l->lock);
5236  } else {
5237  d->to_delete = 0;
5238  /* reset bookmarks */
5239  memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
5240  memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
5241  memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
5242  memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
5243  memset(d->sp, 0, sizeof(d->sp));
5244  }
5245  ast_copy_string(l->name, v->value, sizeof(l->name));
5246  snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
5248  if (!len) /* label is undefined ? */
5249  ast_copy_string(d->softkeylabel[0], v->value, sizeof(d->softkeylabel[0]));
5250  else {
5251  if ((len > 2) && (linelabel[1] == '@')) {
5252  d->softkeylinepos = linelabel[0];
5253  if ((d->softkeylinepos >= '0') && (d->softkeylinepos <= '5')) {
5254  d->softkeylinepos -= '0';
5255  d->softkeyicon[0] = 0;
5256  } else {
5258  "Invalid position for linelabel : must be between 0 and 5\n");
5259  d->softkeylinepos = 0;
5260  }
5261  ast_copy_string(d->softkeylabel[d->softkeylinepos], linelabel + 2,
5262  sizeof(d->softkeylabel[d->softkeylinepos]));
5264  } else
5265  ast_copy_string(d->softkeylabel[0], linelabel,
5266  sizeof(d->softkeylabel[0]));
5267  }
5268  nbsoftkey++;
5269  ast_copy_string(l->context, context, sizeof(l->context));
5270  if (!ast_strlen_zero(l->mailbox)) {
5271  if (unistimdebug)
5272  ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
5273  }
5274 
5275  l->capability = CAPABILITY;
5276  l->parent = d;
5277 
5278  if (create) {
5279  if (!alloc_sub(l, SUB_REAL)) {
5280  ast_mutex_destroy(&l->lock);
5281  ast_free(l);
5282  ast_free(d);
5283  return NULL;
5284  }
5285  l->next = d->lines;
5286  d->lines = l;
5287  }
5288  } else if (!strcasecmp(v->name, "height")) {
5289  /* Allow the user to lower the expected display lines on the phone
5290  * For example the Nortal I2001 and I2002 only have one ! */
5291  d->height = atoi(v->value);
5292  } else
5293  ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
5294  v->lineno);
5295  v = v->next;
5296  }
5297  d->ringvolume = ringvolume;
5298  d->ringstyle = ringstyle;
5299  d->callhistory = callhistory;
5301  if ((d->tz == NULL) && !ast_strlen_zero(d->country))
5302  ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
5303  d->country);
5304  d->datetimeformat = 56 + (dateformat * 4);
5305  d->datetimeformat += timeformat;
5306  if (!d->lines) {
5307  ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
5308  ast_mutex_destroy(&l->lock);
5309  ast_free(l);
5310  if (d->tz) {
5311  d->tz = ast_tone_zone_unref(d->tz);
5312  }
5313  ast_free(d);
5314  return NULL;
5315  }
5316  if ((autoprovisioning == AUTOPROVISIONING_TN) &&
5318  d->extension = EXTENSION_TN;
5319  if (!ast_strlen_zero(d->id))
5321  "tn= and device= can't be used together. Ignoring device= entry\n");
5322  d->id[0] = 'T'; /* magic : this is a tn entry */
5323  ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
5324  d->extension_number[0] = '\0';
5325  } else if (ast_strlen_zero(d->id)) {
5326  if (strcmp(d->name, "template")) {
5327  ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
5328  ast_mutex_destroy(&l->lock);
5329  ast_free(l);
5330  if (d->tz) {
5331  d->tz = ast_tone_zone_unref(d->tz);
5332  }
5333  ast_free(d);
5334  return NULL;
5335  } else
5336  strcpy(d->id, "000000000000");
5337  }
5338  if (!d->rtp_port)
5339  d->rtp_port = 10000;
5340  if (d->contrast == -1)
5341  d->contrast = 8;
5342  if (ast_strlen_zero(d->maintext0))
5343  strcpy(d->maintext0, "Welcome");
5344  if (ast_strlen_zero(d->maintext1))
5345  strcpy(d->maintext1, d->name);
5346  if (ast_strlen_zero(d->titledefault)) {
5347  struct ast_tm tm = { 0, };
5348  struct timeval cur_time = ast_tvnow();
5349 
5350  if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
5351  display_last_error("Error in ast_localtime()");
5352  ast_copy_string(d->titledefault, "UNISTIM for*", 12);
5353  } else {
5354  if (strlen(tm.tm_zone) < 4) {
5355  strcpy(d->titledefault, "TimeZone ");
5356  strcat(d->titledefault, tm.tm_zone);
5357  } else if (strlen(tm.tm_zone) < 9) {
5358  strcpy(d->titledefault, "TZ ");
5359  strcat(d->titledefault, tm.tm_zone);
5360  } else
5361  ast_copy_string(d->titledefault, tm.tm_zone, 12);
5362  }
5363  }
5364  /* Update the chained link if it's a new device */
5365  if (create) {
5367  d->next = devices;
5368  devices = d;
5370  ast_verb(3, "Added device '%s'\n", d->name);
5371  } else {
5372  ast_verb(3, "Device '%s' reloaded\n", d->name);
5373  }
5374  return d;
5375 }
5376 
5377 /*--- reload_config: Re-read unistim.conf config file ---*/
5378 static int reload_config(void)
5379 {
5380  struct ast_config *cfg;
5381  struct ast_variable *v;
5382  struct ast_hostent ahp;
5383  struct hostent *hp;
5384  struct sockaddr_in bindaddr = { 0, };
5385  char *config = "unistim.conf";
5386  char *cat;
5387  struct unistim_device *d;
5388  const int reuseFlag = 1;
5389  struct unistimsession *s;
5390  struct ast_flags config_flags = { 0, };
5391 
5392  cfg = ast_config_load(config, config_flags);
5393  /* We *must* have a config file otherwise stop immediately */
5394  if (!cfg) {
5395  ast_log(LOG_ERROR, "Unable to load config %s\n", config);
5396  return -1;
5397  } else if (cfg == CONFIG_STATUS_FILEINVALID) {
5398  ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
5399  return -1;
5400  }
5401 
5402  /* Copy the default jb config over global_jbconf */
5403  memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
5404 
5405  unistim_keepalive = 120;
5406  unistim_port = 0;
5407  v = ast_variable_browse(cfg, "general");
5408  while (v) {
5409  /* handle jb conf */
5410  if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
5411  continue;
5412 
5413  if (!strcasecmp(v->name, "keepalive"))
5414  unistim_keepalive = atoi(v->value);
5415  else if (!strcasecmp(v->name, "port"))
5416  unistim_port = atoi(v->value);
5417  else if (!strcasecmp(v->name, "tos")) {
5418  if (ast_str2tos(v->value, &qos.tos))
5419  ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
5420  } else if (!strcasecmp(v->name, "tos_audio")) {
5421  if (ast_str2tos(v->value, &qos.tos_audio))
5422  ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
5423  } else if (!strcasecmp(v->name, "cos")) {
5424  if (ast_str2cos(v->value, &qos.cos))
5425  ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
5426  } else if (!strcasecmp(v->name, "cos_audio")) {
5427  if (ast_str2cos(v->value, &qos.cos_audio))
5428  ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
5429  } else if (!strcasecmp(v->name, "autoprovisioning")) {
5430  if (!strcasecmp(v->value, "no"))
5431  autoprovisioning = AUTOPROVISIONING_NO;
5432  else if (!strcasecmp(v->value, "yes"))
5433  autoprovisioning = AUTOPROVISIONING_YES;
5434  else if (!strcasecmp(v->value, "db"))
5435  autoprovisioning = AUTOPROVISIONING_DB;
5436  else if (!strcasecmp(v->value, "tn"))
5437  autoprovisioning = AUTOPROVISIONING_TN;
5438  else
5439  ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
5440  } else if (!strcasecmp(v->name, "public_ip")) {
5441  if (!ast_strlen_zero(v->value)) {
5442  if (!(hp = ast_gethostbyname(v->value, &ahp)))
5443  ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
5444  else {
5445  memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
5446  public_ip.sin_family = AF_INET;
5447  }
5448  }
5449  }
5450  v = v->next;
5451  }
5452  if ((unistim_keepalive < 10) ||
5453  (unistim_keepalive >
5454  255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
5455  ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
5456  ast_config_destroy(cfg);
5457  return -1;
5458  }
5459  packet_send_ping[4] =
5460  unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
5461  if ((unistim_port < 1) || (unistim_port > 65535)) {
5462  ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
5463  ast_config_destroy(cfg);
5464  return -1;
5465  }
5466  unistim_keepalive *= 1000;
5467 
5469  d = devices;
5470  while (d) {
5471  if (d->to_delete >= 0)
5472  d->to_delete = 1;
5473  d = d->next;
5474  }
5476  /* load the device sections */
5477  cat = ast_category_browse(cfg, NULL);
5478  while (cat) {
5479  if (strcasecmp(cat, "general")) {
5480  d = build_device(cat, ast_variable_browse(cfg, cat));
5481  }
5482  cat = ast_category_browse(cfg, cat);
5483  }
5485  d = devices;
5486  while (d) {
5487  if (d->to_delete) {
5488  int i;
5489 
5490  if (unistimdebug)
5491  ast_verb(0, "Removing device '%s'\n", d->name);
5492  if (!d->lines) {
5493  ast_log(LOG_ERROR, "Device '%s' without a line !, aborting\n", d->name);
5494  ast_config_destroy(cfg);
5495  return 0;
5496  }
5497  if (!d->lines->subs[0]) {
5498  ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
5499  d->name);
5500  ast_config_destroy(cfg);
5501  return 0;
5502  }
5503  if (d->lines->subs[0]->owner) {
5505  "Device '%s' was not deleted : a call is in progress. Try again later.\n",
5506  d->name);
5507  d = d->next;
5508  continue;
5509  }
5510  ast_mutex_destroy(&d->lines->subs[0]->lock);
5511  ast_free(d->lines->subs[0]);
5512  for (i = 1; i < MAX_SUBS; i++) {
5513  if (d->lines->subs[i]) {
5515  "Device '%s' with threeway call subchannels allocated, aborting.\n",
5516  d->name);
5517  break;
5518  }
5519  }
5520  if (i < MAX_SUBS) {
5521  d = d->next;
5522  continue;
5523  }
5525  ast_free(d->lines);
5526  if (d->session) {
5527  if (sessions == d->session)
5528  sessions = d->session->next;
5529  else {
5530  s = sessions;
5531  while (s) {
5532  if (s->next == d->session) {
5533  s->next = d->session->next;
5534  break;
5535  }
5536  s = s->next;
5537  }
5538  }
5540  ast_free(d->session);
5541  }
5542  if (devices == d)
5543  devices = d->next;
5544  else {
5545  struct unistim_device *d2 = devices;
5546  while (d2) {
5547  if (d2->next == d) {
5548  d2->next = d->next;
5549  break;
5550  }
5551  d2 = d2->next;
5552  }
5553  }
5554  if (d->tz) {
5555  d->tz = ast_tone_zone_unref(d->tz);
5556  }
5557  ast_free(d);
5558  d = devices;
5559  continue;
5560  }
5561  d = d->next;
5562  }
5563  finish_bookmark();
5565  ast_config_destroy(cfg);
5567  s = sessions;
5568  while (s) {
5569  if (s->device)
5571  s = s->next;
5572  }
5574  /* We don't recreate a socket when reloading (locks would be necessary). */
5575  if (unistimsock > -1)
5576  return 0;
5577  bindaddr.sin_addr.s_addr = INADDR_ANY;
5578  bindaddr.sin_port = htons(unistim_port);
5579  bindaddr.sin_family = AF_INET;
5580  unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
5581  if (unistimsock < 0) {
5582  ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
5583  return -1;
5584  }
5585 #ifdef HAVE_PKTINFO
5586  {
5587  const int pktinfoFlag = 1;
5588  setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
5589  sizeof(pktinfoFlag));
5590  }
5591 #else
5592  if (public_ip.sin_family == 0) {
5594  "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
5595  unistimsock = -1;
5596  return -1;
5597  }
5598 #endif
5599  setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
5600  sizeof(reuseFlag));
5601  if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
5602  ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
5603  ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
5604  strerror(errno));
5605  close(unistimsock);
5606  unistimsock = -1;
5607  } else {
5608  ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
5609  ast_netsock_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
5610  }
5611  return 0;
5612 }
5613 
5614 static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
5615 {
5616  struct unistim_subchannel *sub = chan->tech_pvt;
5617 
5618  if (!sub) {
5620  }
5621  if (!sub->rtp) {
5623  }
5624 
5625  ao2_ref(sub->rtp, +1);
5626  *instance = sub->rtp;
5627 
5629 }
5630 
5631 static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
5632 {
5633  struct unistim_subchannel *sub;
5634  struct sockaddr_in them = { 0, };
5635  struct sockaddr_in us = { 0, };
5636 
5637  if (!rtp) {
5638  return 0;
5639  }
5640 
5641  sub = chan->tech_pvt;
5642  if (!sub) {
5643  ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
5644  return -1;
5645  }
5646  {
5647  struct ast_sockaddr tmp;
5649  ast_sockaddr_to_sin(&tmp, &them);
5651  ast_sockaddr_to_sin(&tmp, &us);
5652  }
5653 
5654  /* TODO: Set rtp on phone in case of direct rtp (not implemented) */
5655 
5656  return 0;
5657 }
5658 
5660  .type = channel_type,
5661  .get_rtp_info = unistim_get_rtp_peer,
5662  .update_peer = unistim_set_rtp_peer,
5663 };
5664 
5665 /*--- load_module: PBX load module - initialization ---*/
5666 int load_module(void)
5667 {
5668  int res;
5669 
5670  if (!(buff = ast_malloc(SIZE_PAGE)))
5671  goto buff_failed;
5672 
5673  io = io_context_create();
5674  if (!io) {
5675  ast_log(LOG_ERROR, "Failed to allocate IO context\n");
5676  goto io_failed;
5677  }
5678 
5679  sched = sched_context_create();
5680  if (!sched) {
5681  ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
5682  goto sched_failed;
5683  }
5684 
5685  res = reload_config();
5686  if (res)
5687  return AST_MODULE_LOAD_DECLINE;
5688 
5689  /* Make sure we can register our unistim channel type */
5690  if (ast_channel_register(&unistim_tech)) {
5691  ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
5692  goto chanreg_failed;
5693  }
5694 
5695  ast_rtp_glue_register(&unistim_rtp_glue);
5696 
5697  ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
5698 
5699  restart_monitor();
5700 
5701  return AST_MODULE_LOAD_SUCCESS;
5702 
5703 chanreg_failed:
5704  /*! XXX \todo Leaking anything allocated by reload_config() ... */
5705  sched_context_destroy(sched);
5706  sched = NULL;
5707 sched_failed:
5708  io_context_destroy(io);
5709  io = NULL;
5710 io_failed:
5711  ast_free(buff);
5712  buff = NULL;
5713 buff_failed:
5714  return AST_MODULE_LOAD_FAILURE;
5715 }
5716 
5717 static int unload_module(void)
5718 {
5719  /* First, take us out of the channel loop */
5720  if (sched)
5721  sched_context_destroy(sched);
5722 
5723  ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
5724 
5725  ast_channel_unregister(&unistim_tech);
5726  ast_rtp_glue_unregister(&unistim_rtp_glue);
5727 
5729  if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
5730  pthread_cancel(monitor_thread);
5731  pthread_kill(monitor_thread, SIGURG);
5732  pthread_join(monitor_thread, NULL);
5733  }
5734  monitor_thread = AST_PTHREADT_STOP;
5736 
5737  if (buff)
5738  ast_free(buff);
5739  if (unistimsock > -1)
5740  close(unistimsock);
5741 
5742  return 0;
5743 }
5744 
5745 /*! reload: Part of Asterisk module interface ---*/
5746 int reload(void)
5747 {
5748  unistim_reload(NULL, 0, NULL);
5749  return 0;
5750 }
5751 
5752 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
5753  .load = load_module,
5754  .unload = unload_module,
5755  .reload = reload,
5756 );
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
Definition: io.c:273
static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
static const unsigned char packet_send_query_basic_manager_10[]
Definition: chan_unistim.c:669
static const char channel_type[]
Definition: chan_unistim.c:678
char * tm_zone
Definition: localtime.h:46
ast_mutex_t lock
Definition: chan_unistim.c:367
static const unsigned char packet_send_select_output[]
Definition: chan_unistim.c:573
static const unsigned char packet_send_icon[]
Definition: chan_unistim.c:635
struct ast_channel * owner
Definition: chan_unistim.c:371
char softkeynumber[6][16]
Definition: chan_unistim.c:438
#define SELECTEXTENSION_START_ENTRY_POS
char call_forward[AST_MAX_EXTENSION]
Definition: chan_unistim.c:461
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
Definition: channel.c:1569
union ast_frame_subclass subclass
Definition: frame.h:146
static const unsigned char packet_send_StartTimer[]
Definition: chan_unistim.c:631
#define TIMER_MWI
Definition: chan_unistim.c:97
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
static int alloc_sub(struct unistim_line *l, int x)
phone_key
Definition: chan_unistim.c:269
Tone Indication Support.
static char * unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
static int unistim_port
Definition: chan_unistim.c:212
static int write_history(struct unistimsession *pte, char way, char ismissed)
static const unsigned char packet_send_S1[]
Definition: chan_unistim.c:670
static struct unistimsession * sessions
struct sockaddr_in sout
Definition: chan_unistim.c:482
Main Channel structure associated with a channel.
Definition: channel.h:742
Music on hold handling.
static void show_history(struct unistimsession *pte, char way)
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
static struct tone_zone_unistim frequency[]
Definition: chan_unistim.c:316
An event.
Definition: event.c:85
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
Definition: chan_unistim.c:801
struct ast_party_connected_line connected
Channel Connected Line ID information.
Definition: channel.h:811
const char *const type
Definition: channel.h:508
Asterisk main include file. File version handling, generic pbx functions.
int rings
Definition: channel.h:840
static int UnregisterExtension(const struct unistimsession *pte)
static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
static struct ast_frame * unistim_rtp_read(const struct ast_channel *ast, const struct unistim_subchannel *sub)
static const char config[]
Definition: cdr_csv.c:57
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame with payload.
Definition: channel.c:1601
struct ast_frame ast_null_frame
Definition: frame.c:131
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
static const unsigned char packet_send_stream_based_tone_off[]
Definition: chan_unistim.c:561
char * strsep(char **str, const char *delims)
static void rcv_resume_connection_with_server(struct unistimsession *pte)
A device containing one or more lines.
Definition: chan_unistim.c:427
char name[DEVICE_NAME_LEN]
Definition: chan_unistim.c:435
static struct @114 qos
static pthread_t monitor_thread
Definition: chan_unistim.c:241
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
Definition: indications.h:204
int priority
Definition: channel.h:841
unsigned short w_second
Definition: chan_unistim.c:362
#define TEXT_LINE2
Definition: chan_unistim.c:144
unsigned int pickupgroup
Definition: chan_unistim.c:411
static struct ast_channel * unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
#define ast_strdup(a)
Definition: astmm.h:109
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
format_t writeformat
Definition: channel.h:854
char parkinglot[AST_MAX_CONTEXT]
Definition: chan_unistim.c:419
static const unsigned char packet_send_date_time2[]
Definition: chan_unistim.c:626
static unsigned int tos
Definition: chan_h323.c:146
#define FAV_ICON_ONHOLD_BLACK
Definition: chan_unistim.c:156
time_t start_call_timestamp
Definition: chan_unistim.c:471
struct ast_party_id id
Connected party ID.
Definition: channel.h:403
char lst_cnm[TEXT_LENGTH_MAX]
Definition: chan_unistim.c:460
struct ast_rtp_instance * rtp
Definition: chan_unistim.c:375
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
static int unistimsock
Definition: chan_unistim.c:215
static struct sockaddr_in address_from
Definition: chan_unistim.c:228
#define AST_CAUSE_SWITCH_CONGESTION
Definition: causes.h:122
char language[MAX_LANGUAGE]
Definition: chan_unistim.c:397
#define MAX_MUSICCLASS
Definition: channel.h:139
struct ast_party_name name
Subscriber name.
Definition: channel.h:290
#define AST_FORMAT_G723_1
Definition: frame.h:242
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
Definition: channel.c:938
#define FAV_ICON_HEADPHONES_ONHOLD
Definition: chan_unistim.c:165
static const unsigned char packet_send_s4[]
Definition: chan_unistim.c:545
unsigned int callgroup
Definition: chan_unistim.c:409
void * tech_pvt
Definition: channel.h:744
#define TEXT_LINE1
Definition: chan_unistim.c:143
static void Keyfavorite(struct unistimsession *pte, char keycode)
#define AST_CAUSE_NETWORK_OUT_OF_ORDER
Definition: causes.h:120
static void check_send_queue(struct unistimsession *pte)
Definition: chan_unistim.c:931
int ast_app_has_voicemail(const char *mailbox, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to &quot;INBOX&quot;. If folder is &quot;INBOX&quot;, includes the number of messages in the &quot;Urgent&quot; folder.
Definition: app.c:421
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
Definition: rtp_engine.c:483
static const unsigned char packet_send_Contrast[]
Definition: chan_unistim.c:629
struct wsabuf wsabufsend[MAX_BUF_NUMBER]
Definition: chan_unistim.c:494
static char * unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
unsigned short w_minute
Definition: chan_unistim.c:361
descriptor for a cli entry.
Definition: cli.h:165
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
static int send_retransmit(struct unistimsession *pte)
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
unsigned short seq_server
Definition: chan_unistim.c:485
phone_state
Definition: chan_unistim.c:251
static struct ast_cli_entry unistim_cli[]
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category)
Goes through variables.
Definition: config.c:597
static const unsigned char packet_send_stream_based_tone_single_freq[]
Definition: chan_unistim.c:569
static void dummy(char *unused,...)
Definition: chan_unistim.c:188
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
Definition: abstract_jb.c:577
int lineno
Definition: config.h:87
#define SUB_THREEWAY
Definition: chan_unistim.c:106
static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz, const char *indication)
#define FAV_ICON_SHARP
Definition: chan_unistim.c:168
#define AST_FRAME_DTMF
Definition: frame.h:128
static struct io_context * io
Definition: chan_unistim.c:224
#define AST_CONFIG_MAX_PATH
Definition: chan_unistim.c:102
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define MAX_BUF_SIZE
Definition: chan_unistim.c:87
autoprovision
Definition: chan_unistim.c:109
static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static struct unistim_device * build_device(const char *cat, const struct ast_variable *v)
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
Definition: rtp_engine.c:774
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:374
format_t rawwriteformat
Definition: channel.h:856
static const unsigned char packet_recv_pick_up[]
Definition: chan_unistim.c:520
#define ast_rtp_glue_register(glue)
Definition: rtp_engine.h:476
static void send_ping(struct unistimsession *pte)
Definition: chan_unistim.c:832
static void unquote(char *out, const char *src, int maxlen)
#define DEBUG_TIMER
Definition: chan_unistim.c:209
#define AST_IO_IN
Definition: io.h:33
Definition: cli.h:146
struct ast_event * ast_event_get_cached(enum ast_event_type,...)
Retrieve an event from the cache.
Definition: event.c:1342
static void send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume, unsigned char mute)
static void key_main_page(struct unistimsession *pte, char keycode)
Configuration File Parser.
int ast_netsock_set_qos(int netsocket, int tos, int cos, const char *desc)
Definition: netsock.c:158
char * str
Subscriber name (Malloced)
Definition: channel.h:214
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:157
static void close_call(struct unistimsession *pte)
static void set_ping_timer(struct unistimsession *pte)
Definition: chan_unistim.c:920
#define BUFFSEND
Definition: chan_unistim.c:675
static const unsigned char packet_send_set_pos_cursor[]
Definition: chan_unistim.c:637
#define IDLE_WAIT
Definition: chan_unistim.c:93
static struct ast_threadstorage buf2
static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
char phone_number[16]
Definition: chan_unistim.c:430
format_t ast_best_codec(format_t fmts)
Pick the best audio codec.
Definition: channel.c:1062
unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]
Definition: chan_unistim.c:495
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
Number of new messages Used by: AST_EVENT_MWI Payload type: UINT.
Definition: event_defs.h:71
handset_state
Definition: chan_unistim.c:264
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
Definition: channel.c:907
static char * tz
Definition: cdr_pgsql.c:56
#define AST_MODULE_INFO(keystr, flags_to_set, desc, fields...)
Definition: module.h:374
char * text
Definition: app_queue.c:1091
format_t nativeformats
Definition: channel.h:852
static const unsigned char packet_send_stream_based_tone_on[]
Definition: chan_unistim.c:567
static void close_client(struct unistimsession *s)
static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
Definition: acl.c:667
format_t codec
Definition: frame.h:137
#define MAX_BUF_NUMBER
Definition: chan_unistim.c:89
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
static const unsigned char packet_send_query_mac_address[]
Definition: chan_unistim.c:668
#define TEXT_NORMAL
Definition: chan_unistim.c:145
const char * data
Definition: channel.h:755
#define FAV_ICON_ONHOOK_BLACK
Definition: chan_unistim.c:150
static const unsigned char packet_send_led_update[]
Definition: chan_unistim.c:665
static void send_date_time3(struct unistimsession *pte)
static const unsigned char packet_send_open_audio_stream_tx[]
Definition: chan_unistim.c:604
static int ParseBookmark(const char *text, struct unistim_device *d)
static void * unistim_ss(void *data)
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
void ast_update_use_count(void)
Notify when usecount has been changed.
Definition: loader.c:1222
const ast_string_field linkedid
Definition: channel.h:787
#define MAX_SUBS
Definition: chan_unistim.c:107
static const unsigned char packet_send_S7[]
Definition: chan_unistim.c:636
enum ast_channel_adsicpe adsicpe
Definition: channel.h:844
format_t rawreadformat
Definition: channel.h:855
static void HandleSelectCodec(struct unistimsession *pte)
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
Definition: channel.c:8051
static void HandleCallOutgoing(struct unistimsession *s)
Socket address structure.
Definition: netsock2.h:63
ast_group_t pickupgroup
Definition: channel.h:819
int tm_year
Definition: localtime.h:41
static struct ast_frame * unistim_read(struct ast_channel *ast)
static const unsigned char packet_send_date_time[]
Definition: chan_unistim.c:536
#define ast_verb(level,...)
Definition: logger.h:243
void ast_config_destroy(struct ast_config *config)
Destroys a config.
Definition: config.c:1037
const char * type
Definition: rtp_engine.h:395
#define TEXT_LENGTH_MAX
Definition: chan_unistim.c:141
struct unistim_subchannel * subs[MAX_SUBS]
Definition: chan_unistim.c:391
static void * do_monitor(void *data)
ast_group_t callgroup
Definition: channel.h:818
static ast_mutex_t sessionlock
Definition: chan_unistim.c:247
ast_mutex_t lock
Definition: chan_unistim.c:480
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
static int load_module(void)
static const unsigned char packet_send_open_audio_stream_rx3[]
Definition: chan_unistim.c:610
static int unistim_answer(struct ast_channel *ast)
#define AST_FORMAT_G729A
Definition: frame.h:258
static int unistim_register(struct unistimsession *s)
#define MAX_LANGUAGE
Definition: channel.h:138
static int mute
Definition: chan_alsa.c:135
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:6114
#define VOLUME_LOW
Definition: chan_unistim.c:130
unsigned short last_seq_ack
Definition: chan_unistim.c:486
static int unistimdebug
Definition: chan_unistim.c:211
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
Definition: channel.c:1581
#define FAV_ICON_HEADPHONES
Definition: chan_unistim.c:164
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static char OpenHistory(struct unistimsession *pte, char way, FILE **f)
#define STATUS_LENGTH_MAX
Definition: chan_unistim.c:147
#define RETRANSMIT_TIMER
Definition: chan_unistim.c:95
static char * unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
#define USTM_LOG_DIR
Definition: chan_unistim.c:84
static char * unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
— unistim_reload: Force reload of module from cli — Runs in the asterisk main thread, so don&#39;t do anything useful but setting a flag and waiting for do_monitor to do the job in our thread
static void send_blink_cursor(struct unistimsession *pte)
static struct unistim_subchannel * find_subchannel_by_name(const char *dest)
static int unistim_send_mwi_to_peer(struct unistimsession *s, unsigned int tick)
struct unistim_device * device
Definition: chan_unistim.c:496
unsigned int subtype
Definition: chan_unistim.c:369
struct unistimsession * next
Definition: chan_unistim.c:497
char accountcode[80]
Definition: chan_unistim.c:413
struct ast_ha * ha
Definition: chan_unistim.c:474
static int unalloc_sub(struct unistim_line *p, int x)
Number structure.
Definition: app_followme.c:109
char name[80]
Definition: chan_unistim.c:387
internal representation of acl entries In principle user applications would have no need for this...
Definition: acl.h:48
static void send_texttitle(struct unistimsession *pte, const char *text)
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
static const char tdesc[]
Definition: chan_unistim.c:677
struct unistim_line * next
Definition: chan_unistim.c:420
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
static void refresh_all_favorite(struct unistimsession *pte)
char titledefault[13]
Definition: chan_unistim.c:446
static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
Definition: chan_unistim.c:983
#define MUTE_OFF
Definition: chan_unistim.c:135
static ast_mutex_t devicelock
Definition: chan_unistim.c:249
static void start_rtp(struct unistim_subchannel *sub)
static const unsigned char packet_recv_firm_version[]
Definition: chan_unistim.c:516
char macaddr[18]
Definition: chan_unistim.c:493
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
unsigned long tick_next_ping
Definition: chan_unistim.c:487
static const unsigned char packet_send_jitter_buffer_conf[]
Definition: chan_unistim.c:590
#define FAV_ICON_PHONE_BLACK
Definition: chan_unistim.c:160
Context IE Used by AST_EVENT_MWI Payload type: str.
Definition: event_defs.h:121
#define DEFAULT_CODEC
Definition: chan_unistim.c:99
ast_mutex_t lock
Definition: chan_unistim.c:385
const char * value
Definition: config.h:79
static struct sockaddr_in public_ip
Definition: chan_unistim.c:226
#define FAV_BLINK_SLOW
Definition: chan_unistim.c:184
#define VOLUME_LOW_SPEAKER
Definition: chan_unistim.c:131
#define OUTPUT_HEADPHONE
Definition: chan_unistim.c:127
static const unsigned char packet_send_ring[]
Definition: chan_unistim.c:575
static const unsigned char packet_send_date_time3[]
Definition: chan_unistim.c:532
#define OUTPUT_HANDSET
Definition: chan_unistim.c:126
General Asterisk PBX channel definitions.
#define DEVICE_NAME_LEN
Definition: chan_unistim.c:101
Asterisk file paths, configured in asterisk.conf.
void io_context_destroy(struct io_context *ioc)
Destroys a context.
Definition: io.c:102
const char * src
Definition: frame.h:158
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
Definition: netsock2.h:642
static const unsigned char packet_send_stop_timer[]
Definition: chan_unistim.c:634
Network socket handling.
A set of tones for a given locale.
Definition: indications.h:73
const int fd
Definition: cli.h:153
#define DEFAULTCALLERNAME
Definition: chan_unistim.c:82
#define AST_FORMAT_ALAW
Definition: frame.h:248
#define ast_config_load(filename, flags)
Load a config file.
Definition: config.h:170
#define DEFAULTCALLERID
Definition: chan_unistim.c:81
static const unsigned char packet_send_favorite[]
Definition: chan_unistim.c:642
static int reload_config(void)
#define AST_PTHREADT_NULL
Definition: lock.h:65
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct unistim_device * next
Definition: chan_unistim.c:476
Access Control of various sorts.
#define SIZE_HEADER
Definition: chan_unistim.c:139
static int unload_module(void)
char softkeydevice[6][16]
Definition: chan_unistim.c:440
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:66
#define AST_MAX_EXTENSION
Definition: channel.h:135
static int get_to_address(int fd, struct sockaddr_in *toAddr)
Definition: chan_unistim.c:842
int datalen
Definition: frame.h:148
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
struct unistimsession * session
Definition: chan_unistim.c:475
int tm_mon
Definition: localtime.h:40
static void key_select_extension(struct unistimsession *pte, char keycode)
#define NB_MAX_RETRANSMIT
Definition: chan_unistim.c:91
#define ao2_ref(o, delta)
Definition: astobj2.h:472
char * ast_category_browse(struct ast_config *config, const char *prev)
Goes through categories.
Definition: config.c:810
static struct ast_jb_conf default_jbconf
Global jitterbuffer configuration - by default, jb is disabled.
Definition: chan_unistim.c:195
char mailbox[AST_MAX_EXTENSION]
Definition: chan_unistim.c:401
#define FAV_ICON_NONE
Definition: chan_unistim.c:149
static char * control2str(int ind)
unsigned int cos_audio
Definition: chan_mgcp.c:173
static int unistim_keepalive
Definition: chan_unistim.c:214
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:226
int ast_rtp_instance_set_remote_address(struct ast_rtp_instance *instance, const struct ast_sockaddr *address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:391
static const unsigned char packet_send_query_basic_manager_04[]
Definition: chan_unistim.c:667
#define MAX_ENTRY_LOG
Definition: chan_unistim.c:103
char softkeylabel[6][11]
Definition: chan_unistim.c:437
static void handle_dial_page(struct unistimsession *pte)
static char language[MAX_LANGUAGE]
Definition: chan_alsa.c:108
const char * name
Definition: config.h:77
static int unistim_sendtext(struct ast_channel *ast, const char *text)
#define TEXT_LINE0
Definition: chan_unistim.c:142
static const unsigned char packet_send_open_audio_stream_tx3[]
Definition: chan_unistim.c:617
struct ast_channel * _bridge
Definition: channel.h:748
char maintext0[25]
Definition: chan_unistim.c:443
ast_group_t ast_get_group(const char *s)
Definition: channel.c:7987
int tm_mday
Definition: localtime.h:39
struct ast_tone_zone * tz
Definition: chan_unistim.c:450
unsigned short w_day_of_week
Definition: chan_unistim.c:358
ast_rtp_glue_result
Definition: rtp_engine.h:125
#define FAV_ICON_SPEAKER_ONHOLD_BLACK
Definition: chan_unistim.c:162
Structure to describe a channel &quot;technology&quot;, ie a channel driver See for examples: ...
Definition: channel.h:507
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel&#39;s frame queue.
Definition: channel.c:1558
#define FAV_BLINK_FAST
Definition: chan_unistim.c:183
enum autoprov_extn extension
Definition: chan_unistim.c:468
char cid_num[AST_MAX_EXTENSION]
Definition: chan_unistim.c:399
char musicclass[MAX_MUSICCLASS]
Definition: chan_unistim.c:407
static struct unistimsession * create_client(const struct sockaddr_in *addr_from)
Definition: chan_unistim.c:875
static unsigned int size_addr_from
Definition: chan_unistim.c:230
static int ReformatNumber(char *number)
#define FAV_ICON_SPEAKER_ONHOOK_BLACK
Definition: chan_unistim.c:152
static int unistim_do_senddigit(struct unistimsession *pte, char digit)
static struct sched_context * sched
Definition: chan_gtalk.c:227
static void send_stop_timer(struct unistimsession *pte)
Definition: chan_unistim.c:963
Wrapper for network related headers, masking differences between various operating systems...
static void send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte, const char *text)
static void ShowExtensionPage(struct unistimsession *pte)
const char *const * argv
Definition: cli.h:155
static const unsigned char packet_send_status2[]
Definition: chan_unistim.c:661
int fds[AST_MAX_FDS]
Definition: channel.h:829
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
Definition: channel.c:8309
static struct ast_jb_conf global_jbconf
Definition: chan_unistim.c:203
static void SendDialTone(struct unistimsession *pte)
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
unsigned short w_milliseconds
Definition: chan_unistim.c:363
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define LOG_ERROR
Definition: logger.h:155
static void send_text_status(struct unistimsession *pte, const char *text)
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
void sched_context_destroy(struct sched_context *c)
destroys a schedule context Destroys (free&#39;s) the given sched_context structure
Definition: sched.c:267
static const unsigned char packet_send_call[]
Definition: chan_unistim.c:552
#define FAV_ICON_CALL_CENTER
Definition: chan_unistim.c:170
static void IgnoreCall(struct unistimsession *pte)
int64_t format_t
Definition: frame_defs.h:32
static const unsigned char packet_send_no_ring[]
Definition: chan_unistim.c:543
static const unsigned char packet_recv_resume_connection_with_server[]
Definition: chan_unistim.c:527
static const unsigned char packet_recv_hangup[]
Definition: chan_unistim.c:522
#define CLI_SHOWUSAGE
Definition: cli.h:44
static void show_main_page(struct unistimsession *pte)
static char country[80]
Definition: pbx_dundi.c:196
static const unsigned char packet_recv_pressed_key[]
Definition: chan_unistim.c:518
static void swap_subs(struct unistim_line *p, int a, int b)
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
Definition: indications.c:451
#define AST_FORMAT_ULAW
Definition: frame.h:246
static void key_history(struct unistimsession *pte, char keycode)
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_cdr_amaflags2int(const char *flag)
Convert a string to a detail record AMA flag.
Definition: cdr.c:1105
Description of a tone.
Definition: indications.h:36
enum ast_channel_state _state
Definition: channel.h:839
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:473
struct ast_channel * ast_bridged_channel(struct ast_channel *chan)
Find bridged channel.
Definition: channel.c:7160
time_t nextmsgcheck
Definition: chan_unistim.c:405
#define FAV_ICON_SPEAKER_OFFHOOK_BLACK
Definition: chan_unistim.c:158
const ast_string_field name
Definition: channel.h:787
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
Definition: channel.c:8040
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static const unsigned char packet_send_s9[]
Definition: chan_unistim.c:585
static const unsigned char packet_send_text[]
Definition: chan_unistim.c:650
#define LOG_NOTICE
Definition: logger.h:133
char redial_number[16]
Definition: chan_unistim.c:431
const char * ast_config_AST_LOG_DIR
Definition: asterisk.c:263
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2733
struct unistim_line * lines
Definition: chan_unistim.c:473
static const unsigned char packet_send_title[]
Definition: chan_unistim.c:647
int fdno
Definition: channel.h:834
static void cancel_dial(struct unistimsession *pte)
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
Definition: channel.c:8355
static const unsigned char packet_send_stream_based_tone_dial_freq[]
Definition: chan_unistim.c:571
int errno
static const char name[]
#define AST_MAX_CONTEXT
Definition: channel.h:136
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
Definition: utils.c:564
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
#define ast_pthread_create(a, b, c, d)
Definition: utils.h:418
static const unsigned char packet_send_end_call[]
Definition: chan_unistim.c:580
u_long len
Definition: chan_unistim.c:351
#define SELECTEXTENSION_MAX_LENGTH
void ast_rtp_instance_get_remote_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.c:447
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
Definition: acl.c:653
static const unsigned char packet_send_rtp_packet_size[]
Definition: chan_unistim.c:588
static struct ast_format f[]
Definition: format_g726.c:181
#define DEFAULTHEIGHT
Definition: chan_unistim.c:83
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
Definition: rtp_engine.c:786
static struct unistim_device * devices
char context[AST_MAX_EXTENSION]
Definition: chan_unistim.c:395
struct sockaddr_in sin
Definition: chan_unistim.c:481
static void send_led_update(struct unistimsession *pte, unsigned char led)
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:308
static int unistim_hangup(struct ast_channel *ast)
char lst_cid[TEXT_LENGTH_MAX]
Definition: chan_unistim.c:459
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
Definition: abstract_jb.h:58
static void send_ring(struct unistimsession *pte, char volume, char style)
int tm_hour
Definition: localtime.h:38
unsigned short seq_phone
Definition: chan_unistim.c:484
static const char type[]
Definition: chan_nbs.c:57
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:430
Structure used to handle boolean flags.
Definition: utils.h:200
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:301
char fullname[80]
Definition: chan_unistim.c:389
static int unistim_reloading
Definition: chan_unistim.c:233
char exten[AST_MAX_EXTENSION]
Definition: chan_unistim.c:393
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
Definition: abstract_jb.c:616
#define TEXT_INVERSE
Definition: chan_unistim.c:146
static void send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte, const char *text)
static struct ast_channel * unistim_request(const char *type, format_t format, const struct ast_channel *requestor, void *data, int *cause)
static int write_entry_history(struct unistimsession *pte, FILE *f, char c, char *line1)
const char * usage
Definition: cli.h:171
uint32_t ast_event_get_ie_uint(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has an integer payload.
Definition: event.c:1075
static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
#define MUTE_ON
Definition: chan_unistim.c:136
static const unsigned char packet_send_blink_cursor[]
Definition: chan_unistim.c:625
#define FAV_MAX_LENGTH
Definition: chan_unistim.c:186
#define SUB_REAL
Definition: chan_unistim.c:105
int tm_sec
Definition: localtime.h:36
#define MUTE_ON_DISCRET
Definition: chan_unistim.c:137
#define CLI_SUCCESS
Definition: cli.h:43
static void parsing(int size, unsigned char *buf, struct unistimsession *pte, struct sockaddr_in *addr_from)
static void HandleCallIncoming(struct unistimsession *s)
static volatile unsigned int seq
Definition: app_sms.c:118
static int reload(void)
static void key_select_codec(struct unistimsession *pte, char keycode)
static const unsigned char packet_send_open_audio_stream_rx[]
Definition: chan_unistim.c:599
struct hostent * ast_gethostbyname(const char *host, struct ast_hostent *hp)
Thread-safe gethostbyname function to use in Asterisk.
Definition: utils.c:195
static char dateformat[256]
Definition: logger.c:69
static void key_call(struct unistimsession *pte, char keycode)
static void send_no_ring(struct unistimsession *pte)
void ast_event_destroy(struct ast_event *event)
Destroy an event.
Definition: event.c:1314
static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
struct sched_context * sched_context_create(void)
New schedule context.
Definition: sched.c:246
unsigned short w_hour
Definition: chan_unistim.c:360
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
Channels have this property if they can create jitter; i.e. most VoIP channels.
Definition: channel.h:888
unsigned int tos_audio
Definition: chan_mgcp.c:171
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
#define ast_calloc(a, b)
Definition: astmm.h:82
static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
char buff_entry[16]
Definition: chan_unistim.c:492
struct unistim_line * parent
Definition: chan_unistim.c:373
static unsigned char * buff
Definition: chan_unistim.c:232
static enum autoprovision autoprovisioning
Definition: chan_unistim.c:213
#define SELECTCODEC_START_ENTRY_POS
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
#define OUTPUT_SPEAKER
Definition: chan_unistim.c:128
static void send_date_time(struct unistimsession *pte)
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
#define AST_PTHREADT_STOP
Definition: lock.h:66
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
Definition: rtp_engine.c:266
static const unsigned char packet_send_status[]
Definition: chan_unistim.c:656
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
#define AST_CAUSE_BUSY
Definition: causes.h:148
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:5926
char * ast_getformatname_multiple(char *buf, size_t size, format_t format)
Get the names of a set of formats.
Definition: frame.c:591
struct unistim_device * parent
Definition: chan_unistim.c:421
static const unsigned char packet_recv_mac_addr[]
Definition: chan_unistim.c:529
static int RegisterExtension(const struct unistimsession *pte)
Data structure associated with a single frame of data.
Definition: frame.h:142
Internal Asterisk hangup causes.
char maintext1[25]
Definition: chan_unistim.c:444
#define SELECTCODEC_MAX_LENGTH
static void send_start_timer(struct unistimsession *pte)
Definition: chan_unistim.c:954
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:319
static void finish_bookmark(void)
unsigned char * buf
Definition: chan_unistim.c:352
static unsigned int get_tick_count(void)
Definition: chan_unistim.c:736
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
Definition: acl.c:399
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
Definition: channel.h:883
const char * data
Description of a tone.
Definition: indications.h:53
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:469
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
Definition: netsock2.h:629
static void show_entry_history(struct unistimsession *pte, FILE **f)
enum ast_frame_type frametype
Definition: frame.h:144
struct ast_variable * next
Definition: config.h:82
static const unsigned char packet_send_arrow[]
Definition: chan_unistim.c:624
static int unistim_indicate(struct ast_channel *ast, int ind, const void *data, size_t datalen)
static struct adsi_event events[]
Definition: app_adsiprog.c:78
#define ast_mutex_init(pmutex)
Definition: lock.h:152
static ast_mutex_t usecnt_lock
Definition: chan_unistim.c:235
unsigned char valid
TRUE if the name information is valid/present.
Definition: channel.h:229
#define CONFIG_STATUS_FILEINVALID
Definition: config.h:52
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
static void key_ringing(struct unistimsession *pte, char keycode)
static void key_dial_page(struct unistimsession *pte, char keycode)
#define ast_mutex_destroy(a)
Definition: lock.h:154
static void display_last_error(const char *sz_msg)
Definition: chan_unistim.c:725
static void change_callerid(struct unistimsession *pte, int type, char *callerid)
#define SELECTCODEC_MSG
static unsigned int cos
Definition: chan_h323.c:147
static const unsigned char packet_rcv_discovery[]
Definition: chan_unistim.c:511
static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
static void init_phone_step2(struct unistimsession *pte)
static int restart_monitor(void)
static struct unistimsession * channel_to_session(struct ast_channel *ast)
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:38
Pluggable RTP Architecture.
#define ast_malloc(a)
Definition: astmm.h:91
Asterisk module definitions.
static struct hostent * hp
Definition: chan_skinny.c:1048
static void send_end_call(struct unistimsession *pte)
Definition: chan_unistim.c:911
#define SELECTEXTENSION_MSG
#define CAPABILITY
Definition: chan_unistim.c:78
unsigned short w_year
Definition: chan_unistim.c:356
static snd_pcm_format_t format
Definition: chan_alsa.c:93
union ast_frame::@172 data
struct ast_channel_tech * tech
Definition: channel.h:743
int ast_rtp_codecs_payload_code(struct ast_rtp_codecs *codecs, const int asterisk_format, const format_t code)
Retrieve a payload based on whether it is an Asterisk format and the code.
Definition: rtp_engine.c:654
static int usecnt
Definition: chan_unistim.c:236
#define FAV_ICON_REFLECT
Definition: chan_unistim.c:173
static const unsigned char packet_send_discovery_ack[]
Definition: chan_unistim.c:513
unsigned short w_day
Definition: chan_unistim.c:359
static void send_date_time2(struct unistimsession *pte)
char extension_number[11]
Definition: chan_unistim.c:469
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, format_t codecs, int nat_active)
General jitterbuffer configuration.
Definition: abstract_jb.h:55
struct ast_silence_generator * silence_generator
Definition: chan_unistim.c:472
static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
#define AST_CAUSE_CONGESTION
Definition: causes.h:152
static void TransferCallStep1(struct unistimsession *pte)
struct unistim_device * sp[6]
Definition: chan_unistim.c:441
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
int tm_min
Definition: localtime.h:37
Structure for mutex and tracking information.
Definition: lock.h:121
static char mailbox[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:197
#define DEFAULTCONTEXT
Definition: chan_unistim.c:80
#define SIZE_PAGE
Definition: chan_unistim.c:100
#define FAV_ICON_OFFHOOK_BLACK
Definition: chan_unistim.c:154
unsigned short w_month
Definition: chan_unistim.c:357
jack_status_t status
Definition: app_jack.c:143
autoprov_extn
Definition: chan_unistim.c:116
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:379
format_t capability
Definition: chan_unistim.c:417
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
Mailbox name.
Definition: event_defs.h:83
static int unistimsock_read(int *id, int fd, short events, void *ignore)
static ast_mutex_t unistim_reload_lock
Definition: chan_unistim.c:234
static struct ast_channel_tech unistim_tech
Definition: chan_unistim.c:706
#define ast_mutex_unlock(a)
Definition: lock.h:156
char maintext2[25]
Definition: chan_unistim.c:445
static ast_mutex_t monlock
Definition: chan_unistim.c:245
static unsigned char packet_send_ping[]
Definition: chan_unistim.c:672
static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
Definition: chan_unistim.c:972
char softkeyicon[6]
Definition: chan_unistim.c:439
static const unsigned char packet_recv_r2[]
Definition: chan_unistim.c:524
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
Definition: callerid.c:1009
enum ast_bridge_result ast_rtp_instance_bridge(struct ast_channel *c0, struct ast_channel *c1, int flags, struct ast_frame **fo, struct ast_channel **rc, int timeoutms)
Bridge two channels that use RTP instances.
Definition: rtp_engine.c:1274
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static struct ast_rtp_glue unistim_rtp_glue
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...
Definition: io.c:76
static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to, const struct sockaddr_in *addr_ourip)
Definition: chan_unistim.c:744