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/rtp_engine.h"
67 #include "asterisk/netsock2.h"
68 #include "asterisk/acl.h"
69 #include "asterisk/callerid.h"
70 #include "asterisk/cli.h"
71 #include "asterisk/app.h"
72 #include "asterisk/musiconhold.h"
73 #include "asterisk/causes.h"
74 #include "asterisk/indications.h"
75 #include "asterisk/pickup.h"
76 #include "asterisk/astobj2.h"
77 #include "asterisk/astdb.h"
78 #include "asterisk/features_config.h"
79 #include "asterisk/bridge.h"
80 #include "asterisk/stasis_channels.h"
82 #define DEFAULTCONTEXT "default"
83 #define DEFAULTCALLERID "Unknown"
84 #define DEFAULTCALLERNAME " "
85 #define DEFAULTHEIGHT 3
86 #define USTM_LOG_DIR "unistimHistory"
87 #define USTM_LANG_DIR "unistimLang"
89 /*! Size of the transmit buffer */
90 #define MAX_BUF_SIZE 64
91 /*! Number of slots for the transmit queue */
92 #define MAX_BUF_NUMBER 150
93 /*! Number of digits displayed on screen */
94 #define MAX_SCREEN_NUMBER 15
95 /*! Try x times before removing the phone */
96 #define NB_MAX_RETRANSMIT 8
97 /*! Nb of milliseconds waited when no events are scheduled */
98 #define IDLE_WAIT 1000
99 /*! Wait x milliseconds before resending a packet */
100 #define RETRANSMIT_TIMER 2000
101 /*! How often the mailbox is checked for new messages */
102 #define TIMER_MWI 5000
103 /*! Timeout value for entered number being dialed */
104 #define DEFAULT_INTERDIGIT_TIMER 4000
107 #define DEFAULT_CODEC 0x00
108 #define SIZE_PAGE 4096
109 #define DEVICE_NAME_LEN 16
110 #define AST_CONFIG_MAX_PATH 255
111 #define MAX_ENTRY_LOG 30
115 #define SUB_THREEWAY 2
118 struct ast_format_cap *global_cap;
121 AUTOPROVISIONING_NO = 0,
122 AUTOPROVISIONING_YES,
127 /*! Do not create an extension into the default dialplan */
129 /*! Prompt user for an extension number and register it */
131 /*! Register an extension with the line=> value */
133 /*! Used with AUTOPROVISIONING_TN */
136 #define OUTPUT_HANDSET 0xC0
137 #define OUTPUT_HEADPHONE 0xC1
138 #define OUTPUT_SPEAKER 0xC2
140 #define VOLUME_LOW 0x01
141 #define VOLUME_LOW_SPEAKER 0x03
142 #define VOLUME_NORMAL 0x02
143 #define VOLUME_INSANELY_LOUD 0x07
145 #define MUTE_OFF 0x00
147 #define MUTE_ON_DISCRET 0xCE
149 #define SIZE_HEADER 6
150 #define SIZE_MAC_ADDR 17
151 #define TEXT_LENGTH_MAX 24
152 #define TEXT_LINE0 0x00
153 #define TEXT_LINE1 0x20
154 #define TEXT_LINE2 0x40
155 #define TEXT_NORMAL 0x05
156 #define TEXT_INVERSE 0x25
157 #define STATUS_LENGTH_MAX 28
159 #define FAV_ICON_NONE 0x00
160 #define FAV_ICON_ONHOOK_BLACK 0x20
161 #define FAV_ICON_ONHOOK_WHITE 0x21
162 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
163 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
164 #define FAV_ICON_OFFHOOK_BLACK 0x24
165 #define FAV_ICON_OFFHOOK_WHITE 0x25
166 #define FAV_ICON_ONHOLD_BLACK 0x26
167 #define FAV_ICON_ONHOLD_WHITE 0x27
168 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
169 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
170 #define FAV_ICON_PHONE_BLACK 0x2A
171 #define FAV_ICON_PHONE_WHITE 0x2B
172 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
173 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
174 #define FAV_ICON_HEADPHONES 0x2E
175 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
176 #define FAV_ICON_HOME 0x30
177 #define FAV_ICON_CITY 0x31
178 #define FAV_ICON_SHARP 0x32
179 #define FAV_ICON_PAGER 0x33
180 #define FAV_ICON_CALL_CENTER 0x34
181 #define FAV_ICON_FAX 0x35
182 #define FAV_ICON_MAILBOX 0x36
183 #define FAV_ICON_REFLECT 0x37
184 #define FAV_ICON_COMPUTER 0x38
185 #define FAV_ICON_FORWARD 0x39
186 #define FAV_ICON_LOCKED 0x3A
187 #define FAV_ICON_TRASH 0x3B
188 #define FAV_ICON_INBOX 0x3C
189 #define FAV_ICON_OUTBOX 0x3D
190 #define FAV_ICON_MEETING 0x3E
191 #define FAV_ICON_BOX 0x3F
193 #define FAV_BLINK_FAST 0x20
194 #define FAV_BLINK_SLOW 0x40
196 #define FAV_MAX_LENGTH 0x0A
200 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
202 static void dummy(char *unused, ...)
207 /*! \brief Global jitterbuffer configuration - by default, jb is disabled
208 * \note Values shown here match the defaults shown in unistim.conf.sample */
209 static struct ast_jb_conf default_jbconf =
213 .resync_threshold = 1000,
217 static struct ast_jb_conf global_jbconf;
220 /* #define DUMP_PACKET 1 */
221 /* #define DEBUG_TIMER ast_verbose */
223 #define DEBUG_TIMER dummy
224 /*! Enable verbose output. can also be set with the CLI */
225 static int unistimdebug = 0;
226 static int unistim_port;
227 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
228 static int unistim_keepalive;
229 static int unistimsock = -1;
233 unsigned int tos_audio;
235 unsigned int cos_audio;
236 } qos = { 0, 0, 0, 0 };
238 static struct io_context *io;
239 static struct ast_sched_context *sched;
240 static struct sockaddr_in public_ip = { 0, };
241 static unsigned char *buff; /*! Receive buffer address */
242 static int unistim_reloading = 0;
243 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
245 /*! This is the thread for the monitor which checks for input on the channels
246 * which are not currently in use. */
247 static pthread_t monitor_thread = AST_PTHREADT_NULL;
249 /*! Protect the monitoring thread, so only one process can kill or start it, and not
250 * when it's doing something critical. */
251 AST_MUTEX_DEFINE_STATIC(monlock);
252 /*! Protect the session list */
253 AST_MUTEX_DEFINE_STATIC(sessionlock);
254 /*! Protect the device list */
255 AST_MUTEX_DEFINE_STATIC(devicelock);
267 STATE_SELECTLANGUAGE,
327 static const int dtmf_row[] = { 697, 770, 852, 941 };
328 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
335 struct unistim_subchannel {
337 unsigned int subtype; /*! SUB_REAL, SUB_RING, SUB_THREEWAY or SUB_ONHOLD */
338 struct ast_channel *owner; /*! Asterisk channel used by the subchannel */
339 struct unistim_line *parent; /*! Unistim line */
340 struct ast_rtp_instance *rtp; /*! RTP handle */
341 int softkey; /*! Softkey assigned */
342 pthread_t ss_thread; /*! unistim_ss thread handle */
346 int moh; /*!< Music on hold in progress */
347 AST_LIST_ENTRY(unistim_subchannel) list;
351 * \todo Convert to stringfields
353 struct unistim_line {
355 char name[80]; /*! Like 200 */
356 char fullname[80]; /*! Like USTM/200\@black */
357 char exten[AST_MAX_EXTENSION]; /*! Extension where to start */
358 char cid_num[AST_MAX_EXTENSION]; /*! CallerID Number */
359 char mailbox[AST_MAX_EXTENSION]; /*! Mailbox for MWI */
360 char musicclass[MAX_MUSICCLASS]; /*! MusicOnHold class */
361 ast_group_t callgroup; /*! Call group */
362 ast_group_t pickupgroup; /*! Pickup group */
363 char accountcode[AST_MAX_ACCOUNT_CODE]; /*! Account code (for billing) */
364 int amaflags; /*! AMA flags (for billing) */
365 struct ast_format_cap *cap; /*! Codec supported */
366 char parkinglot[AST_MAX_CONTEXT]; /*! Parkinglot */
367 struct unistim_line *next;
368 struct unistim_device *parent;
369 AST_LIST_ENTRY(unistim_line) list;
373 * \brief A device containing one or more lines
375 static struct unistim_device {
377 int receiver_state; /*!< state of the receiver (see ReceiverState) */
378 int size_phone_number; /*!< size of the phone number */
379 char context[AST_MAX_EXTENSION]; /*!< Context to start in */
380 char phone_number[AST_MAX_EXTENSION]; /*!< the phone number entered by the user */
381 char redial_number[AST_MAX_EXTENSION]; /*!< the last phone number entered by the user */
382 char id[18]; /*!< mac address of the current phone in ascii */
383 char name[DEVICE_NAME_LEN]; /*!< name of the device */
384 int hasexp; /*!< if device have expansion connected */
385 char expsoftkeylabel[EXPNUM][11]; /*!< soft key label */
386 char softkeylabel[FAVNUM][11]; /*!< soft key label */
387 char softkeynumber[FAVNUM][AST_MAX_EXTENSION]; /*!< number dialed when the soft key is pressed */
388 char softkeyicon[FAVNUM]; /*!< icon number */
389 char softkeydevice[FAVNUM][16]; /*!< name of the device monitored */
390 struct unistim_subchannel *ssub[FAVNUM];
391 struct unistim_line *sline[FAVNUM];
392 struct unistim_device *sp[FAVNUM]; /*!< pointer to the device monitored by this soft key */
393 char language[MAX_LANGUAGE]; /*!< Language for asterisk sounds */
394 int height; /*!< The number of lines the phone can display */
395 char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
396 char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
397 char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
398 char titledefault[13]; /*!< title (text before date/time) */
399 char datetimeformat; /*!< format used for displaying time/date */
400 char contrast; /*!< contrast */
401 char country[3]; /*!< country used for dial tone frequency */
402 struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
403 char ringvolume; /*!< Ring volume */
404 char ringstyle; /*!< Ring melody */
405 char cwvolume; /*!< Ring volume on call waiting */
406 char cwstyle; /*!< Ring melody on call waiting */
407 int interdigit_timer; /*!< Interdigit timer for dialing number by timeout */
408 time_t nextdial; /*!< Timer used for dial by timeout */
409 int rtp_port; /*!< RTP port used by the phone */
410 int rtp_method; /*!< Select the unistim data used to establish a RTP session */
411 int status_method; /*!< Select the unistim packet used for sending status text */
412 char codec_number; /*!< The current codec used to make calls */
413 int missed_call; /*!< Number of call unanswered */
414 int callhistory; /*!< Allowed to record call history */
415 int sharp_dial; /*!< Execute Dial on '#' or not */
416 char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
417 char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
418 char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
419 int output; /*!< Handset, headphone or speaker */
420 int previous_output; /*!< Previous output */
421 int volume; /*!< Default volume */
422 int selected; /*!< softkey selected */
423 int mute; /*!< Mute mode */
424 int lastmsgssent; /*! Used by MWI */
425 time_t nextmsgcheck; /*! Used by MWI */
426 int nat; /*!< Used by the obscure ast_rtp_setnat */
427 enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
428 char extension_number[11]; /*!< Extension number entered by the user */
429 char to_delete; /*!< Used in reload */
430 struct ast_silence_generator *silence_generator;
431 AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
432 AST_LIST_HEAD(,unistim_line) lines;
434 struct unistimsession *session;
435 struct unistim_device *next;
438 static struct unistimsession {
440 struct sockaddr_in sin; /*!< IP address of the phone */
441 struct sockaddr_in sout; /*!< IP address of server */
442 int timeout; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
443 unsigned short seq_phone; /*!< sequence number for the next packet (when we receive a request) */
444 unsigned short seq_server; /*!< sequence number for the next packet (when we send a request) */
445 unsigned short last_seq_ack; /*!< sequence number of the last ACK received */
446 unsigned long tick_next_ping; /*!< time for the next ping */
447 int last_buf_available; /*!< number of a free slot */
448 int nb_retransmit; /*!< number of retransmition */
449 int state; /*!< state of the phone (see phone_state) */
450 int size_buff_entry; /*!< size of the buffer used to enter datas */
451 char buff_entry[16]; /*!< Buffer for temporary datas */
452 char macaddr[18]; /*!< mac adress of the phone (not always available) */
453 char firmware[8]; /*!< firmware of the phone (not always available) */
454 struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
455 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
456 struct unistim_device *device;
457 struct unistimsession *next;
460 /*! Store on screen phone menu item (label and handler function) */
461 struct unistim_menu_item {
464 void (*handle_option)(struct unistimsession *);
467 /*! Language item for currently existed translations */
468 struct unistim_languages {
472 struct ao2_container *trans;
476 * \page Unistim datagram formats
478 * Format of datagrams :
479 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
480 * byte 2 : sequence number (high part)
481 * byte 3 : sequence number (low part)
482 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
483 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
486 static const unsigned char packet_rcv_discovery[] =
487 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
488 static const unsigned char packet_send_discovery_ack[] =
489 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
491 static const unsigned char packet_recv_firm_version[] =
492 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
493 static const unsigned char packet_recv_it_type[] =
494 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
495 static const unsigned char packet_recv_pressed_key[] =
496 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
497 static const unsigned char packet_recv_pick_up[] =
498 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
499 static const unsigned char packet_recv_hangup[] =
500 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
501 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
503 /*! Expansion module (i2004 KEM) */
504 static const unsigned char packet_recv_expansion_pressed_key[] =
505 { 0x00, 0x00, 0x00, 0x13, 0x89, 0x04, 0x59 };
506 static const unsigned char packet_send_expansion_next[] = { 0x09, 0x03, 0x17 };
507 static const unsigned char packet_send_expansion_icon[] = { 0x09, 0x06, 0x59, 0x05, /*pos */ 0x47, /*icon */ 0x20 }; /* display an icon in front of the text zone */
508 static const unsigned char packet_send_expansion_text[] = { 0x09, 0x0f, 0x57, 0x19, /*pos */ 0x47, /*text */ 0x20,
509 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */ };
512 /*! TransportAdapter */
513 static const unsigned char packet_recv_resume_connection_with_server[] =
514 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
515 static const unsigned char packet_recv_mac_addr[] =
516 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
518 static const unsigned char packet_send_date_time3[] =
519 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
520 /*Minutes */ 0x08, 0x32
522 static const unsigned char packet_send_date_time[] =
523 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
524 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
525 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
526 0x05, 0x12, 0x00, 0x78
529 static const unsigned char packet_send_no_ring[] =
530 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
531 static const unsigned char packet_send_s4[] =
532 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
533 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
534 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
535 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
536 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
538 static const unsigned char packet_send_call[] =
539 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
540 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
541 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
542 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
543 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
544 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
547 static const unsigned char packet_send_stream_based_tone_off[] =
548 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
550 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
551 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
552 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
553 static const unsigned char packet_send_stream_based_tone_on[] =
554 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
555 static const unsigned char packet_send_stream_based_tone_single_freq[] =
556 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
557 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
558 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
559 static const unsigned char packet_send_select_output[] =
560 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
561 static const unsigned char packet_send_ring[] =
562 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
563 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
564 0x20, 0x16, 0x04, 0x10, 0x00
566 static const unsigned char packet_send_end_call[] =
567 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
568 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
569 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
571 static const unsigned char packet_send_s9[] =
572 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
574 static const unsigned char packet_send_rtp_packet_size[] =
575 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
576 static const unsigned char packet_send_jitter_buffer_conf[] =
577 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
578 /* early packet resync 2 bytes */ 0x3e, 0x80,
579 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
582 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
583 static unsigned char packet_send_StreamBasedToneCad[] =
584 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
585 static const unsigned char packet_send_open_audio_stream_rx[] =
586 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
587 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
588 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
590 static const unsigned char packet_send_open_audio_stream_tx[] =
591 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
592 0x0e, 0x01, /* Local port */ 0x14, 0x50,
593 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
596 static const unsigned char packet_send_open_audio_stream_rx3[] =
597 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
598 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
599 /* RTCP Port */ 0x14,
600 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
603 static const unsigned char packet_send_open_audio_stream_tx3[] =
604 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
605 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
606 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
607 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
610 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
611 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
612 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
613 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
615 static const unsigned char packet_send_Contrast[] =
616 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
617 static const unsigned char packet_send_start_timer[] =
618 { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
619 /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
620 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
621 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
622 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
623 static const unsigned char packet_send_set_pos_cursor[] =
624 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
626 /*static unsigned char packet_send_MonthLabelsDownload[] =
627 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
628 static const unsigned char packet_send_favorite[] =
629 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
630 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
631 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
633 static const unsigned char packet_send_title[] =
634 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
635 0x20, 0x20, 0x20, 0x20 /*end_text */ };
636 static const unsigned char packet_send_text[] =
637 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
638 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
639 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
640 /*end_text */ 0x17, 0x04, 0x10, 0x87
642 static const unsigned char packet_send_status[] =
643 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
644 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
645 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
647 static const unsigned char packet_send_status2[] =
648 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
649 0x20, 0x20, 0x20 /* end_text */ };
651 /* Multiple character set support */
652 /* ISO-8859-1 - Western European) */
653 static const unsigned char packet_send_charset_iso_8859_1[] =
654 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
655 /* ISO-8859-2 - Central European) */
656 static const unsigned char packet_send_charset_iso_8859_2[] =
657 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
658 /* ISO-8859-4 - Baltic) */
659 static const unsigned char packet_send_charset_iso_8859_4[] =
660 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
661 /* ISO 8859-5 - cyrilic */
662 static const unsigned char packet_send_charset_iso_8859_5[] =
663 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
664 /* Japaneese (ISO-2022-JP ?) */
665 static const unsigned char packet_send_charset_iso_2022_jp[] =
666 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
668 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
670 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
671 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
672 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
673 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
675 static unsigned char packet_send_ping[] =
676 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
678 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
680 static const char tdesc[] = "UNISTIM Channel Driver";
681 static const char channel_type[] = "USTM";
684 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
685 static int load_module(void);
686 static int reload(void);
687 static int unload_module(void);
688 static int reload_config(void);
689 static void unistim_set_owner(struct unistim_subchannel *sub, struct ast_channel *chan);
690 static void show_main_page(struct unistimsession *pte);
691 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
692 const char *dest, int *cause);
693 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
694 static int unistim_hangup(struct ast_channel *ast);
695 static int unistim_answer(struct ast_channel *ast);
696 static struct ast_frame *unistim_read(struct ast_channel *ast);
697 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
698 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
700 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
701 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
702 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
703 unsigned int duration);
704 static int unistim_sendtext(struct ast_channel *ast, const char *text);
706 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
708 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
710 static struct ast_channel_tech unistim_tech = {
711 .type = channel_type,
712 .description = tdesc,
713 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
714 .requester = unistim_request,
715 .call = unistim_call,
716 .hangup = unistim_hangup,
717 .answer = unistim_answer,
718 .read = unistim_read,
719 .write = unistim_write,
720 .indicate = unistim_indicate,
721 .fixup = unistim_fixup,
722 .send_digit_begin = unistim_senddigit_begin,
723 .send_digit_end = unistim_senddigit_end,
724 .send_text = unistim_sendtext,
727 static void send_start_rtp(struct unistim_subchannel *);
729 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
730 static void key_favorite(struct unistimsession *, char);
732 static void handle_select_codec(struct unistimsession *);
733 static void handle_select_language(struct unistimsession *);
734 static int find_language(const char*);
736 static int unistim_free_sub(struct unistim_subchannel *);
738 static struct unistim_menu_item options_menu[] =
740 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
741 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
745 static struct unistim_languages options_languages[] =
747 {"English", "en", ISO_8859_1, NULL},
748 {"French", "fr", ISO_8859_1, NULL},
749 {"Russian", "ru", ISO_8859_5, NULL},
750 {NULL, NULL, 0, NULL}
753 static char ustm_strcopy[1024];
755 struct ustm_lang_entry {
756 const char *str_orig;
757 const char *str_trans;
760 static int lang_hash_fn(const void *obj, const int flags)
762 const struct ustm_lang_entry *entry = obj;
763 return ast_str_hash(entry->str_orig);
766 static int lang_cmp_fn(void *obj, void *arg, int flags)
768 struct ustm_lang_entry *entry1 = obj;
769 struct ustm_lang_entry *entry2 = arg;
771 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
774 static const char *ustmtext(const char *str, struct unistimsession *pte)
776 struct ustm_lang_entry *lang_entry;
777 struct ustm_lang_entry le_search;
778 struct unistim_languages *lang = NULL;
782 lang = &options_languages[find_language(pte->device->language)];
787 /* Check if specified language exists */
789 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
792 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
793 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
796 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
797 USTM_LANG_DIR, lang->lang_short);
800 ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
803 while (fgets(tmp, sizeof(tmp), f)) {
804 if (!(p = strchr(tmp, '\n'))) {
805 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
809 if (!(p = strchr(tmp, '"'))) {
812 if (tmp == strstr(tmp, "msgid")) {
813 p_orig = ast_strdup(p + 1);
814 p = strchr(p_orig, '"');
815 } else if (tmp == strstr(tmp, "msgstr")) {
816 p_trans = ast_strdup(p + 1);
817 p = strchr(p_trans, '"');
822 if (!p_trans || !p_orig) {
825 if (ast_strlen_zero(p_trans)) {
832 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
837 lang_entry->str_trans = p_trans;
838 lang_entry->str_orig = p_orig;
839 ao2_link(lang->trans, lang_entry);
847 le_search.str_orig = str;
848 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
849 size = strlen(lang_entry->str_trans)+1;
853 memcpy(ustm_strcopy, lang_entry->str_trans, size);
854 ao2_ref(lang_entry, -1);
861 static void display_last_error(const char *sz_msg)
863 /* Display the error message */
864 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
867 static unsigned int get_tick_count(void)
869 struct timeval now = ast_tvnow();
871 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
874 /* Send data to a phone without retransmit nor buffering */
875 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
876 const struct sockaddr_in *addr_ourip)
879 struct iovec msg_iov;
881 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
882 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
883 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
885 /* cast this to a non-const pointer, since the sendmsg() API
886 * does not provide read-only and write-only flavors of the
887 * structures used for its arguments, but in this case we know
888 * the data will not be modified
890 msg_iov.iov_base = (char *) data;
891 msg_iov.iov_len = size;
893 msg.msg_name = addr_to; /* optional address */
894 msg.msg_namelen = sizeof(struct sockaddr_in); /* size of address */
895 msg.msg_iov = &msg_iov; /* scatter/gather array */
896 msg.msg_iovlen = 1; /* # elements in msg_iov */
897 msg.msg_control = ip_msg; /* ancillary data */
898 msg.msg_controllen = sizeof(buffer); /* ancillary data buffer len */
899 msg.msg_flags = 0; /* flags on received message */
901 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
902 ip_msg->cmsg_level = IPPROTO_IP;
903 ip_msg->cmsg_type = IP_PKTINFO;
904 pki->ipi_ifindex = 0; /* Interface index, 0 = use interface specified in routing table */
905 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr; /* Local address */
906 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
911 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
912 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
913 ast_inet_ntoa(addr_to->sin_addr));
914 for (tmp = 0; tmp < size; tmp++)
915 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
916 ast_verb(0, "\n******************************************\n");
921 if (sendmsg(unistimsock, &msg, 0) == -1) {
922 display_last_error("Error sending datas");
925 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
927 display_last_error("Error sending datas");
931 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
935 unsigned short seq = ntohs(++pte->seq_server);
937 ast_mutex_lock(&pte->lock);
938 buf_pos = pte->last_buf_available;
940 if (buf_pos >= MAX_BUF_NUMBER) {
941 ast_log(LOG_WARNING, "Error : send queue overflow\n");
942 ast_mutex_unlock(&pte->lock);
945 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
946 pte->wsabufsend[buf_pos].len = size;
947 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
949 tick = get_tick_count();
950 pte->timeout = tick + RETRANSMIT_TIMER;
952 /*#ifdef DUMP_PACKET */
954 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
957 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
959 pte->last_buf_available++;
960 ast_mutex_unlock(&pte->lock);
963 static void send_ping(struct unistimsession *pte)
967 ast_verb(6, "Sending ping\n");
969 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
970 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
971 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
974 static int get_to_address(int fd, struct sockaddr_in *toAddr)
982 struct in_addr address;
985 /* Zero out the structures before we use them */
986 /* This sets several key values to NULL */
987 memset(&msg, 0, sizeof(msg));
988 memset(&ip_msg, 0, sizeof(ip_msg));
990 /* Initialize the message structure */
991 msg.msg_control = &ip_msg;
992 msg.msg_controllen = sizeof(ip_msg);
993 /* Get info about the incoming packet */
994 err = recvmsg(fd, &msg, MSG_PEEK);
996 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
998 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
1001 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
1006 /* Allocate memory & initialize structures for a new phone */
1007 /* addr_from : ip address of the phone */
1008 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
1011 struct unistimsession *s;
1013 if (!(s = ast_calloc(1, sizeof(*s))))
1016 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
1017 get_to_address(unistimsock, &s->sout);
1018 s->sout.sin_family = AF_INET;
1020 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
1021 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
1023 ast_mutex_init(&s->lock);
1024 ast_mutex_lock(&sessionlock);
1028 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
1029 s->state = STATE_INIT;
1030 s->tick_next_ping = get_tick_count() + unistim_keepalive;
1031 /* Initialize struct wsabuf */
1032 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
1033 s->wsabufsend[tmp].buf = s->buf[tmp];
1035 ast_mutex_unlock(&sessionlock);
1039 static void send_end_call(struct unistimsession *pte)
1043 ast_verb(0, "Sending end call\n");
1045 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
1046 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
1049 static void set_ping_timer(struct unistimsession *pte)
1051 unsigned int tick = 0; /* XXX what is this for, anyways */
1053 pte->timeout = pte->tick_next_ping;
1054 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
1058 /* Checking if our send queue is empty,
1059 * if true, setting up a timer for keepalive */
1060 static void check_send_queue(struct unistimsession *pte)
1062 /* Check if our send queue contained only one element */
1063 if (pte->last_buf_available == 1) {
1065 ast_verb(6, "Our single packet was ACKed.\n");
1067 pte->last_buf_available--;
1068 set_ping_timer(pte);
1071 /* Check if this ACK catch up our latest packet */
1072 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
1074 ast_verb(6, "Our send queue is completely ACKed.\n");
1076 pte->last_buf_available = 0; /* Purge the send queue */
1077 set_ping_timer(pte);
1081 ast_verb(6, "We still have packets in our send queue\n");
1086 static void send_start_timer(struct unistimsession *pte)
1090 ast_verb(0, "Sending start timer\n");
1092 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
1093 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
1096 static void send_stop_timer(struct unistimsession *pte)
1100 ast_verb(0, "Sending stop timer\n");
1102 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
1103 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
1106 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1110 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
1112 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
1114 buffsend[10] = status;
1115 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
1118 static void send_expansion_next(struct unistimsession *pte)
1121 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_next, sizeof(packet_send_expansion_next));
1122 send_client(SIZE_HEADER + sizeof(packet_send_expansion_next), buffsend, pte);
1126 static void send_expansion_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
1130 ast_verb(0, "Sending expansion icon pos %d with status 0x%.2x\n", pos, status);
1132 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_icon, sizeof(packet_send_expansion_icon));
1134 buffsend[11] = status;
1135 send_client(SIZE_HEADER + sizeof(packet_send_expansion_icon), buffsend, pte);
1138 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1139 static void send_expansion_text(unsigned char pos, struct unistimsession *pte, const char *text)
1144 ast_log(LOG_ERROR, "[expansion] Asked to display NULL text (pos %d)\n", pos);
1148 ast_verb(0, "[expansion] Sending text at pos %d\n", pos);
1150 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_text, sizeof(packet_send_expansion_text));
1153 if (i > TEXT_LENGTH_MAX) {
1154 i = TEXT_LENGTH_MAX;
1156 memcpy(buffsend + 11, text, i);
1157 send_client(SIZE_HEADER + sizeof(packet_send_expansion_text), buffsend, pte);
1160 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1165 ast_verb(0, "Sending Stream Based Tone Off\n");
1167 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1168 sizeof(packet_send_stream_based_tone_off));
1169 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1172 /* Since most of the world use a continuous tone, it's useless
1174 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
1175 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
1176 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
1178 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1182 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1183 sizeof(packet_send_stream_based_tone_single_freq));
1184 buffsend[10] = (tone1 & 0xff00) >> 8;
1185 buffsend[11] = (tone1 & 0x00ff);
1186 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1190 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
1191 sizeof(packet_send_stream_based_tone_dial_freq));
1192 buffsend[10] = (tone1 & 0xff00) >> 8;
1193 buffsend[11] = (tone1 & 0x00ff);
1194 buffsend[12] = (tone2 & 0xff00) >> 8;
1195 buffsend[13] = (tone2 & 0x00ff);
1196 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
1201 ast_verb(0, "Sending Stream Based Tone On\n");
1203 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1204 sizeof(packet_send_stream_based_tone_on));
1205 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1208 /* Positions for favorites
1209 |--------------------|
1210 | 5 2 | <-- not on screen in i2002
1215 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1217 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
1224 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
1226 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
1229 buffsend[25] = status;
1230 i = strlen(ustmtext(text, pte));
1231 if (i > FAV_MAX_LENGTH) {
1234 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1235 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
1238 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1239 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
1243 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
1244 if (pte->device->selected != -1) {
1245 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
1250 static void send_expansion_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
1251 send_expansion_icon(pos, status, pte);
1252 send_expansion_text(pos, pte, ustmtext(pte->device->expsoftkeylabel[pos], pte));
1253 send_expansion_next(pte);
1257 static int soft_key_visible(struct unistim_device* d, unsigned char num)
1259 if(d->height == 1 && num % 3 == 2) {
1265 static void refresh_all_favorite(struct unistimsession *pte)
1267 unsigned char i = 0;
1269 struct unistim_line *line;
1270 line = AST_LIST_FIRST(&pte->device->lines);
1273 ast_verb(0, "Refreshing all favorite\n");
1275 for (i = 0; i < FAVNUM; i++) {
1276 unsigned char status = pte->device->softkeyicon[i];
1278 if (!soft_key_visible(pte->device, i)) {
1281 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
1282 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
1283 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1287 send_favorite_short(i, status, pte);
1289 if (pte->device->hasexp) {
1290 for (i = 0; i < EXPNUM; i++) {
1291 send_expansion_short(i, FAV_ICON_NONE, pte);
1296 static int is_key_favorite(struct unistim_device *d, int fav)
1298 if ((fav < 0) && (fav > 5)) {
1301 if (d->sline[fav]) {
1304 if (d->softkeynumber[fav][0] == '\0') {
1310 static int is_key_line(struct unistim_device *d, int fav)
1312 if ((fav < 0) && (fav > 5)) {
1315 if (!d->sline[fav]) {
1318 if (is_key_favorite(d, fav)) {
1324 static int get_active_softkey(struct unistimsession *pte)
1326 return pte->device->selected;
1329 static int get_avail_softkey(struct unistimsession *pte, const char* name)
1333 if (!is_key_line(pte->device, pte->device->selected)) {
1334 pte->device->selected = -1;
1336 for (i = 0; i < FAVNUM; i++) {
1337 if (pte->device->selected != -1 && pte->device->selected != i) {
1340 if (!soft_key_visible(pte->device, i)) {
1343 if (pte->device->ssub[i]) {
1346 if (is_key_line(pte->device, i)) {
1347 if (name && strcmp(name, pte->device->sline[i]->name)) {
1351 ast_verb(0, "Found softkey %d for device %s\n", i, name);
1360 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1361 * use FAV_ICON_*_BLACK constant in status parameters */
1362 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
1364 struct unistim_device *d = devices;
1366 /* Update the current phone line softkey icon */
1367 if (pte->state != STATE_CLEANING) {
1368 int softkeylinepos = get_active_softkey(pte);
1369 if (softkeylinepos != -1) {
1370 send_favorite_short(softkeylinepos, status, pte);
1373 /* Notify other phones if we're in their bookmark */
1375 for (i = 0; i < FAVNUM; i++) {
1376 if (d->sp[i] == pte->device) { /* It's us ? */
1377 if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
1378 d->softkeyicon[i] = status;
1380 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
1389 static int register_extension(const struct unistimsession *pte)
1391 struct unistim_line *line;
1392 line = AST_LIST_FIRST(&pte->device->lines);
1394 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1395 pte->device->extension_number, pte->device->context,
1398 return ast_add_extension(pte->device->context, 0,
1399 pte->device->extension_number, 1, NULL, NULL, "Dial",
1400 line->fullname, 0, "Unistim");
1403 static int unregister_extension(const struct unistimsession *pte)
1406 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1407 pte->device->extension_number, pte->device->context);
1409 return ast_context_remove_extension(pte->device->context,
1410 pte->device->extension_number, 1, "Unistim");
1413 /* Free memory allocated for a phone */
1414 static void close_client(struct unistimsession *s)
1416 struct unistim_subchannel *sub = NULL;
1417 struct unistimsession *cur, *prev = NULL;
1418 ast_mutex_lock(&sessionlock);
1420 /* Looking for the session in the linked chain */
1428 if (cur) { /* Session found ? */
1429 if (cur->device) { /* This session was registered ? */
1430 s->state = STATE_CLEANING;
1432 ast_verb(0, "close_client session %p device %p\n", s, s->device);
1434 change_favorite_icon(s, FAV_ICON_NONE);
1435 ast_mutex_lock(&s->device->lock);
1436 AST_LIST_LOCK(&s->device->subs);
1437 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
1441 if (sub->owner) { /* Call in progress ? */
1443 ast_verb(0, "Aborting call\n");
1445 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
1448 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
1450 AST_LIST_REMOVE_CURRENT(list);
1451 unistim_free_sub(sub);
1454 AST_LIST_TRAVERSE_SAFE_END;
1455 AST_LIST_UNLOCK(&s->device->subs);
1457 if (!ast_strlen_zero(s->device->extension_number)) {
1458 unregister_extension(s);
1460 cur->device->session = NULL;
1461 ast_mutex_unlock(&s->device->lock);
1464 ast_verb(0, "Freeing an unregistered client\n");
1468 prev->next = cur->next;
1470 sessions = cur->next;
1472 ast_mutex_destroy(&s->lock);
1475 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
1477 ast_mutex_unlock(&sessionlock);
1481 /* Return 1 if the session chained link was modified */
1482 static int send_retransmit(struct unistimsession *pte)
1486 ast_mutex_lock(&pte->lock);
1487 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
1489 ast_verb(0, "Too many retransmit - freeing client\n");
1491 ast_mutex_unlock(&pte->lock);
1495 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
1497 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
1498 i < pte->last_buf_available; i++) {
1500 ast_log(LOG_WARNING,
1501 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1502 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
1507 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
1510 seq = ntohs(sbuf[1]);
1511 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
1512 seq, pte->last_seq_ack);
1514 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
1517 ast_mutex_unlock(&pte->lock);
1521 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1522 static void send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
1528 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1531 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
1535 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
1537 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
1539 buffsend[11] = inverse;
1541 if (i > TEXT_LENGTH_MAX) {
1542 i = TEXT_LENGTH_MAX;
1544 memcpy(buffsend + 12, text, i);
1545 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
1548 static void send_text_status(struct unistimsession *pte, const char *text)
1553 ast_verb(0, "Sending status text\n");
1556 if (pte->device->status_method == 1) { /* For new firmware and i2050 soft phone */
1557 int n = strlen(text);
1558 /* Must send individual button separately */
1560 for (i = 0, j = 0; i < 4; i++, j += 7) {
1561 int pos = 0x08 + (i * 0x20);
1562 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1563 sizeof(packet_send_status2));
1566 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
1567 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
1574 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
1576 if (i > STATUS_LENGTH_MAX) {
1577 i = STATUS_LENGTH_MAX;
1579 memcpy(buffsend + 10, text, i);
1580 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
1584 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1585 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1586 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1587 * 18 = mute off, 19 mute on */
1588 static void send_led_update(struct unistimsession *pte, unsigned char led)
1592 ast_verb(0, "Sending led_update (%x)\n", led);
1594 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
1596 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
1599 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1600 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1601 * mute = MUTE_OFF, MUTE_ON */
1603 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
1608 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
1611 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1612 sizeof(packet_send_select_output));
1613 buffsend[9] = output;
1614 if (output == OUTPUT_SPEAKER) {
1615 volume = VOLUME_LOW_SPEAKER;
1617 volume = VOLUME_LOW;
1619 buffsend[10] = volume;
1620 if (mute == MUTE_ON_DISCRET) {
1621 buffsend[11] = MUTE_ON;
1623 buffsend[11] = mute;
1625 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
1626 if (mute == MUTE_OFF) {
1627 send_led_update(pte, 0x18);
1628 } else if (mute == MUTE_ON) {
1629 send_led_update(pte, 0x19);
1631 pte->device->mute = mute;
1632 if (output == OUTPUT_HANDSET) {
1633 if (mute == MUTE_ON) {
1634 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
1636 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
1638 send_led_update(pte, 0x08);
1639 send_led_update(pte, 0x10);
1640 } else if (output == OUTPUT_HEADPHONE) {
1641 if (mute == MUTE_ON) {
1642 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
1644 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
1646 send_led_update(pte, 0x08);
1647 send_led_update(pte, 0x11);
1648 } else if (output == OUTPUT_SPEAKER) {
1649 send_led_update(pte, 0x10);
1650 send_led_update(pte, 0x09);
1651 if (pte->device->receiver_state == STATE_OFFHOOK) {
1652 if (mute == MUTE_ON) {
1653 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1655 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
1658 if (mute == MUTE_ON) {
1659 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
1661 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
1665 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
1667 if (output != pte->device->output) {
1668 pte->device->previous_output = pte->device->output;
1670 pte->device->output = output;
1673 static void send_ring(struct unistimsession *pte, char volume, char style)
1677 ast_verb(0, "Sending ring packet\n");
1679 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
1680 buffsend[24] = style + 0x10;
1681 buffsend[29] = volume * 0x10;
1682 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
1685 static void send_no_ring(struct unistimsession *pte)
1689 ast_verb(0, "Sending no ring packet\n");
1691 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
1692 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
1695 static void send_texttitle(struct unistimsession *pte, const char *text)
1700 ast_verb(0, "Sending title text\n");
1702 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
1707 memcpy(buffsend + 10, text, i);
1708 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
1712 static void send_idle_clock(struct unistimsession *pte)
1714 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
1717 static void send_date_time(struct unistimsession *pte)
1720 struct timeval now = ast_tvnow();
1721 struct ast_tm atm = { 0, };
1724 ast_verb(0, "Sending Time & Date\n");
1726 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
1727 ast_localtime(&now, &atm, NULL);
1728 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1729 buffsend[11] = (unsigned char) atm.tm_mday;
1730 buffsend[12] = (unsigned char) atm.tm_hour;
1731 buffsend[13] = (unsigned char) atm.tm_min;
1732 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
1735 static void send_date_time2(struct unistimsession *pte)
1738 struct timeval now = ast_tvnow();
1739 struct ast_tm atm = { 0, };
1742 ast_verb(0, "Sending Time & Date #2\n");
1744 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
1745 ast_localtime(&now, &atm, NULL);
1747 buffsend[9] = pte->device->datetimeformat;
1751 buffsend[14] = (unsigned char) atm.tm_mon + 1;
1752 buffsend[15] = (unsigned char) atm.tm_mday;
1753 buffsend[16] = (unsigned char) atm.tm_hour;
1754 buffsend[17] = (unsigned char) atm.tm_min;
1755 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
1758 static void send_date_time3(struct unistimsession *pte)
1761 struct timeval now = ast_tvnow();
1762 struct ast_tm atm = { 0, };
1765 ast_verb(0, "Sending Time & Date #3\n");
1767 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
1768 ast_localtime(&now, &atm, NULL);
1769 buffsend[10] = (unsigned char) atm.tm_mon + 1;
1770 buffsend[11] = (unsigned char) atm.tm_mday;
1771 buffsend[12] = (unsigned char) atm.tm_hour;
1772 buffsend[13] = (unsigned char) atm.tm_min;
1773 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
1776 static void send_blink_cursor(struct unistimsession *pte)
1780 ast_verb(0, "Sending set blink\n");
1782 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
1783 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
1787 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1788 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
1792 ast_verb(0, "Sending set cursor position\n");
1794 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1795 sizeof(packet_send_set_pos_cursor));
1797 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
1801 static void send_charset_update(struct unistimsession *pte, int charset)
1803 const unsigned char* packet_send_charset;
1807 ast_verb(0, "Sending set default charset\n");
1809 if (charset == LANG_DEFAULT) {
1810 charset = options_languages[find_language(pte->device->language)].encoding;
1814 packet_send_charset = packet_send_charset_iso_8859_2;
1815 packet_size = sizeof(packet_send_charset_iso_8859_2);
1818 packet_send_charset = packet_send_charset_iso_8859_4;
1819 packet_size = sizeof(packet_send_charset_iso_8859_4);
1822 packet_send_charset = packet_send_charset_iso_8859_5;
1823 packet_size = sizeof(packet_send_charset_iso_8859_5);
1826 packet_send_charset = packet_send_charset_iso_2022_jp;
1827 packet_size = sizeof(packet_send_charset_iso_2022_jp);
1831 packet_send_charset = packet_send_charset_iso_8859_1;
1832 packet_size = sizeof(packet_send_charset_iso_8859_1);
1834 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1835 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1839 static void rcv_resume_connection_with_server(struct unistimsession *pte)
1843 ast_verb(0, "ResumeConnectionWithServer received\n");
1844 ast_verb(0, "Sending packet_send_query_mac_address\n");
1846 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1847 sizeof(packet_send_query_mac_address));
1848 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
1852 static int unistim_register(struct unistimsession *s)
1854 struct unistim_device *d;
1856 ast_mutex_lock(&devicelock);
1859 if (!strcasecmp(s->macaddr, d->id)) {
1860 /* XXX Deal with IP authentication */
1863 d->codec_number = DEFAULT_CODEC;
1865 d->receiver_state = STATE_ONHOOK;
1870 ast_mutex_unlock(&devicelock);
1879 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
1881 struct ast_format_cap *tmp = src->cap;
1882 memcpy(dst, src, sizeof(*dst)); /* this over writes the cap ptr, so we have to reset it */
1884 ast_format_cap_copy(src->cap, dst->cap);
1887 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
1892 l->cap = ast_format_cap_destroy(l->cap);
1897 static struct unistim_line *unistim_line_alloc(void)
1899 struct unistim_line *l;
1900 if (!(l = ast_calloc(1, sizeof(*l)))) {
1904 if (!(l->cap = ast_format_cap_alloc(AST_FORMAT_CAP_FLAG_NOLOCK))) {
1911 static int unistim_free_sub(struct unistim_subchannel *sub) {
1913 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
1915 ast_mutex_destroy(&sub->lock);
1920 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
1922 struct unistim_subchannel *sub;
1923 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
1928 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
1930 sub->ss_thread = AST_PTHREADT_NULL;
1932 AST_LIST_LOCK(&d->subs);
1933 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
1934 AST_LIST_UNLOCK(&d->subs);
1935 ast_mutex_init(&sub->lock);
1939 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
1941 struct unistim_subchannel *s;
1943 AST_LIST_LOCK(&d->subs);
1944 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
1951 AST_LIST_REMOVE_CURRENT(list);
1952 unistim_free_sub(sub);
1954 AST_LIST_TRAVERSE_SAFE_END;
1955 AST_LIST_UNLOCK(&d->subs);
1959 static const char *subtype_tostr(const int type)
1974 static const char *ptestate_tostr(const int type)
1979 case STATE_AUTHDENY:
1981 case STATE_MAINPAGE:
1983 case STATE_EXTENSION:
1985 case STATE_DIALPAGE:
1991 case STATE_SELECTOPTION:
1992 return "SELECTOPTION";
1993 case STATE_SELECTCODEC:
1994 return "SELECTCODEC";
1995 case STATE_SELECTLANGUAGE:
1996 return "SELECTLANGUAGE";
1997 case STATE_CLEANING:
2005 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
2011 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
2012 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
2016 ast_verb(0, "MAC Address received: %s\n", addrmac);
2018 strcpy(pte->macaddr, addrmac);
2019 res = unistim_register(pte);
2021 switch (autoprovisioning) {
2022 case AUTOPROVISIONING_NO:
2023 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
2024 pte->state = STATE_AUTHDENY;
2026 case AUTOPROVISIONING_YES:
2028 struct unistim_device *d = NULL, *newd = NULL;
2029 struct unistim_line *newl = NULL, *l = NULL;
2031 ast_verb(0, "New phone, autoprovisioning on\n");
2033 /* First : locate the [template] section */
2034 ast_mutex_lock(&devicelock);
2037 if (strcasecmp(d->name, "template")) {
2041 /* Found, cloning this entry */
2042 if (!(newd = ast_malloc(sizeof(*newd)))) {
2043 ast_mutex_unlock(&devicelock);
2046 memcpy(newd, d, sizeof(*newd));
2047 ast_mutex_init(&newd->lock);
2048 newd->lines.first = NULL;
2049 newd->lines.last = NULL;
2050 AST_LIST_LOCK(&d->lines);
2051 AST_LIST_TRAVERSE(&d->lines, l, list) {
2052 if (!(newl = unistim_line_alloc())) {
2055 unistim_line_copy(l, newl);
2056 newl->parent = newd;
2057 ast_copy_string(newl->name, l->name, sizeof(newl->name));
2058 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
2059 newl->name, newd->name);
2060 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
2062 AST_LIST_LOCK(&newd->lines);
2063 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
2064 AST_LIST_UNLOCK(&newd->lines);
2066 AST_LIST_UNLOCK(&d->lines);
2069 ast_mutex_unlock(&devicelock);
2072 /* Ok, now updating some fields */
2073 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
2074 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
2075 if (newd->extension == EXTENSION_NONE) {
2076 newd->extension = EXTENSION_ASK;
2079 newd->receiver_state = STATE_ONHOOK;
2080 newd->session = pte;
2081 newd->language[0] = '\0';
2082 newd->to_delete = -1;
2086 /* Go to the end of the linked chain */
2094 ast_mutex_unlock(&devicelock);
2096 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
2097 pte->state = STATE_AUTHDENY;
2101 case AUTOPROVISIONING_TN:
2102 pte->state = STATE_AUTHDENY;
2105 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
2109 if (pte->state != STATE_AUTHDENY) {
2110 struct unistim_line *line;
2111 struct unistim_subchannel *sub;
2113 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
2115 AST_LIST_LOCK(&pte->device->subs);
2116 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
2118 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
2119 AST_LIST_REMOVE_CURRENT(list);
2123 AST_LIST_TRAVERSE_SAFE_END;
2124 AST_LIST_UNLOCK(&pte->device->subs);
2126 switch (pte->device->extension) {
2127 case EXTENSION_NONE:
2128 pte->state = STATE_MAINPAGE;
2131 /* Checking if we already have an extension number */
2132 if (ast_strlen_zero(pte->device->extension_number)) {
2133 pte->state = STATE_EXTENSION;
2135 /* Yes, because of a phone reboot. We don't ask again for the TN */
2136 if (register_extension(pte)) {
2137 pte->state = STATE_EXTENSION;
2139 pte->state = STATE_MAINPAGE;
2143 case EXTENSION_LINE:
2144 line = AST_LIST_FIRST(&pte->device->lines);
2145 ast_copy_string(pte->device->extension_number, line->name,
2146 sizeof(pte->device->extension_number));
2147 if (register_extension(pte)) {
2148 pte->state = STATE_EXTENSION;
2150 pte->state = STATE_MAINPAGE;
2154 /* If we are here, it's because of a phone reboot */
2155 pte->state = STATE_MAINPAGE;
2158 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
2159 pte->device->extension);
2160 pte->state = STATE_AUTHDENY;
2164 if (pte->state == STATE_EXTENSION) {
2165 if (pte->device->extension != EXTENSION_TN) {
2166 pte->device->extension = EXTENSION_ASK;
2168 pte->device->extension_number[0] = '\0';
2171 ast_verb(0, "\nSending S1\n");
2173 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
2174 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
2177 ast_verb(0, "Sending query_basic_manager_04\n");
2179 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2180 sizeof(packet_send_query_basic_manager_04));
2181 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2184 ast_verb(0, "Sending query_basic_manager_10\n");
2186 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2187 sizeof(packet_send_query_basic_manager_10));
2188 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2190 send_date_time(pte);
2194 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
2196 if (fwrite(&c, 1, 1, f) != 1) {
2197 display_last_error("Unable to write history log header.");
2200 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2201 display_last_error("Unable to write history entry - date.");
2204 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2205 display_last_error("Unable to write history entry - callerid.");
2208 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2209 display_last_error("Unable to write history entry - callername.");
2215 static int write_history(struct unistimsession *pte, char way, char ismissed)
2217 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2218 char line1[TEXT_LENGTH_MAX + 1];
2219 char count = 0, *histbuf;
2222 struct timeval now = ast_tvnow();
2223 struct ast_tm atm = { 0, };
2228 if (!pte->device->callhistory) {
2231 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
2232 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
2237 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2238 if (ast_mkdir(tmp, 0770)) {
2239 ast_log(LOG_WARNING, "Unable to create directory for history\n");
2243 ast_localtime(&now, &atm, NULL);
2246 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
2248 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
2251 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
2253 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
2254 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
2255 atm.tm_min, atm.tm_sec, tmp2);
2257 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2258 USTM_LOG_DIR, pte->device->name, way);
2259 if ((f = fopen(tmp, "r"))) {
2260 struct stat bufstat;
2262 if (stat(tmp, &bufstat)) {
2263 display_last_error("Unable to stat history log.");
2267 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2268 if (bufstat.st_size != size) {
2269 ast_log(LOG_WARNING,
2270 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2271 tmp, (int) bufstat.st_size, size);
2278 /* If we can't open the log file, we create a brand new one */
2283 if ((errno != ENOENT) && (count == 0)) {
2284 display_last_error("Unable to open history log.");
2287 f = fopen(tmp, "w");
2289 display_last_error("Unable to create history log.");
2292 if (write_entry_history(pte, f, c, line1)) {
2296 memset(line1, ' ', TEXT_LENGTH_MAX);
2297 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2298 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2299 display_last_error("Unable to write history entry - stuffing.");
2305 display_last_error("Unable to close history - creation.");
2309 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
2310 if (fread(&count, 1, 1, f) != 1) {
2311 display_last_error("Unable to read history header.");
2315 if (count > MAX_ENTRY_LOG) {
2316 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
2317 count, MAX_ENTRY_LOG);
2321 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2322 USTM_LOG_DIR, pte->device->name, way);
2323 if (!(f2 = fopen(tmp2, "w"))) {
2324 display_last_error("Unable to create temporary history log.");
2329 if (++count > MAX_ENTRY_LOG) {
2330 count = MAX_ENTRY_LOG;
2332 if (write_entry_history(pte, f2, count, line1)) {
2337 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2338 if (!(histbuf = ast_malloc(size))) {
2344 if (fread(histbuf, size, 1, f) != 1) {
2348 display_last_error("Unable to read previous history entries.");
2351 if (fwrite(histbuf, size, 1, f2) != 1) {
2355 display_last_error("Unable to write previous history entries.");
2360 display_last_error("Unable to close history log.");
2363 display_last_error("Unable to close temporary history log.");
2366 display_last_error("Unable to remove old history log.");
2368 if (rename(tmp2, tmp)) {
2369 display_last_error("Unable to rename new history log.");
2374 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
2376 RAII_VAR(struct ast_channel *, chana, NULL, ast_channel_unref);
2377 RAII_VAR(struct ast_channel *, chanb, NULL, ast_channel_unref);
2379 if (!p1->owner || !p2->owner) {
2380 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
2383 chana = ast_channel_ref(p1->owner);
2384 chanb = ast_channel_ref(p2->owner);
2386 switch (ast_bridge_transfer_attended(chana, chanb)) {
2387 case AST_BRIDGE_TRANSFER_INVALID:
2388 ast_log(LOG_WARNING, "Transfer failed. Invalid bridge setup\n");
2390 case AST_BRIDGE_TRANSFER_NOT_PERMITTED:
2391 ast_log(LOG_WARNING, "Transfer not permitted\n");
2393 case AST_BRIDGE_TRANSFER_FAIL:
2394 ast_log(LOG_WARNING, "Transfer encountered internal error\n");
2396 case AST_BRIDGE_TRANSFER_SUCCESS:
2400 /* Control only reaches this point if transfer has failed */
2401 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
2402 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
2406 void change_callerid(struct unistimsession *pte, int type, char *callerid)
2412 data = pte->device->lst_cnm;
2414 data = pte->device->lst_cid;
2417 /* This is very nearly strncpy(), except that the remaining buffer
2418 * is padded with ' ', instead of '\0' */
2419 memset(data, ' ', TEXT_LENGTH_MAX);
2420 size = strlen(callerid);
2421 if (size > TEXT_LENGTH_MAX) {
2422 size = TEXT_LENGTH_MAX;
2424 memcpy(data, callerid, size);
2427 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
2429 struct unistim_subchannel *sub = NULL;
2431 AST_LIST_LOCK(&device->subs);
2432 AST_LIST_TRAVERSE(&device->subs, sub, list) {
2436 if (sub->subtype == type) {
2440 AST_LIST_UNLOCK(&device->subs);
2445 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2447 /* Silence our channel */
2448 if (!pte->device->silence_generator) {
2449 pte->device->silence_generator =
2450 ast_channel_start_silence_generator(sub->owner);
2451 if (pte->device->silence_generator == NULL) {
2452 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
2453 } else if (unistimdebug) {
2454 ast_verb(0, "Starting silence generator\n");
2460 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
2462 /* Stop the silence generator */
2463 if (pte->device->silence_generator) {
2465 ast_verb(0, "Stopping silence generator\n");
2468 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
2470 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
2472 pte->device->silence_generator = NULL;
2476 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
2482 sub->subtype = SUB_ONHOLD;
2483 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2484 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
2485 send_stop_timer(pte);
2487 ast_queue_hold(sub->owner, NULL);
2493 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
2495 struct unistim_subchannel *sub_real;
2497 sub_real = get_sub(pte->device, SUB_REAL);
2499 sub_hold(pte, sub_real);
2503 sub->subtype = SUB_REAL;
2504 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2505 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2506 send_start_timer(pte);
2508 ast_queue_unhold(sub->owner);
2510 send_start_rtp(sub);
2516 static void close_call(struct unistimsession *pte)
2518 struct unistim_subchannel *sub, *sub_transf;
2520 sub = get_sub(pte->device, SUB_REAL);
2521 sub_transf = get_sub(pte->device, SUB_THREEWAY);
2522 send_stop_timer(pte);
2524 ast_log(LOG_WARNING, "Close call without sub\n");
2527 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
2529 sub->alreadygone = 1;
2531 sub_transf->alreadygone = 1;
2532 if (attempt_transfer(sub, sub_transf) < 0) {
2533 ast_verb(0, "attempt_transfer failed.\n");
2536 ast_queue_hangup(sub->owner);
2540 if (sub_transf->owner) {
2541 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
2543 ast_log(LOG_WARNING, "threeway sub without owner\n");
2546 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
2547 pte->device->name, sub->softkey);
2550 change_callerid(pte, 0, pte->device->redial_number);
2551 change_callerid(pte, 1, "");
2552 write_history(pte, 'o', pte->device->missed_call);
2553 pte->device->missed_call = 0;
2554 show_main_page(pte);
2558 static void ignore_call(struct unistimsession *pte)
2564 static void discard_call(struct unistimsession *pte)
2566 struct unistim_subchannel* sub;
2567 sub = get_sub(pte->device, SUB_RING);
2572 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
2576 static void *unistim_ss(void *data)
2578 struct ast_channel *chan = data;
2579 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
2580 struct unistim_line *l = sub->parent;
2581 struct unistimsession *s = l->parent->session;
2584 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
2585 ast_channel_lock(chan);
2586 ast_channel_exten_set(chan, s->device->phone_number);
2587 ast_setstate(chan, AST_STATE_RING);
2588 ast_channel_unlock(chan);
2589 ast_copy_string(s->device->redial_number, s->device->phone_number,
2590 sizeof(s->device->redial_number));
2591 res = ast_pbx_run(chan);
2593 ast_log(LOG_WARNING, "PBX exited non-zero\n");
2594 send_tone(s, 1000, 0);
2599 static int find_rtp_port(struct unistim_subchannel *s)
2601 struct unistim_subchannel *sub = NULL;
2602 int rtp_start = s->parent->parent->rtp_port;
2603 struct ast_sockaddr us_tmp;
2604 struct sockaddr_in us = { 0, };
2606 AST_LIST_LOCK(&s->parent->parent->subs);
2607 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
2612 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
2613 ast_sockaddr_to_sin(&us_tmp, &us);
2614 if (htons(us.sin_port)) {
2615 rtp_start = htons(us.sin_port) + 1;
2620 AST_LIST_UNLOCK(&s->parent->parent->subs);
2624 static void send_start_rtp(struct unistim_subchannel *sub)
2629 struct sockaddr_in public = { 0, };
2630 struct sockaddr_in us = { 0, };
2631 struct sockaddr_in sin = { 0, };
2632 struct ast_sockaddr us_tmp;
2633 struct ast_sockaddr sin_tmp;
2634 struct unistimsession *pte;
2636 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
2637 ast_sockaddr_to_sin(&us_tmp, &us);
2638 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
2639 ast_sockaddr_to_sin(&sin_tmp, &sin);
2641 /* Setting up RTP of the phone */
2642 if (public_ip.sin_family == 0) { /* NAT IP override ? */
2643 memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
2645 memcpy(&public, &public_ip, sizeof(public)); /* override */
2648 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
2649 ast_inet_ntoa(us.sin_addr),
2650 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
2651 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2652 ast_inet_ntoa(public.sin_addr));
2655 pte = sub->parent->parent->session;
2656 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
2657 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
2658 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
2660 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
2662 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2663 sizeof(packet_send_rtp_packet_size));
2664 buffsend[10] = (int) codec & 0xffffffffLL;
2665 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
2668 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2670 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2671 sizeof(packet_send_jitter_buffer_conf));
2672 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2673 if (pte->device->rtp_method != 0) {
2674 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2677 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
2679 if (pte->device->rtp_method == 3) {
2680 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2681 sizeof(packet_send_open_audio_stream_tx3));
2683 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2684 sizeof(packet_send_open_audio_stream_tx));
2686 if (pte->device->rtp_method != 2) {
2687 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2688 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2689 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2690 buffsend[23] = (rtcpsin_port & 0x00ff);
2691 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2692 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2693 buffsend[24] = (us.sin_port & 0x00ff);
2694 buffsend[27] = (rtcpsin_port & 0x00ff);
2695 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2697 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2698 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2699 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2700 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2701 buffsend[19] = (us.sin_port & 0x00ff);
2703 buffsend[11] = codec; /* rx */
2704 buffsend[12] = codec; /* tx */
2705 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2708 ast_verb(0, "Sending OpenAudioStreamRX\n");
2710 if (pte->device->rtp_method == 3) {
2711 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2712 sizeof(packet_send_open_audio_stream_rx3));
2714 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2715 sizeof(packet_send_open_audio_stream_rx));
2717 if (pte->device->rtp_method != 2) {
2718 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
2719 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
2720 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
2721 buffsend[23] = (rtcpsin_port & 0x00ff);
2722 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
2723 buffsend[25] = (us.sin_port & 0xff00) >> 8;
2724 buffsend[24] = (us.sin_port & 0x00ff);
2725 buffsend[27] = (rtcpsin_port & 0x00ff);
2726 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
2728 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
2729 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
2730 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
2731 buffsend[20] = (us.sin_port & 0xff00) >> 8;
2732 buffsend[19] = (us.sin_port & 0x00ff);
2734 buffsend[11] = codec; /* rx */
2735 buffsend[12] = codec; /* tx */
2736 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2738 uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
2741 ast_verb(0, "Sending packet_send_call default method\n");
2744 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
2745 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
2746 /* Destination port when sending RTP */
2747 buffsend[49] = (us.sin_port & 0x00ff);
2748 buffsend[50] = (us.sin_port & 0xff00) >> 8;
2749 /* Destination port when sending RTCP */
2750 buffsend[52] = (rtcpsin_port & 0x00ff);
2751 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
2753 buffsend[40] = codec;
2754 buffsend[41] = codec;
2755 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
2756 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2757 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
2758 buffsend[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2759 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
2760 buffsend[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2761 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
2762 buffsend[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2764 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
2765 ast_getformatname(ast_channel_readformat(sub->owner)));
2767 /* Source port for transmit RTP and Destination port for receiving RTP */
2768 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
2769 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
2770 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
2771 buffsend[48] = (rtcpsin_port & 0x00ff);
2772 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
2776 static void start_rtp(struct unistim_subchannel *sub)
2778 struct sockaddr_in sin = { 0, };
2779 struct sockaddr_in sout = { 0, };
2780 struct ast_sockaddr sin_tmp;
2781 struct ast_sockaddr sout_tmp;
2785 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
2789 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
2792 if (!sub->parent->parent) {
2793 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
2796 if (!sub->parent->parent->session) {
2797 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
2801 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
2804 sout = sub->parent->parent->session->sout;
2805 ast_mutex_lock(&sub->lock);
2806 /* Allocate the RTP */
2808 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
2810 ast_sockaddr_from_sin(&sout_tmp, &sout);
2811 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
2813 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
2814 strerror(errno), ast_inet_ntoa(sout.sin_addr));
2815 ast_mutex_unlock(&sub->lock);
2818 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
2819 ast_rtp_instance_set_channel_id(sub->rtp, ast_channel_uniqueid(sub->owner));
2820 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
2821 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
2822 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
2823 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
2825 /* Create the RTP connection */
2826 sin.sin_family = AF_INET;
2827 /* Setting up RTP for our side */
2828 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
2829 sizeof(sin.sin_addr));
2831 sin.sin_port = htons(find_rtp_port(sub));
2832 ast_sockaddr_from_sin(&sin_tmp, &sin);
2833 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
2834 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
2835 struct ast_format tmpfmt;
2837 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
2838 ast_log(LOG_WARNING,
2839 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2840 ast_getformatname(ast_channel_readformat(sub->owner)),
2841 ast_getformatname(&tmpfmt),
2842 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
2844 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
2845 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
2847 send_start_rtp(sub);
2848 ast_mutex_unlock(&sub->lock);
2851 static void send_dial_tone(struct unistimsession *pte)
2853 struct ast_tone_zone_sound *ts = NULL;
2854 struct ast_tone_zone_part tone_data;
2858 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
2859 ind = ast_strdupa(ts->data);
2860 s = strsep(&ind, ",");
2861 ast_tone_zone_part_parse(s, &tone_data);
2862 if (tone_data.modulate) {
2863 tone_data.freq2 = 0;
2865 send_tone(pte, tone_data.freq1, tone_data.freq2);
2867 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2868 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
2870 ts = ast_tone_zone_sound_unref(ts);
2874 static void show_phone_number(struct unistimsession *pte)
2876 char tmp[TEXT_LENGTH_MAX + 1];
2877 const char *tmp_number = ustmtext("Number:", pte);
2878 int line, tmp_copy, offset = 0, i;
2880 pte->device->phone_number[pte->device->size_phone_number] = '\0';
2881 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
2882 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
2883 if (offset > strlen(tmp_number)) {
2884 offset = strlen(tmp_number);
2886 tmp_copy = strlen(tmp_number) - offset + 1;
2887 if (tmp_copy > sizeof(tmp)) {
2888 tmp_copy = sizeof(tmp);
2890 memcpy(tmp, tmp_number + offset, tmp_copy);
2892 ast_copy_string(tmp, tmp_number, sizeof(tmp));
2895 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
2896 if (pte->device->size_phone_number) {
2897 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
2899 offset = strlen(tmp);
2901 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2906 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2907 send_text(line, TEXT_NORMAL, pte, tmp);
2908 send_blink_cursor(pte);
2909 send_cursor_pos(pte, (unsigned char) (line + offset));
2910 send_led_update(pte, 0);
2913 static void handle_dial_page(struct unistimsession *pte)
2915 pte->state = STATE_DIALPAGE;
2916 if (pte->device->call_forward[0] == -1) {
2917 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
2918 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
2919 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
2920 if (pte->device->call_forward[1] != 0) {
2921 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
2922 sizeof(pte->device->phone_number));
2923 show_phone_number(pte);
2924 send_led_update(pte, 0);
2928 if ((pte->device->output == OUTPUT_HANDSET) &&
2929 (pte->device->receiver_state == STATE_ONHOOK)) {
2930 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
2932 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
2934 send_dial_tone(pte);
2936 if (pte->device->height > 1) {
2937 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
2938 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
2940 if (ast_strlen_zero(pte->device->redial_number)) {
2941 send_text_status(pte, ustmtext("Call BackSp Erase", pte));
2943 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
2947 pte->device->size_phone_number = 0;
2948 pte->device->phone_number[0] = 0;
2949 show_phone_number(pte);
2950 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
2951 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
2952 pte->device->missed_call = 0;
2953 send_led_update(pte, 0);
2954 pte->device->lastmsgssent = -1;
2958 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
2960 struct ast_rtp_instance *rtp;
2964 ast_verb(0, "Swapping %p and %p\n", a, b);
2966 if ((!a->owner) || (!b->owner)) {
2967 ast_log(LOG_WARNING,
2968 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
2969 a, a->owner, b, b->owner);
2976 fds = ast_channel_fd(a->owner, 0);
2977 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
2978 ast_channel_internal_fd_set(b->owner, 0, fds);
2980 fds = ast_channel_fd(a->owner, 1);
2981 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
2982 ast_channel_internal_fd_set(b->owner, 1, fds);
2985 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2986 static void transfer_call_step1(struct unistimsession *pte)
2988 struct unistim_subchannel *sub /*, *sub_trans */;
2989 struct unistim_device *d = pte->device;
2991 sub = get_sub(d, SUB_REAL);
2992 /* sub_trans = get_sub(d, SUB_THREEWAY); */
2994 if (!sub || !sub->owner) {
2995 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
2998 /* Start music on hold if appropriate */
3000 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
3002 ast_queue_hold(sub->owner, sub->parent->musicclass);
3004 sub->subtype = SUB_THREEWAY;
3006 sub_start_silence(pte, sub);
3007 handle_dial_page(pte);
3010 static void transfer_cancel_step2(struct unistimsession *pte)
3012 struct unistim_subchannel *sub, *sub_trans;
3013 struct unistim_device *d = pte->device;
3015 sub = get_sub(d, SUB_REAL);
3016 sub_trans = get_sub(d, SUB_THREEWAY);
3018 if (!sub || !sub->owner) {
3019 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
3024 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
3027 swap_subs(sub, sub_trans);
3028 ast_queue_unhold(sub_trans->owner);
3030 sub_trans->subtype = SUB_REAL;
3031 sub->subtype = SUB_THREEWAY;
3032 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
3034 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
3040 /* From phone to PBX */
3041 static void handle_call_outgoing(struct unistimsession *s)
3043 struct ast_channel *c;
3044 struct unistim_subchannel *sub;
3047 s->state = STATE_CALL;
3049 sub = get_sub(s->device, SUB_THREEWAY);
3051 /* If sub for threway call created than we use transfer behaviuor */
3052 struct unistim_subchannel *sub_trans = NULL;
3053 struct unistim_device *d = s->device;
3055 sub_trans = get_sub(d, SUB_REAL);
3057 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
3061 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
3065 sub_trans = unistim_alloc_sub(d, SUB_REAL);
3067 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
3070 sub_trans->parent = sub->parent;
3071 sub_stop_silence(s, sub);
3073 /* Make new channel */
3074 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
3076 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
3079 /* Swap things around between the three-way and real call */
3080 swap_subs(sub, sub_trans);
3081 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
3082 if (s->device->height == 1) {
3083 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
3085 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
3086 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
3087 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
3089 send_text_status(s, ustmtext("TransfrCancel", s));
3091 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
3092 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
3093 sub->ss_thread = AST_PTHREADT_NULL;
3098 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
3099 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);