2 * Asterisk -- An open source telephony toolkit.
4 * UNISTIM channel driver for asterisk
6 * Copyright (C) 2005 - 2007, Cedric Hans
8 * Cedric Hans <cedric.hans@mlkj.net>
10 * Asterisk 1.4 patch by Peter Be
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.
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.
26 * \brief chan_unistim channel driver for Asterisk
27 * \author Cedric Hans <cedric.hans@mlkj.net>
29 * Unistim (Unified Networks IP Stimulus) channel driver
30 * for Nortel i2002, i2004 and i2050
32 * \ingroup channel_drivers
36 <support_level>extended</support_level>
41 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
46 #if defined(__CYGWIN__)
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.
58 #endif /* __CYGWIN__ */
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/netsock2.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 #include "asterisk/features.h"
77 #include "asterisk/astobj2.h"
78 #include "asterisk/astdb.h"
81 #define DEFAULTCONTEXT "default"
82 #define DEFAULTCALLERID "Unknown"
83 #define DEFAULTCALLERNAME " "
84 #define DEFAULTHEIGHT 3
85 #define USTM_LOG_DIR "unistimHistory"
86 #define USTM_LANG_DIR "unistimLang"
88 /*! Size of the transmit buffer */
89 #define MAX_BUF_SIZE 64
90 /*! Number of slots for the transmit queue */
91 #define MAX_BUF_NUMBER 50
92 /*! Number of digits displayed on screen */
93 #define MAX_SCREEN_NUMBER 15
94 /*! Try x times before removing the phone */
95 #define NB_MAX_RETRANSMIT 8
96 /*! Nb of milliseconds waited when no events are scheduled */
97 #define IDLE_WAIT 1000
98 /*! Wait x milliseconds before resending a packet */
99 #define RETRANSMIT_TIMER 2000
100 /*! How often the mailbox is checked for new messages */
101 #define TIMER_MWI 5000
102 /*! Timeout value for entered number being dialed */
103 #define DEFAULT_INTERDIGIT_TIMER 4000
106 #define DEFAULT_CODEC 0x00
107 #define SIZE_PAGE 4096
108 #define DEVICE_NAME_LEN 16
109 #define AST_CONFIG_MAX_PATH 255
110 #define MAX_ENTRY_LOG 30
114 #define SUB_THREEWAY 2
117 struct ast_format_cap *global_cap;
120 AUTOPROVISIONING_NO = 0,
121 AUTOPROVISIONING_YES,
126 /*! Do not create an extension into the default dialplan */
128 /*! Prompt user for an extension number and register it */
130 /*! Register an extension with the line=> value */
132 /*! Used with AUTOPROVISIONING_TN */
135 #define OUTPUT_HANDSET 0xC0
136 #define OUTPUT_HEADPHONE 0xC1
137 #define OUTPUT_SPEAKER 0xC2
139 #define VOLUME_LOW 0x01
140 #define VOLUME_LOW_SPEAKER 0x03
141 #define VOLUME_NORMAL 0x02
142 #define VOLUME_INSANELY_LOUD 0x07
144 #define MUTE_OFF 0x00
146 #define MUTE_ON_DISCRET 0xCE
148 #define SIZE_HEADER 6
149 #define SIZE_MAC_ADDR 17
150 #define TEXT_LENGTH_MAX 24
151 #define TEXT_LINE0 0x00
152 #define TEXT_LINE1 0x20
153 #define TEXT_LINE2 0x40
154 #define TEXT_NORMAL 0x05
155 #define TEXT_INVERSE 0x25
156 #define STATUS_LENGTH_MAX 28
158 #define FAV_ICON_NONE 0x00
159 #define FAV_ICON_ONHOOK_BLACK 0x20
160 #define FAV_ICON_ONHOOK_WHITE 0x21
161 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
162 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
163 #define FAV_ICON_OFFHOOK_BLACK 0x24
164 #define FAV_ICON_OFFHOOK_WHITE 0x25
165 #define FAV_ICON_ONHOLD_BLACK 0x26
166 #define FAV_ICON_ONHOLD_WHITE 0x27
167 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
168 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
169 #define FAV_ICON_PHONE_BLACK 0x2A
170 #define FAV_ICON_PHONE_WHITE 0x2B
171 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
172 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
173 #define FAV_ICON_HEADPHONES 0x2E
174 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
175 #define FAV_ICON_HOME 0x30
176 #define FAV_ICON_CITY 0x31
177 #define FAV_ICON_SHARP 0x32
178 #define FAV_ICON_PAGER 0x33
179 #define FAV_ICON_CALL_CENTER 0x34
180 #define FAV_ICON_FAX 0x35
181 #define FAV_ICON_MAILBOX 0x36
182 #define FAV_ICON_REFLECT 0x37
183 #define FAV_ICON_COMPUTER 0x38
184 #define FAV_ICON_FORWARD 0x39
185 #define FAV_ICON_LOCKED 0x3A
186 #define FAV_ICON_TRASH 0x3B
187 #define FAV_ICON_INBOX 0x3C
188 #define FAV_ICON_OUTBOX 0x3D
189 #define FAV_ICON_MEETING 0x3E
190 #define FAV_ICON_BOX 0x3F
192 #define FAV_BLINK_FAST 0x20
193 #define FAV_BLINK_SLOW 0x40
195 #define FAV_MAX_LENGTH 0x0A
198 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
200 static void dummy(char *unused, ...)
205 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
206 * \note Values shown here match the defaults shown in unistim.conf.sample */
207 static struct ast_jb_conf default_jbconf =
211 .resync_threshold = 1000,
215 static struct ast_jb_conf global_jbconf;
218 /* #define DUMP_PACKET 1 */
219 /* #define DEBUG_TIMER ast_verbose */
221 #define DEBUG_TIMER dummy
222 /*! Enable verbose output. can also be set with the CLI */
223 static int unistimdebug = 0;
224 static int unistim_port;
225 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
226 static int unistim_keepalive;
227 static int unistimsock = -1;
231 unsigned int tos_audio;
233 unsigned int cos_audio;
234 } qos = { 0, 0, 0, 0 };
236 static struct io_context *io;
237 static struct ast_sched_context *sched;
238 static struct sockaddr_in public_ip = { 0, };
239 static unsigned char *buff; /*! Receive buffer address */
240 static int unistim_reloading = 0;
241 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
243 /*! This is the thread for the monitor which checks for input on the channels
244 * which are not currently in use. */
245 static pthread_t monitor_thread = AST_PTHREADT_NULL;
247 /*! Protect the monitoring thread, so only one process can kill or start it, and not
248 * when it's doing something critical. */
249 AST_MUTEX_DEFINE_STATIC(monlock);
250 /*! Protect the session list */
251 AST_MUTEX_DEFINE_STATIC(sessionlock);
252 /*! Protect the device list */
253 AST_MUTEX_DEFINE_STATIC(devicelock);
265 STATE_SELECTLANGUAGE,
325 static const int dtmf_row[] = { 697, 770, 852, 941 };
326 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
333 struct unistim_subchannel {
335 unsigned int subtype; /*! SUB_REAL, SUB_RING, SUB_THREEWAY or SUB_ONHOLD */
336 struct ast_channel *owner; /*! Asterisk channel used by the subchannel */
337 struct unistim_line *parent; /*! Unistim line */
338 struct ast_rtp_instance *rtp; /*! RTP handle */
339 int softkey; /*! Softkey assigned */
340 pthread_t ss_thread; /*! unistim_ss thread handle */
344 int moh; /*!< Music on hold in progress */
345 AST_LIST_ENTRY(unistim_subchannel) list;
349 * \todo Convert to stringfields
351 struct unistim_line {
353 char name[80]; /*! Like 200 */
354 char fullname[80]; /*! Like USTM/200\@black */
355 char exten[AST_MAX_EXTENSION]; /*! Extension where to start */
356 char cid_num[AST_MAX_EXTENSION]; /*! CallerID Number */
357 char mailbox[AST_MAX_EXTENSION]; /*! Mailbox for MWI */
358 char musicclass[MAX_MUSICCLASS]; /*! MusicOnHold class */
359 ast_group_t callgroup; /*! Call group */
360 ast_group_t pickupgroup; /*! Pickup group */
361 char accountcode[AST_MAX_ACCOUNT_CODE]; /*! Account code (for billing) */
362 int amaflags; /*! AMA flags (for billing) */
363 struct ast_format_cap *cap; /*! Codec supported */
364 char parkinglot[AST_MAX_CONTEXT]; /*! Parkinglot */
365 struct unistim_line *next;
366 struct unistim_device *parent;
367 AST_LIST_ENTRY(unistim_line) list;
371 * \brief A device containing one or more lines
373 static struct unistim_device {
375 int receiver_state; /*!< state of the receiver (see ReceiverState) */
376 int size_phone_number; /*!< size of the phone number */
377 char context[AST_MAX_EXTENSION]; /*!< Context to start in */
378 char phone_number[AST_MAX_EXTENSION]; /*!< the phone number entered by the user */
379 char redial_number[AST_MAX_EXTENSION]; /*!< the last phone number entered by the user */
380 char id[18]; /*!< mac address of the current phone in ascii */
381 char name[DEVICE_NAME_LEN]; /*!< name of the device */
382 char softkeylabel[FAVNUM][11]; /*!< soft key label */
383 char softkeynumber[FAVNUM][AST_MAX_EXTENSION]; /*!< number dialed when the soft key is pressed */
384 char softkeyicon[FAVNUM]; /*!< icon number */
385 char softkeydevice[FAVNUM][16]; /*!< name of the device monitored */
386 struct unistim_subchannel *ssub[FAVNUM];
387 struct unistim_line *sline[FAVNUM];
388 struct unistim_device *sp[FAVNUM]; /*!< pointer to the device monitored by this soft key */
389 char language[MAX_LANGUAGE]; /*!< Language for asterisk sounds */
390 int height; /*!< The number of lines the phone can display */
391 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
392 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
393 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
394 char titledefault[13]; /*!< title (text before date/time) */
395 char datetimeformat; /*!< format used for displaying time/date */
396 char contrast; /*!< contrast */
397 char country[3]; /*!< country used for dial tone frequency */
398 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
399 char ringvolume; /*!< Ring volume */
400 char ringstyle; /*!< Ring melody */
401 char cwvolume; /*!< Ring volume on call waiting */
402 char cwstyle; /*!< Ring melody on call waiting */
403 int interdigit_timer; /*!< Interdigit timer for dialing number by timeout */
404 time_t nextdial; /*!< Timer used for dial by timeout */
405 int rtp_port; /*!< RTP port used by the phone */
406 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
407 int status_method; /*!< Select the unistim packet used for sending status text */
408 char codec_number; /*!< The current codec used to make calls */
409 int missed_call; /*!< Number of call unanswered */
410 int callhistory; /*!< Allowed to record call history */
411 int sharp_dial; /*!< Execute Dial on '#' or not */
412 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
413 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
414 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
415 int output; /*!< Handset, headphone or speaker */
416 int previous_output; /*!< Previous output */
417 int volume; /*!< Default volume */
418 int selected; /*!< softkey selected */
419 int mute; /*!< Mute mode */
420 int lastmsgssent; /*! Used by MWI */
421 time_t nextmsgcheck; /*! Used by MWI */
422 int nat; /*!< Used by the obscure ast_rtp_setnat */
423 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
424 char extension_number[11]; /*!< Extension number entered by the user */
425 char to_delete; /*!< Used in reload */
426 struct ast_silence_generator *silence_generator;
427 AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
428 AST_LIST_HEAD(,unistim_line) lines;
430 struct unistimsession *session;
431 struct unistim_device *next;
434 static struct unistimsession {
436 struct sockaddr_in sin; /*!< IP address of the phone */
437 struct sockaddr_in sout; /*!< IP address of server */
438 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
439 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
440 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
441 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
442 unsigned long tick_next_ping; /*!< time for the next ping */
443 int last_buf_available; /*!< number of a free slot */
444 int nb_retransmit; /*!< number of retransmition */
445 int state; /*!< state of the phone (see phone_state) */
446 int size_buff_entry; /*!< size of the buffer used to enter datas */
447 char buff_entry[16]; /*!< Buffer for temporary datas */
448 char macaddr[18]; /*!< mac adress of the phone (not always available) */
449 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
450 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
451 struct unistim_device *device;
452 struct unistimsession *next;
455 /*! Store on screen phone menu item (label and handler function) */
456 struct unistim_menu_item {
459 void (*handle_option)(struct unistimsession *);
462 /*! Language item for currently existed translations */
463 struct unistim_languages {
467 struct ao2_container *trans;
471 * \page Unistim datagram formats
473 * Format of datagrams :
474 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
475 * byte 2 : sequence number (high part)
476 * byte 3 : sequence number (low part)
477 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
478 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
481 static const unsigned char packet_rcv_discovery[] =
482 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
483 static const unsigned char packet_send_discovery_ack[] =
484 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
486 static const unsigned char packet_recv_firm_version[] =
487 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
488 static const unsigned char packet_recv_it_type[] =
489 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
490 static const unsigned char packet_recv_pressed_key[] =
491 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
492 static const unsigned char packet_recv_pick_up[] =
493 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
494 static const unsigned char packet_recv_hangup[] =
495 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
496 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
498 /*! TransportAdapter */
499 static const unsigned char packet_recv_resume_connection_with_server[] =
500 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
501 static const unsigned char packet_recv_mac_addr[] =
502 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
504 static const unsigned char packet_send_date_time3[] =
505 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
506 /*Minutes */ 0x08, 0x32
508 static const unsigned char packet_send_date_time[] =
509 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
510 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
511 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
512 0x05, 0x12, 0x00, 0x78
515 static const unsigned char packet_send_no_ring[] =
516 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
517 static const unsigned char packet_send_s4[] =
518 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
519 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
520 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
521 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
522 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
524 static const unsigned char packet_send_call[] =
525 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
526 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
527 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
528 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
529 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
530 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
533 static const unsigned char packet_send_stream_based_tone_off[] =
534 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
536 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
537 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
538 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
539 static const unsigned char packet_send_stream_based_tone_on[] =
540 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
541 static const unsigned char packet_send_stream_based_tone_single_freq[] =
542 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
543 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
544 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
545 static const unsigned char packet_send_select_output[] =
546 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
547 static const unsigned char packet_send_ring[] =
548 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
549 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
550 0x20, 0x16, 0x04, 0x10, 0x00
552 static const unsigned char packet_send_end_call[] =
553 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
554 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
555 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
557 static const unsigned char packet_send_s9[] =
558 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
560 static const unsigned char packet_send_rtp_packet_size[] =
561 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
562 static const unsigned char packet_send_jitter_buffer_conf[] =
563 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
564 /* early packet resync 2 bytes */ 0x3e, 0x80,
565 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
568 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
569 static unsigned char packet_send_StreamBasedToneCad[] =
570 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
571 static const unsigned char packet_send_open_audio_stream_rx[] =
572 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
573 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
574 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
576 static const unsigned char packet_send_open_audio_stream_tx[] =
577 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
578 0x0e, 0x01, /* Local port */ 0x14, 0x50,
579 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
582 static const unsigned char packet_send_open_audio_stream_rx3[] =
583 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
584 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
585 /* RTCP Port */ 0x14,
586 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
589 static const unsigned char packet_send_open_audio_stream_tx3[] =
590 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
591 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
592 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
593 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
596 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
597 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
598 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
599 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
601 static const unsigned char packet_send_Contrast[] =
602 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
603 static const unsigned char packet_send_start_timer[] =
604 { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
605 /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
606 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
607 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
608 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
609 static const unsigned char packet_send_set_pos_cursor[] =
610 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
612 /*static unsigned char packet_send_MonthLabelsDownload[] =
613 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
614 static const unsigned char packet_send_favorite[] =
615 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
616 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
617 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
619 static const unsigned char packet_send_title[] =
620 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
621 0x20, 0x20, 0x20, 0x20 /*end_text */ };
622 static const unsigned char packet_send_text[] =
623 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
624 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
625 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
626 /*end_text */ 0x17, 0x04, 0x10, 0x87
628 static const unsigned char packet_send_status[] =
629 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
630 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
631 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
633 static const unsigned char packet_send_status2[] =
634 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
635 0x20, 0x20, 0x20 /* end_text */ };
637 /* Multiple character set support */
638 /* ISO-8859-1 - Western European) */
639 static const unsigned char packet_send_charset_iso_8859_1[] =
640 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
641 /* ISO-8859-2 - Central European) */
642 static const unsigned char packet_send_charset_iso_8859_2[] =
643 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
644 /* ISO-8859-4 - Baltic) */
645 static const unsigned char packet_send_charset_iso_8859_4[] =
646 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
647 /* ISO 8859-5 - cyrilic */
648 static const unsigned char packet_send_charset_iso_8859_5[] =
649 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
650 /* Japaneese (ISO-2022-JP ?) */
651 static const unsigned char packet_send_charset_iso_2022_jp[] =
652 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
654 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
656 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
657 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
658 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
659 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
661 static unsigned char packet_send_ping[] =
662 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
664 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
666 static const char tdesc[] = "UNISTIM Channel Driver";
667 static const char channel_type[] = "USTM";
670 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
671 static int load_module(void);
672 static int reload(void);
673 static int unload_module(void);
674 static int reload_config(void);
675 static void show_main_page(struct unistimsession *pte);
676 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
677 const char *dest, int *cause);
678 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
679 static int unistim_hangup(struct ast_channel *ast);
680 static int unistim_answer(struct ast_channel *ast);
681 static struct ast_frame *unistim_read(struct ast_channel *ast);
682 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
683 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
685 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
686 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
687 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
688 unsigned int duration);
689 static int unistim_sendtext(struct ast_channel *ast, const char *text);
691 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
693 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
695 static struct ast_channel_tech unistim_tech = {
696 .type = channel_type,
697 .description = tdesc,
698 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
699 .requester = unistim_request,
700 .call = unistim_call,
701 .hangup = unistim_hangup,
702 .answer = unistim_answer,
703 .read = unistim_read,
704 .write = unistim_write,
705 .indicate = unistim_indicate,
706 .fixup = unistim_fixup,
707 .send_digit_begin = unistim_senddigit_begin,
708 .send_digit_end = unistim_senddigit_end,
709 .send_text = unistim_sendtext,
710 .bridge = ast_rtp_instance_bridge,
713 static void send_start_rtp(struct unistim_subchannel *);
715 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
716 static void key_favorite(struct unistimsession *, char);
718 static void handle_select_codec(struct unistimsession *);
719 static void handle_select_language(struct unistimsession *);
720 static int find_language(const char*);
722 static int unistim_free_sub(struct unistim_subchannel *);
724 static struct unistim_menu_item options_menu[] =
726 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
727 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
731 static struct unistim_languages options_languages[] =
733 {"English", "en", ISO_8859_1, NULL},
734 {"French", "fr", ISO_8859_1, NULL},
735 {"Russian", "ru", ISO_8859_5, NULL},
736 {NULL, NULL, 0, NULL}
739 static char ustm_strcopy[1024];
741 struct ustm_lang_entry {
742 const char *str_orig;
743 const char *str_trans;
746 static int lang_hash_fn(const void *obj, const int flags)
748 const struct ustm_lang_entry *entry = obj;
749 return ast_str_hash(entry->str_orig);
752 static int lang_cmp_fn(void *obj, void *arg, int flags)
754 struct ustm_lang_entry *entry1 = obj;
755 struct ustm_lang_entry *entry2 = arg;
757 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
760 static const char *ustmtext(const char *str, struct unistimsession *pte)
762 struct ustm_lang_entry *lang_entry;
763 struct ustm_lang_entry le_search;
764 struct unistim_languages *lang = NULL;
768 lang = &options_languages[find_language(pte->device->language)];
773 /* Check if specified language exists */
775 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
778 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
779 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
782 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
783 USTM_LANG_DIR, lang->lang_short);
786 ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
789 while (fgets(tmp, sizeof(tmp), f)) {
790 if (!(p = strchr(tmp, '\n'))) {
791 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
795 if (!(p = strchr(tmp, '"'))) {
798 if (tmp == strstr(tmp, "msgid")) {
799 p_orig = ast_strdup(p + 1);
800 p = strchr(p_orig, '"');
801 } else if (tmp == strstr(tmp, "msgstr")) {
802 p_trans = ast_strdup(p + 1);
803 p = strchr(p_trans, '"');
808 if (!p_trans || !p_orig) {
811 if (ast_strlen_zero(p_trans)) {
818 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
823 lang_entry->str_trans = p_trans;
824 lang_entry->str_orig = p_orig;
825 ao2_link(lang->trans, lang_entry);
833 le_search.str_orig = str;
834 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
835 size = strlen(lang_entry->str_trans)+1;
839 memcpy(ustm_strcopy, lang_entry->str_trans, size);
840 ao2_ref(lang_entry, -1);
847 static void display_last_error(const char *sz_msg)
849 /* Display the error message */
850 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
853 static unsigned int get_tick_count(void)
855 struct timeval now = ast_tvnow();
857 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
860 /* Send data to a phone without retransmit nor buffering */
861 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
862 const struct sockaddr_in *addr_ourip)
865 struct iovec msg_iov;
867 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
868 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
869 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
871 /* cast this to a non-const pointer, since the sendmsg() API
872 * does not provide read-only and write-only flavors of the
873 * structures used for its arguments, but in this case we know
874 * the data will not be modified
876 msg_iov.iov_base = (char *) data;
877 msg_iov.iov_len = size;
879 msg.msg_name = addr_to; /* optional address */
880 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
881 msg.msg_iov = &msg_iov; /* scatter/gather array */
882 msg.msg_iovlen = 1; /* # elements in msg_iov */
883 msg.msg_control = ip_msg; /* ancillary data */
884 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
885 msg.msg_flags = 0; /* flags on received message */
887 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
888 ip_msg->cmsg_level = IPPROTO_IP;
889 ip_msg->cmsg_type = IP_PKTINFO;
890 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
891 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
892 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
897 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
898 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
899 ast_inet_ntoa(addr_to->sin_addr));
900 for (tmp = 0; tmp < size; tmp++)
901 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
902 ast_verb(0, "\n******************************************\n");
907 if (sendmsg(unistimsock, &msg, 0) == -1) {
908 display_last_error("Error sending datas");
911 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
913 display_last_error("Error sending datas");
917 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
921 unsigned short seq = ntohs(++pte->seq_server);
923 ast_mutex_lock(&pte->lock);
924 buf_pos = pte->last_buf_available;
926 if (buf_pos >= MAX_BUF_NUMBER) {
927 ast_log(LOG_WARNING, "Error : send queue overflow\n");
928 ast_mutex_unlock(&pte->lock);
931 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
932 pte->wsabufsend[buf_pos].len = size;
933 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
935 tick = get_tick_count();
936 pte->timeout = tick + RETRANSMIT_TIMER;
938 /*#ifdef DUMP_PACKET */
940 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
943 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
945 pte->last_buf_available++;
946 ast_mutex_unlock(&pte->lock);
949 static void send_ping(struct unistimsession *pte)
953 ast_verb(6, "Sending ping\n");
955 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
956 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
957 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
960 static int get_to_address(int fd, struct sockaddr_in *toAddr)
968 struct in_addr address;
971 /* Zero out the structures before we use them */
972 /* This sets several key values to NULL */
973 memset(&msg, 0, sizeof(msg));
974 memset(&ip_msg, 0, sizeof(ip_msg));
976 /* Initialize the message structure */
977 msg.msg_control = &ip_msg;
978 msg.msg_controllen = sizeof(ip_msg);
979 /* Get info about the incoming packet */
980 err = recvmsg(fd, &msg, MSG_PEEK);
982 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
984 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
987 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
992 /* Allocate memory & initialize structures for a new phone */
993 /* addr_from : ip address of the phone */
994 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
997 struct unistimsession *s;
999 if (!(s = ast_calloc(1, sizeof(*s))))
1002 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1003 get_to_address(unistimsock, &s->sout);
1004 s->sout.sin_family = AF_INET;
1006 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1007 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1009 ast_mutex_init(&s->lock);
1010 ast_mutex_lock(&sessionlock);
1014 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1015 s->state = STATE_INIT;
1016 s->tick_next_ping = get_tick_count() + unistim_keepalive;
1017 /* Initialize struct wsabuf */
1018 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1019 s->wsabufsend[tmp].buf = s->buf[tmp];
1021 ast_mutex_unlock(&sessionlock);
1025 static void send_end_call(struct unistimsession *pte)
1029 ast_verb(0, "Sending end call\n");
1031 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1032 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1035 static void set_ping_timer(struct unistimsession *pte)
1037 unsigned int tick = 0; /* XXX what is this for, anyways */
1039 pte->timeout = pte->tick_next_ping;
1040 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1044 /* Checking if our send queue is empty,
1045 * if true, setting up a timer for keepalive */
1046 static void check_send_queue(struct unistimsession *pte)
1048 /* Check if our send queue contained only one element */
1049 if (pte->last_buf_available == 1) {
1051 ast_verb(6, "Our single packet was ACKed.\n");
1053 pte->last_buf_available--;
1054 set_ping_timer(pte);
1057 /* Check if this ACK catch up our latest packet */
1058 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1060 ast_verb(6, "Our send queue is completely ACKed.\n");
1062 pte->last_buf_available = 0; /* Purge the send queue */
1063 set_ping_timer(pte);
1067 ast_verb(6, "We still have packets in our send queue\n");
1072 static void send_start_timer(struct unistimsession *pte)
1076 ast_verb(0, "Sending start timer\n");
1078 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1079 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1082 static void send_stop_timer(struct unistimsession *pte)
1086 ast_verb(0, "Sending stop timer\n");
1088 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1089 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1092 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1096 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1098 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1100 buffsend[10] = status;
1101 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1104 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1109 ast_verb(0, "Sending Stream Based Tone Off\n");
1111 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1112 sizeof(packet_send_stream_based_tone_off));
1113 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1116 /* Since most of the world use a continuous tone, it's useless
1118 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1119 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1120 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1122 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1126 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1127 sizeof(packet_send_stream_based_tone_single_freq));
1128 buffsend[10] = (tone1 & 0xff00) >> 8;
1129 buffsend[11] = (tone1 & 0x00ff);
1130 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1134 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1135 sizeof(packet_send_stream_based_tone_dial_freq));
1136 buffsend[10] = (tone1 & 0xff00) >> 8;
1137 buffsend[11] = (tone1 & 0x00ff);
1138 buffsend[12] = (tone2 & 0xff00) >> 8;
1139 buffsend[13] = (tone2 & 0x00ff);
1140 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1145 ast_verb(0, "Sending Stream Based Tone On\n");
1147 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1148 sizeof(packet_send_stream_based_tone_on));
1149 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1152 /* Positions for favorites
1153 |--------------------|
1154 | 5 2 | <-- not on screen in i2002
1159 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1161 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1168 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1170 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1173 buffsend[25] = status;
1174 i = strlen(ustmtext(text, pte));
1175 if (i > FAV_MAX_LENGTH) {
1178 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1179 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1182 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1183 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1187 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1188 if (pte->device->selected != -1) {
1189 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1194 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1196 if(d->height == 1 && num % 3 == 2) {
1202 static void refresh_all_favorite(struct unistimsession *pte)
1204 unsigned char i = 0;
1206 struct unistim_line *line;
1207 line = AST_LIST_FIRST(&pte->device->lines);
1210 ast_verb(0, "Refreshing all favorite\n");
1212 for (i = 0; i < FAVNUM; i++) {
1213 unsigned char status = pte->device->softkeyicon[i];
1215 if (!soft_key_visible(pte->device, i)) {
1218 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1219 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1220 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1224 send_favorite_short(i, status, pte);
1228 static int is_key_favorite(struct unistim_device *d, int fav)
1230 if ((fav < 0) && (fav > 5)) {
1233 if (d->sline[fav]) {
1236 if (d->softkeynumber[fav][0] == '\0') {
1242 static int is_key_line(struct unistim_device *d, int fav)
1244 if ((fav < 0) && (fav > 5)) {
1247 if (!d->sline[fav]) {
1250 if (is_key_favorite(d, fav)) {
1256 static int get_active_softkey(struct unistimsession *pte)
1258 return pte->device->selected;
1261 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1265 if (!is_key_line(pte->device, pte->device->selected)) {
1266 pte->device->selected = -1;
1268 for (i = 0; i < FAVNUM; i++) {
1269 if (pte->device->selected != -1 && pte->device->selected != i) {
1272 if (!soft_key_visible(pte->device, i)) {
1275 if (pte->device->ssub[i]) {
1278 if (is_key_line(pte->device, i)) {
1279 if (name && strcmp(name, pte->device->sline[i]->name)) {
1283 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1292 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1293 * use FAV_ICON_*_BLACK constant in status parameters */
1294 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1296 struct unistim_device *d = devices;
1298 /* Update the current phone line softkey icon */
1299 if (pte->state != STATE_CLEANING) {
1300 int softkeylinepos = get_active_softkey(pte);
1301 if (softkeylinepos != -1) {
1302 send_favorite_short(softkeylinepos, status, pte);
1305 /* Notify other phones if we're in their bookmark */
1307 for (i = 0; i < FAVNUM; i++) {
1308 if (d->sp[i] == pte->device) { /* It's us ? */
1309 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1310 d->softkeyicon[i] = status;
1312 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1321 static int register_extension(const struct unistimsession *pte)
1323 struct unistim_line *line;
1324 line = AST_LIST_FIRST(&pte->device->lines);
1326 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1327 pte->device->extension_number, pte->device->context,
1330 return ast_add_extension(pte->device->context, 0,
1331 pte->device->extension_number, 1, NULL, NULL, "Dial",
1332 line->fullname, 0, "Unistim");
1335 static int unregister_extension(const struct unistimsession *pte)
1338 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1339 pte->device->extension_number, pte->device->context);
1341 return ast_context_remove_extension(pte->device->context,
1342 pte->device->extension_number, 1, "Unistim");
1345 /* Free memory allocated for a phone */
1346 static void close_client(struct unistimsession *s)
1348 struct unistim_subchannel *sub = NULL;
1349 struct unistimsession *cur, *prev = NULL;
1350 ast_mutex_lock(&sessionlock);
1352 /* Looking for the session in the linked chain */
1360 if (cur) { /* Session found ? */
1361 if (cur->device) { /* This session was registered ? */
1362 s->state = STATE_CLEANING;
1364 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1366 change_favorite_icon(s, FAV_ICON_NONE);
1367 ast_mutex_lock(&s->device->lock);
1368 AST_LIST_LOCK(&s->device->subs);
1369 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1373 if (sub->owner) { /* Call in progress ? */
1375 ast_verb(0, "Aborting call\n");
1377 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1380 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1382 AST_LIST_REMOVE_CURRENT(list);
1383 unistim_free_sub(sub);
1386 AST_LIST_TRAVERSE_SAFE_END;
1387 AST_LIST_UNLOCK(&s->device->subs);
1389 if (!ast_strlen_zero(s->device->extension_number)) {
1390 unregister_extension(s);
1392 cur->device->session = NULL;
1393 ast_mutex_unlock(&s->device->lock);
1396 ast_verb(0, "Freeing an unregistered client\n");
1400 prev->next = cur->next;
1402 sessions = cur->next;
1404 ast_mutex_destroy(&s->lock);
1407 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1409 ast_mutex_unlock(&sessionlock);
1413 /* Return 1 if the session chained link was modified */
1414 static int send_retransmit(struct unistimsession *pte)
1418 ast_mutex_lock(&pte->lock);
1419 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1421 ast_verb(0, "Too many retransmit - freeing client\n");
1423 ast_mutex_unlock(&pte->lock);
1427 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1429 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1430 i < pte->last_buf_available; i++) {
1432 ast_log(LOG_WARNING,
1433 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1434 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1439 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1442 seq = ntohs(sbuf[1]);
1443 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1444 seq, pte->last_seq_ack);
1446 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1449 ast_mutex_unlock(&pte->lock);
1453 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1455 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1461 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1464 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1468 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1470 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1472 buffsend[11] = inverse;
1474 if (i > TEXT_LENGTH_MAX) {
1475 i = TEXT_LENGTH_MAX;
1477 memcpy(buffsend + 12, text, i);
1478 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1481 static void send_text_status(struct unistimsession *pte, const char *text)
1486 ast_verb(0, "Sending status text\n");
1489 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1490 int n = strlen(text);
1491 /* Must send individual button separately */
1493 for (i = 0, j = 0; i < 4; i++, j += 7) {
1494 int pos = 0x08 + (i * 0x20);
1495 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1496 sizeof(packet_send_status2));
1499 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1500 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1507 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1509 if (i > STATUS_LENGTH_MAX) {
1510 i = STATUS_LENGTH_MAX;
1512 memcpy(buffsend + 10, text, i);
1513 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1517 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1518 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1519 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1520 * 18 = mute off, 19 mute on */
1521 static void send_led_update(struct unistimsession *pte, unsigned char led)
1525 ast_verb(0, "Sending led_update (%x)\n", led);
1527 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1529 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1532 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1533 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1534 * mute = MUTE_OFF, MUTE_ON */
1536 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1541 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1544 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1545 sizeof(packet_send_select_output));
1546 buffsend[9] = output;
1547 if (output == OUTPUT_SPEAKER) {
1548 volume = VOLUME_LOW_SPEAKER;
1550 volume = VOLUME_LOW;
1552 buffsend[10] = volume;
1553 if (mute == MUTE_ON_DISCRET) {
1554 buffsend[11] = MUTE_ON;
1556 buffsend[11] = mute;
1558 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1559 if (mute == MUTE_OFF) {
1560 send_led_update(pte, 0x18);
1561 } else if (mute == MUTE_ON) {
1562 send_led_update(pte, 0x19);
1564 pte->device->mute = mute;
1565 if (output == OUTPUT_HANDSET) {
1566 if (mute == MUTE_ON) {
1567 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1569 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1571 send_led_update(pte, 0x08);
1572 send_led_update(pte, 0x10);
1573 } else if (output == OUTPUT_HEADPHONE) {
1574 if (mute == MUTE_ON) {
1575 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1577 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1579 send_led_update(pte, 0x08);
1580 send_led_update(pte, 0x11);
1581 } else if (output == OUTPUT_SPEAKER) {
1582 send_led_update(pte, 0x10);
1583 send_led_update(pte, 0x09);
1584 if (pte->device->receiver_state == STATE_OFFHOOK) {
1585 if (mute == MUTE_ON) {
1586 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1588 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1591 if (mute == MUTE_ON) {
1592 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1594 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1598 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1600 if (output != pte->device->output) {
1601 pte->device->previous_output = pte->device->output;
1603 pte->device->output = output;
1606 static void send_ring(struct unistimsession *pte, char volume, char style)
1610 ast_verb(0, "Sending ring packet\n");
1612 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1613 buffsend[24] = style + 0x10;
1614 buffsend[29] = volume * 0x10;
1615 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1618 static void send_no_ring(struct unistimsession *pte)
1622 ast_verb(0, "Sending no ring packet\n");
1624 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1625 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1628 static void send_texttitle(struct unistimsession *pte, const char *text)
1633 ast_verb(0, "Sending title text\n");
1635 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1640 memcpy(buffsend + 10, text, i);
1641 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1645 static void send_idle_clock(struct unistimsession *pte)
1647 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1650 static void send_date_time(struct unistimsession *pte)
1653 struct timeval now = ast_tvnow();
1654 struct ast_tm atm = { 0, };
1657 ast_verb(0, "Sending Time & Date\n");
1659 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1660 ast_localtime(&now, &atm, NULL);
1661 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1662 buffsend[11] = (unsigned char) atm.tm_mday;
1663 buffsend[12] = (unsigned char) atm.tm_hour;
1664 buffsend[13] = (unsigned char) atm.tm_min;
1665 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1668 static void send_date_time2(struct unistimsession *pte)
1671 struct timeval now = ast_tvnow();
1672 struct ast_tm atm = { 0, };
1675 ast_verb(0, "Sending Time & Date #2\n");
1677 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1678 ast_localtime(&now, &atm, NULL);
1680 buffsend[9] = pte->device->datetimeformat;
1684 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1685 buffsend[15] = (unsigned char) atm.tm_mday;
1686 buffsend[16] = (unsigned char) atm.tm_hour;
1687 buffsend[17] = (unsigned char) atm.tm_min;
1688 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1691 static void send_date_time3(struct unistimsession *pte)
1694 struct timeval now = ast_tvnow();
1695 struct ast_tm atm = { 0, };
1698 ast_verb(0, "Sending Time & Date #3\n");
1700 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1701 ast_localtime(&now, &atm, NULL);
1702 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1703 buffsend[11] = (unsigned char) atm.tm_mday;
1704 buffsend[12] = (unsigned char) atm.tm_hour;
1705 buffsend[13] = (unsigned char) atm.tm_min;
1706 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1709 static void send_blink_cursor(struct unistimsession *pte)
1713 ast_verb(0, "Sending set blink\n");
1715 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1716 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1720 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1721 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1725 ast_verb(0, "Sending set cursor position\n");
1727 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1728 sizeof(packet_send_set_pos_cursor));
1730 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1734 static void send_charset_update(struct unistimsession *pte, int charset)
1736 const unsigned char* packet_send_charset;
1740 ast_verb(0, "Sending set default charset\n");
1742 if (charset == LANG_DEFAULT) {
1743 charset = options_languages[find_language(pte->device->language)].encoding;
1747 packet_send_charset = packet_send_charset_iso_8859_2;
1748 packet_size = sizeof(packet_send_charset_iso_8859_2);
1751 packet_send_charset = packet_send_charset_iso_8859_4;
1752 packet_size = sizeof(packet_send_charset_iso_8859_4);
1755 packet_send_charset = packet_send_charset_iso_8859_5;
1756 packet_size = sizeof(packet_send_charset_iso_8859_5);
1759 packet_send_charset = packet_send_charset_iso_2022_jp;
1760 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1764 packet_send_charset = packet_send_charset_iso_8859_1;
1765 packet_size = sizeof(packet_send_charset_iso_8859_1);
1767 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1768 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1772 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1776 ast_verb(0, "ResumeConnectionWithServer received\n");
1777 ast_verb(0, "Sending packet_send_query_mac_address\n");
1779 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1780 sizeof(packet_send_query_mac_address));
1781 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1785 static int unistim_register(struct unistimsession *s)
1787 struct unistim_device *d;
1789 ast_mutex_lock(&devicelock);
1792 if (!strcasecmp(s->macaddr, d->id)) {
1793 /* XXX Deal with IP authentication */
1796 d->codec_number = DEFAULT_CODEC;
1798 d->receiver_state = STATE_ONHOOK;
1803 ast_mutex_unlock(&devicelock);
1812 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1814 struct ast_format_cap *tmp = src->cap;
1815 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1817 ast_format_cap_copy(src->cap, dst->cap);
1820 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1825 l->cap = ast_format_cap_destroy(l->cap);
1830 static struct unistim_line *unistim_line_alloc(void)
1832 struct unistim_line *l;
1833 if (!(l = ast_calloc(1, sizeof(*l)))) {
1837 if (!(l->cap = ast_format_cap_alloc_nolock())) {
1844 static int unistim_free_sub(struct unistim_subchannel *sub) {
1846 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1848 ast_mutex_destroy(&sub->lock);
1853 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1855 struct unistim_subchannel *sub;
1856 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1861 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1863 sub->ss_thread = AST_PTHREADT_NULL;
1865 AST_LIST_LOCK(&d->subs);
1866 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1867 AST_LIST_UNLOCK(&d->subs);
1868 ast_mutex_init(&sub->lock);
1872 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1874 struct unistim_subchannel *s;
1876 AST_LIST_LOCK(&d->subs);
1877 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1884 AST_LIST_REMOVE_CURRENT(list);
1885 unistim_free_sub(sub);
1887 AST_LIST_TRAVERSE_SAFE_END;
1888 AST_LIST_UNLOCK(&d->subs);
1892 static const char *subtype_tostr(const int type)
1907 static const char *ptestate_tostr(const int type)
1912 case STATE_AUTHDENY:
1914 case STATE_MAINPAGE:
1916 case STATE_EXTENSION:
1918 case STATE_DIALPAGE:
1924 case STATE_SELECTOPTION:
1925 return "SELECTOPTION";
1926 case STATE_SELECTCODEC:
1927 return "SELECTCODEC";
1928 case STATE_SELECTLANGUAGE:
1929 return "SELECTLANGUAGE";
1930 case STATE_CLEANING:
1938 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
1944 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
1945 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
1949 ast_verb(0, "MAC Address received: %s\n", addrmac);
1951 strcpy(pte->macaddr, addrmac);
1952 res = unistim_register(pte);
1954 switch (autoprovisioning) {
1955 case AUTOPROVISIONING_NO:
1956 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
1957 pte->state = STATE_AUTHDENY;
1959 case AUTOPROVISIONING_YES:
1961 struct unistim_device *d = NULL, *newd = NULL;
1962 struct unistim_line *newl = NULL, *l = NULL;
1964 ast_verb(0, "New phone, autoprovisioning on\n");
1966 /* First : locate the [template] section */
1967 ast_mutex_lock(&devicelock);
1970 if (strcasecmp(d->name, "template")) {
1974 /* Found, cloning this entry */
1975 if (!(newd = ast_malloc(sizeof(*newd)))) {
1976 ast_mutex_unlock(&devicelock);
1979 memcpy(newd, d, sizeof(*newd));
1980 ast_mutex_init(&newd->lock);
1981 newd->lines.first = NULL;
1982 newd->lines.last = NULL;
1983 AST_LIST_LOCK(&d->lines);
1984 AST_LIST_TRAVERSE(&d->lines, l, list) {
1985 if (!(newl = unistim_line_alloc())) {
1988 unistim_line_copy(l, newl);
1989 newl->parent = newd;
1990 ast_copy_string(newl->name, l->name, sizeof(newl->name));
1991 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
1992 newl->name, newd->name);
1993 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
1995 AST_LIST_LOCK(&newd->lines);
1996 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
1997 AST_LIST_UNLOCK(&newd->lines);
1999 AST_LIST_UNLOCK(&d->lines);
2002 ast_mutex_unlock(&devicelock);
2005 /* Ok, now updating some fields */
2006 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2007 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2008 if (newd->extension == EXTENSION_NONE) {
2009 newd->extension = EXTENSION_ASK;
2012 newd->receiver_state = STATE_ONHOOK;
2013 newd->session = pte;
2014 newd->language[0] = '\0';
2015 newd->to_delete = -1;
2019 /* Go to the end of the linked chain */
2027 ast_mutex_unlock(&devicelock);
2029 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2030 pte->state = STATE_AUTHDENY;
2034 case AUTOPROVISIONING_TN:
2035 pte->state = STATE_AUTHDENY;
2038 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2042 if (pte->state != STATE_AUTHDENY) {
2043 struct unistim_line *line;
2044 struct unistim_subchannel *sub;
2046 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2048 AST_LIST_LOCK(&pte->device->subs);
2049 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2051 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2052 AST_LIST_REMOVE_CURRENT(list);
2056 AST_LIST_TRAVERSE_SAFE_END;
2057 AST_LIST_UNLOCK(&pte->device->subs);
2059 switch (pte->device->extension) {
2060 case EXTENSION_NONE:
2061 pte->state = STATE_MAINPAGE;
2064 /* Checking if we already have an extension number */
2065 if (ast_strlen_zero(pte->device->extension_number)) {
2066 pte->state = STATE_EXTENSION;
2068 /* Yes, because of a phone reboot. We don't ask again for the TN */
2069 if (register_extension(pte)) {
2070 pte->state = STATE_EXTENSION;
2072 pte->state = STATE_MAINPAGE;
2076 case EXTENSION_LINE:
2077 line = AST_LIST_FIRST(&pte->device->lines);
2078 ast_copy_string(pte->device->extension_number, line->name,
2079 sizeof(pte->device->extension_number));
2080 if (register_extension(pte)) {
2081 pte->state = STATE_EXTENSION;
2083 pte->state = STATE_MAINPAGE;
2087 /* If we are here, it's because of a phone reboot */
2088 pte->state = STATE_MAINPAGE;
2091 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2092 pte->device->extension);
2093 pte->state = STATE_AUTHDENY;
2097 if (pte->state == STATE_EXTENSION) {
2098 if (pte->device->extension != EXTENSION_TN) {
2099 pte->device->extension = EXTENSION_ASK;
2101 pte->device->extension_number[0] = '\0';
2104 ast_verb(0, "\nSending S1\n");
2106 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2107 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2110 ast_verb(0, "Sending query_basic_manager_04\n");
2112 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2113 sizeof(packet_send_query_basic_manager_04));
2114 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2117 ast_verb(0, "Sending query_basic_manager_10\n");
2119 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2120 sizeof(packet_send_query_basic_manager_10));
2121 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2123 send_date_time(pte);
2127 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2129 if (fwrite(&c, 1, 1, f) != 1) {
2130 display_last_error("Unable to write history log header.");
2133 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2134 display_last_error("Unable to write history entry - date.");
2137 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2138 display_last_error("Unable to write history entry - callerid.");
2141 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2142 display_last_error("Unable to write history entry - callername.");
2148 static int write_history(struct unistimsession *pte, char way, char ismissed)
2150 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2151 char line1[TEXT_LENGTH_MAX + 1];
2152 char count = 0, *histbuf;
2155 struct timeval now = ast_tvnow();
2156 struct ast_tm atm = { 0, };
2161 if (!pte->device->callhistory) {
2164 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2165 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2170 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2171 if (ast_mkdir(tmp, 0770)) {
2172 ast_log(LOG_WARNING, "Unable to create directory for history\n");
2176 ast_localtime(&now, &atm, NULL);
2179 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2181 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2184 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2186 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2187 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2188 atm.tm_min, atm.tm_sec, tmp2);
2190 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2191 USTM_LOG_DIR, pte->device->name, way);
2192 if ((f = fopen(tmp, "r"))) {
2193 struct stat bufstat;
2195 if (stat(tmp, &bufstat)) {
2196 display_last_error("Unable to stat history log.");
2200 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2201 if (bufstat.st_size != size) {
2202 ast_log(LOG_WARNING,
2203 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2204 tmp, (int) bufstat.st_size, size);
2211 /* If we can't open the log file, we create a brand new one */
2216 if ((errno != ENOENT) && (count == 0)) {
2217 display_last_error("Unable to open history log.");
2220 f = fopen(tmp, "w");
2222 display_last_error("Unable to create history log.");
2225 if (write_entry_history(pte, f, c, line1)) {
2229 memset(line1, ' ', TEXT_LENGTH_MAX);
2230 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2231 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2232 display_last_error("Unable to write history entry - stuffing.");
2238 display_last_error("Unable to close history - creation.");
2242 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2243 if (fread(&count, 1, 1, f) != 1) {
2244 display_last_error("Unable to read history header.");
2248 if (count > MAX_ENTRY_LOG) {
2249 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2250 count, MAX_ENTRY_LOG);
2254 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2255 USTM_LOG_DIR, pte->device->name, way);
2256 if (!(f2 = fopen(tmp2, "w"))) {
2257 display_last_error("Unable to create temporary history log.");
2262 if (++count > MAX_ENTRY_LOG) {
2263 count = MAX_ENTRY_LOG;
2265 if (write_entry_history(pte, f2, count, line1)) {
2270 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2271 if (!(histbuf = ast_malloc(size))) {
2277 if (fread(histbuf, size, 1, f) != 1) {
2281 display_last_error("Unable to read previous history entries.");
2284 if (fwrite(histbuf, size, 1, f2) != 1) {
2288 display_last_error("Unable to write previous history entries.");
2293 display_last_error("Unable to close history log.");
2296 display_last_error("Unable to close temporary history log.");
2299 display_last_error("Unable to remove old history log.");
2301 if (rename(tmp2, tmp)) {
2302 display_last_error("Unable to rename new history log.");
2307 static void unistim_quiet_chan(struct ast_channel *chan)
2309 if (chan && ast_channel_state(chan) == AST_STATE_UP) {
2310 if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MOH)) {
2312 } else if (ast_channel_generatordata(chan)) {
2313 ast_deactivate_generator(chan);
2318 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2322 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
2323 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
2325 if (!p1->owner || !p2->owner) {
2326 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2331 bridgea = ast_bridged_channel(chana);
2332 bridgeb = ast_bridged_channel(chanb);
2339 } else if (bridgeb) {
2346 if (peera && peerb && peerc && (peerb != peerc)) {
2347 unistim_quiet_chan(peera);
2348 unistim_quiet_chan(peerb);
2349 unistim_quiet_chan(peerc);
2351 unistim_quiet_chan(peerd);
2354 ast_log(LOG_NOTICE, "UNISTIM transfer: trying to masquerade %s into %s\n", ast_channel_name(peerc), ast_channel_name(peerb));
2355 if (ast_channel_masquerade(peerb, peerc)) {
2356 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", ast_channel_name(peerb),
2357 ast_channel_name(peerc));
2363 "Transfer attempted with no appropriate bridged calls to transfer\n");
2365 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2368 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2375 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2381 data = pte->device->lst_cnm;
2383 data = pte->device->lst_cid;
2386 /* This is very nearly strncpy(), except that the remaining buffer
2387 * is padded with ' ', instead of '\0' */
2388 memset(data, ' ', TEXT_LENGTH_MAX);
2389 size = strlen(callerid);
2390 if (size > TEXT_LENGTH_MAX) {
2391 size = TEXT_LENGTH_MAX;
2393 memcpy(data, callerid, size);
2396 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2398 struct unistim_subchannel *sub = NULL;
2400 AST_LIST_LOCK(&device->subs);
2401 AST_LIST_TRAVERSE(&device->subs, sub, list) {
2405 if (sub->subtype == type) {
2409 AST_LIST_UNLOCK(&device->subs);
2414 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2416 /* Silence our channel */
2417 if (!pte->device->silence_generator) {
2418 pte->device->silence_generator =
2419 ast_channel_start_silence_generator(sub->owner);
2420 if (pte->device->silence_generator == NULL) {
2421 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2422 } else if (unistimdebug) {
2423 ast_verb(0, "Starting silence generator\n");
2429 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2431 /* Stop the silence generator */
2432 if (pte->device->silence_generator) {
2434 ast_verb(0, "Stopping silence generator\n");
2437 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2439 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2441 pte->device->silence_generator = NULL;
2445 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2451 sub->subtype = SUB_ONHOLD;
2452 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2453 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2454 send_stop_timer(pte);
2456 ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, NULL, 0);
2462 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2464 struct unistim_subchannel *sub_real;
2466 sub_real = get_sub(pte->device, SUB_REAL);
2468 sub_hold(pte, sub_real);
2472 sub->subtype = SUB_REAL;
2473 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2474 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2475 send_start_timer(pte);
2477 ast_queue_control_data(sub->owner, AST_CONTROL_UNHOLD, NULL, 0);
2479 send_start_rtp(sub);
2485 static void close_call(struct unistimsession *pte)
2487 struct unistim_subchannel *sub, *sub_transf;
2489 sub = get_sub(pte->device, SUB_REAL);
2490 sub_transf = get_sub(pte->device, SUB_THREEWAY);
2491 send_stop_timer(pte);
2493 ast_log(LOG_WARNING, "Close call without sub\n");
2496 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2498 sub->alreadygone = 1;
2500 sub_transf->alreadygone = 1;
2501 if (attempt_transfer(sub, sub_transf) < 0) {
2502 ast_verb(0, "attempt_transfer failed.\n");
2505 ast_queue_hangup(sub->owner);
2509 if (sub_transf->owner) {
2510 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2512 ast_log(LOG_WARNING, "threeway sub without owner\n");
2515 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2516 pte->device->name, sub->softkey);
2519 change_callerid(pte, 0, pte->device->redial_number);
2520 change_callerid(pte, 1, "");
2521 write_history(pte, 'o', pte->device->missed_call);
2522 pte->device->missed_call = 0;
2523 show_main_page(pte);
2527 static void ignore_call(struct unistimsession *pte)
2533 static void discard_call(struct unistimsession *pte)
2535 struct unistim_subchannel* sub;
2536 sub = get_sub(pte->device, SUB_RING);
2541 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2545 static void *unistim_ss(void *data)
2547 struct ast_channel *chan = data;
2548 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2549 struct unistim_line *l = sub->parent;
2550 struct unistimsession *s = l->parent->session;
2553 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2554 ast_channel_exten_set(chan, s->device->phone_number);
2555 ast_copy_string(s->device->redial_number, s->device->phone_number,
2556 sizeof(s->device->redial_number));
2557 ast_setstate(chan, AST_STATE_RING);
2558 res = ast_pbx_run(chan);
2560 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2561 send_tone(s, 1000, 0);
2566 static int find_rtp_port(struct unistim_subchannel *s)
2568 struct unistim_subchannel *sub = NULL;
2569 int rtp_start = s->parent->parent->rtp_port;
2570 struct ast_sockaddr us_tmp;
2571 struct sockaddr_in us = { 0, };
2573 AST_LIST_LOCK(&s->parent->parent->subs);
2574 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2579 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2580 ast_sockaddr_to_sin(&us_tmp, &us);
2581 if (htons(us.sin_port)) {
2582 rtp_start = htons(us.sin_port) + 1;
2587 AST_LIST_UNLOCK(&s->parent->parent->subs);
2591 static void send_start_rtp(struct unistim_subchannel *sub)
2596 struct sockaddr_in public = { 0, };
2597 struct sockaddr_in us = { 0, };
2598 struct sockaddr_in sin = { 0, };
2599 struct ast_sockaddr us_tmp;
2600 struct ast_sockaddr sin_tmp;
2601 struct unistimsession *pte;
2603 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2604 ast_sockaddr_to_sin(&us_tmp, &us);
2605 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2606 ast_sockaddr_to_sin(&sin_tmp, &sin);
2608 /* Setting up RTP of the phone */
2609 if (public_ip.sin_family == 0) { /* NAT IP override ? */
2610 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2612 memcpy(&public, &public_ip, sizeof(public)); /* override */
2615 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2616 ast_inet_ntoa(us.sin_addr),
2617 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2618 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2619 ast_inet_ntoa(public.sin_addr));
2622 pte = sub->parent->parent->session;
2623 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2624 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2625 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2627 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2629 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2630 sizeof(packet_send_rtp_packet_size));
2631 buffsend[10] = (int) codec & 0xffffffffLL;
2632 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2635 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2637 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2638 sizeof(packet_send_jitter_buffer_conf));
2639 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2640 if (pte->device->rtp_method != 0) {
2641 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2644 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2646 if (pte->device->rtp_method == 3) {
2647 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2648 sizeof(packet_send_open_audio_stream_tx3));
2650 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2651 sizeof(packet_send_open_audio_stream_tx));
2653 if (pte->device->rtp_method != 2) {
2654 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2655 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2656 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2657 buffsend[23] = (rtcpsin_port & 0x00ff);
2658 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2659 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2660 buffsend[24] = (us.sin_port & 0x00ff);
2661 buffsend[27] = (rtcpsin_port & 0x00ff);
2662 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2664 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2665 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2666 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2667 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2668 buffsend[19] = (us.sin_port & 0x00ff);
2669 buffsend[11] = codec;
2671 buffsend[12] = codec;
2672 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2675 ast_verb(0, "Sending OpenAudioStreamRX\n");
2677 if (pte->device->rtp_method == 3) {
2678 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2679 sizeof(packet_send_open_audio_stream_rx3));
2681 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2682 sizeof(packet_send_open_audio_stream_rx));
2684 if (pte->device->rtp_method != 2) {
2685 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2686 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2687 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2688 buffsend[23] = (rtcpsin_port & 0x00ff);
2689 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2690 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2691 buffsend[24] = (us.sin_port & 0x00ff);
2692 buffsend[27] = (rtcpsin_port & 0x00ff);
2693 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2695 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2696 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2697 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2698 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2699 buffsend[19] = (us.sin_port & 0x00ff);
2700 buffsend[12] = codec;
2702 buffsend[11] = codec;
2703 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2705 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2708 ast_verb(0, "Sending packet_send_call default method\n");
2711 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2712 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2713 /* Destination port when sending RTP */
2714 buffsend[49] = (us.sin_port & 0x00ff);
2715 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2716 /* Destination port when sending RTCP */
2717 buffsend[52] = (rtcpsin_port & 0x00ff);
2718 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2720 buffsend[40] = codec;
2721 buffsend[41] = codec;
2722 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2723 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2724 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2725 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2726 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2727 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2728 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2729 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2731 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2732 ast_getformatname(ast_channel_readformat(sub->owner)));
2734 /* Source port for transmit RTP and Destination port for receiving RTP */
2735 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2736 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2737 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2738 buffsend[48] = (rtcpsin_port & 0x00ff);
2739 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2743 static void start_rtp(struct unistim_subchannel *sub)
2745 struct sockaddr_in sin = { 0, };
2746 struct sockaddr_in sout = { 0, };
2747 struct ast_sockaddr sin_tmp;
2748 struct ast_sockaddr sout_tmp;
2752 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2756 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2759 if (!sub->parent->parent) {
2760 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2763 if (!sub->parent->parent->session) {
2764 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2768 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2771 sout = sub->parent->parent->session->sout;
2772 ast_mutex_lock(&sub->lock);
2773 /* Allocate the RTP */
2775 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2777 ast_sockaddr_from_sin(&sout_tmp, &sout);
2778 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2780 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2781 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2782 ast_mutex_unlock(&sub->lock);
2785 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2786 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2787 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2788 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2789 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2791 /* Create the RTP connection */
2792 sin.sin_family = AF_INET;
2793 /* Setting up RTP for our side */
2794 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2795 sizeof(sin.sin_addr));
2797 sin.sin_port = htons(find_rtp_port(sub));
2798 ast_sockaddr_from_sin(&sin_tmp, &sin);
2799 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2800 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2801 struct ast_format tmpfmt;
2803 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2804 ast_log(LOG_WARNING,
2805 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2806 ast_getformatname(ast_channel_readformat(sub->owner)),
2807 ast_getformatname(&tmpfmt),
2808 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2810 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2811 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2813 send_start_rtp(sub);
2814 ast_mutex_unlock(&sub->lock);
2817 static void send_dial_tone(struct unistimsession *pte)
2819 struct ast_tone_zone_sound *ts = NULL;
2820 struct ast_tone_zone_part tone_data;
2824 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2825 ind = ast_strdupa(ts->data);
2826 s = strsep(&ind, ",");
2827 ast_tone_zone_part_parse(s, &tone_data);
2828 if (tone_data.modulate) {
2829 tone_data.freq2 = 0;
2831 send_tone(pte, tone_data.freq1, tone_data.freq2);
2833 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2834 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2836 ts = ast_tone_zone_sound_unref(ts);
2840 static void show_phone_number(struct unistimsession *pte)
2842 char tmp[TEXT_LENGTH_MAX + 1];
2843 const char *tmp_number = ustmtext("Number:", pte);
2844 int line, tmp_copy, offset = 0, i;
2846 pte->device->phone_number[pte->device->size_phone_number] = '\0';
2847 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2848 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2849 if (offset > strlen(tmp_number)) {
2850 offset = strlen(tmp_number);
2852 tmp_copy = strlen(tmp_number) - offset + 1;
2853 if (tmp_copy > sizeof(tmp)) {
2854 tmp_copy = sizeof(tmp);
2856 memcpy(tmp, tmp_number + offset, tmp_copy);
2858 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2861 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2862 if (pte->device->size_phone_number) {
2863 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2865 offset = strlen(tmp);
2867 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2872 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2873 send_text(line, TEXT_NORMAL, pte, tmp);
2874 send_blink_cursor(pte);
2875 send_cursor_pos(pte, (unsigned char) (line + offset));
2876 send_led_update(pte, 0);
2879 static void handle_dial_page(struct unistimsession *pte)
2881 pte->state = STATE_DIALPAGE;
2882 if (pte->device->call_forward[0] == -1) {
2883 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2884 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2885 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
2886 if (pte->device->call_forward[1] != 0) {
2887 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2888 sizeof(pte->device->phone_number));
2889 show_phone_number(pte);
2890 send_led_update(pte, 0);
2894 if ((pte->device->output == OUTPUT_HANDSET) &&
2895 (pte->device->receiver_state == STATE_ONHOOK)) {
2896 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2898 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2900 send_dial_tone(pte);
2902 if (pte->device->height > 1) {
2903 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2904 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2906 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
2909 pte->device->size_phone_number = 0;
2910 pte->device->phone_number[0] = 0;
2911 show_phone_number(pte);
2912 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2913 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2914 pte->device->missed_call = 0;
2915 send_led_update(pte, 0);
2916 pte->device->lastmsgssent = -1;
2920 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2922 struct ast_rtp_instance *rtp;
2926 ast_verb(0, "Swapping %p and %p\n", a, b);
2928 if ((!a->owner) || (!b->owner)) {
2929 ast_log(LOG_WARNING,
2930 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2931 a, a->owner, b, b->owner);
2938 fds = ast_channel_fd(a->owner, 0);
2939 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2940 ast_channel_internal_fd_set(b->owner, 0, fds);
2942 fds = ast_channel_fd(a->owner, 1);
2943 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2944 ast_channel_internal_fd_set(b->owner, 1, fds);
2947 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2948 static void transfer_call_step1(struct unistimsession *pte)
2950 struct unistim_subchannel *sub /*, *sub_trans */;
2951 struct unistim_device *d = pte->device;
2953 sub = get_sub(d, SUB_REAL);
2954 /* sub_trans = get_sub(d, SUB_THREEWAY); */
2956 if (!sub || !sub->owner) {
2957 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2960 /* Start music on hold if appropriate */
2962 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
2964 if (ast_bridged_channel(sub->owner)) {
2965 ast_moh_start(ast_bridged_channel(sub->owner),
2966 sub->parent->musicclass, NULL);
2968 sub->subtype = SUB_THREEWAY;
2970 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
2974 sub_start_silence(pte, sub);
2975 handle_dial_page(pte);
2978 static void transfer_cancel_step2(struct unistimsession *pte)
2980 struct unistim_subchannel *sub, *sub_trans;
2981 struct unistim_device *d = pte->device;
2983 sub = get_sub(d, SUB_REAL);
2984 sub_trans = get_sub(d, SUB_THREEWAY);
2986 if (!sub || !sub->owner) {
2987 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2992 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2995 swap_subs(sub, sub_trans);
2996 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
2998 sub_trans->subtype = SUB_REAL;
2999 sub->subtype = SUB_THREEWAY;
3000 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
3002 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
3008 /* From phone to PBX */
3009 static void handle_call_outgoing(struct unistimsession *s)
3011 struct ast_channel *c;
3012 struct unistim_subchannel *sub;
3015 s->state = STATE_CALL;
3017 sub = get_sub(s->device, SUB_THREEWAY);
3019 /* If sub for threway call created than we use transfer behaviuor */
3020 struct unistim_subchannel *sub_trans = NULL;
3021 struct unistim_device *d = s->device;
3023 sub_trans = get_sub(d, SUB_REAL);
3025 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
3029 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
3033 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3035 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3038 sub_trans->parent = sub->parent;
3039 sub_stop_silence(s, sub);
3041 /* Make new channel */
3042 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3044 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3047 /* Swap things around between the three-way and real call */
3048 swap_subs(sub, sub_trans);
3049 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3050 if (s->device->height == 1) {
3051 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3053 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3054 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3055 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3057 send_text_status(s, ustmtext("TransfrCancel", s));
3059 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3060 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3061 sub->ss_thread = AST_PTHREADT_NULL;
3066 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3067 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
3072 softkey = get_avail_softkey(s, NULL);
3073 if (softkey == -1) {
3074 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
3077 sub = get_sub(s->device, SUB_REAL);
3078 if (sub) { /* have already call assigned */
3079 sub_hold(s, sub); /* Need to put on hold */
3081 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
3082 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
3085 sub->parent = s->device->sline[softkey];
3086 s->device->ssub[softkey] = sub;
3087 sub->softkey = softkey;
3090 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
3092 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
3093 s->device->selected = -1;
3094 if (!sub->owner) { /* A call is already in progress&nbs