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
37 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
42 #if defined(__CYGWIN__)
44 * cygwin headers are partly inconsistent. struct iovec is defined in sys/uio.h
45 * which is not included by default by sys/socket.h - in_pktinfo is defined in
46 * w32api/ws2tcpip.h but this probably has compatibility problems with sys/socket.h
47 * So for the time being we simply disable HAVE_PKTINFO when building under cygwin.
48 * This should be done in some common header, but for now this is the only file
49 * using iovec and in_pktinfo so it suffices to apply the fix here.
54 #endif /* __CYGWIN__ */
56 #include "asterisk/paths.h" /* ast_config_AST_LOG_DIR used in (too ?) many places */
57 #include "asterisk/network.h"
58 #include "asterisk/channel.h"
59 #include "asterisk/config.h"
60 #include "asterisk/module.h"
61 #include "asterisk/pbx.h"
62 #include "asterisk/event.h"
63 #include "asterisk/rtp.h"
64 #include "asterisk/netsock.h"
65 #include "asterisk/acl.h"
66 #include "asterisk/callerid.h"
67 #include "asterisk/cli.h"
68 #include "asterisk/app.h"
69 #include "asterisk/musiconhold.h"
70 #include "asterisk/causes.h"
71 #include "asterisk/indications.h"
73 /*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
74 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
76 #define DEFAULTCONTEXT "default"
77 #define DEFAULTCALLERID "Unknown"
78 #define DEFAULTCALLERNAME " "
79 #define USTM_LOG_DIR "unistimHistory"
81 /*! Size of the transmit buffer */
82 #define MAX_BUF_SIZE 64
83 /*! Number of slots for the transmit queue */
84 #define MAX_BUF_NUMBER 50
85 /*! Try x times before removing the phone */
86 #define NB_MAX_RETRANSMIT 8
87 /*! Nb of milliseconds waited when no events are scheduled */
88 #define IDLE_WAIT 1000
89 /*! Wait x milliseconds before resending a packet */
90 #define RETRANSMIT_TIMER 2000
91 /*! How often the mailbox is checked for new messages */
92 #define TIMER_MWI 10000
94 #define DEFAULT_CODEC 0x00
95 #define SIZE_PAGE 4096
96 #define DEVICE_NAME_LEN 16
97 #define AST_CONFIG_MAX_PATH 255
98 #define MAX_ENTRY_LOG 30
101 #define SUB_THREEWAY 1
105 AUTOPROVISIONING_NO
= 0,
106 AUTOPROVISIONING_YES
,
112 /*! Do not create an extension into the default dialplan */
114 /*! Prompt user for an extension number and register it */
116 /*! Register an extension with the line=> value */
118 /*! Used with AUTOPROVISIONING_TN */
121 #define OUTPUT_HANDSET 0xC0
122 #define OUTPUT_HEADPHONE 0xC1
123 #define OUTPUT_SPEAKER 0xC2
125 #define VOLUME_LOW 0x01
126 #define VOLUME_LOW_SPEAKER 0x03
127 #define VOLUME_NORMAL 0x02
128 #define VOLUME_INSANELY_LOUD 0x07
130 #define MUTE_OFF 0x00
132 #define MUTE_ON_DISCRET 0xCE
134 #define SIZE_HEADER 6
135 #define SIZE_MAC_ADDR 17
136 #define TEXT_LENGTH_MAX 24
137 #define TEXT_LINE0 0x00
138 #define TEXT_LINE1 0x20
139 #define TEXT_LINE2 0x40
140 #define TEXT_NORMAL 0x05
141 #define TEXT_INVERSE 0x25
142 #define STATUS_LENGTH_MAX 28
144 #define FAV_ICON_NONE 0x00
145 #define FAV_ICON_ONHOOK_BLACK 0x20
146 #define FAV_ICON_ONHOOK_WHITE 0x21
147 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
148 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
149 #define FAV_ICON_OFFHOOK_BLACK 0x24
150 #define FAV_ICON_OFFHOOK_WHITE 0x25
151 #define FAV_ICON_ONHOLD_BLACK 0x26
152 #define FAV_ICON_ONHOLD_WHITE 0x27
153 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
154 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
155 #define FAV_ICON_PHONE_BLACK 0x2A
156 #define FAV_ICON_PHONE_WHITE 0x2B
157 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
158 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
159 #define FAV_ICON_HEADPHONES 0x2E
160 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
161 #define FAV_ICON_HOME 0x30
162 #define FAV_ICON_CITY 0x31
163 #define FAV_ICON_SHARP 0x32
164 #define FAV_ICON_PAGER 0x33
165 #define FAV_ICON_CALL_CENTER 0x34
166 #define FAV_ICON_FAX 0x35
167 #define FAV_ICON_MAILBOX 0x36
168 #define FAV_ICON_REFLECT 0x37
169 #define FAV_ICON_COMPUTER 0x38
170 #define FAV_ICON_FORWARD 0x39
171 #define FAV_ICON_LOCKED 0x3A
172 #define FAV_ICON_TRASH 0x3B
173 #define FAV_ICON_INBOX 0x3C
174 #define FAV_ICON_OUTBOX 0x3D
175 #define FAV_ICON_MEETING 0x3E
176 #define FAV_ICON_BOX 0x3F
178 #define FAV_BLINK_FAST 0x20
179 #define FAV_BLINK_SLOW 0x40
181 #define FAV_MAX_LENGTH 0x0A
183 static void dummy(char *unused
, ...)
188 /*! \brief Global jitterbuffer configuration - by default, jb is disabled */
189 static struct ast_jb_conf default_jbconf
=
193 .resync_threshold
= -1,
196 static struct ast_jb_conf global_jbconf
;
199 /* #define DUMP_PACKET 1 */
200 /* #define DEBUG_TIMER ast_verbose */
202 #define DEBUG_TIMER dummy
203 /*! Enable verbose output. can also be set with the CLI */
204 static int unistimdebug
= 0;
205 static int unistim_port
;
206 static enum autoprovision autoprovisioning
= AUTOPROVISIONING_NO
;
207 static int unistim_keepalive
;
208 static int unistimsock
= -1;
212 unsigned int tos_audio
;
214 unsigned int cos_audio
;
215 } qos
= { 0, 0, 0, 0 };
217 static struct io_context
*io
;
218 static struct sched_context
*sched
;
219 static struct sockaddr_in public_ip
= { 0, };
220 /*! give the IP address for the last packet received */
221 static struct sockaddr_in address_from
;
222 /*! size of the sockaddr_in (in WSARecvFrom) */
223 static unsigned int size_addr_from
= sizeof(address_from
);
224 /*! Receive buffer address */
225 static unsigned char *buff
;
226 static int unistim_reloading
= 0;
227 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock
);
228 AST_MUTEX_DEFINE_STATIC(usecnt_lock
);
229 static int usecnt
= 0;
230 /* extern char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH]; */
232 /*! This is the thread for the monitor which checks for input on the channels
233 * which are not currently in use. */
234 static pthread_t monitor_thread
= AST_PTHREADT_NULL
;
236 /*! Protect the monitoring thread, so only one process can kill or start it, and not
237 * when it's doing something critical. */
238 AST_MUTEX_DEFINE_STATIC(monlock
);
239 /*! Protect the session list */
240 AST_MUTEX_DEFINE_STATIC(sessionlock
);
241 /*! Protect the device list */
242 AST_MUTEX_DEFINE_STATIC(devicelock
);
303 struct tone_zone_unistim
{
309 static const struct tone_zone_unistim frequency
[] = {
349 unsigned short w_year
;
350 unsigned short w_month
;
351 unsigned short w_day_of_week
;
352 unsigned short w_day
;
353 unsigned short w_hour
;
354 unsigned short w_minute
;
355 unsigned short w_second
;
356 unsigned short w_milliseconds
;
359 struct unistim_subchannel
{
361 /*! SUBS_REAL or SUBS_THREEWAY */
362 unsigned int subtype
;
363 /*! Asterisk channel used by the subchannel */
364 struct ast_channel
*owner
;
366 struct unistim_line
*parent
;
375 * \todo Convert to stringfields
377 struct unistim_line
{
381 /*! Like USTM/200\@black */
383 /*! pointer to our current connection, channel... */
384 struct unistim_subchannel
*subs
[MAX_SUBS
];
385 /*! Extension where to start */
386 char exten
[AST_MAX_EXTENSION
];
387 /*! Context to start in */
388 char context
[AST_MAX_EXTENSION
];
389 /*! Language for asterisk sounds */
390 char language
[MAX_LANGUAGE
];
391 /*! CallerID Number */
392 char cid_num
[AST_MAX_EXTENSION
];
393 /*! Mailbox for MWI */
394 char mailbox
[AST_MAX_EXTENSION
];
399 /*! MusicOnHold class */
400 char musicclass
[MAX_MUSICCLASS
];
402 unsigned int callgroup
;
404 unsigned int pickupgroup
;
405 /*! Account code (for billing) */
406 char accountcode
[80];
407 /*! AMA flags (for billing) */
409 /*! Codec supported */
412 char parkinglot
[AST_MAX_CONTEXT
];
413 struct unistim_line
*next
;
414 struct unistim_device
*parent
;
418 * \brief A device containing one or more lines
420 static struct unistim_device
{
421 int receiver_state
; /*!< state of the receiver (see ReceiverState) */
422 int size_phone_number
; /*!< size of the phone number */
423 char phone_number
[16]; /*!< the phone number entered by the user */
424 char redial_number
[16]; /*!< the last phone number entered by the user */
425 int phone_current
; /*!< Number of the current phone */
426 int pos_fav
; /*!< Position of the displayed favorites (used for scrolling) */
427 char id
[18]; /*!< mac address of the current phone in ascii */
428 char name
[DEVICE_NAME_LEN
]; /*!< name of the device */
429 int softkeylinepos
; /*!< position of the line softkey (default 0) */
430 char softkeylabel
[6][11]; /*!< soft key label */
431 char softkeynumber
[6][16]; /*!< number dialed when the soft key is pressed */
432 char softkeyicon
[6]; /*!< icon number */
433 char softkeydevice
[6][16]; /*!< name of the device monitored */
434 struct unistim_device
*sp
[6]; /*!< pointer to the device monitored by this soft key */
435 char maintext0
[25]; /*!< when the phone is idle, display this string on line 0 */
436 char maintext1
[25]; /*!< when the phone is idle, display this string on line 1 */
437 char maintext2
[25]; /*!< when the phone is idle, display this string on line 2 */
438 char titledefault
[13]; /*!< title (text before date/time) */
439 char datetimeformat
; /*!< format used for displaying time/date */
440 char contrast
; /*!< contrast */
441 char country
[3]; /*!< country used for dial tone frequency */
442 struct ind_tone_zone
*tz
; /*!< Tone zone for res_indications (ring, busy, congestion) */
443 char ringvolume
; /*!< Ring volume */
444 char ringstyle
; /*!< Ring melody */
445 int rtp_port
; /*!< RTP port used by the phone */
446 int rtp_method
; /*!< Select the unistim data used to establish a RTP session */
447 int status_method
; /*!< Select the unistim packet used for sending status text */
448 char codec_number
; /*!< The current codec used to make calls */
449 int missed_call
; /*!< Number of call unanswered */
450 int callhistory
; /*!< Allowed to record call history */
451 char lst_cid
[TEXT_LENGTH_MAX
]; /*!< Last callerID received */
452 char lst_cnm
[TEXT_LENGTH_MAX
]; /*!< Last callername recevied */
453 char call_forward
[AST_MAX_EXTENSION
]; /*!< Forward number */
454 int output
; /*!< Handset, headphone or speaker */
455 int previous_output
; /*!< Previous output */
456 int volume
; /*!< Default volume */
457 int mute
; /*!< Mute mode */
458 int moh
; /*!< Music on hold in progress */
459 int nat
; /*!< Used by the obscure ast_rtp_setnat */
460 enum autoprov_extn extension
; /*!< See ifdef EXTENSION for valid values */
461 char extension_number
[11]; /*!< Extension number entered by the user */
462 char to_delete
; /*!< Used in reload */
463 time_t start_call_timestamp
; /*!< timestamp for the length calculation of the call */
464 struct ast_silence_generator
*silence_generator
;
465 struct unistim_line
*lines
;
467 struct unistimsession
*session
;
468 struct unistim_device
*next
;
471 static struct unistimsession
{
473 struct sockaddr_in sin
; /*!< IP address of the phone */
474 struct sockaddr_in sout
; /*!< IP address of server */
475 int timeout
; /*!< time-out in ticks : resend packet if no ack was received before the timeout occured */
476 unsigned short seq_phone
; /*!< sequence number for the next packet (when we receive a request) */
477 unsigned short seq_server
; /*!< sequence number for the next packet (when we send a request) */
478 unsigned short last_seq_ack
; /*!< sequence number of the last ACK received */
479 unsigned long tick_next_ping
; /*!< time for the next ping */
480 int last_buf_available
; /*!< number of a free slot */
481 int nb_retransmit
; /*!< number of retransmition */
482 int state
; /*!< state of the phone (see phone_state) */
483 int size_buff_entry
; /*!< size of the buffer used to enter datas */
484 char buff_entry
[16]; /*!< Buffer for temporary datas */
485 char macaddr
[18]; /*!< mac adress of the phone (not always available) */
486 struct wsabuf wsabufsend
[MAX_BUF_NUMBER
]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
487 unsigned char buf
[MAX_BUF_NUMBER
][MAX_BUF_SIZE
]; /*!< Buffer array used to keep the lastest non-acked paquets */
488 struct unistim_device
*device
;
489 struct unistimsession
*next
;
493 * \page Unistim datagram formats
495 * Format of datagrams :
496 * bytes 0 & 1 : ffff for discovery packet, 0000 for everything else
497 * byte 2 : sequence number (high part)
498 * byte 3 : sequence number (low part)
499 * byte 4 : 2 = ask question or send info, 1 = answer or ACK, 0 = retransmit request
500 * byte 5 : direction, 1 = server to phone, 2 = phone to server arguments
503 static const unsigned char packet_rcv_discovery
[] =
504 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
505 static unsigned char packet_send_discovery_ack
[] =
506 { 0x00, 0x00, /*Initial Seq (2 bytes) */ 0x00, 0x00, 0x00, 0x01 };
508 static const unsigned char packet_recv_firm_version
[] =
509 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
510 static const unsigned char packet_recv_pressed_key
[] =
511 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
512 static const unsigned char packet_recv_pick_up
[] =
513 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
514 static const unsigned char packet_recv_hangup
[] =
515 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
516 static const unsigned char packet_recv_r2
[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
518 /*! TransportAdapter */
519 static const unsigned char packet_recv_resume_connection_with_server
[] =
520 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
521 static const unsigned char packet_recv_mac_addr
[] =
522 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 /*MacAddr */ };
524 static const unsigned char packet_send_date_time3
[] =
525 { 0x11, 0x09, 0x02, 0x02, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07,
526 /*Minutes */ 0x08, 0x32
528 static const unsigned char packet_send_date_time
[] =
529 { 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */ 0x06, /*Hour */ 0x07, /*Minutes */
530 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
531 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
532 0x05, 0x12, 0x00, 0x78
535 static const unsigned char packet_send_no_ring
[] =
536 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
537 static const unsigned char packet_send_s4
[] =
538 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
539 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
540 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
541 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
542 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
544 static const unsigned char packet_send_call
[] =
545 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
546 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
547 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
548 0x00, /*codec */ 0x12, 0x12, /* frames per packet */ 0x01, 0x5c, 0x00, /*port RTP */
549 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41,
550 /*port RTP */ 0x0f, 0xa0, /* port RTCP */ 0x9c, 0x41, /* IP Address */ 0x0a, 0x01,
553 static const unsigned char packet_send_stream_based_tone_off
[] =
554 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
556 /* static const unsigned char packet_send_Mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
557 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
558 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };*/
559 static const unsigned char packet_send_stream_based_tone_on
[] =
560 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
561 static const unsigned char packet_send_stream_based_tone_single_freq
[] =
562 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
563 static const unsigned char packet_send_stream_based_tone_dial_freq
[] =
564 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
565 static const unsigned char packet_send_select_output
[] =
566 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
567 static const unsigned char packet_send_ring
[] =
568 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
569 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 /* Ring type 10 to 17 */ , 0x18, 0x16, 0x04, 0x18, /* volume 00, 10, 20... */
570 0x20, 0x16, 0x04, 0x10, 0x00
572 static const unsigned char packet_send_end_call
[] =
573 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
574 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
575 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
577 static const unsigned char packet_send_s9
[] =
578 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
580 static const unsigned char packet_send_rtp_packet_size
[] =
581 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
582 static const unsigned char packet_send_jitter_buffer_conf
[] =
583 { 0x16, 0x0e, 0x3a, 0x00, /* jitter */ 0x02, /* high water mark */ 0x04, 0x00, 0x00,
584 /* early packet resync 2 bytes */ 0x3e, 0x80,
585 0x00, 0x00, /* late packet resync 2 bytes */ 0x3e, 0x80
588 /* Duration in ms div 2 (0x20 = 64ms, 0x08 = 16ms)
589 static unsigned char packet_send_StreamBasedToneCad[] =
590 { 0x16, 0x0a, 0x1e, 0x00, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x0d, duration on 0x0a, duration off 0x2b }; */
591 static const unsigned char packet_send_open_audio_stream_rx
[] =
592 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
593 0x0e, 0x01, /* Port */ 0x14, 0x50, 0x00,
594 0x00, /* Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
596 static const unsigned char packet_send_open_audio_stream_tx
[] =
597 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
598 0x0e, 0x01, /* Local port */ 0x14, 0x50,
599 0x00, 0x00, /* Rmt Port */ 0x14, 0x50, 0x00, 0x00, /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
602 static const unsigned char packet_send_open_audio_stream_rx3
[] =
603 { 0x16, 0x1a, 0x30, 0x00, 0xff, /* Codec */ 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
604 0x06, 0x81, /* RTP Port */ 0x14, 0x50,
605 /* RTCP Port */ 0x14,
606 0x51, /* RTP Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00, /* Dest IP */ 0x0a, 0x93,
609 static const unsigned char packet_send_open_audio_stream_tx3
[] =
610 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, /* Codec */ 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
611 0x06, 0x81, /* RTP Local port */ 0x14, 0x50,
612 /* RTCP Port */ 0x00, 0x00, /* RTP Rmt Port */ 0x14, 0x50, /* RTCP Port */ 0x00, 0x00,
613 /* Dest IP */ 0x0a, 0x93, 0x69, 0x05
616 static const unsigned char packet_send_arrow
[] = { 0x17, 0x04, 0x04, 0x00 };
617 static const unsigned char packet_send_blink_cursor
[] = { 0x17, 0x04, 0x10, 0x86 };
618 static const unsigned char packet_send_date_time2
[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, /*Month */ 0x05, /*Day */
619 0x06, /*Hour */ 0x07, /*Minutes */ 0x08, 0x32
621 static const unsigned char packet_send_Contrast
[] =
622 { 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
623 static const unsigned char packet_send_StartTimer
[] =
624 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
626 static const unsigned char packet_send_stop_timer
[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
627 static const unsigned char packet_send_icon
[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
628 static const unsigned char packet_send_S7
[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
629 static const unsigned char packet_send_set_pos_cursor
[] =
630 { 0x17, 0x06, 0x10, 0x81, 0x04, /*pos */ 0x20 };
632 /*static unsigned char packet_send_MonthLabelsDownload[] =
633 { 0x17, 0x0a, 0x15, Month (3 char) 0x46, 0x65, 0x62, 0x4d, 0xe4, 0x72, 0x20 }; */
634 static const unsigned char packet_send_favorite
[] =
635 { 0x17, 0x0f, 0x19, 0x10, /*pos */ 0x01, /*name */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
636 0x20, 0x20, 0x20, 0x20, /*end_name */ 0x19,
637 0x05, 0x0f, /*pos */ 0x01, /*icone */ 0x00
639 static const unsigned char packet_send_title
[] =
640 { 0x17, 0x10, 0x19, 0x02, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
641 0x20, 0x20, 0x20, 0x20 /*end_text */ };
642 static const unsigned char packet_send_text
[] =
643 { 0x17, 0x1e, 0x1b, 0x04, /*pos */ 0x00, /*inverse */ 0x25, /*text */ 0x20, 0x20,
644 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
645 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
646 /*end_text */ 0x17, 0x04, 0x10, 0x87
648 static const unsigned char packet_send_status
[] =
649 { 0x17, 0x20, 0x19, 0x08, /*text */ 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
650 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
651 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 /*end_text */
653 static const unsigned char packet_send_status2
[] =
654 { 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
655 0x20, 0x20, 0x20 /* end_text */ };
657 static const unsigned char packet_send_led_update
[] = { 0x19, 0x04, 0x00, 0x00 };
659 static const unsigned char packet_send_query_basic_manager_04
[] = { 0x1a, 0x04, 0x01, 0x04 };
660 static const unsigned char packet_send_query_mac_address
[] = { 0x1a, 0x04, 0x01, 0x08 };
661 static const unsigned char packet_send_query_basic_manager_10
[] = { 0x1a, 0x04, 0x01, 0x10 };
662 static const unsigned char packet_send_S1
[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
664 static unsigned char packet_send_ping
[] =
665 { 0x1e, 0x05, 0x12, 0x00, /*Watchdog timer */ 0x78 };
667 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
669 static const char tdesc
[] = "UNISTIM Channel Driver";
670 static const char channel_type
[] = "USTM";
673 static struct ast_channel
*unistim_new(struct unistim_subchannel
*sub
, int state
);
674 static int load_module(void);
675 static int reload(void);
676 static int unload_module(void);
677 static int reload_config(void);
678 static void show_main_page(struct unistimsession
*pte
);
679 static struct ast_channel
*unistim_request(const char *type
, int format
,
680 void *data
, int *cause
);
681 static int unistim_call(struct ast_channel
*ast
, char *dest
, int timeout
);
682 static int unistim_hangup(struct ast_channel
*ast
);
683 static int unistim_answer(struct ast_channel
*ast
);
684 static struct ast_frame
*unistim_read(struct ast_channel
*ast
);
685 static int unistim_write(struct ast_channel
*ast
, struct ast_frame
*frame
);
686 static int unistim_indicate(struct ast_channel
*ast
, int ind
, const void *data
,
688 static int unistim_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
);
689 static int unistim_senddigit_begin(struct ast_channel
*ast
, char digit
);
690 static int unistim_senddigit_end(struct ast_channel
*ast
, char digit
,
691 unsigned int duration
);
692 static int unistim_sendtext(struct ast_channel
*ast
, const char *text
);
694 static int write_entry_history(struct unistimsession
*pte
, FILE * f
, char c
,
696 static void change_callerid(struct unistimsession
*pte
, int type
, char *callerid
);
698 static const struct ast_channel_tech unistim_tech
= {
699 .type
= channel_type
,
700 .description
= tdesc
,
701 .capabilities
= CAPABILITY
,
702 .properties
= AST_CHAN_TP_WANTSJITTER
| AST_CHAN_TP_CREATESJITTER
,
703 .requester
= unistim_request
,
704 .call
= unistim_call
,
705 .hangup
= unistim_hangup
,
706 .answer
= unistim_answer
,
707 .read
= unistim_read
,
708 .write
= unistim_write
,
709 .indicate
= unistim_indicate
,
710 .fixup
= unistim_fixup
,
711 .send_digit_begin
= unistim_senddigit_begin
,
712 .send_digit_end
= unistim_senddigit_end
,
713 .send_text
= unistim_sendtext
,
714 /* .bridge = ast_rtp_bridge, */
717 static void display_last_error(const char *sz_msg
)
723 /* Display the error message */
724 ast_log(LOG_WARNING
, "%s %s : (%u) %s\n", ctime(&cur_time
), sz_msg
, errno
,
728 static unsigned int get_tick_count(void)
730 struct timeval now
= ast_tvnow();
732 return (now
.tv_sec
* 1000) + (now
.tv_usec
/ 1000);
735 /* Send data to a phone without retransmit nor buffering */
736 static void send_raw_client(int size
, unsigned char *data
, struct sockaddr_in
*addr_to
,
737 const struct sockaddr_in
*addr_ourip
)
740 struct iovec msg_iov
;
742 char buffer
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
743 struct cmsghdr
*ip_msg
= (struct cmsghdr
*) buffer
;
744 struct in_pktinfo
*pki
= (struct in_pktinfo
*) CMSG_DATA(ip_msg
);
746 msg_iov
.iov_base
= data
;
747 msg_iov
.iov_len
= size
;
749 msg
.msg_name
= addr_to
; /* optional address */
750 msg
.msg_namelen
= sizeof(struct sockaddr_in
); /* size of address */
751 msg
.msg_iov
= &msg_iov
; /* scatter/gather array */
752 msg
.msg_iovlen
= 1; /* # elements in msg_iov */
753 msg
.msg_control
= ip_msg
; /* ancillary data */
754 msg
.msg_controllen
= sizeof(buffer
); /* ancillary data buffer len */
755 msg
.msg_flags
= 0; /* flags on received message */
757 ip_msg
->cmsg_len
= CMSG_LEN(sizeof(*pki
));
758 ip_msg
->cmsg_level
= IPPROTO_IP
;
759 ip_msg
->cmsg_type
= IP_PKTINFO
;
760 pki
->ipi_ifindex
= 0; /* Interface index, 0 = use interface specified in routing table */
761 pki
->ipi_spec_dst
.s_addr
= addr_ourip
->sin_addr
.s_addr
; /* Local address */
762 /* pki->ipi_addr = ; Header Destination address - ignored by kernel */
767 char iabuf
[INET_ADDRSTRLEN
];
768 char iabuf2
[INET_ADDRSTRLEN
];
769 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
770 ast_inet_ntoa(addr_ourip
->sin_addr
), (int) size
,
771 ast_inet_ntoa(addr_to
->sin_addr
));
772 for (tmp
= 0; tmp
< size
; tmp
++)
773 ast_verb(0, "%.2x ", (unsigned char) data
[tmp
]);
774 ast_verb(0, "\n******************************************\n");
779 if (sendmsg(unistimsock
, &msg
, 0) == -1)
780 display_last_error("Error sending datas");
782 if (sendto(unistimsock
, data
, size
, 0, (struct sockaddr
*) addr_to
, sizeof(*addr_to
))
784 display_last_error("Error sending datas");
788 static void send_client(int size
, const unsigned char *data
, struct unistimsession
*pte
)
792 unsigned short *sdata
= (unsigned short *) data
;
794 ast_mutex_lock(&pte
->lock
);
795 buf_pos
= pte
->last_buf_available
;
797 if (buf_pos
>= MAX_BUF_NUMBER
) {
798 ast_log(LOG_WARNING
, "Error : send queue overflow\n");
799 ast_mutex_unlock(&pte
->lock
);
802 sdata
[1] = ntohs(++(pte
->seq_server
));
803 pte
->wsabufsend
[buf_pos
].len
= size
;
804 memcpy(pte
->wsabufsend
[buf_pos
].buf
, data
, size
);
806 tick
= get_tick_count();
807 pte
->timeout
= tick
+ RETRANSMIT_TIMER
;
809 /*#ifdef DUMP_PACKET */
811 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte
->seq_server
, buf_pos
);
813 send_raw_client(pte
->wsabufsend
[buf_pos
].len
, pte
->wsabufsend
[buf_pos
].buf
, &(pte
->sin
),
815 pte
->last_buf_available
++;
816 ast_mutex_unlock(&pte
->lock
);
819 static void send_ping(struct unistimsession
*pte
)
823 ast_verb(6, "Sending ping\n");
824 pte
->tick_next_ping
= get_tick_count() + unistim_keepalive
;
825 memcpy(buffsend
+ SIZE_HEADER
, packet_send_ping
, sizeof(packet_send_ping
));
826 send_client(SIZE_HEADER
+ sizeof(packet_send_ping
), buffsend
, pte
);
829 static int get_to_address(int fd
, struct sockaddr_in
*toAddr
)
837 struct in_addr address
;
840 /* Zero out the structures before we use them */
841 /* This sets several key values to NULL */
842 memset(&msg
, 0, sizeof(msg
));
843 memset(&ip_msg
, 0, sizeof(ip_msg
));
845 /* Initialize the message structure */
846 msg
.msg_control
= &ip_msg
;
847 msg
.msg_controllen
= sizeof(ip_msg
);
848 /* Get info about the incoming packet */
849 err
= recvmsg(fd
, &msg
, MSG_PEEK
);
851 ast_log(LOG_WARNING
, "recvmsg returned an error: %s\n", strerror(errno
));
852 memcpy(&toAddr
->sin_addr
, &ip_msg
.address
, sizeof(struct in_addr
));
855 memcpy(&toAddr
, &public_ip
, sizeof(&toAddr
));
860 /* Allocate memory & initialize structures for a new phone */
861 /* addr_from : ip address of the phone */
862 static struct unistimsession
*create_client(const struct sockaddr_in
*addr_from
)
865 struct unistimsession
*s
;
867 if (!(s
= ast_calloc(1, sizeof(*s
))))
870 memcpy(&s
->sin
, addr_from
, sizeof(struct sockaddr_in
));
871 get_to_address(unistimsock
, &s
->sout
);
873 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
874 ast_inet_ntoa(addr_from
->sin_addr
), ast_inet_ntoa(s
->sout
.sin_addr
));
876 ast_mutex_init(&s
->lock
);
877 ast_mutex_lock(&sessionlock
);
881 s
->timeout
= get_tick_count() + RETRANSMIT_TIMER
;
882 s
->seq_phone
= (short) 0x0000;
883 s
->seq_server
= (short) 0x0000;
884 s
->last_seq_ack
= (short) 0x000;
885 s
->last_buf_available
= 0;
886 s
->nb_retransmit
= 0;
887 s
->state
= STATE_INIT
;
888 s
->tick_next_ping
= get_tick_count() + unistim_keepalive
;
889 /* Initialize struct wsabuf */
890 for (tmp
= 0; tmp
< MAX_BUF_NUMBER
; tmp
++) {
891 s
->wsabufsend
[tmp
].buf
= s
->buf
[tmp
];
893 ast_mutex_unlock(&sessionlock
);
897 static void send_end_call(struct unistimsession
*pte
)
901 ast_verb(0, "Sending end call\n");
902 memcpy(buffsend
+ SIZE_HEADER
, packet_send_end_call
, sizeof(packet_send_end_call
));
903 send_client(SIZE_HEADER
+ sizeof(packet_send_end_call
), buffsend
, pte
);
906 static void set_ping_timer(struct unistimsession
*pte
)
908 unsigned int tick
= 0; /* XXX what is this for, anyways */
910 pte
->timeout
= pte
->tick_next_ping
;
911 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick
, pte
->timeout
);
915 /* Checking if our send queue is empty,
916 * if true, setting up a timer for keepalive */
917 static void check_send_queue(struct unistimsession
*pte
)
919 /* Check if our send queue contained only one element */
920 if (pte
->last_buf_available
== 1) {
922 ast_verb(6, "Our single packet was ACKed.\n");
923 pte
->last_buf_available
--;
927 /* Check if this ACK catch up our latest packet */
928 else if (pte
->last_seq_ack
+ 1 == pte
->seq_server
+ 1) {
930 ast_verb(6, "Our send queue is completely ACKed.\n");
931 pte
->last_buf_available
= 0; /* Purge the send queue */
936 ast_verb(6, "We still have packets in our send queue\n");
940 static void send_start_timer(struct unistimsession
*pte
)
944 ast_verb(0, "Sending start timer\n");
945 memcpy(buffsend
+ SIZE_HEADER
, packet_send_StartTimer
, sizeof(packet_send_StartTimer
));
946 send_client(SIZE_HEADER
+ sizeof(packet_send_StartTimer
), buffsend
, pte
);
949 static void send_stop_timer(struct unistimsession
*pte
)
953 ast_verb(0, "Sending stop timer\n");
954 memcpy(buffsend
+ SIZE_HEADER
, packet_send_stop_timer
, sizeof(packet_send_stop_timer
));
955 send_client(SIZE_HEADER
+ sizeof(packet_send_stop_timer
), buffsend
, pte
);
958 static void Sendicon(unsigned char pos
, unsigned char status
, struct unistimsession
*pte
)
962 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos
, status
);
963 memcpy(buffsend
+ SIZE_HEADER
, packet_send_icon
, sizeof(packet_send_icon
));
965 buffsend
[10] = status
;
966 send_client(SIZE_HEADER
+ sizeof(packet_send_icon
), buffsend
, pte
);
969 static void send_tone(struct unistimsession
*pte
, uint16_t tone1
, uint16_t tone2
)
974 ast_verb(0, "Sending Stream Based Tone Off\n");
975 memcpy(buffsend
+ SIZE_HEADER
, packet_send_stream_based_tone_off
,
976 sizeof(packet_send_stream_based_tone_off
));
977 send_client(SIZE_HEADER
+ sizeof(packet_send_stream_based_tone_off
), buffsend
, pte
);
980 /* Since most of the world use a continuous tone, it's useless
982 ast_verb(0, "Sending Stream Based Tone Cadence Download\n");
983 memcpy (buffsend + SIZE_HEADER, packet_send_StreamBasedToneCad, sizeof (packet_send_StreamBasedToneCad));
984 send_client (SIZE_HEADER + sizeof (packet_send_StreamBasedToneCad), buffsend, pte); */
986 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1
, tone2
);
989 memcpy(buffsend
+ SIZE_HEADER
, packet_send_stream_based_tone_single_freq
,
990 sizeof(packet_send_stream_based_tone_single_freq
));
991 buffsend
[10] = (tone1
& 0xff00) >> 8;
992 buffsend
[11] = (tone1
& 0x00ff);
993 send_client(SIZE_HEADER
+ sizeof(packet_send_stream_based_tone_single_freq
), buffsend
,
997 memcpy(buffsend
+ SIZE_HEADER
, packet_send_stream_based_tone_dial_freq
,
998 sizeof(packet_send_stream_based_tone_dial_freq
));
999 buffsend
[10] = (tone1
& 0xff00) >> 8;
1000 buffsend
[11] = (tone1
& 0x00ff);
1001 buffsend
[12] = (tone2
& 0xff00) >> 8;
1002 buffsend
[13] = (tone2
& 0x00ff);
1003 send_client(SIZE_HEADER
+ sizeof(packet_send_stream_based_tone_dial_freq
), buffsend
,
1008 ast_verb(0, "Sending Stream Based Tone On\n");
1009 memcpy(buffsend
+ SIZE_HEADER
, packet_send_stream_based_tone_on
,
1010 sizeof(packet_send_stream_based_tone_on
));
1011 send_client(SIZE_HEADER
+ sizeof(packet_send_stream_based_tone_on
), buffsend
, pte
);
1014 /* Positions for favorites
1015 |--------------------|
1021 /* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
1023 send_favorite(unsigned char pos
, unsigned char status
, struct unistimsession
*pte
,
1030 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos
, status
);
1031 memcpy(buffsend
+ SIZE_HEADER
, packet_send_favorite
, sizeof(packet_send_favorite
));
1034 buffsend
[25] = status
;
1036 if (i
> FAV_MAX_LENGTH
)
1038 memcpy(buffsend
+ FAV_MAX_LENGTH
+ 1, text
, i
);
1039 send_client(SIZE_HEADER
+ sizeof(packet_send_favorite
), buffsend
, pte
);
1042 static void refresh_all_favorite(struct unistimsession
*pte
)
1047 ast_verb(0, "Refreshing all favorite\n");
1048 for (i
= 0; i
< 6; i
++) {
1049 if ((pte
->device
->softkeyicon
[i
] <= FAV_ICON_HEADPHONES_ONHOLD
) &&
1050 (pte
->device
->softkeylinepos
!= i
))
1051 send_favorite((unsigned char) i
, pte
->device
->softkeyicon
[i
] + 1, pte
,
1052 pte
->device
->softkeylabel
[i
]);
1054 send_favorite((unsigned char) i
, pte
->device
->softkeyicon
[i
], pte
,
1055 pte
->device
->softkeylabel
[i
]);
1060 /* Change the status for this phone (pte) and update for each phones where pte is bookmarked
1061 * use FAV_ICON_*_BLACK constant in status parameters */
1062 static void change_favorite_icon(struct unistimsession
*pte
, unsigned char status
)
1064 struct unistim_device
*d
= devices
;
1066 /* Update the current phone */
1067 if (pte
->state
!= STATE_CLEANING
)
1068 send_favorite(pte
->device
->softkeylinepos
, status
, pte
,
1069 pte
->device
->softkeylabel
[pte
->device
->softkeylinepos
]);
1070 /* Notify other phones if we're in their bookmark */
1072 for (i
= 0; i
< 6; i
++) {
1073 if (d
->sp
[i
] == pte
->device
) { /* It's us ? */
1074 if (d
->softkeyicon
[i
] != status
) { /* Avoid resending the same icon */
1075 d
->softkeyicon
[i
] = status
;
1077 send_favorite(i
, status
+ 1, d
->session
, d
->softkeylabel
[i
]);
1085 static int RegisterExtension(const struct unistimsession
*pte
)
1088 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
1089 pte
->device
->extension_number
, pte
->device
->lines
->context
,
1090 pte
->device
->lines
->fullname
);
1091 return ast_add_extension(pte
->device
->lines
->context
, 0,
1092 pte
->device
->extension_number
, 1, NULL
, NULL
, "Dial",
1093 pte
->device
->lines
->fullname
, 0, "Unistim");
1096 static int UnregisterExtension(const struct unistimsession
*pte
)
1099 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
1100 pte
->device
->extension_number
, pte
->device
->lines
->context
);
1101 return ast_context_remove_extension(pte
->device
->lines
->context
,
1102 pte
->device
->extension_number
, 1, "Unistim");
1105 /* Free memory allocated for a phone */
1106 static void close_client(struct unistimsession
*s
)
1108 struct unistim_subchannel
*sub
;
1109 struct unistimsession
*cur
, *prev
= NULL
;
1110 ast_mutex_lock(&sessionlock
);
1112 /* Looking for the session in the linked chain */
1119 if (cur
) { /* Session found ? */
1120 if (cur
->device
) { /* This session was registred ? */
1121 s
->state
= STATE_CLEANING
;
1123 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
1124 s
, s
->device
, s
->device
->lines
,
1125 s
->device
->lines
->subs
[SUB_REAL
]);
1126 change_favorite_icon(s
, FAV_ICON_NONE
);
1127 sub
= s
->device
->lines
->subs
[SUB_REAL
];
1129 if (sub
->owner
) { /* Call in progress ? */
1131 ast_verb(0, "Aborting call\n");
1132 ast_queue_hangup_with_cause(sub
->owner
, AST_CAUSE_NETWORK_OUT_OF_ORDER
);
1135 ast_log(LOG_WARNING
, "Freeing a client with no subchannel !\n");
1136 if (!ast_strlen_zero(s
->device
->extension_number
))
1137 UnregisterExtension(s
);
1138 cur
->device
->session
= NULL
;
1141 ast_verb(0, "Freeing an unregistered client\n");
1144 prev
->next
= cur
->next
;
1146 sessions
= cur
->next
;
1147 ast_mutex_destroy(&s
->lock
);
1150 ast_log(LOG_WARNING
, "Trying to delete non-existent session %p?\n", s
);
1151 ast_mutex_unlock(&sessionlock
);
1155 /* Return 1 if the session chained link was modified */
1156 static int send_retransmit(struct unistimsession
*pte
)
1160 ast_mutex_lock(&pte
->lock
);
1161 if (++pte
->nb_retransmit
>= NB_MAX_RETRANSMIT
) {
1163 ast_verb(0, "Too many retransmit - freeing client\n");
1164 ast_mutex_unlock(&pte
->lock
);
1168 pte
->timeout
= get_tick_count() + RETRANSMIT_TIMER
;
1170 for (i
= pte
->last_buf_available
- (pte
->seq_server
- pte
->last_seq_ack
);
1171 i
< pte
->last_buf_available
; i
++) {
1173 ast_log(LOG_WARNING
,
1174 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
1175 pte
->last_buf_available
, pte
->seq_server
, pte
->last_seq_ack
);
1180 unsigned short *sbuf
= (unsigned short *) pte
->wsabufsend
[i
].buf
;
1183 seq
= ntohs(sbuf
[1]);
1184 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i
,
1185 seq
, pte
->last_seq_ack
);
1187 send_raw_client(pte
->wsabufsend
[i
].len
, pte
->wsabufsend
[i
].buf
, &pte
->sin
,
1190 ast_mutex_unlock(&pte
->lock
);
1194 /* inverse : TEXT_INVERSE : yes, TEXT_NORMAL : no */
1196 send_text(unsigned char pos
, unsigned char inverse
, struct unistimsession
*pte
,
1202 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos
, inverse
);
1203 memcpy(buffsend
+ SIZE_HEADER
, packet_send_text
, sizeof(packet_send_text
));
1205 buffsend
[11] = inverse
;
1207 if (i
> TEXT_LENGTH_MAX
)
1208 i
= TEXT_LENGTH_MAX
;
1209 memcpy(buffsend
+ 12, text
, i
);
1210 send_client(SIZE_HEADER
+ sizeof(packet_send_text
), buffsend
, pte
);
1213 static void send_text_status(struct unistimsession
*pte
, const char *text
)
1218 ast_verb(0, "Sending status text\n");
1220 if (pte
->device
->status_method
== 1) { /* For new firmware and i2050 soft phone */
1221 int n
= strlen(text
);
1222 /* Must send individual button separately */
1224 for (i
= 0, j
= 0; i
< 4; i
++, j
+= 7) {
1225 int pos
= 0x08 + (i
* 0x20);
1226 memcpy(buffsend
+ SIZE_HEADER
, packet_send_status2
,
1227 sizeof(packet_send_status2
));
1230 memcpy(buffsend
+ 10, (j
< n
) ? (text
+ j
) : " ", 7);
1231 send_client(SIZE_HEADER
+ sizeof(packet_send_status2
), buffsend
, pte
);
1238 memcpy(buffsend
+ SIZE_HEADER
, packet_send_status
, sizeof(packet_send_status
));
1240 if (i
> STATUS_LENGTH_MAX
)
1241 i
= STATUS_LENGTH_MAX
;
1242 memcpy(buffsend
+ 10, text
, i
);
1243 send_client(SIZE_HEADER
+ sizeof(packet_send_status
), buffsend
, pte
);
1247 /* led values in hexa : 0 = bar off, 1 = bar on, 2 = bar 1s on/1s off, 3 = bar 2.5s on/0.5s off
1248 * 4 = bar 0.6s on/0.3s off, 5 = bar 0.5s on/0.5s off, 6 = bar 2s on/0.5s off
1249 * 7 = bar off, 8 = speaker off, 9 = speaker on, 10 = headphone off, 11 = headphone on
1250 * 18 = mute off, 19 mute on */
1251 static void send_led_update(struct unistimsession
*pte
, unsigned char led
)
1255 ast_verb(0, "Sending led_update (%x)\n", led
);
1256 memcpy(buffsend
+ SIZE_HEADER
, packet_send_led_update
, sizeof(packet_send_led_update
));
1258 send_client(SIZE_HEADER
+ sizeof(packet_send_led_update
), buffsend
, pte
);
1261 /* output = OUTPUT_HANDSET, OUTPUT_HEADPHONE or OUTPUT_SPEAKER
1262 * volume = VOLUME_LOW, VOLUME_NORMAL, VOLUME_INSANELY_LOUD
1263 * mute = MUTE_OFF, MUTE_ON */
1265 send_select_output(struct unistimsession
*pte
, unsigned char output
, unsigned char volume
,
1270 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output
,
1272 memcpy(buffsend
+ SIZE_HEADER
, packet_send_select_output
,
1273 sizeof(packet_send_select_output
));
1274 buffsend
[9] = output
;
1275 if (output
== OUTPUT_SPEAKER
)
1276 volume
= VOLUME_LOW_SPEAKER
;
1278 volume
= VOLUME_LOW
;
1279 buffsend
[10] = volume
;
1280 if (mute
== MUTE_ON_DISCRET
)
1281 buffsend
[11] = MUTE_ON
;
1283 buffsend
[11] = mute
;
1284 send_client(SIZE_HEADER
+ sizeof(packet_send_select_output
), buffsend
, pte
);
1285 if (mute
== MUTE_OFF
)
1286 send_led_update(pte
, 0x18);
1287 else if (mute
== MUTE_ON
)
1288 send_led_update(pte
, 0x19);
1289 pte
->device
->mute
= mute
;
1290 if (output
== OUTPUT_HANDSET
) {
1291 if (mute
== MUTE_ON
)
1292 change_favorite_icon(pte
, FAV_ICON_ONHOLD_BLACK
);
1294 change_favorite_icon(pte
, FAV_ICON_OFFHOOK_BLACK
);
1295 send_led_update(pte
, 0x08);
1296 send_led_update(pte
, 0x10);
1297 } else if (output
== OUTPUT_HEADPHONE
) {
1298 if (mute
== MUTE_ON
)
1299 change_favorite_icon(pte
, FAV_ICON_HEADPHONES_ONHOLD
);
1301 change_favorite_icon(pte
, FAV_ICON_HEADPHONES
);
1302 send_led_update(pte
, 0x08);
1303 send_led_update(pte
, 0x11);
1304 } else if (output
== OUTPUT_SPEAKER
) {
1305 send_led_update(pte
, 0x10);
1306 send_led_update(pte
, 0x09);
1307 if (pte
->device
->receiver_state
== STATE_OFFHOOK
) {
1308 if (mute
== MUTE_ON
)
1309 change_favorite_icon(pte
, FAV_ICON_SPEAKER_ONHOLD_BLACK
);
1311 change_favorite_icon(pte
, FAV_ICON_SPEAKER_ONHOOK_BLACK
);
1313 if (mute
== MUTE_ON
)
1314 change_favorite_icon(pte
, FAV_ICON_SPEAKER_ONHOLD_BLACK
);
1316 change_favorite_icon(pte
, FAV_ICON_SPEAKER_OFFHOOK_BLACK
);
1319 ast_log(LOG_WARNING
, "Invalid ouput (%d)\n", output
);
1320 if (output
!= pte
->device
->output
)
1321 pte
->device
->previous_output
= pte
->device
->output
;
1322 pte
->device
->output
= output
;
1325 static void send_ring(struct unistimsession
*pte
, char volume
, char style
)
1329 ast_verb(0, "Sending ring packet\n");
1330 memcpy(buffsend
+ SIZE_HEADER
, packet_send_ring
, sizeof(packet_send_ring
));
1331 buffsend
[24] = style
+ 0x10;
1332 buffsend
[29] = volume
* 0x10;
1333 send_client(SIZE_HEADER
+ sizeof(packet_send_ring
), buffsend
, pte
);
1336 static void send_no_ring(struct unistimsession
*pte
)
1340 ast_verb(0, "Sending no ring packet\n");
1341 memcpy(buffsend
+ SIZE_HEADER
, packet_send_no_ring
, sizeof(packet_send_no_ring
));
1342 send_client(SIZE_HEADER
+ sizeof(packet_send_no_ring
), buffsend
, pte
);
1345 static void send_texttitle(struct unistimsession
*pte
, const char *text
)
1350 ast_verb(0, "Sending title text\n");
1351 memcpy(buffsend
+ SIZE_HEADER
, packet_send_title
, sizeof(packet_send_title
));
1355 memcpy(buffsend
+ 10, text
, i
);
1356 send_client(SIZE_HEADER
+ sizeof(packet_send_title
), buffsend
, pte
);
1360 static void send_date_time(struct unistimsession
*pte
)
1363 struct timeval now
= ast_tvnow();
1364 struct ast_tm atm
= { 0, };
1367 ast_verb(0, "Sending Time & Date\n");
1368 memcpy(buffsend
+ SIZE_HEADER
, packet_send_date_time
, sizeof(packet_send_date_time
));
1369 ast_localtime(&now
, &atm
, NULL
);
1370 buffsend
[10] = (unsigned char) atm
.tm_mon
+ 1;
1371 buffsend
[11] = (unsigned char) atm
.tm_mday
;
1372 buffsend
[12] = (unsigned char) atm
.tm_hour
;
1373 buffsend
[13] = (unsigned char) atm
.tm_min
;
1374 send_client(SIZE_HEADER
+ sizeof(packet_send_date_time
), buffsend
, pte
);
1377 static void send_date_time2(struct unistimsession
*pte
)
1380 struct timeval now
= ast_tvnow();
1381 struct ast_tm atm
= { 0, };
1384 ast_verb(0, "Sending Time & Date #2\n");
1385 memcpy(buffsend
+ SIZE_HEADER
, packet_send_date_time2
, sizeof(packet_send_date_time2
));
1386 ast_localtime(&now
, &atm
, NULL
);
1388 buffsend
[9] = pte
->device
->datetimeformat
;
1391 buffsend
[14] = (unsigned char) atm
.tm_mon
+ 1;
1392 buffsend
[15] = (unsigned char) atm
.tm_mday
;
1393 buffsend
[16] = (unsigned char) atm
.tm_hour
;
1394 buffsend
[17] = (unsigned char) atm
.tm_min
;
1395 send_client(SIZE_HEADER
+ sizeof(packet_send_date_time2
), buffsend
, pte
);
1398 static void send_date_time3(struct unistimsession
*pte
)
1401 struct timeval now
= ast_tvnow();
1402 struct ast_tm atm
= { 0, };
1405 ast_verb(0, "Sending Time & Date #3\n");
1406 memcpy(buffsend
+ SIZE_HEADER
, packet_send_date_time3
, sizeof(packet_send_date_time3
));
1407 ast_localtime(&now
, &atm
, NULL
);
1408 buffsend
[10] = (unsigned char) atm
.tm_mon
+ 1;
1409 buffsend
[11] = (unsigned char) atm
.tm_mday
;
1410 buffsend
[12] = (unsigned char) atm
.tm_hour
;
1411 buffsend
[13] = (unsigned char) atm
.tm_min
;
1412 send_client(SIZE_HEADER
+ sizeof(packet_send_date_time3
), buffsend
, pte
);
1415 static void send_blink_cursor(struct unistimsession
*pte
)
1419 ast_verb(0, "Sending set blink\n");
1420 memcpy(buffsend
+ SIZE_HEADER
, packet_send_blink_cursor
, sizeof(packet_send_blink_cursor
));
1421 send_client(SIZE_HEADER
+ sizeof(packet_send_blink_cursor
), buffsend
, pte
);
1425 /* pos : 0xab (a=0/2/4 = line ; b = row) */
1426 static void send_cursor_pos(struct unistimsession
*pte
, unsigned char pos
)
1430 ast_verb(0, "Sending set cursor position\n");
1431 memcpy(buffsend
+ SIZE_HEADER
, packet_send_set_pos_cursor
,
1432 sizeof(packet_send_set_pos_cursor
));
1434 send_client(SIZE_HEADER
+ sizeof(packet_send_set_pos_cursor
), buffsend
, pte
);
1438 static void rcv_resume_connection_with_server(struct unistimsession
*pte
)
1442 ast_verb(0, "ResumeConnectionWithServer received\n");
1443 ast_verb(0, "Sending packet_send_query_mac_address\n");
1445 memcpy(buffsend
+ SIZE_HEADER
, packet_send_query_mac_address
,
1446 sizeof(packet_send_query_mac_address
));
1447 send_client(SIZE_HEADER
+ sizeof(packet_send_query_mac_address
), buffsend
, pte
);
1451 static int unistim_register(struct unistimsession
*s
)
1453 struct unistim_device
*d
;
1455 ast_mutex_lock(&devicelock
);
1458 if (!strcasecmp(s
->macaddr
, d
->id
)) {
1459 /* XXX Deal with IP authentication */
1462 d
->codec_number
= DEFAULT_CODEC
;
1465 d
->receiver_state
= STATE_ONHOOK
;
1470 ast_mutex_unlock(&devicelock
);
1478 static int alloc_sub(struct unistim_line
*l
, int x
)
1480 struct unistim_subchannel
*sub
;
1481 if (!(sub
= ast_calloc(1, sizeof(*sub
))))
1485 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x
, l
->name
, l
->parent
->name
, sub
);
1489 ast_mutex_init(&sub
->lock
);
1493 static int unalloc_sub(struct unistim_line
*p
, int x
)
1496 ast_log(LOG_WARNING
, "Trying to unalloc the real channel %s@%s?!?\n", p
->name
,
1501 ast_debug(1, "Released sub %d of channel %s@%s\n", x
, p
->name
,
1503 ast_mutex_destroy(&p
->lock
);
1504 ast_free(p
->subs
[x
]);
1509 static void rcv_mac_addr(struct unistimsession
*pte
, const unsigned char *buf
)
1516 ast_verb(0, "Mac Address received : ");
1517 for (tmp
= 15; tmp
< 15 + SIZE_HEADER
; tmp
++) {
1518 sprintf(&addrmac
[i
], "%.2x", (unsigned char) buf
[tmp
]);
1522 ast_verb(0, "%s\n", addrmac
);
1523 strcpy(pte
->macaddr
, addrmac
);
1524 res
= unistim_register(pte
);
1526 switch (autoprovisioning
) {
1527 case AUTOPROVISIONING_NO
:
1528 ast_log(LOG_WARNING
, "No entry found for this phone : %s\n", addrmac
);
1529 pte
->state
= STATE_AUTHDENY
;
1531 case AUTOPROVISIONING_YES
:
1533 struct unistim_device
*d
, *newd
;
1534 struct unistim_line
*newl
;
1536 ast_verb(0, "New phone, autoprovisioning on\n");
1537 /* First : locate the [template] section */
1538 ast_mutex_lock(&devicelock
);
1541 if (!strcasecmp(d
->name
, "template")) {
1542 /* Found, cloning this entry */
1543 if (!(newd
= ast_malloc(sizeof(*newd
)))) {
1544 ast_mutex_unlock(&devicelock
);
1548 memcpy(newd
, d
, sizeof(*newd
));
1549 if (!(newl
= ast_malloc(sizeof(*newl
)))) {
1551 ast_mutex_unlock(&devicelock
);
1555 memcpy(newl
, d
->lines
, sizeof(*newl
));
1556 if (!alloc_sub(newl
, SUB_REAL
)) {
1559 ast_mutex_unlock(&devicelock
);
1562 /* Ok, now updating some fields */
1563 ast_copy_string(newd
->id
, addrmac
, sizeof(newd
->id
));
1564 ast_copy_string(newd
->name
, addrmac
, sizeof(newd
->name
));
1565 if (newd
->extension
== EXTENSION_NONE
)
1566 newd
->extension
= EXTENSION_ASK
;
1568 newd
->receiver_state
= STATE_ONHOOK
;
1569 newd
->session
= pte
;
1570 newd
->to_delete
= -1;
1573 newl
->parent
= newd
;
1574 strcpy(newl
->name
, d
->lines
->name
);
1575 snprintf(d
->lines
->name
, sizeof(d
->lines
->name
), "%d",
1576 atoi(d
->lines
->name
) + 1);
1577 snprintf(newl
->fullname
, sizeof(newl
->fullname
), "USTM/%s@%s",
1578 newl
->name
, newd
->name
);
1579 /* Go to the end of the linked chain */
1589 ast_mutex_unlock(&devicelock
);
1591 ast_log(LOG_WARNING
, "No entry [template] found in unistim.conf\n");
1592 pte
->state
= STATE_AUTHDENY
;
1596 case AUTOPROVISIONING_TN
:
1597 pte
->state
= STATE_AUTHDENY
;
1599 case AUTOPROVISIONING_DB
:
1600 ast_log(LOG_WARNING
,
1601 "Autoprovisioning with database is not yet functional\n");
1604 ast_log(LOG_WARNING
, "Internal error : unknown autoprovisioning value = %d\n",
1608 if (pte
->state
!= STATE_AUTHDENY
) {
1609 ast_verb(3, "Device '%s' successfuly registered\n", pte
->device
->name
);
1610 switch (pte
->device
->extension
) {
1611 case EXTENSION_NONE
:
1612 pte
->state
= STATE_MAINPAGE
;
1615 /* Checking if we already have an extension number */
1616 if (ast_strlen_zero(pte
->device
->extension_number
))
1617 pte
->state
= STATE_EXTENSION
;
1619 /* Yes, because of a phone reboot. We don't ask again for the TN */
1620 if (RegisterExtension(pte
))
1621 pte
->state
= STATE_EXTENSION
;
1623 pte
->state
= STATE_MAINPAGE
;
1626 case EXTENSION_LINE
:
1627 ast_copy_string(pte
->device
->extension_number
, pte
->device
->lines
->name
,
1628 sizeof(pte
->device
->extension_number
));
1629 if (RegisterExtension(pte
))
1630 pte
->state
= STATE_EXTENSION
;
1632 pte
->state
= STATE_MAINPAGE
;
1635 /* If we are here, it's because of a phone reboot */
1636 pte
->state
= STATE_MAINPAGE
;
1639 ast_log(LOG_WARNING
, "Internal error, extension value unknown : %d\n",
1640 pte
->device
->extension
);
1641 pte
->state
= STATE_AUTHDENY
;
1645 if (pte
->state
== STATE_EXTENSION
) {
1646 if (pte
->device
->extension
!= EXTENSION_TN
)
1647 pte
->device
->extension
= EXTENSION_ASK
;
1648 pte
->device
->extension_number
[0] = '\0';
1651 ast_verb(0, "\nSending S1\n");
1652 memcpy(buffsend
+ SIZE_HEADER
, packet_send_S1
, sizeof(packet_send_S1
));
1653 send_client(SIZE_HEADER
+ sizeof(packet_send_S1
), buffsend
, pte
);
1656 ast_verb(0, "Sending query_basic_manager_04\n");
1657 memcpy(buffsend
+ SIZE_HEADER
, packet_send_query_basic_manager_04
,
1658 sizeof(packet_send_query_basic_manager_04
));
1659 send_client(SIZE_HEADER
+ sizeof(packet_send_query_basic_manager_04
), buffsend
, pte
);
1662 ast_verb(0, "Sending query_basic_manager_10\n");
1663 memcpy(buffsend
+ SIZE_HEADER
, packet_send_query_basic_manager_10
,
1664 sizeof(packet_send_query_basic_manager_10
));
1665 send_client(SIZE_HEADER
+ sizeof(packet_send_query_basic_manager_10
), buffsend
, pte
);
1667 send_date_time(pte
);
1671 static int write_entry_history(struct unistimsession
*pte
, FILE * f
, char c
, char *line1
)
1673 if (fwrite(&c
, 1, 1, f
) != 1) {
1674 display_last_error("Unable to write history log header.");
1677 if (fwrite(line1
, TEXT_LENGTH_MAX
, 1, f
) != 1) {
1678 display_last_error("Unable to write history entry - date.");
1681 if (fwrite(pte
->device
->lst_cid
, TEXT_LENGTH_MAX
, 1, f
) != 1) {
1682 display_last_error("Unable to write history entry - callerid.");
1685 if (fwrite(pte
->device
->lst_cnm
, TEXT_LENGTH_MAX
, 1, f
) != 1) {
1686 display_last_error("Unable to write history entry - callername.");
1692 static int write_history(struct unistimsession
*pte
, char way
, char ismissed
)
1694 char tmp
[AST_CONFIG_MAX_PATH
], tmp2
[AST_CONFIG_MAX_PATH
];
1695 char line1
[TEXT_LENGTH_MAX
+ 1];
1696 char count
= 0, *histbuf
;
1699 struct timeval now
= ast_tvnow();
1700 struct ast_tm atm
= { 0, };
1704 if (!pte
->device
->callhistory
)
1706 if (strchr(pte
->device
->name
, '/') || (pte
->device
->name
[0] == '.')) {
1707 ast_log(LOG_WARNING
, "Account code '%s' insecure for writing file\n",
1712 snprintf(tmp
, sizeof(tmp
), "%s/%s", ast_config_AST_LOG_DIR
, USTM_LOG_DIR
);
1713 if (ast_mkdir(tmp
, 0770)) {
1714 if (errno
!= EEXIST
) {
1715 display_last_error("Unable to create directory for history");
1720 ast_localtime(&now
, &atm
, NULL
);
1723 strcpy(tmp2
, "Miss");
1725 strcpy(tmp2
, "Fail");
1727 strcpy(tmp2
, "Answ");
1728 snprintf(line1
, sizeof(line1
), "%04d/%02d/%02d %02d:%02d:%02d %s",
1729 atm
.tm_year
+ 1900, atm
.tm_mon
+ 1, atm
.tm_mday
, atm
.tm_hour
,
1730 atm
.tm_min
, atm
.tm_sec
, tmp2
);
1732 snprintf(tmp
, sizeof(tmp
), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR
,
1733 USTM_LOG_DIR
, pte
->device
->name
, way
);
1734 if ((f
= fopen(tmp
, "r"))) {
1735 struct stat bufstat
;
1737 if (stat(tmp
, &bufstat
)) {
1738 display_last_error("Unable to stat history log.");
1742 size
= 1 + (MAX_ENTRY_LOG
* TEXT_LENGTH_MAX
* 3);
1743 if (bufstat
.st_size
!= size
) {
1744 ast_log(LOG_WARNING
,
1745 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
1746 tmp
, (int) bufstat
.st_size
, size
);
1753 /* If we can't open the log file, we create a brand new one */
1758 if ((errno
!= ENOENT
) && (count
== 0)) {
1759 display_last_error("Unable to open history log.");
1762 f
= fopen(tmp
, "w");
1764 display_last_error("Unable to create history log.");
1767 if (write_entry_history(pte
, f
, c
, line1
)) {
1771 memset(line1
, ' ', TEXT_LENGTH_MAX
);
1772 for (i
= 3; i
< MAX_ENTRY_LOG
* 3; i
++) {
1773 if (fwrite(line1
, TEXT_LENGTH_MAX
, 1, f
) != 1) {
1774 display_last_error("Unable to write history entry - stuffing.");
1780 display_last_error("Unable to close history - creation.");
1783 /* We can open the log file, we create a temporary one, we add our entry and copy the rest */
1784 if (fread(&count
, 1, 1, f
) != 1) {
1785 display_last_error("Unable to read history header.");
1789 if (count
> MAX_ENTRY_LOG
) {
1790 ast_log(LOG_WARNING
, "Invalid count in history header of %s (%d max %d)\n", tmp
,
1791 count
, MAX_ENTRY_LOG
);
1795 snprintf(tmp2
, sizeof(tmp2
), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR
,
1796 USTM_LOG_DIR
, pte
->device
->name
, way
);
1797 if (!(f2
= fopen(tmp2
, "w"))) {
1798 display_last_error("Unable to create temporary history log.");
1803 if (++count
> MAX_ENTRY_LOG
)
1804 count
= MAX_ENTRY_LOG
;
1806 if (write_entry_history(pte
, f2
, count
, line1
)) {
1812 size
= (MAX_ENTRY_LOG
- 1) * TEXT_LENGTH_MAX
* 3;
1813 if (!(histbuf
= ast_malloc(size
))) {
1819 if (fread(histbuf
, size
, 1, f
) != 1) {
1823 display_last_error("Unable to read previous history entries.");
1826 if (fwrite(histbuf
, size
, 1, f2
) != 1) {
1830 display_last_error("Unable to write previous history entries.");
1835 display_last_error("Unable to close history log.");
1837 display_last_error("Unable to close temporary history log.");
1839 display_last_error("Unable to remove old history log.");
1840 if (rename(tmp2
, tmp
))
1841 display_last_error("Unable to rename new history log.");
1845 static void cancel_dial(struct unistimsession
*pte
)
1848 pte
->device
->missed_call
++;
1849 write_history(pte
, 'i', 1);
1850 show_main_page(pte
);
1854 static void swap_subs(struct unistim_line
*p
, int a
, int b
)
1856 /* struct ast_channel *towner; */
1857 struct ast_rtp
*rtp
;
1861 ast_verb(0, "Swapping %d and %d\n", a
, b
);
1863 if ((!p
->subs
[a
]->owner
) || (!p
->subs
[b
]->owner
)) {
1864 ast_log(LOG_WARNING
,
1865 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
1866 a
, p
->subs
[a
]->owner
, b
, p
->subs
[b
]->owner
);
1869 rtp
= p
->subs
[a
]->rtp
;
1870 p
->subs
[a
]->rtp
= p
->subs
[b
]->rtp
;
1871 p
->subs
[b
]->rtp
= rtp
;
1873 fds
= p
->subs
[a
]->owner
->fds
[0];
1874 p
->subs
[a
]->owner
->fds
[0] = p
->subs
[b
]->owner
->fds
[0];
1875 p
->subs
[b
]->owner
->fds
[0] = fds
;
1877 fds
= p
->subs
[a
]->owner
->fds
[1];
1878 p
->subs
[a
]->owner
->fds
[1] = p
->subs
[b
]->owner
->fds
[1];
1879 p
->subs
[b
]->owner
->fds
[1] = fds
;
1882 static int attempt_transfer(struct unistim_subchannel
*p1
, struct unistim_subchannel
*p2
)
1886 *chana
= NULL
, *chanb
= NULL
, *bridgea
= NULL
, *bridgeb
= NULL
, *peera
=
1887 NULL
, *peerb
= NULL
, *peerc
= NULL
, *peerd
= NULL
;
1889 if (!p1
->owner
|| !p2
->owner
) {
1890 ast_log(LOG_WARNING
, "Transfer attempted without dual ownership?\n");
1895 bridgea
= ast_bridged_channel(chana
);
1896 bridgeb
= ast_bridged_channel(chanb
);
1903 } else if (bridgeb
) {
1910 if (peera
&& peerb
&& peerc
&& (peerb
!= peerc
)) {
1911 /*ast_quiet_chan(peera);
1912 ast_quiet_chan(peerb);
1913 ast_quiet_chan(peerc);
1914 ast_quiet_chan(peerd); */
1916 if (peera
->cdr
&& peerb
->cdr
) {
1917 peerb
->cdr
= ast_cdr_append(peerb
->cdr
, peera
->cdr
);
1918 } else if (peera
->cdr
) {
1919 peerb
->cdr
= peera
->cdr
;
1923 if (peerb
->cdr
&& peerc
->cdr
) {
1924 peerb
->cdr
= ast_cdr_append(peerb
->cdr
, peerc
->cdr
);
1925 } else if (peerc
->cdr
) {
1926 peerb
->cdr
= peerc
->cdr
;
1930 if (ast_channel_masquerade(peerb
, peerc
)) {
1931 ast_log(LOG_WARNING
, "Failed to masquerade %s into %s\n", peerb
->name
,
1938 "Transfer attempted with no appropriate bridged calls to transfer\n");
1940 ast_softhangup_nolock(chana
, AST_SOFTHANGUP_DEV
);
1942 ast_softhangup_nolock(chanb
, AST_SOFTHANGUP_DEV
);
1948 void change_callerid(struct unistimsession
*pte
, int type
, char *callerid
)
1954 data
= pte
->device
->lst_cnm
;
1956 data
= pte
->device
->lst_cid
;
1958 /* This is very nearly strncpy(), except that the remaining buffer
1959 * is padded with ' ', instead of '\0' */
1960 memset(data
, ' ', TEXT_LENGTH_MAX
);
1961 size
= strlen(callerid
);
1962 if (size
> TEXT_LENGTH_MAX
)
1963 size
= TEXT_LENGTH_MAX
;
1964 memcpy(data
, callerid
, size
);
1967 static void close_call(struct unistimsession
*pte
)
1969 struct unistim_subchannel
*sub
;
1970 struct unistim_line
*l
= pte
->device
->lines
;
1972 sub
= pte
->device
->lines
->subs
[SUB_REAL
];
1973 send_stop_timer(pte
);
1975 sub
->alreadygone
= 1;
1976 if (l
->subs
[SUB_THREEWAY
]) {
1977 l
->subs
[SUB_THREEWAY
]->alreadygone
= 1;
1978 if (attempt_transfer(sub
, l
->subs
[SUB_THREEWAY
]) < 0)
1979 ast_verb(0, "attempt_transfer failed.\n");
1981 ast_queue_hangup(sub
->owner
);
1983 if (l
->subs
[SUB_THREEWAY
]) {
1984 if (l
->subs
[SUB_THREEWAY
]->owner
)
1985 ast_queue_hangup_with_cause(l
->subs
[SUB_THREEWAY
]->owner
, AST_CAUSE_NORMAL_CLEARING
);
1987 ast_log(LOG_WARNING
, "threeway sub without owner\n");
1989 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub
->parent
->name
,
1990 sub
->parent
->parent
->name
, sub
->subtype
);
1992 change_callerid(pte
, 0, pte
->device
->redial_number
);
1993 change_callerid(pte
, 1, "");
1994 write_history(pte
, 'o', pte
->device
->missed_call
);
1995 pte
->device
->missed_call
= 0;
1996 show_main_page(pte
);
2000 static void IgnoreCall(struct unistimsession
*pte
)
2006 static void *unistim_ss(void *data
)
2008 struct ast_channel
*chan
= data
;
2009 struct unistim_subchannel
*sub
= chan
->tech_pvt
;
2010 struct unistim_line
*l
= sub
->parent
;
2011 struct unistimsession
*s
= l
->parent
->session
;
2014 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l
->name
, l
->parent
->name
, sub
->subtype
, s
->device
->phone_number
);
2015 ast_copy_string(chan
->exten
, s
->device
->phone_number
, sizeof(chan
->exten
));
2016 ast_copy_string(s
->device
->redial_number
, s
->device
->phone_number
,
2017 sizeof(s
->device
->redial_number
));
2018 ast_setstate(chan
, AST_STATE_RING
);
2019 res
= ast_pbx_run(chan
);
2021 ast_log(LOG_WARNING
, "PBX exited non-zero\n");
2022 send_tone(s
, 1000, 0);;
2027 static void start_rtp(struct unistim_subchannel
*sub
)
2030 struct sockaddr_in us
;
2031 struct sockaddr_in
public;
2032 struct sockaddr_in sin
;
2034 struct sockaddr_in sout
;
2038 ast_log(LOG_WARNING
, "start_rtp with a null subchannel !\n");
2042 ast_log(LOG_WARNING
, "start_rtp with a null line !\n");
2045 if (!sub
->parent
->parent
) {
2046 ast_log(LOG_WARNING
, "start_rtp with a null device !\n");
2049 if (!sub
->parent
->parent
->session
) {
2050 ast_log(LOG_WARNING
, "start_rtp with a null session !\n");
2053 sout
= sub
->parent
->parent
->session
->sout
;
2055 ast_mutex_lock(&sub
->lock
);
2056 /* Allocate the RTP */
2058 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout
.sin_addr
));
2059 sub
->rtp
= ast_rtp_new_with_bindaddr(sched
, io
, 1, 0, sout
.sin_addr
);
2061 ast_log(LOG_WARNING
, "Unable to create RTP session: %s binaddr=%s\n",
2062 strerror(errno
), ast_inet_ntoa(sout
.sin_addr
));
2063 ast_mutex_unlock(&sub
->lock
);
2066 if (sub
->rtp
&& sub
->owner
) {
2067 sub
->owner
->fds
[0] = ast_rtp_fd(sub
->rtp
);
2068 sub
->owner
->fds
[1] = ast_rtcp_fd(sub
->rtp
);
2071 ast_rtp_setqos(sub
->rtp
, qos
.tos_audio
, qos
.cos_audio
, "UNISTIM RTP");
2072 ast_rtp_setnat(sub
->rtp
, sub
->parent
->parent
->nat
);
2075 /* Create the RTP connection */
2076 ast_rtp_get_us(sub
->rtp
, &us
);
2077 sin
.sin_family
= AF_INET
;
2078 /* Setting up RTP for our side */
2079 memcpy(&sin
.sin_addr
, &sub
->parent
->parent
->session
->sin
.sin_addr
,
2080 sizeof(sin
.sin_addr
));
2081 sin
.sin_port
= htons(sub
->parent
->parent
->rtp_port
);
2082 ast_rtp_set_peer(sub
->rtp
, &sin
);
2083 if (!(sub
->owner
->nativeformats
& sub
->owner
->readformat
)) {
2085 fmt
= ast_best_codec(sub
->owner
->nativeformats
);
2086 ast_log(LOG_WARNING
,
2087 "Our read/writeformat has been changed to something incompatible : %s (%d), using %s (%d) best codec from %d\n",
2088 ast_getformatname(sub
->owner
->readformat
),
2089 sub
->owner
->readformat
, ast_getformatname(fmt
), fmt
,
2090 sub
->owner
->nativeformats
);
2091 sub
->owner
->readformat
= fmt
;
2092 sub
->owner
->writeformat
= fmt
;
2094 codec
= ast_rtp_lookup_code(sub
->rtp
, 1, sub
->owner
->readformat
);
2095 /* Setting up RTP of the phone */
2096 if (public_ip
.sin_family
== 0) /* NAT IP override ? */
2097 memcpy(&public, &us
, sizeof(public)); /* No defined, using IP from recvmsg */
2099 memcpy(&public, &public_ip
, sizeof(public)); /* override */
2101 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s (%d)\n",
2102 ast_inet_ntoa(us
.sin_addr
),
2103 htons(us
.sin_port
), ast_getformatname(sub
->owner
->readformat
),
2104 sub
->owner
->readformat
);
2105 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
2106 ast_inet_ntoa(public.sin_addr
));
2108 if ((sub
->owner
->readformat
== AST_FORMAT_ULAW
) ||
2109 (sub
->owner
->readformat
== AST_FORMAT_ALAW
)) {
2111 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec
);
2112 memcpy(buffsend
+ SIZE_HEADER
, packet_send_rtp_packet_size
,
2113 sizeof(packet_send_rtp_packet_size
));
2114 buffsend
[10] = codec
;
2115 send_client(SIZE_HEADER
+ sizeof(packet_send_rtp_packet_size
), buffsend
,
2116 sub
->parent
->parent
->session
);
2119 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
2120 memcpy(buffsend
+ SIZE_HEADER
, packet_send_jitter_buffer_conf
,
2121 sizeof(packet_send_jitter_buffer_conf
));
2122 send_client(SIZE_HEADER
+ sizeof(packet_send_jitter_buffer_conf
), buffsend
,
2123 sub
->parent
->parent
->session
);
2124 if (sub
->parent
->parent
->rtp_method
!= 0) {
2125 uint16_t rtcpsin_port
= htons(us
.sin_port
) + 1; /* RTCP port is RTP + 1 */
2128 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
2129 sub
->parent
->parent
->rtp_method
);
2130 if (sub
->parent
->parent
->rtp_method
== 3)
2131 memcpy(buffsend
+ SIZE_HEADER
, packet_send_open_audio_stream_tx3
,
2132 sizeof(packet_send_open_audio_stream_tx3
));
2134 memcpy(buffsend
+ SIZE_HEADER
, packet_send_open_audio_stream_tx
,
2135 sizeof(packet_send_open_audio_stream_tx
));
2136 if (sub
->parent
->parent
->rtp_method
!= 2) {
2137 memcpy(buffsend
+ 28, &public.sin_addr
, sizeof(public.sin_addr
));
2138 buffsend
[20] = (htons(sin
.sin_port
) & 0xff00) >> 8;
2139 buffsend
[21] = (htons(sin
.sin_port
) & 0x00ff);
2140 buffsend
[23] = (rtcpsin_port
& 0x00ff);
2141 buffsend
[22] = (rtcpsin_port
& 0xff00) >> 8;
2142 buffsend
[25] = (us
.sin_port
& 0xff00) >> 8;
2143 buffsend
[24] = (us
.sin_port
& 0x00ff);
2144 buffsend
[27] = (rtcpsin_port
& 0x00ff);
2145 buffsend
[26] = (rtcpsin_port
& 0xff00) >> 8;
2147 memcpy(buffsend
+ 23, &public.sin_addr
, sizeof(public.sin_addr
));
2148 buffsend
[15] = (htons(sin
.sin_port
) & 0xff00) >> 8;
2149 buffsend
[16] = (htons(sin
.sin_port
) & 0x00ff);
2150 buffsend
[20] = (us
.sin_port
& 0xff00) >> 8;
2151 buffsend
[19] = (us
.sin_port
& 0x00ff);
2152 buffsend
[11] = codec
;
2154 buffsend
[12] = codec
;
2155 send_client(SIZE_HEADER
+ sizeof(packet_send_open_audio_stream_tx
), buffsend
,
2156 sub
->parent
->parent
->session
);
2159 ast_verb(0, "Sending OpenAudioStreamRX\n");
2160 if (sub
->parent
->parent
->rtp_method
== 3)
2161 memcpy(buffsend
+ SIZE_HEADER
, packet_send_open_audio_stream_rx3
,
2162 sizeof(packet_send_open_audio_stream_rx3
));
2164 memcpy(buffsend
+ SIZE_HEADER
, packet_send_open_audio_stream_rx
,
2165 sizeof(packet_send_open_audio_stream_rx
));
2166 if (sub
->parent
->parent
->rtp_method
!= 2) {
2167 memcpy(buffsend
+ 28, &public.sin_addr
, sizeof(public.sin_addr
));
2168 buffsend
[20] = (htons(sin
.sin_port
) & 0xff00) >> 8;
2169 buffsend
[21] = (htons(sin
.sin_port
) & 0x00ff);
2170 buffsend
[23] = (rtcpsin_port
& 0x00ff);
2171 buffsend
[22] = (rtcpsin_port
& 0xff00) >> 8;
2172 buffsend
[25] = (us
.sin_port
& 0xff00) >> 8;
2173 buffsend
[24] = (us
.sin_port
& 0x00ff);
2174 buffsend
[27] = (rtcpsin_port
& 0x00ff);
2175 buffsend
[26] = (rtcpsin_port
& 0xff00) >> 8;
2177 memcpy(buffsend
+ 23, &public.sin_addr
, sizeof(public.sin_addr
));
2178 buffsend
[15] = (htons(sin
.sin_port
) & 0xff00) >> 8;
2179 buffsend
[16] = (htons(sin
.sin_port
) & 0x00ff);
2180 buffsend
[20] = (us
.sin_port
& 0xff00) >> 8;
2181 buffsend
[19] = (us
.sin_port
& 0x00ff);
2182 buffsend
[12] = codec
;
2184 buffsend
[11] = codec
;
2185 send_client(SIZE_HEADER
+ sizeof(packet_send_open_audio_stream_rx
), buffsend
,
2186 sub
->parent
->parent
->session
);
2188 uint16_t rtcpsin_port
= htons(us
.sin_port
) + 1; /* RTCP port is RTP + 1 */
2191 ast_verb(0, "Sending packet_send_call default method\n");
2193 memcpy(buffsend
+ SIZE_HEADER
, packet_send_call
, sizeof(packet_send_call
));
2194 memcpy(buffsend
+ 53, &public.sin_addr
, sizeof(public.sin_addr
));
2195 /* Destination port when sending RTP */
2196 buffsend
[49] = (us
.sin_port
& 0x00ff);
2197 buffsend
[50] = (us
.sin_port
& 0xff00) >> 8;
2198 /* Destination port when sending RTCP */
2199 buffsend
[52] = (rtcpsin_port
& 0x00ff);
2200 buffsend
[51] = (rtcpsin_port
& 0xff00) >> 8;
2202 buffsend
[40] = codec
;
2203 buffsend
[41] = codec
;
2204 if (sub
->owner
->readformat
== AST_FORMAT_ULAW
)
2205 buffsend
[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2206 else if (sub
->owner
->readformat
== AST_FORMAT_ALAW
)
2207 buffsend
[42] = 1; /* 1 = 20ms (160 bytes), 2 = 40ms (320 bytes) */
2208 else if (sub
->owner
->readformat
== AST_FORMAT_G723_1
)
2209 buffsend
[42] = 2; /* 1 = 30ms (24 bytes), 2 = 60 ms (48 bytes) */
2210 else if (sub
->owner
->readformat
== AST_FORMAT_G729A
)
2211 buffsend
[42] = 2; /* 1 = 10ms (10 bytes), 2 = 20ms (20 bytes) */
2213 ast_log(LOG_WARNING
, "Unsupported codec %s (%d) !\n",
2214 ast_getformatname(sub
->owner
->readformat
), sub
->owner
->readformat
);
2215 /* Source port for transmit RTP and Destination port for receiving RTP */
2216 buffsend
[45] = (htons(sin
.sin_port
) & 0xff00) >> 8;
2217 buffsend
[46] = (htons(sin
.sin_port
) & 0x00ff);
2218 buffsend
[47] = (rtcpsin_port
& 0xff00) >> 8;
2219 buffsend
[48] = (rtcpsin_port
& 0x00ff);
2220 send_client(SIZE_HEADER
+ sizeof(packet_send_call
), buffsend
,
2221 sub
->parent
->parent
->session
);
2223 ast_mutex_unlock(&sub
->lock
);
2226 static void SendDialTone(struct unistimsession
*pte
)
2229 /* No country defined ? Using US tone */
2230 if (ast_strlen_zero(pte
->device
->country
)) {
2232 ast_verb(0, "No country defined, using US tone\n");
2233 send_tone(pte
, 350, 440);
2236 if (strlen(pte
->device
->country
) != 2) {
2238 ast_verb(0, "Country code != 2 char, using US tone\n");
2239 send_tone(pte
, 350, 440);
2243 while (frequency
[i
].freq1
) {
2244 if ((frequency
[i
].country
[0] == pte
->device
->country
[0]) &&
2245 (frequency
[i
].country
[1] == pte
->device
->country
[1])) {
2247 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
2248 frequency
[i
].country
, frequency
[i
].freq1
, frequency
[i
].freq2
);
2249 send_tone(pte
, frequency
[i
].freq1
, frequency
[i
].freq2
);
2255 static void handle_dial_page(struct unistimsession
*pte
)
2257 pte
->state
= STATE_DIALPAGE
;
2258 if (pte
->device
->call_forward
[0] == -1) {
2259 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "");
2260 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "Enter forward");
2261 send_text_status(pte
, "ForwardCancel BackSpcErase");
2262 if (pte
->device
->call_forward
[1] != 0) {
2263 char tmp
[TEXT_LENGTH_MAX
+ 1];
2265 ast_copy_string(pte
->device
->phone_number
, pte
->device
->call_forward
+ 1,
2266 sizeof(pte
->device
->phone_number
));
2267 pte
->device
->size_phone_number
= strlen(pte
->device
->phone_number
);
2268 if (pte
->device
->size_phone_number
> 15)
2269 pte
->device
->size_phone_number
= 15;
2270 strcpy(tmp
, "Number : ...............");
2271 memcpy(tmp
+ 9, pte
->device
->phone_number
, pte
->device
->size_phone_number
);
2272 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmp
);
2273 send_blink_cursor(pte
);
2274 send_cursor_pos(pte
,
2275 (unsigned char) (TEXT_LINE2
+ 0x09 +
2276 pte
->device
->size_phone_number
));
2277 send_led_update(pte
, 0);
2281 if ((pte
->device
->output
== OUTPUT_HANDSET
) &&
2282 (pte
->device
->receiver_state
== STATE_ONHOOK
))
2283 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
2285 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_OFF
);
2287 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Enter the number to dial");
2288 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "and press Call");
2289 send_text_status(pte
, "Call Redial BackSpcErase");
2291 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, "Number : ...............");
2292 send_blink_cursor(pte
);
2293 send_cursor_pos(pte
, TEXT_LINE2
+ 0x09);
2294 pte
->device
->size_phone_number
= 0;
2295 pte
->device
->phone_number
[0] = 0;
2296 change_favorite_icon(pte
, FAV_ICON_PHONE_BLACK
);
2297 Sendicon(TEXT_LINE0
, FAV_ICON_NONE
, pte
);
2298 pte
->device
->missed_call
= 0;
2299 send_led_update(pte
, 0);
2303 /* Step 1 : Music On Hold for peer, Dialing screen for us */
2304 static void TransferCallStep1(struct unistimsession
*pte
)
2306 struct unistim_subchannel
*sub
;
2307 struct unistim_line
*p
= pte
->device
->lines
;
2309 sub
= p
->subs
[SUB_REAL
];
2312 ast_log(LOG_WARNING
, "Unable to find subchannel for music on hold\n");
2315 if (p
->subs
[SUB_THREEWAY
]) {
2317 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
2318 if (p
->subs
[SUB_THREEWAY
]->owner
)
2319 ast_queue_hangup_with_cause(p
->subs
[SUB_THREEWAY
]->owner
, AST_CAUSE_NORMAL_CLEARING
);
2321 ast_log(LOG_WARNING
, "Canceling a threeway channel without owner\n");
2324 /* Start music on hold if appropriate */
2325 if (pte
->device
->moh
)
2326 ast_log(LOG_WARNING
, "Transfer with peer already listening music on hold\n");
2328 if (ast_bridged_channel(p
->subs
[SUB_REAL
]->owner
)) {
2329 ast_moh_start(ast_bridged_channel(p
->subs
[SUB_REAL
]->owner
),
2330 pte
->device
->lines
->musicclass
, NULL
);
2331 pte
->device
->moh
= 1;
2333 ast_log(LOG_WARNING
, "Unable to find peer subchannel for music on hold\n");
2337 /* Silence our channel */
2338 if (!pte
->device
->silence_generator
) {
2339 pte
->device
->silence_generator
=
2340 ast_channel_start_silence_generator(p
->subs
[SUB_REAL
]->owner
);
2341 if (pte
->device
->silence_generator
== NULL
)
2342 ast_log(LOG_WARNING
, "Unable to start a silence generator.\n");
2343 else if (unistimdebug
)
2344 ast_verb(0, "Starting silence generator\n");
2346 handle_dial_page(pte
);
2349 /* From phone to PBX */
2350 static void HandleCallOutgoing(struct unistimsession
*s
)
2352 struct ast_channel
*c
;
2353 struct unistim_subchannel
*sub
;
2355 s
->state
= STATE_CALL
;
2356 sub
= s
->device
->lines
->subs
[SUB_REAL
];
2358 ast_log(LOG_NOTICE
, "No available lines on: %s\n", s
->device
->name
);
2361 if (!sub
->owner
) { /* A call is already in progress ? */
2362 c
= unistim_new(sub
, AST_STATE_DOWN
); /* No, starting a new one */
2364 /* Need to start RTP before calling ast_pbx_run */
2367 send_select_output(s
, s
->device
->output
, s
->device
->volume
, MUTE_OFF
);
2368 send_text(TEXT_LINE0
, TEXT_NORMAL
, s
, "Calling :");
2369 send_text(TEXT_LINE1
, TEXT_NORMAL
, s
, s
->device
->phone_number
);
2370 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "Dialing...");
2371 send_text_status(s
, "Hangup");
2373 if (ast_pthread_create(&t
, NULL
, unistim_ss
, c
)) {
2374 display_last_error("Unable to create switch thread");
2375 ast_queue_hangup_with_cause(c
, AST_CAUSE_SWITCH_CONGESTION
);
2378 ast_log(LOG_WARNING
, "Unable to create channel for %s@%s\n",
2379 sub
->parent
->name
, s
->device
->name
);
2380 } else { /* We already have a call, so we switch in a threeway call */
2382 if (s
->device
->moh
) {
2383 struct unistim_subchannel
*subchannel
;
2384 struct unistim_line
*p
= s
->device
->lines
;
2385 subchannel
= p
->subs
[SUB_REAL
];
2387 if (!subchannel
->owner
) {
2388 ast_log(LOG_WARNING
, "Unable to find subchannel for music on hold\n");
2391 if (p
->subs
[SUB_THREEWAY
]) {
2392 ast_log(LOG_WARNING
,
2393 "Can't transfer while an another transfer is taking place\n");
2396 if (!alloc_sub(p
, SUB_THREEWAY
)) {
2397 ast_log(LOG_WARNING
, "Unable to allocate three-way subchannel\n");
2400 /* Stop the silence generator */
2401 if (s
->device
->silence_generator
) {
2403 ast_verb(0, "Stopping silence generator\n");
2404 ast_channel_stop_silence_generator(subchannel
->owner
,
2405 s
->device
->silence_generator
);
2406 s
->device
->silence_generator
= NULL
;
2409 /* Make new channel */
2410 c
= unistim_new(p
->subs
[SUB_THREEWAY
], AST_STATE_DOWN
);
2412 ast_log(LOG_WARNING
, "Cannot allocate new structure on channel %p\n", p
);
2415 /* Swap things around between the three-way and real call */
2416 swap_subs(p
, SUB_THREEWAY
, SUB_REAL
);
2417 send_select_output(s
, s
->device
->output
, s
->device
->volume
, MUTE_OFF
);
2418 send_text(TEXT_LINE0
, TEXT_NORMAL
, s
, "Calling (pre-transfer)");
2419 send_text(TEXT_LINE1
, TEXT_NORMAL
, s
, s
->device
->phone_number
);
2420 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "Dialing...");
2421 send_text_status(s
, "TransfrCancel");
2423 if (ast_pthread_create(&t
, NULL
, unistim_ss
, p
->subs
[SUB_THREEWAY
]->owner
)) {
2424 ast_log(LOG_WARNING
, "Unable to start simple switch on channel %p\n", p
);
2429 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
2430 p
->subs
[SUB_THREEWAY
]->owner
, p
->subs
[SUB_THREEWAY
]->owner
->name
,
2431 p
->subs
[SUB_THREEWAY
]->subtype
);
2433 ast_debug(1, "Current sub [%s] already has owner\n", sub
->owner
->name
);
2438 /* From PBX to phone */
2439 static void HandleCallIncoming(struct unistimsession
*s
)
2441 struct unistim_subchannel
*sub
;
2442 s
->state
= STATE_CALL
;
2443 s
->device
->missed_call
= 0;
2445 sub
= s
->device
->lines
->subs
[SUB_REAL
];
2447 ast_log(LOG_NOTICE
, "No available lines on: %s\n", s
->device
->name
);
2449 } else if (unistimdebug
)
2450 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub
->parent
->name
,
2454 ast_log(LOG_WARNING
, "Unable to create channel for %s@%s\n", sub
->parent
->name
,
2456 ast_queue_control(sub
->owner
, AST_CONTROL_ANSWER
);
2457 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "is on-line");
2458 send_text_status(s
, "Hangup Transf");
2459 send_start_timer(s
);
2461 if ((s
->device
->output
== OUTPUT_HANDSET
) &&
2462 (s
->device
->receiver_state
== STATE_ONHOOK
))
2463 send_select_output(s
, OUTPUT_SPEAKER
, s
->device
->volume
, MUTE_OFF
);
2465 send_select_output(s
, s
->device
->output
, s
->device
->volume
, MUTE_OFF
);
2466 s
->device
->start_call_timestamp
= time(0);
2467 write_history(s
, 'i', 0);
2471 static int unistim_do_senddigit(struct unistimsession
*pte
, char digit
)
2474 struct ast_frame f
= { 0, };
2475 struct unistim_subchannel
*sub
;
2476 sub
= pte
->device
->lines
->subs
[SUB_REAL
];
2478 ast_log(LOG_WARNING
, "Unable to find subchannel in dtmf senddigit\n");
2482 ast_verb(0, "Send Digit %c\n", digit
);
2485 send_tone(pte
, 941, 1336);
2488 send_tone(pte
, 697, 1209);
2491 send_tone(pte
, 697, 1336);
2494 send_tone(pte
, 697, 1477);
2497 send_tone(pte
, 770, 1209);
2500 send_tone(pte
, 770, 1336);
2503 send_tone(pte
, 770, 1477);
2506 send_tone(pte
, 852, 1209);
2509 send_tone(pte
, 852, 1336);
2512 send_tone(pte
, 852, 1477);
2515 send_tone(pte
, 697, 1633);
2518 send_tone(pte
, 770, 1633);
2521 send_tone(pte
, 852, 1633);
2524 send_tone(pte
, 941, 1633);
2527 send_tone(pte
, 941, 1209);
2530 send_tone(pte
, 941, 1477);
2533 send_tone(pte
, 500, 2000);
2535 usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
2536 send_tone(pte
, 0, 0);
2537 f
.frametype
= AST_FRAME_DTMF
;
2540 ast_queue_frame(sub
->owner
, &f
);
2544 static void key_call(struct unistimsession
*pte
, char keycode
)
2546 if ((keycode
>= KEY_0
) && (keycode
<= KEY_SHARP
)) {
2547 if (keycode
== KEY_SHARP
)
2549 else if (keycode
== KEY_STAR
)
2553 unistim_do_senddigit(pte
, keycode
);
2562 TransferCallStep1(pte
);
2565 if (pte
->device
->output
== OUTPUT_HEADPHONE
)
2566 send_select_output(pte
, OUTPUT_HANDSET
, pte
->device
->volume
, MUTE_OFF
);
2568 send_select_output(pte
, OUTPUT_HEADPHONE
, pte
->device
->volume
, MUTE_OFF
);
2571 if (pte
->device
->output
!= OUTPUT_SPEAKER
)
2572 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
2574 send_select_output(pte
, pte
->device
->previous_output
, pte
->device
->volume
,
2578 if (!pte
->device
->moh
) {
2579 if (pte
->device
->mute
== MUTE_ON
)
2580 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_OFF
);
2582 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_ON
);
2587 struct unistim_subchannel
*sub
;
2588 struct ast_channel
*bridgepeer
= NULL
;
2589 sub
= pte
->device
->lines
->subs
[SUB_REAL
];
2591 ast_log(LOG_WARNING
, "Unable to find subchannel for music on hold\n");
2594 if ((bridgepeer
= ast_bridged_channel(sub
->owner
))) {
2595 if (pte
->device
->moh
) {
2596 ast_moh_stop(bridgepeer
);
2597 pte
->device
->moh
= 0;
2598 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
,
2601 ast_moh_start(bridgepeer
, pte
->device
->lines
->musicclass
, NULL
);
2602 pte
->device
->moh
= 1;
2603 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
,
2607 ast_log(LOG_WARNING
,
2608 "Unable to find peer subchannel for music on hold\n");
2615 static void key_ringing(struct unistimsession
*pte
, char keycode
)
2617 if (keycode
== KEY_FAV0
+ pte
->device
->softkeylinepos
) {
2618 HandleCallIncoming(pte
);
2627 HandleCallIncoming(pte
);
2633 static void Keyfavorite(struct unistimsession
*pte
, char keycode
)
2637 if ((keycode
< KEY_FAV1
) && (keycode
> KEY_FAV5
)) {
2638 ast_log(LOG_WARNING
, "It's not a favorite key\n");
2641 if (keycode
== KEY_FAV0
)
2643 fav
= keycode
- KEY_FAV0
;
2644 if (pte
->device
->softkeyicon
[fav
] == 0)
2646 ast_copy_string(pte
->device
->phone_number
, pte
->device
->softkeynumber
[fav
],
2647 sizeof(pte
->device
->phone_number
));
2648 HandleCallOutgoing(pte
);
2652 static void key_dial_page(struct unistimsession
*pte
, char keycode
)
2654 if (keycode
== KEY_FUNC3
) {
2655 if (pte
->device
->size_phone_number
<= 1)
2656 keycode
= KEY_FUNC4
;
2658 pte
->device
->size_phone_number
-= 2;
2659 keycode
= pte
->device
->phone_number
[pte
->device
->size_phone_number
] + 0x10;
2662 if ((keycode
>= KEY_0
) && (keycode
<= KEY_SHARP
)) {
2663 char tmpbuf
[] = "Number : ...............";
2666 if (pte
->device
->size_phone_number
>= 15)
2668 if (pte
->device
->size_phone_number
== 0)
2669 send_tone(pte
, 0, 0);
2670 while (i
< pte
->device
->size_phone_number
) {
2671 tmpbuf
[i
+ 9] = pte
->device
->phone_number
[i
];
2674 if (keycode
== KEY_SHARP
)
2676 else if (keycode
== KEY_STAR
)
2680 tmpbuf
[i
+ 9] = keycode
;
2681 pte
->device
->phone_number
[i
] = keycode
;
2682 pte
->device
->size_phone_number
++;
2683 pte
->device
->phone_number
[i
+ 1] = 0;
2684 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmpbuf
);
2685 send_blink_cursor(pte
);
2686 send_cursor_pos(pte
, (unsigned char) (TEXT_LINE2
+ 0x0a + i
));
2689 if (keycode
== KEY_FUNC4
) {
2691 pte
->device
->size_phone_number
= 0;
2692 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, "Number : ...............");
2693 send_blink_cursor(pte
);
2694 send_cursor_pos(pte
, TEXT_LINE2
+ 0x09);
2698 if (pte
->device
->call_forward
[0] == -1) {
2699 if (keycode
== KEY_FUNC1
) {
2700 ast_copy_string(pte
->device
->call_forward
, pte
->device
->phone_number
,
2701 sizeof(pte
->device
->call_forward
));
2702 show_main_page(pte
);
2703 } else if ((keycode
== KEY_FUNC2
) || (keycode
== KEY_HANGUP
)) {
2704 pte
->device
->call_forward
[0] = '\0';
2705 show_main_page(pte
);
2711 if (ast_strlen_zero(pte
->device
->redial_number
))
2713 ast_copy_string(pte
->device
->phone_number
, pte
->device
->redial_number
,
2714 sizeof(pte
->device
->phone_number
));
2716 HandleCallOutgoing(pte
);
2719 if (pte
->device
->lines
->subs
[SUB_REAL
]->owner
) {
2720 /* Stop the silence generator */
2721 if (pte
->device
->silence_generator
) {
2723 ast_verb(0, "Stopping silence generator\n");
2724 ast_channel_stop_silence_generator(pte
->device
->lines
->subs
[SUB_REAL
]->
2725 owner
, pte
->device
->silence_generator
);
2726 pte
->device
->silence_generator
= NULL
;
2728 send_tone(pte
, 0, 0);
2729 ast_moh_stop(ast_bridged_channel(pte
->device
->lines
->subs
[SUB_REAL
]->owner
));
2730 pte
->device
->moh
= 0;
2731 pte
->state
= STATE_CALL
;
2732 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Dialing canceled,");
2733 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "switching back to");
2734 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, "previous call.");
2735 send_text_status(pte
, "Hangup Transf");
2737 show_main_page(pte
);
2744 Keyfavorite(pte
, keycode
);
2747 if (pte
->device
->output
== OUTPUT_SPEAKER
) {
2748 if (pte
->device
->receiver_state
== STATE_OFFHOOK
)
2749 send_select_output(pte
, pte
->device
->previous_output
, pte
->device
->volume
,
2752 show_main_page(pte
);
2754 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
2757 if (pte
->device
->output
== OUTPUT_HEADPHONE
) {
2758 if (pte
->device
->receiver_state
== STATE_OFFHOOK
)
2759 send_select_output(pte
, OUTPUT_HANDSET
, pte
->device
->volume
, MUTE_OFF
);
2761 show_main_page(pte
);
2763 send_select_output(pte
, OUTPUT_HEADPHONE
, pte
->device
->volume
, MUTE_OFF
);
2769 #define SELECTCODEC_START_ENTRY_POS 15
2770 #define SELECTCODEC_MAX_LENGTH 2
2771 #define SELECTCODEC_MSG "Codec number : .."
2772 static void HandleSelectCodec(struct unistimsession
*pte
)
2774 char buf
[30], buf2
[5];
2776 pte
->state
= STATE_SELECTCODEC
;
2777 strcpy(buf
, "Using codec ");
2778 sprintf(buf2
, "%d", pte
->device
->codec_number
);
2780 strcat(buf
, " (G711u=0,");
2782 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, buf
);
2783 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "G723=4,G711a=8,G729A=18)");
2784 send_text(TEXT_LINE2
, TEXT_INVERSE
, pte
, SELECTCODEC_MSG
);
2785 send_blink_cursor(pte
);
2786 send_cursor_pos(pte
, TEXT_LINE2
+ SELECTCODEC_START_ENTRY_POS
);
2787 pte
->size_buff_entry
= 0;
2788 send_text_status(pte
, "Select BackSpcErase Cancel");
2792 static void key_select_codec(struct unistimsession
*pte
, char keycode
)
2794 if (keycode
== KEY_FUNC2
) {
2795 if (pte
->size_buff_entry
<= 1)
2796 keycode
= KEY_FUNC3
;
2798 pte
->size_buff_entry
-= 2;
2799 keycode
= pte
->buff_entry
[pte
->size_buff_entry
] + 0x10;
2802 if ((keycode
>= KEY_0
) && (keycode
<= KEY_9
)) {
2803 char tmpbuf
[] = SELECTCODEC_MSG
;
2806 if (pte
->size_buff_entry
>= SELECTCODEC_MAX_LENGTH
)
2809 while (i
< pte
->size_buff_entry
) {
2810 tmpbuf
[i
+ SELECTCODEC_START_ENTRY_POS
] = pte
->buff_entry
[i
];
2813 tmpbuf
[i
+ SELECTCODEC_START_ENTRY_POS
] = keycode
- 0x10;
2814 pte
->buff_entry
[i
] = keycode
- 0x10;
2815 pte
->size_buff_entry
++;
2816 send_text(TEXT_LINE2
, TEXT_INVERSE
, pte
, tmpbuf
);
2817 send_blink_cursor(pte
);
2818 send_cursor_pos(pte
,
2819 (unsigned char) (TEXT_LINE2
+ SELECTCODEC_START_ENTRY_POS
+ 1 + i
));
2825 if (pte
->size_buff_entry
== 1)
2826 pte
->device
->codec_number
= pte
->buff_entry
[0] - 48;
2827 else if (pte
->size_buff_entry
== 2)
2828 pte
->device
->codec_number
=
2829 ((pte
->buff_entry
[0] - 48) * 10) + (pte
->buff_entry
[1] - 48);
2830 show_main_page(pte
);
2833 pte
->size_buff_entry
= 0;
2834 send_text(TEXT_LINE2
, TEXT_INVERSE
, pte
, SELECTCODEC_MSG
);
2835 send_blink_cursor(pte
);
2836 send_cursor_pos(pte
, TEXT_LINE2
+ SELECTCODEC_START_ENTRY_POS
);
2840 show_main_page(pte
);
2846 #define SELECTEXTENSION_START_ENTRY_POS 0
2847 #define SELECTEXTENSION_MAX_LENGTH 10
2848 #define SELECTEXTENSION_MSG ".........."
2849 static void ShowExtensionPage(struct unistimsession
*pte
)
2851 pte
->state
= STATE_EXTENSION
;
2853 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Please enter a Terminal");
2854 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "Number (TN) :");
2855 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, SELECTEXTENSION_MSG
);
2856 send_blink_cursor(pte
);
2857 send_cursor_pos(pte
, TEXT_LINE2
+ SELECTEXTENSION_START_ENTRY_POS
);
2858 send_text_status(pte
, "Enter BackSpcErase");
2859 pte
->size_buff_entry
= 0;
2863 static void key_select_extension(struct unistimsession
*pte
, char keycode
)
2865 if (keycode
== KEY_FUNC2
) {
2866 if (pte
->size_buff_entry
<= 1)
2867 keycode
= KEY_FUNC3
;
2869 pte
->size_buff_entry
-= 2;
2870 keycode
= pte
->buff_entry
[pte
->size_buff_entry
] + 0x10;
2873 if ((keycode
>= KEY_0
) && (keycode
<= KEY_9
)) {
2874 char tmpbuf
[] = SELECTEXTENSION_MSG
;
2877 if (pte
->size_buff_entry
>= SELECTEXTENSION_MAX_LENGTH
)
2880 while (i
< pte
->size_buff_entry
) {
2881 tmpbuf
[i
+ SELECTEXTENSION_START_ENTRY_POS
] = pte
->buff_entry
[i
];
2884 tmpbuf
[i
+ SELECTEXTENSION_START_ENTRY_POS
] = keycode
- 0x10;
2885 pte
->buff_entry
[i
] = keycode
- 0x10;
2886 pte
->size_buff_entry
++;
2887 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmpbuf
);
2888 send_blink_cursor(pte
);
2889 send_cursor_pos(pte
,
2890 (unsigned char) (TEXT_LINE2
+ SELECTEXTENSION_START_ENTRY_POS
+ 1 +
2897 if (pte
->size_buff_entry
< 1)
2899 if (autoprovisioning
== AUTOPROVISIONING_TN
) {
2900 struct unistim_device
*d
;
2902 /* First step : looking for this TN in our device list */
2903 ast_mutex_lock(&devicelock
);
2905 pte
->buff_entry
[pte
->size_buff_entry
] = '\0';
2907 if (d
->id
[0] == 'T') { /* It's a TN device ? */
2908 /* It's the TN we're looking for ? */
2909 if (!strcmp((d
->id
) + 1, pte
->buff_entry
)) {
2912 d
->codec_number
= DEFAULT_CODEC
;
2915 d
->receiver_state
= STATE_ONHOOK
;
2916 strcpy(d
->id
, pte
->macaddr
);
2917 pte
->device
->extension_number
[0] = 'T';
2918 pte
->device
->extension
= EXTENSION_TN
;
2919 ast_copy_string((pte
->device
->extension_number
) + 1,
2920 pte
->buff_entry
, pte
->size_buff_entry
+ 1);
2921 ast_mutex_unlock(&devicelock
);
2922 show_main_page(pte
);
2923 refresh_all_favorite(pte
);
2929 ast_mutex_unlock(&devicelock
);
2930 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Invalid Terminal Number.");
2931 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "Please try again :");
2932 send_cursor_pos(pte
,
2933 (unsigned char) (TEXT_LINE2
+ SELECTEXTENSION_START_ENTRY_POS
+
2934 pte
->size_buff_entry
));
2935 send_blink_cursor(pte
);
2937 ast_copy_string(pte
->device
->extension_number
, pte
->buff_entry
,
2938 pte
->size_buff_entry
+ 1);
2939 if (RegisterExtension(pte
)) {
2940 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Invalid extension.");
2941 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "Please try again :");
2942 send_cursor_pos(pte
,
2943 (unsigned char) (TEXT_LINE2
+
2944 SELECTEXTENSION_START_ENTRY_POS
+
2945 pte
->size_buff_entry
));
2946 send_blink_cursor(pte
);
2948 show_main_page(pte
);
2952 pte
->size_buff_entry
= 0;
2953 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, SELECTEXTENSION_MSG
);
2954 send_blink_cursor(pte
);
2955 send_cursor_pos(pte
, TEXT_LINE2
+ SELECTEXTENSION_START_ENTRY_POS
);
2961 static int ReformatNumber(char *number
)
2963 int pos
= 0, i
= 0, size
= strlen(number
);
2965 for (; i
< size
; i
++) {
2966 if ((number
[i
] >= '0') && (number
[i
] <= '9')) {
2971 number
[pos
] = number
[i
];
2979 static void show_entry_history(struct unistimsession
*pte
, FILE ** f
)
2981 char line
[TEXT_LENGTH_MAX
+ 1], status
[STATUS_LENGTH_MAX
+ 1], func1
[10], func2
[10],
2984 if (fread(line
, TEXT_LENGTH_MAX
, 1, *f
) != 1) {
2985 display_last_error("Can't read history date entry");
2989 line
[sizeof(line
) - 1] = '\0';
2990 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, line
);
2991 if (fread(line
, TEXT_LENGTH_MAX
, 1, *f
) != 1) {
2992 display_last_error("Can't read callerid entry");
2996 line
[sizeof(line
) - 1] = '\0';
2997 ast_copy_string(pte
->device
->lst_cid
, line
, sizeof(pte
->device
->lst_cid
));
2998 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, line
);
2999 if (fread(line
, TEXT_LENGTH_MAX
, 1, *f
) != 1) {
3000 display_last_error("Can't read callername entry");
3004 line
[sizeof(line
) - 1] = '\0';
3005 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, line
);
3008 snprintf(line
, sizeof(line
), "Call %03d/%03d", pte
->buff_entry
[2],
3009 pte
->buff_entry
[1]);
3010 send_texttitle(pte
, line
);
3012 if (pte
->buff_entry
[2] == 1)
3015 strcpy(func1
, "Prvious");
3016 if (pte
->buff_entry
[2] >= pte
->buff_entry
[1])
3019 strcpy(func2
, "Next ");
3020 if (ReformatNumber(pte
->device
->lst_cid
))
3021 strcpy(func3
, "Redial ");
3024 snprintf(status
, sizeof(status
), "%s%s%sCancel", func1
, func2
, func3
);
3025 send_text_status(pte
, status
);
3028 static char OpenHistory(struct unistimsession
*pte
, char way
, FILE ** f
)
3030 char tmp
[AST_CONFIG_MAX_PATH
];
3033 snprintf(tmp
, sizeof(tmp
), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR
,
3034 USTM_LOG_DIR
, pte
->device
->name
, way
);
3035 *f
= fopen(tmp
, "r");
3037 display_last_error("Unable to open history file");
3040 if (fread(&count
, 1, 1, *f
) != 1) {
3041 display_last_error("Unable to read history header - display.");
3045 if (count
> MAX_ENTRY_LOG
) {
3046 ast_log(LOG_WARNING
, "Invalid count in history header of %s (%d max %d)\n", tmp
,
3047 count
, MAX_ENTRY_LOG
);
3054 static void show_history(struct unistimsession
*pte
, char way
)
3061 if (!pte
->device
->callhistory
)
3063 count
= OpenHistory(pte
, way
, &f
);
3066 pte
->buff_entry
[0] = way
;
3067 pte
->buff_entry
[1] = count
;
3068 pte
->buff_entry
[2] = 1;
3069 show_entry_history(pte
, &f
);
3070 pte
->state
= STATE_HISTORY
;
3073 static void show_main_page(struct unistimsession
*pte
)
3075 char tmpbuf
[TEXT_LENGTH_MAX
+ 1];
3078 if ((pte
->device
->extension
== EXTENSION_ASK
) &&
3079 (ast_strlen_zero(pte
->device
->extension_number
))) {
3080 ShowExtensionPage(pte
);
3084 pte
->state
= STATE_MAINPAGE
;
3086 send_tone(pte
, 0, 0);
3087 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_ON_DISCRET
);
3088 pte
->device
->lines
->lastmsgssent
= 0;
3089 send_favorite(pte
->device
->softkeylinepos
, FAV_ICON_ONHOOK_BLACK
, pte
,
3090 pte
->device
->softkeylabel
[pte
->device
->softkeylinepos
]);
3091 if (!ast_strlen_zero(pte
->device
->call_forward
)) {
3092 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Call forwarded to :");
3093 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, pte
->device
->call_forward
);
3094 Sendicon(TEXT_LINE0
, FAV_ICON_REFLECT
+ FAV_BLINK_SLOW
, pte
);
3095 send_text_status(pte
, "Dial Redial NoForwd");
3097 if ((pte
->device
->extension
== EXTENSION_ASK
) ||
3098 (pte
->device
->extension
== EXTENSION_TN
))
3099 send_text_status(pte
, "Dial Redial ForwardUnregis");
3101 send_text_status(pte
, "Dial Redial Forward");
3103 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, pte
->device
->maintext1
);
3104 if (pte
->device
->missed_call
== 0)
3105 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, pte
->device
->maintext0
);
3107 sprintf(tmpbuf
, "%d unanswered call(s)", pte
->device
->missed_call
);
3108 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, tmpbuf
);
3109 Sendicon(TEXT_LINE0
, FAV_ICON_CALL_CENTER
+ FAV_BLINK_SLOW
, pte
);
3112 if (ast_strlen_zero(pte
->device
->maintext2
)) {
3113 strcpy(tmpbuf
, "IP : ");
3114 strcat(tmpbuf
, ast_inet_ntoa(pte
->sin
.sin_addr
));
3115 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmpbuf
);
3117 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, pte
->device
->maintext2
);
3118 send_texttitle(pte
, pte
->device
->titledefault
);
3119 change_favorite_icon(pte
, FAV_ICON_ONHOOK_BLACK
);
3122 static void key_main_page(struct unistimsession
*pte
, char keycode
)
3124 if (pte
->device
->missed_call
) {
3125 Sendicon(TEXT_LINE0
, FAV_ICON_NONE
, pte
);
3126 pte
->device
->missed_call
= 0;
3128 if ((keycode
>= KEY_0
) && (keycode
<= KEY_SHARP
)) {
3129 handle_dial_page(pte
);
3130 key_dial_page(pte
, keycode
);
3135 handle_dial_page(pte
);
3138 if (ast_strlen_zero(pte
->device
->redial_number
))
3140 if ((pte
->device
->output
== OUTPUT_HANDSET
) &&
3141 (pte
->device
->receiver_state
== STATE_ONHOOK
))
3142 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
3144 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_OFF
);
3146 ast_copy_string(pte
->device
->phone_number
, pte
->device
->redial_number
,
3147 sizeof(pte
->device
->phone_number
));
3148 HandleCallOutgoing(pte
);
3151 if (!ast_strlen_zero(pte
->device
->call_forward
)) {
3152 /* Cancel call forwarding */
3153 memmove(pte
->device
->call_forward
+ 1, pte
->device
->call_forward
,
3154 sizeof(pte
->device
->call_forward
));
3155 pte
->device
->call_forward
[0] = '\0';
3156 Sendicon(TEXT_LINE0
, FAV_ICON_NONE
, pte
);
3157 pte
->device
->output
= OUTPUT_HANDSET
; /* Seems to be reseted somewhere */
3158 show_main_page(pte
);
3161 pte
->device
->call_forward
[0] = -1;
3162 handle_dial_page(pte
);
3165 if (pte
->device
->extension
== EXTENSION_ASK
) {
3166 UnregisterExtension(pte
);
3167 pte
->device
->extension_number
[0] = '\0';
3168 ShowExtensionPage(pte
);
3169 } else if (pte
->device
->extension
== EXTENSION_TN
) {
3170 ast_mutex_lock(&devicelock
);
3171 strcpy(pte
->device
->id
, pte
->device
->extension_number
);
3172 pte
->buff_entry
[0] = '\0';
3173 pte
->size_buff_entry
= 0;
3174 pte
->device
->session
= NULL
;
3176 ast_mutex_unlock(&devicelock
);
3177 ShowExtensionPage(pte
);
3181 handle_dial_page(pte
);
3188 if ((pte
->device
->output
== OUTPUT_HANDSET
) &&
3189 (pte
->device
->receiver_state
== STATE_ONHOOK
))
3190 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
3192 send_select_output(pte
, pte
->device
->output
, pte
->device
->volume
, MUTE_OFF
);
3193 Keyfavorite(pte
, keycode
);
3196 HandleSelectCodec(pte
);
3199 send_select_output(pte
, OUTPUT_SPEAKER
, pte
->device
->volume
, MUTE_OFF
);
3200 handle_dial_page(pte
);
3203 send_select_output(pte
, OUTPUT_HEADPHONE
, pte
->device
->volume
, MUTE_OFF
);
3204 handle_dial_page(pte
);
3207 show_history(pte
, 'o');
3210 show_history(pte
, 'i');
3216 static void key_history(struct unistimsession
*pte
, char keycode
)
3226 if (pte
->buff_entry
[2] <= 1)
3228 pte
->buff_entry
[2]--;
3229 count
= OpenHistory(pte
, pte
->buff_entry
[0], &f
);
3232 offset
= ((pte
->buff_entry
[2] - 1) * TEXT_LENGTH_MAX
* 3);
3233 if (fseek(f
, offset
, SEEK_CUR
)) {
3234 display_last_error("Unable to seek history entry.");
3238 show_entry_history(pte
, &f
);
3243 if (pte
->buff_entry
[2] >= pte
->buff_entry
[1])
3245 pte
->buff_entry
[2]++;
3246 count
= OpenHistory(pte
, pte
->buff_entry
[0], &f
);
3249 offset
= ((pte
->buff_entry
[2] - 1) * TEXT_LENGTH_MAX
* 3);
3250 if (fseek(f
, offset
, SEEK_CUR
)) {
3251 display_last_error("Unable to seek history entry.");
3255 show_entry_history(pte
, &f
);
3258 if (!ReformatNumber(pte
->device
->lst_cid
))
3260 ast_copy_string(pte
->device
->redial_number
, pte
->device
->lst_cid
,
3261 sizeof(pte
->device
->redial_number
));
3262 key_main_page(pte
, KEY_FUNC2
);
3266 show_main_page(pte
);
3269 if (pte
->buff_entry
[0] == 'i')
3270 show_history(pte
, 'o');
3272 show_main_page(pte
);
3275 if (pte
->buff_entry
[0] == 'i')
3276 show_main_page(pte
);
3278 show_history(pte
, 'i');
3284 static void init_phone_step2(struct unistimsession
*pte
)
3288 ast_verb(0, "Sending S4\n");
3289 memcpy(buffsend
+ SIZE_HEADER
, packet_send_s4
, sizeof(packet_send_s4
));
3290 send_client(SIZE_HEADER
+ sizeof(packet_send_s4
), buffsend
, pte
);
3291 send_date_time2(pte
);
3292 send_date_time3(pte
);
3294 ast_verb(0, "Sending S7\n");
3295 memcpy(buffsend
+ SIZE_HEADER
, packet_send_S7
, sizeof(packet_send_S7
));
3296 send_client(SIZE_HEADER
+ sizeof(packet_send_S7
), buffsend
, pte
);
3298 ast_verb(0, "Sending Contrast\n");
3299 memcpy(buffsend
+ SIZE_HEADER
, packet_send_Contrast
, sizeof(packet_send_Contrast
));
3300 if (pte
->device
!= NULL
)
3301 buffsend
[9] = pte
->device
->contrast
;
3302 send_client(SIZE_HEADER
+ sizeof(packet_send_Contrast
), buffsend
, pte
);
3305 ast_verb(0, "Sending S9\n");
3306 memcpy(buffsend
+ SIZE_HEADER
, packet_send_s9
, sizeof(packet_send_s9
));
3307 send_client(SIZE_HEADER
+ sizeof(packet_send_s9
), buffsend
, pte
);
3311 ast_verb(0, "Sending S7\n");
3312 memcpy(buffsend
+ SIZE_HEADER
, packet_send_S7
, sizeof(packet_send_S7
));
3313 send_client(SIZE_HEADER
+ sizeof(packet_send_S7
), buffsend
, pte
);
3314 send_led_update(pte
, 0);
3316 if (pte
->state
< STATE_MAINPAGE
) {
3317 if (autoprovisioning
== AUTOPROVISIONING_TN
) {
3318 ShowExtensionPage(pte
);
3324 for (i
= 1; i
< 6; i
++)
3325 send_favorite(i
, 0, pte
, "");
3326 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Sorry, this phone is not");
3327 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, "registred in unistim.cfg");
3328 strcpy(tmp
, "MAC = ");
3329 strcat(tmp
, pte
->macaddr
);
3330 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmp
);
3331 send_text_status(pte
, "");
3332 send_texttitle(pte
, "UNISTIM for*");
3336 show_main_page(pte
);
3337 refresh_all_favorite(pte
);
3339 ast_verb(0, "Sending arrow\n");
3340 memcpy(buffsend
+ SIZE_HEADER
, packet_send_arrow
, sizeof(packet_send_arrow
));
3341 send_client(SIZE_HEADER
+ sizeof(packet_send_arrow
), buffsend
, pte
);
3345 static void process_request(int size
, unsigned char *buf
, struct unistimsession
*pte
)
3349 (buf
+ SIZE_HEADER
, packet_recv_resume_connection_with_server
,
3350 sizeof(packet_recv_resume_connection_with_server
)) == 0) {
3351 rcv_resume_connection_with_server(pte
);
3354 if (memcmp(buf
+ SIZE_HEADER
, packet_recv_firm_version
, sizeof(packet_recv_firm_version
)) ==
3358 ast_verb(0, "Got the firmware version : '%s'\n", buf
+ 13);
3359 init_phone_step2(pte
);
3362 if (memcmp(buf
+ SIZE_HEADER
, packet_recv_mac_addr
, sizeof(packet_recv_mac_addr
)) == 0) {
3363 rcv_mac_addr(pte
, buf
);
3366 if (memcmp(buf
+ SIZE_HEADER
, packet_recv_r2
, sizeof(packet_recv_r2
)) == 0) {
3368 ast_verb(0, "R2 received\n");
3372 if (pte
->state
< STATE_MAINPAGE
) {
3374 ast_verb(0, "Request not authorized in this state\n");
3377 if (!memcmp(buf
+ SIZE_HEADER
, packet_recv_pressed_key
, sizeof(packet_recv_pressed_key
))) {
3378 char keycode
= buf
[13];
3381 ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode
,
3384 switch (pte
->state
) {
3387 ast_verb(0, "No keys allowed in the init state\n");
3389 case STATE_AUTHDENY
:
3391 ast_verb(0, "No keys allowed in authdeny state\n");
3393 case STATE_MAINPAGE
:
3394 key_main_page(pte
, keycode
);
3396 case STATE_DIALPAGE
:
3397 key_dial_page(pte
, keycode
);
3400 key_ringing(pte
, keycode
);
3403 key_call(pte
, keycode
);
3405 case STATE_EXTENSION
:
3406 key_select_extension(pte
, keycode
);
3408 case STATE_SELECTCODEC
:
3409 key_select_codec(pte
, keycode
);
3412 key_history(pte
, keycode
);
3415 ast_log(LOG_WARNING
, "Key : Unknown state\n");
3419 if (memcmp(buf
+ SIZE_HEADER
, packet_recv_pick_up
, sizeof(packet_recv_pick_up
)) == 0) {
3421 ast_verb(0, "Handset off hook\n");
3422 if (!pte
->device
) /* We are not yet registred (asking for a TN in AUTOPROVISIONING_TN) */
3424 pte
->device
->receiver_state
= STATE_OFFHOOK
;
3425 if (pte
->device
->output
== OUTPUT_HEADPHONE
)
3426 send_select_output(pte
, OUTPUT_HEADPHONE
, pte
->device
->volume
, MUTE_OFF
);
3428 send_select_output(pte
, OUTPUT_HANDSET
, pte
->device
->volume
, MUTE_OFF
);
3429 if (pte
->state
== STATE_RINGING
)
3430 HandleCallIncoming(pte
);
3431 else if ((pte
->state
== STATE_DIALPAGE
) || (pte
->state
== STATE_CALL
))
3432 send_select_output(pte
, OUTPUT_HANDSET
, pte
->device
->volume
, MUTE_OFF
);
3433 else if (pte
->state
== STATE_EXTENSION
) /* We must have a TN before calling */
3436 send_select_output(pte
, OUTPUT_HANDSET
, pte
->device
->volume
, MUTE_OFF
);
3437 handle_dial_page(pte
);
3441 if (memcmp(buf
+ SIZE_HEADER
, packet_recv_hangup
, sizeof(packet_recv_hangup
)) == 0) {
3443 ast_verb(0, "Handset on hook\n");
3446 pte
->device
->receiver_state
= STATE_ONHOOK
;
3447 if (pte
->state
== STATE_CALL
)
3449 else if (pte
->device
->lines
->subs
[SUB_REAL
]->owner
)
3451 else if (pte
->state
== STATE_EXTENSION
)
3454 show_main_page(pte
);
3457 strcpy(tmpbuf
, ast_inet_ntoa(pte
->sin
.sin_addr
));
3458 strcat(tmpbuf
, " Unknown request packet\n");
3460 ast_debug(1, "%s", tmpbuf
);
3464 static void parsing(int size
, unsigned char *buf
, struct unistimsession
*pte
,
3465 struct sockaddr_in
*addr_from
)
3467 unsigned short *sbuf
= (unsigned short *) buf
;
3471 strcpy(tmpbuf
, ast_inet_ntoa(addr_from
->sin_addr
));
3475 ast_log(LOG_WARNING
, "%s Read error\n", tmpbuf
);
3477 ast_log(LOG_NOTICE
, "%s Packet too short - ignoring\n", tmpbuf
);
3481 if (sbuf
[0] == 0xffff) { /* Starting with 0xffff ? *//* Yes, discovery packet ? */
3482 if (size
!= sizeof(packet_rcv_discovery
)) {
3483 ast_log(LOG_NOTICE
, "%s Invalid size of a discovery packet\n", tmpbuf
);
3485 if (memcmp(buf
, packet_rcv_discovery
, sizeof(packet_rcv_discovery
)) == 0) {
3487 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
3488 if (pte
) { /* A session was already active for this IP ? */
3489 if (pte
->state
== STATE_INIT
) { /* Yes, but it's a dupe */
3491 ast_verb(1, "Duplicated Discovery packet\n");
3492 send_raw_client(sizeof(packet_send_discovery_ack
),
3493 packet_send_discovery_ack
, addr_from
, &pte
->sout
);
3494 pte
->seq_phone
= (short) 0x0000; /* reset sequence number */
3495 } else { /* No, probably a reboot, phone side */
3496 close_client(pte
); /* Cleanup the previous session */
3497 if (create_client(addr_from
))
3498 send_raw_client(sizeof(packet_send_discovery_ack
),
3499 packet_send_discovery_ack
, addr_from
, &pte
->sout
);
3502 /* Creating new entry in our phone list */
3503 if ((pte
= create_client(addr_from
)))
3504 send_raw_client(sizeof(packet_send_discovery_ack
),
3505 packet_send_discovery_ack
, addr_from
, &pte
->sout
);
3509 ast_log(LOG_NOTICE
, "%s Invalid discovery packet\n", tmpbuf
);
3515 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n",
3520 if (sbuf
[0] != 0) { /* Starting with something else than 0x0000 ? */
3521 ast_log(LOG_NOTICE
, "Unknown packet received - ignoring\n");
3525 ast_log(LOG_NOTICE
, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf
,
3529 seq
= ntohs(sbuf
[1]);
3531 ast_mutex_lock(&pte
->lock
);
3533 ast_verb(6, "ACK received for packet #0x%.4x\n", seq
);
3534 pte
->nb_retransmit
= 0;
3536 if ((pte
->last_seq_ack
) + 1 == seq
) {
3537 pte
->last_seq_ack
++;
3538 check_send_queue(pte
);
3539 ast_mutex_unlock(&pte
->lock
);
3542 if (pte
->last_seq_ack
> seq
) {
3543 if (pte
->last_seq_ack
== 0xffff) {
3544 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
3545 pte
->last_seq_ack
= 0;
3548 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
3549 tmpbuf
, seq
, pte
->last_seq_ack
);
3550 ast_mutex_unlock(&pte
->lock
);
3553 if (pte
->seq_server
< seq
) {
3555 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
3556 tmpbuf
, pte
->seq_server
);
3557 ast_mutex_unlock(&pte
->lock
);
3561 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
3562 tmpbuf
, seq
, pte
->last_seq_ack
);
3563 pte
->last_seq_ack
= seq
;
3564 check_send_queue(pte
);
3565 ast_mutex_unlock(&pte
->lock
);
3570 ast_verb(0, "Request received\n");
3571 if (pte
->seq_phone
== seq
) {
3575 send_raw_client(SIZE_HEADER
, buf
, addr_from
, &pte
->sout
);
3578 process_request(size
, buf
, pte
);
3581 if (pte
->seq_phone
> seq
) {
3583 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
3584 tmpbuf
, seq
, pte
->seq_phone
);
3585 /* BUG ? pte->device->seq_phone = seq; */
3589 send_raw_client(SIZE_HEADER
, buf
, addr_from
, &pte
->sout
);
3593 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
3594 tmpbuf
, seq
, pte
->seq_phone
);
3598 ast_log(LOG_NOTICE
, "%s Retransmit request for packet #0x%.4x\n", tmpbuf
, seq
);
3599 if (pte
->last_seq_ack
> seq
) {
3601 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
3602 tmpbuf
, pte
->last_seq_ack
);
3605 if (pte
->seq_server
< seq
) {
3607 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
3608 tmpbuf
, pte
->seq_server
);
3611 send_retransmit(pte
);
3614 ast_log(LOG_NOTICE
, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
3619 static struct unistimsession
*channel_to_session(struct ast_channel
*ast
)
3621 struct unistim_subchannel
*sub
;
3623 ast_log(LOG_WARNING
, "Unistim callback function called with a null channel\n");
3626 if (!ast
->tech_pvt
) {
3627 ast_log(LOG_WARNING
, "Unistim callback function called without a tech_pvt\n");
3630 sub
= ast
->tech_pvt
;
3633 ast_log(LOG_WARNING
, "Unistim callback function called without a line\n");
3636 if (!sub
->parent
->parent
) {
3637 ast_log(LOG_WARNING
, "Unistim callback function called without a device\n");
3640 if (!sub
->parent
->parent
->session
) {
3641 ast_log(LOG_WARNING
, "Unistim callback function called without a session\n");
3644 return sub
->parent
->parent
->session
;
3647 /*--- unistim_call: Initiate UNISTIM call from PBX ---*/
3648 /* used from the dial() application */
3649 static int unistim_call(struct ast_channel
*ast
, char *dest
, int timeout
)
3652 struct unistim_subchannel
*sub
;
3653 struct unistimsession
*session
;
3655 session
= channel_to_session(ast
);
3657 ast_log(LOG_ERROR
, "Device not registered, cannot call %s\n", dest
);
3661 sub
= ast
->tech_pvt
;
3662 if ((ast
->_state
!= AST_STATE_DOWN
) && (ast
->_state
!= AST_STATE_RESERVED
)) {
3663 ast_log(LOG_WARNING
, "unistim_call called on %s, neither down nor reserved\n",
3669 ast_verb(3, "unistim_call(%s)\n", ast
->name
);
3671 session
->state
= STATE_RINGING
;
3672 Sendicon(TEXT_LINE0
, FAV_ICON_NONE
, session
);
3675 if (sub
->owner
->cid
.cid_num
) {
3676 send_text(TEXT_LINE1
, TEXT_NORMAL
, session
, sub
->owner
->cid
.cid_num
);
3677 change_callerid(session
, 0, sub
->owner
->cid
.cid_num
);
3679 send_text(TEXT_LINE1
, TEXT_NORMAL
, session
, DEFAULTCALLERID
);
3680 change_callerid(session
, 0, DEFAULTCALLERID
);
3682 if (sub
->owner
->cid
.cid_name
) {
3683 send_text(TEXT_LINE0
, TEXT_NORMAL
, session
, sub
->owner
->cid
.cid_name
);
3684 change_callerid(session
, 1, sub
->owner
->cid
.cid_name
);
3686 send_text(TEXT_LINE0
, TEXT_NORMAL
, session
, DEFAULTCALLERNAME
);
3687 change_callerid(session
, 1, DEFAULTCALLERNAME
);
3690 send_text(TEXT_LINE2
, TEXT_NORMAL
, session
, "is calling you.");
3691 send_text_status(session
, "Accept Ignore");
3693 if (sub
->ringstyle
== -1)
3694 send_ring(session
, session
->device
->ringvolume
, session
->device
->ringstyle
);
3696 if (sub
->ringvolume
== -1)
3697 send_ring(session
, session
->device
->ringvolume
, sub
->ringstyle
);
3699 send_ring(session
, sub
->ringvolume
, sub
->ringstyle
);
3701 change_favorite_icon(session
, FAV_ICON_SPEAKER_ONHOOK_BLACK
+ FAV_BLINK_FAST
);
3703 ast_setstate(ast
, AST_STATE_RINGING
);
3704 ast_queue_control(ast
, AST_CONTROL_RINGING
);
3708 /*--- unistim_hangup: Hangup UNISTIM call */
3709 static int unistim_hangup(struct ast_channel
*ast
)
3711 struct unistim_subchannel
*sub
;
3712 struct unistim_line
*l
;
3713 struct unistimsession
*s
;
3715 s
= channel_to_session(ast
);
3716 sub
= ast
->tech_pvt
;
3718 ast_debug(1, "Asked to hangup channel not connected\n");
3719 ast_mutex_lock(&sub
->lock
);
3721 ast
->tech_pvt
= NULL
;
3722 sub
->alreadygone
= 0;
3723 ast_mutex_unlock(&sub
->lock
);
3726 ast_verb(0, "Destroying RTP session\n");
3727 ast_rtp_destroy(sub
->rtp
);
3734 ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast
->name
, l
->name
, l
->parent
->name
);
3736 if ((l
->subs
[SUB_THREEWAY
]) && (sub
->subtype
== SUB_REAL
)) {
3738 ast_verb(0, "Real call disconnected while talking to threeway\n");
3740 ast
->tech_pvt
= NULL
;
3743 if ((l
->subs
[SUB_REAL
]->owner
) && (sub
->subtype
== SUB_THREEWAY
) &&
3744 (sub
->alreadygone
== 0)) {
3746 ast_verb(0, "threeway call disconnected, switching to real call\n");
3747 send_text(TEXT_LINE0
, TEXT_NORMAL
, s
, "Three way call canceled,");
3748 send_text(TEXT_LINE1
, TEXT_NORMAL
, s
, "switching back to");
3749 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "previous call.");
3750 send_text_status(s
, "Hangup Transf");
3751 ast_moh_stop(ast_bridged_channel(l
->subs
[SUB_REAL
]->owner
));
3752 swap_subs(l
, SUB_THREEWAY
, SUB_REAL
);
3754 ast_mutex_lock(&sub
->lock
);
3756 ast
->tech_pvt
= NULL
;
3757 ast_mutex_unlock(&sub
->lock
);
3758 unalloc_sub(l
, SUB_THREEWAY
);
3761 ast_mutex_lock(&sub
->lock
);
3763 ast
->tech_pvt
= NULL
;
3764 sub
->alreadygone
= 0;
3765 ast_mutex_unlock(&sub
->lock
);
3768 ast_verb(0, "Asked to hangup channel not connected (no session)\n");
3771 ast_verb(0, "Destroying RTP session\n");
3772 ast_rtp_destroy(sub
->rtp
);
3777 if (sub
->subtype
== SUB_REAL
) {
3778 /* Stop the silence generator */
3779 if (s
->device
->silence_generator
) {
3781 ast_verb(0, "Stopping silence generator\n");
3783 ast_channel_stop_silence_generator(sub
->owner
,
3784 s
->device
->silence_generator
);
3786 ast_log(LOG_WARNING
,
3787 "Trying to stop silence generator on a null channel !\n");
3788 s
->device
->silence_generator
= NULL
;
3796 ast_verb(0, "Destroying RTP session\n");
3797 ast_rtp_destroy(sub
->rtp
);
3799 } else if (unistimdebug
)
3800 ast_verb(0, "No RTP session to destroy\n");
3801 if (l
->subs
[SUB_THREEWAY
]) {
3803 ast_verb(0, "Cleaning other subchannels\n");
3804 unalloc_sub(l
, SUB_THREEWAY
);
3806 if (s
->state
== STATE_RINGING
)
3808 else if (s
->state
== STATE_CALL
)
3814 /*--- unistim_answer: Answer UNISTIM call */
3815 static int unistim_answer(struct ast_channel
*ast
)
3818 struct unistim_subchannel
*sub
;
3819 struct unistim_line
*l
;
3820 struct unistimsession
*s
;
3822 s
= channel_to_session(ast
);
3824 ast_log(LOG_WARNING
, "unistim_answer on a disconnected device ?\n");
3827 sub
= ast
->tech_pvt
;
3830 if ((!sub
->rtp
) && (!l
->subs
[SUB_THREEWAY
]))
3833 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast
->name
, l
->name
,
3834 l
->parent
->name
, sub
->subtype
);
3835 send_text(TEXT_LINE2
, TEXT_NORMAL
, l
->parent
->session
, "is now on-line");
3836 if (l
->subs
[SUB_THREEWAY
])
3837 send_text_status(l
->parent
->session
, "Transf Cancel");
3839 send_text_status(l
->parent
->session
, "Hangup Transf");
3840 send_start_timer(l
->parent
->session
);
3841 if (ast
->_state
!= AST_STATE_UP
)
3842 ast_setstate(ast
, AST_STATE_UP
);
3846 /*--- unistimsock_read: Read data from UNISTIM socket ---*/
3847 /* Successful messages is connected to UNISTIM call and forwarded to parsing() */
3848 static int unistimsock_read(int *id
, int fd
, short events
, void *ignore
)
3850 struct sockaddr_in addr_from
= { 0, };
3851 struct unistimsession
*cur
= NULL
;
3854 int dw_num_bytes_rcvd
;
3856 int dw_num_bytes_rcvdd
;
3857 char iabuf
[INET_ADDRSTRLEN
];
3861 recvfrom(unistimsock
, buff
, SIZE_PAGE
, 0, (struct sockaddr
*) &addr_from
,
3863 if (dw_num_bytes_rcvd
== -1) {
3864 if (errno
== EAGAIN
)
3865 ast_log(LOG_NOTICE
, "UNISTIM: Received packet with bad UDP checksum\n");
3866 else if (errno
!= ECONNREFUSED
)
3867 ast_log(LOG_WARNING
, "Recv error %d (%s)\n", errno
, strerror(errno
));
3871 /* Looking in the phone list if we already have a registration for him */
3872 ast_mutex_lock(&sessionlock
);
3875 if (cur
->sin
.sin_addr
.s_addr
== addr_from
.sin_addr
.s_addr
) {
3882 ast_mutex_unlock(&sessionlock
);
3886 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
3887 dw_num_bytes_rcvd
, ast_inet_ntoa(addr_from
.sin_addr
), tmp
);
3888 for (dw_num_bytes_rcvdd
= 0; dw_num_bytes_rcvdd
< dw_num_bytes_rcvd
;
3889 dw_num_bytes_rcvdd
++)
3890 ast_verb(0, "%.2x ", (unsigned char) buff
[dw_num_bytes_rcvdd
]);
3891 ast_verb(0, "\n******************************************\n");
3896 ast_verb(0, "Received a packet from an unknown source\n");
3897 parsing(dw_num_bytes_rcvd
, buff
, NULL
, (struct sockaddr_in
*) &addr_from
);
3900 parsing(dw_num_bytes_rcvd
, buff
, cur
, (struct sockaddr_in
*) &addr_from
);
3905 static struct ast_frame
*unistim_rtp_read(const struct ast_channel
*ast
,
3906 const struct unistim_subchannel
*sub
)
3908 /* Retrieve audio/etc from channel. Assumes sub->lock is already held. */
3909 struct ast_frame
*f
;
3912 ast_log(LOG_WARNING
, "Channel NULL while reading\n");
3913 return &ast_null_frame
;
3917 ast_log(LOG_WARNING
, "RTP handle NULL while reading on subchannel %d\n",
3919 return &ast_null_frame
;
3922 switch (ast
->fdno
) {
3924 f
= ast_rtp_read(sub
->rtp
); /* RTP Audio */
3927 f
= ast_rtcp_read(sub
->rtp
); /* RTCP Control Channel */
3930 f
= &ast_null_frame
;
3934 /* We already hold the channel lock */
3935 if (f
->frametype
== AST_FRAME_VOICE
) {
3936 if (f
->subclass
!= sub
->owner
->nativeformats
) {
3938 "Oooh, format changed from %s (%d) to %s (%d)\n",
3939 ast_getformatname(sub
->owner
->nativeformats
),
3940 sub
->owner
->nativeformats
, ast_getformatname(f
->subclass
),
3943 sub
->owner
->nativeformats
= f
->subclass
;
3944 ast_set_read_format(sub
->owner
, sub
->owner
->readformat
);
3945 ast_set_write_format(sub
->owner
, sub
->owner
->writeformat
);
3953 static struct ast_frame
*unistim_read(struct ast_channel
*ast
)
3955 struct ast_frame
*fr
;
3956 struct unistim_subchannel
*sub
= ast
->tech_pvt
;
3958 ast_mutex_lock(&sub
->lock
);
3959 fr
= unistim_rtp_read(ast
, sub
);
3960 ast_mutex_unlock(&sub
->lock
);
3965 static int unistim_write(struct ast_channel
*ast
, struct ast_frame
*frame
)
3967 struct unistim_subchannel
*sub
= ast
->tech_pvt
;
3970 if (frame
->frametype
!= AST_FRAME_VOICE
) {
3971 if (frame
->frametype
== AST_FRAME_IMAGE
)
3974 ast_log(LOG_WARNING
, "Can't send %d type frames with unistim_write\n",
3979 if (!(frame
->subclass
& ast
->nativeformats
)) {
3980 ast_log(LOG_WARNING
,
3981 "Asked to transmit frame type %s (%d), while native formats is %s (%d) (read/write = %s (%d)/%d)\n",
3982 ast_getformatname(frame
->subclass
), frame
->subclass
,
3983 ast_getformatname(ast
->nativeformats
), ast
->nativeformats
,
3984 ast_getformatname(ast
->readformat
), ast
->readformat
,
3991 ast_mutex_lock(&sub
->lock
);
3993 res
= ast_rtp_write(sub
->rtp
, frame
);
3995 ast_mutex_unlock(&sub
->lock
);
4001 static int unistim_fixup(struct ast_channel
*oldchan
, struct ast_channel
*newchan
)
4003 struct unistim_subchannel
*p
= newchan
->tech_pvt
;
4004 struct unistim_line
*l
= p
->parent
;
4006 ast_mutex_lock(&p
->lock
);
4008 ast_debug(1, "New owner for channel USTM/%s@%s-%d is %s\n", l
->name
,
4009 l
->parent
->name
, p
->subtype
, newchan
->name
);
4011 if (p
->owner
!= oldchan
) {
4012 ast_log(LOG_WARNING
, "old channel wasn't %s (%p) but was %s (%p)\n",
4013 oldchan
->name
, oldchan
, p
->owner
->name
, p
->owner
);
4019 ast_mutex_unlock(&p
->lock
);
4025 static char *control2str(int ind
)
4028 case AST_CONTROL_HANGUP
:
4029 return "Other end has hungup";
4030 case AST_CONTROL_RING
:
4031 return "Local ring";
4032 case AST_CONTROL_RINGING
:
4033 return "Remote end is ringing";
4034 case AST_CONTROL_ANSWER
:
4035 return "Remote end has answered";
4036 case AST_CONTROL_BUSY
:
4037 return "Remote end is busy";
4038 case AST_CONTROL_TAKEOFFHOOK
:
4039 return "Make it go off hook";
4040 case AST_CONTROL_OFFHOOK
:
4041 return "Line is off hook";
4042 case AST_CONTROL_CONGESTION
:
4043 return "Congestion (circuits busy)";
4044 case AST_CONTROL_FLASH
:
4045 return "Flash hook";
4046 case AST_CONTROL_WINK
:
4048 case AST_CONTROL_OPTION
:
4049 return "Set a low-level option";
4050 case AST_CONTROL_RADIO_KEY
:
4052 case AST_CONTROL_RADIO_UNKEY
:
4053 return "Un-Key Radio";
4060 static void in_band_indication(struct ast_channel
*ast
, const struct ind_tone_zone
*tz
,
4061 const char *indication
)
4063 const struct ind_tone_zone_sound
*ts
= NULL
;
4065 ts
= ast_get_indication_tone(tz
, indication
);
4067 if (ts
&& ts
->data
[0])
4068 ast_playtones_start(ast
, 0, ts
->data
, 1);
4070 ast_log(LOG_WARNING
, "Unable to get indication tone for %s\n", indication
);
4073 static int unistim_indicate(struct ast_channel
*ast
, int ind
, const void *data
,
4076 struct unistim_subchannel
*sub
;
4077 struct unistim_line
*l
;
4078 struct unistimsession
*s
;
4081 ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
4082 control2str(ind
), ast
->name
);
4085 s
= channel_to_session(ast
);
4089 sub
= ast
->tech_pvt
;
4093 case AST_CONTROL_RINGING
:
4094 if (ast
->_state
!= AST_STATE_UP
) {
4095 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "Ringing...");
4096 in_band_indication(ast
, l
->parent
->tz
, "ring");
4097 s
->device
->missed_call
= -1;
4101 case AST_CONTROL_BUSY
:
4102 if (ast
->_state
!= AST_STATE_UP
) {
4103 sub
->alreadygone
= 1;
4104 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "Busy");
4105 in_band_indication(ast
, l
->parent
->tz
, "busy");
4106 s
->device
->missed_call
= -1;
4110 case AST_CONTROL_CONGESTION
:
4111 if (ast
->_state
!= AST_STATE_UP
) {
4112 sub
->alreadygone
= 1;
4113 send_text(TEXT_LINE2
, TEXT_NORMAL
, s
, "Congestion");
4114 in_band_indication(ast
, l
->parent
->tz
, "congestion");
4115 s
->device
->missed_call
= -1;
4119 case AST_CONTROL_HOLD
:
4120 ast_moh_start(ast
, data
, NULL
);
4122 case AST_CONTROL_UNHOLD
:
4125 case AST_CONTROL_PROGRESS
:
4126 case AST_CONTROL_SRCUPDATE
:
4129 ast_playtones_stop(ast
);
4130 s
->device
->missed_call
= 0;
4132 case AST_CONTROL_PROCEEDING
:
4135 ast_log(LOG_WARNING
, "Don't know how to indicate condition %d\n", ind
);
4142 static struct unistim_subchannel
*find_subchannel_by_name(const char *dest
)
4144 struct unistim_line
*l
;
4145 struct unistim_device
*d
;
4150 ast_copy_string(line
, dest
, sizeof(line
));
4151 at
= strchr(line
, '@');
4153 ast_log(LOG_NOTICE
, "Device '%s' has no @ (at) sign!\n", dest
);
4159 ast_mutex_lock(&devicelock
);
4161 at
= strchr(device
, '/'); /* Extra options ? */
4165 if (!strcasecmp(d
->name
, device
)) {
4167 ast_verb(0, "Found device: %s\n", d
->name
);
4168 /* Found the device */
4171 /* Search for the right line */
4172 if (!strcasecmp(l
->name
, line
)) {
4173 l
->subs
[SUB_REAL
]->ringvolume
= -1;
4174 l
->subs
[SUB_REAL
]->ringstyle
= -1;
4175 if (at
) { /* Other options ? */
4176 at
++; /* Skip slash */
4177 if (*at
== 'r') { /* distinctive ring */
4179 if ((*at
< '0') || (*at
> '7')) /* ring style */
4180 ast_log(LOG_WARNING
, "Invalid ring selection (%s)", at
);
4182 char ring_volume
= -1;
4183 char ring_style
= *at
- '0';
4185 if ((*at
>= '0') && (*at
<= '3')) /* ring volume */
4186 ring_volume
= *at
- '0';
4188 ast_verb(0, "Distinctive ring : style #%d volume %d\n",
4189 ring_style
, ring_volume
);
4190 l
->subs
[SUB_REAL
]->ringvolume
= ring_volume
;
4191 l
->subs
[SUB_REAL
]->ringstyle
= ring_style
;
4195 ast_mutex_unlock(&devicelock
);
4196 return l
->subs
[SUB_REAL
];
4203 /* Device not found */
4204 ast_mutex_unlock(&devicelock
);
4209 static int unistim_senddigit_begin(struct ast_channel
*ast
, char digit
)
4211 struct unistimsession
*pte
= channel_to_session(ast
);
4216 return unistim_do_senddigit(pte
, digit
);
4219 static int unistim_senddigit_end(struct ast_channel
*ast
, char digit
, unsigned int duration
)
4221 struct unistimsession
*pte
= channel_to_session(ast
);
4222 struct ast_frame f
= { 0, };
4223 struct unistim_subchannel
*sub
;
4225 sub
= pte
->device
->lines
->subs
[SUB_REAL
];
4228 ast_log(LOG_WARNING
, "Unable to find subchannel in dtmf senddigiti_end\n");
4233 ast_verb(0, "Send Digit off %c\n", digit
);
4238 send_tone(pte
, 0, 0);
4239 f
.frametype
= AST_FRAME_DTMF
;
4242 ast_queue_frame(sub
->owner
, &f
);
4247 /*--- unistim_sendtext: Display a text on the phone screen ---*/
4248 /* Called from PBX core text message functions */
4249 static int unistim_sendtext(struct ast_channel
*ast
, const char *text
)
4251 struct unistimsession
*pte
= channel_to_session(ast
);
4253 char tmp
[TEXT_LENGTH_MAX
+ 1];
4256 ast_verb(0, "unistim_sendtext called\n");
4259 ast_log(LOG_WARNING
, "unistim_sendtext called with a null text\n");
4263 size
= strlen(text
);
4264 if (text
[0] == '@') {
4265 int pos
= 0, i
= 1, tok
= 0, sz
= 0;
4271 memset(label
, 0, 11);
4272 memset(number
, 0, 16);
4277 if ((cur
< '0') && (cur
> '5')) {
4278 ast_log(LOG_WARNING
,
4279 "sendtext failed : position must be a number beetween 0 and 5\n");
4287 ast_log(LOG_WARNING
, "sendtext failed : invalid position\n");
4293 if ((cur
< '3') && (cur
> '6')) {
4294 ast_log(LOG_WARNING
,
4295 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
4298 icon
= (cur
- '0') * 10;
4302 if ((cur
< '0') && (cur
> '9')) {
4303 ast_log(LOG_WARNING
,
4304 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
4307 icon
+= (cur
- '0');
4312 ast_log(LOG_WARNING
,
4313 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
4331 ast_log(LOG_WARNING
,
4332 "sendtext failed : extension too long = %d (15 car max)\n",
4342 ast_log(LOG_WARNING
, "sendtext failed : incomplet command\n");
4346 ast_log(LOG_WARNING
, "sendtext failed : no device ?\n");
4349 strcpy(pte
->device
->softkeylabel
[pos
], label
);
4350 strcpy(pte
->device
->softkeynumber
[pos
], number
);
4351 pte
->device
->softkeyicon
[pos
] = icon
;
4352 send_favorite(pos
, icon
, pte
, label
);
4356 if (size
<= TEXT_LENGTH_MAX
* 2) {
4357 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, "Message :");
4358 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, text
);
4359 if (size
<= TEXT_LENGTH_MAX
) {
4360 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, "");
4363 memcpy(tmp
, text
+ TEXT_LENGTH_MAX
, TEXT_LENGTH_MAX
);
4364 tmp
[sizeof(tmp
) - 1] = '\0';
4365 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmp
);
4368 send_text(TEXT_LINE0
, TEXT_NORMAL
, pte
, text
);
4369 memcpy(tmp
, text
+ TEXT_LENGTH_MAX
, TEXT_LENGTH_MAX
);
4370 tmp
[sizeof(tmp
) - 1] = '\0';
4371 send_text(TEXT_LINE1
, TEXT_NORMAL
, pte
, tmp
);
4372 memcpy(tmp
, text
+ TEXT_LENGTH_MAX
* 2, TEXT_LENGTH_MAX
);
4373 tmp
[sizeof(tmp
) - 1] = '\0';
4374 send_text(TEXT_LINE2
, TEXT_NORMAL
, pte
, tmp
);
4378 /*--- unistim_send_mwi_to_peer: Send message waiting indication ---*/
4379 static int unistim_send_mwi_to_peer(struct unistimsession
*s
, unsigned int tick
)
4381 struct ast_event
*event
;
4383 char *mailbox
, *context
;
4384 struct unistim_line
*peer
= s
->device
->lines
;
4386 context
= mailbox
= ast_strdupa(peer
->mailbox
);
4387 strsep(&context
, "@");
4388 if (ast_strlen_zero(context
))
4389 context
= "default";
4391 event
= ast_event_get_cached(AST_EVENT_MWI
,
4392 AST_EVENT_IE_MAILBOX
, AST_EVENT_IE_PLTYPE_STR
, mailbox
,
4393 AST_EVENT_IE_CONTEXT
, AST_EVENT_IE_PLTYPE_STR
, context
,
4394 AST_EVENT_IE_NEWMSGS
, AST_EVENT_IE_PLTYPE_EXISTS
,
4398 new = ast_event_get_ie_uint(event
, AST_EVENT_IE_NEWMSGS
);
4399 ast_event_destroy(event
);
4400 } else { /* Fall back on checking the mailbox directly */
4401 new = ast_app_has_voicemail(peer
->mailbox
, "INBOX");
4404 peer
->nextmsgcheck
= tick
+ TIMER_MWI
;
4406 /* Return now if it's the same thing we told them last time */
4407 if (new == peer
->lastmsgssent
) {
4411 peer
->lastmsgssent
= new;
4413 send_led_update(s
, 0);
4415 send_led_update(s
, 1);
4421 /*--- unistim_new: Initiate a call in the UNISTIM channel */
4422 /* called from unistim_request (calls from the pbx ) */
4423 static struct ast_channel
*unistim_new(struct unistim_subchannel
*sub
, int state
)
4425 struct ast_channel
*tmp
;
4426 struct unistim_line
*l
;
4430 ast_log(LOG_WARNING
, "subchannel null in unistim_new\n");
4434 ast_log(LOG_WARNING
, "no line for subchannel %p\n", sub
);
4438 tmp
= ast_channel_alloc(1, state
, l
->cid_num
, NULL
, l
->accountcode
, l
->exten
,
4439 l
->context
, l
->amaflags
, "%s-%08x", l
->fullname
, (int) (long) sub
);
4441 ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub
->subtype
, sub
, tmp
);
4443 ast_log(LOG_WARNING
, "Unable to allocate channel structure\n");
4447 tmp
->nativeformats
= l
->capability
;
4448 if (!tmp
->nativeformats
)
4449 tmp
->nativeformats
= CAPABILITY
;
4450 fmt
= ast_best_codec(tmp
->nativeformats
);
4452 ast_verb(0, "Best codec = %d from nativeformats %d (line cap=%d global=%d)\n", fmt
,
4453 tmp
->nativeformats
, l
->capability
, CAPABILITY
);
4454 ast_string_field_build(tmp
, name
, "USTM/%s@%s-%d", l
->name
, l
->parent
->name
,
4456 if ((sub
->rtp
) && (sub
->subtype
== 0)) {
4458 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
4459 tmp
->fds
[0] = ast_rtp_fd(sub
->rtp
);
4460 tmp
->fds
[1] = ast_rtcp_fd(sub
->rtp
);
4463 ast_jb_configure(tmp
, &global_jbconf
);
4465 /* tmp->type = type; */
4466 ast_setstate(tmp
, state
);
4467 if (state
== AST_STATE_RING
)
4469 tmp
->adsicpe
= AST_ADSI_UNAVAILABLE
;
4470 tmp
->writeformat
= fmt
;
4471 tmp
->rawwriteformat
= fmt
;
4472 tmp
->readformat
= fmt
;
4473 tmp
->rawreadformat
= fmt
;
4474 tmp
->tech_pvt
= sub
;
4475 tmp
->tech
= &unistim_tech
;
4476 if (!ast_strlen_zero(l
->language
))
4477 ast_string_field_set(tmp
, language
, l
->language
);
4479 ast_mutex_lock(&usecnt_lock
);
4481 ast_mutex_unlock(&usecnt_lock
);
4482 ast_update_use_count();
4483 tmp
->callgroup
= l
->callgroup
;
4484 tmp
->pickupgroup
= l
->pickupgroup
;
4485 ast_string_field_set(tmp
, call_forward
, l
->parent
->call_forward
);
4486 if (!ast_strlen_zero(l
->cid_num
)) {
4487 char *name
, *loc
, *instr
;
4488 instr
= ast_strdup(l
->cid_num
);
4490 ast_callerid_parse(instr
, &name
, &loc
);
4491 tmp
->cid
.cid_num
= ast_strdup(loc
);
4492 tmp
->cid
.cid_name
= ast_strdup(name
);
4497 if (state
!= AST_STATE_DOWN
) {
4499 ast_verb(0, "Starting pbx in unistim_new\n");
4500 if (ast_pbx_start(tmp
)) {
4501 ast_log(LOG_WARNING
, "Unable to start PBX on %s\n", tmp
->name
);
4510 static void *do_monitor(void *data
)
4512 struct unistimsession
*cur
= NULL
;
4513 unsigned int dw_timeout
= 0;
4518 /* Add an I/O event to our UDP socket */
4519 if (unistimsock
> -1)
4520 ast_io_add(io
, unistimsock
, unistimsock_read
, AST_IO_IN
, NULL
);
4522 /* This thread monitors our UDP socket and timers */
4524 /* This loop is executed at least every IDLE_WAITus (1s) or every time a packet is received */
4525 /* Looking for the smallest time-out value */
4526 tick
= get_tick_count();
4527 dw_timeout
= UINT_MAX
;
4528 ast_mutex_lock(&sessionlock
);
4530 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur
, tick
);
4532 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur
,
4534 /* Check if we have miss something */
4535 if (cur
->timeout
<= tick
) {
4536 DEBUG_TIMER("Event for session %p\n", cur
);
4537 /* If the queue is empty, send a ping */
4538 if (cur
->last_buf_available
== 0)
4541 if (send_retransmit(cur
)) {
4542 DEBUG_TIMER("The chained link was modified, restarting...\n");
4544 dw_timeout
= UINT_MAX
;
4549 if (dw_timeout
> cur
->timeout
- tick
)
4550 dw_timeout
= cur
->timeout
- tick
;
4551 /* Checking if the phone is logged on for a new MWI */
4553 if ((!ast_strlen_zero(cur
->device
->lines
->mailbox
)) &&
4554 ((tick
>= cur
->device
->lines
->nextmsgcheck
))) {
4555 DEBUG_TIMER("Checking mailbox for MWI\n");
4556 unistim_send_mwi_to_peer(cur
, tick
);
4562 ast_mutex_unlock(&sessionlock
);
4563 DEBUG_TIMER("Waiting for %dus\n", dw_timeout
);
4565 /* We should not wait more than IDLE_WAIT */
4566 if ((res
< 0) || (res
> IDLE_WAIT
))
4568 /* Wait for UDP messages for a maximum of res us */
4569 res
= ast_io_wait(io
, res
); /* This function will call unistimsock_read if a packet is received */
4570 /* Check for a reload request */
4571 ast_mutex_lock(&unistim_reload_lock
);
4572 reloading
= unistim_reloading
;
4573 unistim_reloading
= 0;
4574 ast_mutex_unlock(&unistim_reload_lock
);
4576 ast_verb(1, "Reloading unistim.conf...\n");
4579 pthread_testcancel();
4585 /*--- restart_monitor: Start the channel monitor thread ---*/
4586 static int restart_monitor(void)
4588 pthread_attr_t attr
;
4589 /* If we're supposed to be stopped -- stay stopped */
4590 if (monitor_thread
== AST_PTHREADT_STOP
)
4592 if (ast_mutex_lock(&monlock
)) {
4593 ast_log(LOG_WARNING
, "Unable to lock monitor\n");
4596 if (monitor_thread
== pthread_self()) {
4597 ast_mutex_unlock(&monlock
);
4598 ast_log(LOG_WARNING
, "Cannot kill myself\n");
4601 if (monitor_thread
!= AST_PTHREADT_NULL
) {
4602 /* Wake up the thread */
4603 pthread_kill(monitor_thread
, SIGURG
);
4605 pthread_attr_init(&attr
);
4606 pthread_attr_setdetachstate(&attr
, PTHREAD_CREATE_JOINABLE
);
4607 /* Start a new monitor */
4608 if (ast_pthread_create(&monitor_thread
, &attr
, do_monitor
, NULL
) < 0) {
4609 ast_mutex_unlock(&monlock
);
4610 ast_log(LOG_ERROR
, "Unable to start monitor thread.\n");
4614 ast_mutex_unlock(&monlock
);
4618 /*--- unistim_request: PBX interface function ---*/
4619 /* UNISTIM calls initiated by the PBX arrive here */
4620 static struct ast_channel
*unistim_request(const char *type
, int format
, void *data
,
4624 struct unistim_subchannel
*sub
;
4625 struct ast_channel
*tmpc
= NULL
;
4630 format
&= CAPABILITY
;
4632 "Asked to get a channel of format %s while capability is %d result : %s (%d) \n",
4633 ast_getformatname(oldformat
), CAPABILITY
, ast_getformatname(format
), format
);
4636 "Asked to get a channel of unsupported format %s while capability is %s\n",
4637 ast_getformatname(oldformat
), ast_getformatname(CAPABILITY
));
4641 ast_copy_string(tmp
, dest
, sizeof(tmp
));
4642 if (ast_strlen_zero(tmp
)) {
4643 ast_log(LOG_NOTICE
, "Unistim channels require a device\n");
4647 sub
= find_subchannel_by_name(tmp
);
4649 ast_log(LOG_NOTICE
, "No available lines on: %s\n", dest
);
4650 *cause
= AST_CAUSE_CONGESTION
;
4654 ast_verb(3, "unistim_request(%s)\n", tmp
);
4658 ast_verb(0, "Can't create channel : Busy !\n");
4659 *cause
= AST_CAUSE_BUSY
;
4662 sub
->parent
->capability
= format
;
4663 tmpc
= unistim_new(sub
, AST_STATE_DOWN
);
4665 ast_log(LOG_WARNING
, "Unable to make channel for '%s'\n", tmp
);
4667 ast_verb(0, "unistim_request owner = %p\n", sub
->owner
);
4674 static char *unistim_info(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
4676 struct unistim_device
*device
= devices
;
4677 struct unistim_line
*line
;
4678 struct unistim_subchannel
*sub
;
4679 struct unistimsession
*s
;
4681 struct ast_channel
*tmp
;
4685 e
->command
= "unistim info";
4687 "Usage: unistim info\n"
4688 " Dump internal structures.\n";
4692 return NULL
; /* no completion */
4695 if (a
->argc
!= e
->args
)
4696 return CLI_SHOWUSAGE
;
4698 ast_cli(a
->fd
, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
4700 ast_cli(a
->fd
, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
4701 device
->name
, device
->id
, device
->lines
, device
->ha
, device
->session
,
4703 line
= device
->lines
;
4706 "->name=%s fullname=%s exten=%s callid=%s cap=%d device=%p line=%p\n",
4707 line
->name
, line
->fullname
, line
->exten
, line
->cid_num
,
4708 line
->capability
, line
->parent
, line
);
4709 for (i
= 0; i
< MAX_SUBS
; i
++) {
4710 sub
= line
->subs
[i
];
4716 tmp
= sub
->owner
->_bridge
;
4717 if (sub
->subtype
!= i
)
4718 ast_cli(a
->fd
, "Warning ! subchannel->subs[%d] have a subtype=%d\n", i
,
4721 "-->subtype=%d chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
4722 sub
->subtype
, sub
->owner
, sub
->rtp
, tmp
, sub
->parent
,
4727 device
= device
->next
;
4729 ast_cli(a
->fd
, "\nSessions:\n");
4730 ast_mutex_lock(&sessionlock
);
4734 "sin=%s timeout=%u state=%d macaddr=%s device=%p session=%p\n",
4735 ast_inet_ntoa(s
->sin
.sin_addr
), s
->timeout
, s
->state
, s
->macaddr
,
4739 ast_mutex_unlock(&sessionlock
);
4744 static char *unistim_sp(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
4747 struct unistim_subchannel
*sub
;
4749 unsigned char c
, cc
;
4754 e
->command
= "unistim sp";
4756 "Usage: unistim sp USTM/line@name hexa\n"
4757 " unistim sp USTM/1000@hans 19040004\n";
4761 return NULL
; /* no completion */
4765 return CLI_SHOWUSAGE
;
4767 if (strlen(a
->argv
[2]) < 9)
4768 return CLI_SHOWUSAGE
;
4770 len
= strlen(a
->argv
[3]);
4772 return CLI_SHOWUSAGE
;
4774 ast_copy_string(tmp
, a
->argv
[2] + 5, sizeof(tmp
));
4775 sub
= find_subchannel_by_name(tmp
);
4777 ast_cli(a
->fd
, "Can't find '%s'\n", tmp
);
4780 if (!sub
->parent
->parent
->session
) {
4781 ast_cli(a
->fd
, "'%s' is not connected\n", tmp
);
4784 ast_cli(a
->fd
, "Sending '%s' to %s (%p)\n", a
->argv
[3], tmp
, sub
->parent
->parent
->session
);
4785 for (i
= 0; i
< len
; i
++) {
4797 tmp
[j
++] = (c
<< 4) | cc
;
4799 memcpy(buffsend
+ SIZE_HEADER
, tmp
, j
);
4800 send_client(SIZE_HEADER
+ j
, buffsend
, sub
->parent
->parent
->session
);
4804 static char *unistim_do_debug(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
4808 e
->command
= "unistim set debug {on|off}";
4810 "Usage: unistim set debug\n"
4811 " Display debug messages.\n";
4815 return NULL
; /* no completion */
4818 if (a
->argc
!= e
->args
)
4819 return CLI_SHOWUSAGE
;
4821 if (!strcasecmp(a
->argv
[3], "on")) {
4823 ast_cli(a
->fd
, "UNISTIM Debugging Enabled\n");
4824 } else if (!strcasecmp(a
->argv
[3], "off")) {
4826 ast_cli(a
->fd
, "UNISTIM Debugging Disabled\n");
4828 return CLI_SHOWUSAGE
;
4833 /*! \brief --- unistim_reload: Force reload of module from cli ---
4834 * Runs in the asterisk main thread, so don't do anything useful
4835 * but setting a flag and waiting for do_monitor to do the job
4837 static char *unistim_reload(struct ast_cli_entry
*e
, int cmd
, struct ast_cli_args
*a
)
4841 e
->command
= "unistim reload";
4843 "Usage: unistim reload\n"
4844 " Reloads UNISTIM configuration from unistim.conf\n";
4848 return NULL
; /* no completion */
4851 if (e
&& a
&& a
->argc
!= e
->args
)
4852 return CLI_SHOWUSAGE
;
4855 ast_verb(0, "reload unistim\n");
4857 ast_mutex_lock(&unistim_reload_lock
);
4858 if (!unistim_reloading
)
4859 unistim_reloading
= 1;
4860 ast_mutex_unlock(&unistim_reload_lock
);
4867 static struct ast_cli_entry unistim_cli
[] = {
4868 AST_CLI_DEFINE(unistim_reload
, "Reload UNISTIM configuration"),
4869 AST_CLI_DEFINE(unistim_info
, "Show UNISTIM info"),
4870 AST_CLI_DEFINE(unistim_sp
, "Send packet (for reverse engineering)"),
4871 AST_CLI_DEFINE(unistim_do_debug
, "Toggle UNITSTIM debugging"),
4874 static void unquote(char *out
, const char *src
, int maxlen
)
4876 int len
= strlen(src
);
4879 if ((len
> 1) && src
[0] == '\"') {
4880 /* This is a quoted string */
4882 /* Don't take more than what's there */
4884 if (maxlen
> len
- 1)
4886 memcpy(out
, src
, maxlen
);
4887 ((char *) out
)[maxlen
] = '\0';
4889 memcpy(out
, src
, maxlen
);
4893 static int ParseBookmark(const char *text
, struct unistim_device
*d
)
4900 int len
= strlen(text
);
4902 ast_copy_string(line
, text
, sizeof(line
));
4903 /* Position specified ? */
4904 if ((len
> 2) && (line
[1] == '@')) {
4906 if ((p
>= '0') && (p
<= '5'))
4909 ast_log(LOG_WARNING
,
4910 "Invalid position for bookmark : must be between 0 and 5\n");
4913 if (d
->softkeyicon
[p
] != 0) {
4914 ast_log(LOG_WARNING
, "Invalid position %d for bookmark : already used\n:", p
);
4917 memmove(line
, line
+ 2, sizeof(line
));
4919 /* No position specified, looking for a free slot */
4920 for (p
= 0; p
<= 5; p
++) {
4921 if (!d
->softkeyicon
[p
])
4925 ast_log(LOG_WARNING
, "No more free bookmark position\n");
4929 at
= strchr(line
, '@');
4931 ast_log(LOG_NOTICE
, "Bookmark entry '%s' has no @ (at) sign!\n", text
);
4937 at
= strchr(at
, '@');
4938 if (ast_strlen_zero(number
)) {
4939 ast_log(LOG_NOTICE
, "Bookmark entry '%s' has no number\n", text
);
4942 if (ast_strlen_zero(line
)) {
4943 ast_log(LOG_NOTICE
, "Bookmark entry '%s' has no description\n", text
);
4947 at
= strchr(number
, '@');
4949 d
->softkeyicon
[p
] = FAV_ICON_SHARP
; /* default icon */
4954 if (ast_strlen_zero(icon
)) {
4955 ast_log(LOG_NOTICE
, "Bookmark entry '%s' has no icon value\n", text
);
4958 if (strncmp(icon
, "USTM/", 5))
4959 d
->softkeyicon
[p
] = atoi(icon
);
4961 d
->softkeyicon
[p
] = 1;
4962 ast_copy_string(d
->softkeydevice
[p
], icon
+ 5, sizeof(d
->softkeydevice
[p
]));
4965 ast_copy_string(d
->softkeylabel
[p
], line
, sizeof(d
->softkeylabel
[p
]));
4966 ast_copy_string(d
->softkeynumber
[p
], number
, sizeof(d
->softkeynumber
[p
]));
4968 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
4969 p
, d
->softkeylabel
[p
], d
->softkeynumber
[p
], d
->softkeyicon
[p
]);
4973 /* Looking for dynamic icons entries in bookmarks */
4974 static void finish_bookmark(void)
4976 struct unistim_device
*d
= devices
;
4979 for (i
= 0; i
< 6; i
++) {
4980 if (d
->softkeyicon
[i
] == 1) { /* Something for us */
4981 struct unistim_device
*d2
= devices
;
4983 if (!strcmp(d
->softkeydevice
[i
], d2
->name
)) {
4985 d
->softkeyicon
[i
] = 0;
4990 if (d
->sp
[i
] == NULL
)
4991 ast_log(LOG_NOTICE
, "Bookmark entry with device %s not found\n",
4992 d
->softkeydevice
[i
]);
4999 static struct unistim_device
*build_device(const char *cat
, const struct ast_variable
*v
)
5001 struct unistim_device
*d
;
5002 struct unistim_line
*l
= NULL
;
5004 int nbsoftkey
, dateformat
, timeformat
, callhistory
;
5005 char linelabel
[AST_MAX_EXTENSION
];
5006 char context
[AST_MAX_EXTENSION
];
5007 char ringvolume
, ringstyle
;
5009 /* First, we need to know if we already have this name in our list */
5010 /* Get a lock for the device chained list */
5011 ast_mutex_lock(&devicelock
);
5014 if (!strcmp(d
->name
, cat
)) {
5015 /* Yep, we alreay have this one */
5016 if (unistimsock
< 0) {
5018 ast_log(LOG_WARNING
, "Duplicate entry found (%s), ignoring.\n", cat
);
5019 ast_mutex_unlock(&devicelock
);
5022 /* we're reloading right now */
5029 ast_mutex_unlock(&devicelock
);
5031 if (!(d
= ast_calloc(1, sizeof(*d
))))
5034 if (!(l
= ast_calloc(1, sizeof(*l
)))) {
5038 ast_copy_string(d
->name
, cat
, sizeof(d
->name
));
5040 ast_copy_string(context
, DEFAULTCONTEXT
, sizeof(context
));
5042 d
->output
= OUTPUT_HANDSET
;
5043 d
->previous_output
= OUTPUT_HANDSET
;
5044 d
->volume
= VOLUME_LOW
;
5046 linelabel
[0] = '\0';
5054 if (!strcasecmp(v
->name
, "rtp_port"))
5055 d
->rtp_port
= atoi(v
->value
);
5056 else if (!strcasecmp(v
->name
, "rtp_method"))
5057 d
->rtp_method
= atoi(v
->value
);
5058 else if (!strcasecmp(v
->name
, "status_method"))
5059 d
->status_method
= atoi(v
->value
);
5060 else if (!strcasecmp(v
->name
, "device"))
5061 ast_copy_string(d
->id
, v
->value
, sizeof(d
->id
));
5062 else if (!strcasecmp(v
->name
, "tn"))
5063 ast_copy_string(d
->extension_number
, v
->value
, sizeof(d
->extension_number
));
5064 else if (!strcasecmp(v
->name
, "permit") || !strcasecmp(v
->name
, "deny"))
5065 d
->ha
= ast_append_ha(v
->name
, v
->value
, d
->ha
, NULL
);
5066 else if (!strcasecmp(v
->name
, "context"))
5067 ast_copy_string(context
, v
->value
, sizeof(context
));
5068 else if (!strcasecmp(v
->name
, "maintext0"))
5069 unquote(d
->maintext0
, v
->value
, sizeof(d
->maintext0
) - 1);
5070 else if (!strcasecmp(v
->name
, "maintext1"))
5071 unquote(d
->maintext1
, v
->value
, sizeof(d
->maintext1
) - 1);
5072 else if (!strcasecmp(v
->name
, "maintext2"))
5073 unquote(d
->maintext2
, v
->value
, sizeof(d
->maintext2
) - 1);
5074 else if (!strcasecmp(v
->name
, "titledefault"))
5075 unquote(d
->titledefault
, v
->value
, sizeof(d
->titledefault
) - 1);
5076 else if (!strcasecmp(v
->name
, "dateformat"))
5077 dateformat
= atoi(v
->value
);
5078 else if (!strcasecmp(v
->name
, "timeformat"))
5079 timeformat
= atoi(v
->value
);
5080 else if (!strcasecmp(v
->name
, "contrast")) {
5081 d
->contrast
= atoi(v
->value
);
5082 if ((d
->contrast
< 0) || (d
->contrast
> 15)) {
5083 ast_log(LOG_WARNING
, "constrast must be beetween 0 and 15");
5086 } else if (!strcasecmp(v
->name
, "nat"))
5087 d
->nat
= ast_true(v
->value
);
5088 else if (!strcasecmp(v
->name
, "ringvolume"))
5089 ringvolume
= atoi(v
->value
);
5090 else if (!strcasecmp(v
->name
, "ringstyle"))
5091 ringstyle
= atoi(v
->value
);
5092 else if (!strcasecmp(v
->name
, "callhistory"))
5093 callhistory
= atoi(v
->value
);
5094 else if (!strcasecmp(v
->name
, "callerid")) {
5095 if (!strcasecmp(v
->value
, "asreceived"))
5096 l
->cid_num
[0] = '\0';
5098 ast_copy_string(l
->cid_num
, v
->value
, sizeof(l
->cid_num
));
5099 } else if (!strcasecmp(v
->name
, "language"))
5100 ast_copy_string(l
->language
, v
->value
, sizeof(l
->language
));
5101 else if (!strcasecmp(v
->name
, "country"))
5102 ast_copy_string(d
->country
, v
->value
, sizeof(d
->country
));
5103 else if (!strcasecmp(v
->name
, "accountcode"))
5104 ast_copy_string(l
->accountcode
, v
->value
, sizeof(l
->accountcode
));
5105 else if (!strcasecmp(v
->name
, "amaflags")) {
5107 y
= ast_cdr_amaflags2int(v
->value
);
5109 ast_log(LOG_WARNING
, "Invalid AMA flags: %s at line %d\n", v
->value
,
5113 } else if (!strcasecmp(v
->name
, "musiconhold"))
5114 ast_copy_string(l
->musicclass
, v
->value
, sizeof(l
->musicclass
));
5115 else if (!strcasecmp(v
->name
, "callgroup"))
5116 l
->callgroup
= ast_get_group(v
->value
);
5117 else if (!strcasecmp(v
->name
, "pickupgroup"))
5118 l
->pickupgroup
= ast_get_group(v
->value
);
5119 else if (!strcasecmp(v
->name
, "mailbox"))
5120 ast_copy_string(l
->mailbox
, v
->value
, sizeof(l
->mailbox
));
5121 else if (!strcasecmp(v
->name
, "parkinglot"))
5122 ast_copy_string(l
->parkinglot
, v
->value
, sizeof(l
->parkinglot
));
5123 else if (!strcasecmp(v
->name
, "linelabel"))
5124 unquote(linelabel
, v
->value
, sizeof(linelabel
) - 1);
5125 else if (!strcasecmp(v
->name
, "extension")) {
5126 if (!strcasecmp(v
->value
, "none"))
5127 d
->extension
= EXTENSION_NONE
;
5128 else if (!strcasecmp(v
->value
, "ask"))
5129 d
->extension
= EXTENSION_ASK
;
5130 else if (!strcasecmp(v
->value
, "line"))
5131 d
->extension
= EXTENSION_LINE
;
5133 ast_log(LOG_WARNING
, "Unknown extension option.\n");
5134 } else if (!strcasecmp(v
->name
, "bookmark")) {
5136 ast_log(LOG_WARNING
,
5137 "More than 6 softkeys defined. Ignoring new entries.\n");
5139 if (ParseBookmark(v
->value
, d
))
5142 } else if (!strcasecmp(v
->name
, "line")) {
5143 int len
= strlen(linelabel
);
5146 ast_log(LOG_WARNING
,
5147 "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
5155 ast_mutex_init(&l
->lock
);
5158 /* reset bookmarks */
5159 memset(d
->softkeylabel
, 0, sizeof(d
->softkeylabel
));
5160 memset(d
->softkeynumber
, 0, sizeof(d
->softkeynumber
));
5161 memset(d
->softkeyicon
, 0, sizeof(d
->softkeyicon
));
5162 memset(d
->softkeydevice
, 0, sizeof(d
->softkeydevice
));
5163 memset(d
->sp
, 0, sizeof(d
->sp
));
5165 ast_copy_string(l
->name
, v
->value
, sizeof(l
->name
));
5166 snprintf(l
->fullname
, sizeof(l
->fullname
), "USTM/%s@%s", l
->name
, d
->name
);
5167 d
->softkeyicon
[0] = FAV_ICON_ONHOOK_BLACK
;
5168 if (!len
) /* label is undefined ? */
5169 ast_copy_string(d
->softkeylabel
[0], v
->value
, sizeof(d
->softkeylabel
[0]));
5171 if ((len
> 2) && (linelabel
[1] == '@')) {
5172 d
->softkeylinepos
= linelabel
[0];
5173 if ((d
->softkeylinepos
>= '0') && (d
->softkeylinepos
<= '5')) {
5174 d
->softkeylinepos
-= '0';
5175 d
->softkeyicon
[0] = 0;
5177 ast_log(LOG_WARNING
,
5178 "Invalid position for linelabel : must be between 0 and 5\n");
5179 d
->softkeylinepos
= 0;
5181 ast_copy_string(d
->softkeylabel
[d
->softkeylinepos
], linelabel
+ 2,
5182 sizeof(d
->softkeylabel
[d
->softkeylinepos
]));
5183 d
->softkeyicon
[d
->softkeylinepos
] = FAV_ICON_ONHOOK_BLACK
;
5185 ast_copy_string(d
->softkeylabel
[0], linelabel
,
5186 sizeof(d
->softkeylabel
[0]));
5189 ast_copy_string(l
->context
, context
, sizeof(l
->context
));
5190 if (!ast_strlen_zero(l
->mailbox
)) {
5192 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l
->mailbox
, d
->name
, l
->name
);
5195 l
->capability
= CAPABILITY
;
5199 if (!alloc_sub(l
, SUB_REAL
)) {
5200 ast_mutex_destroy(&l
->lock
);
5209 ast_log(LOG_WARNING
, "Don't know keyword '%s' at line %d\n", v
->name
,
5213 d
->ringvolume
= ringvolume
;
5214 d
->ringstyle
= ringstyle
;
5215 d
->callhistory
= callhistory
;
5216 d
->tz
= ast_get_indication_zone(d
->country
);
5217 if ((d
->tz
== NULL
) && !ast_strlen_zero(d
->country
))
5218 ast_log(LOG_WARNING
, "Country '%s' was not found in indications.conf\n",
5220 d
->datetimeformat
= 56 + (dateformat
* 4);
5221 d
->datetimeformat
+= timeformat
;
5223 ast_log(LOG_ERROR
, "An Unistim device must have at least one line!\n");
5224 ast_mutex_destroy(&l
->lock
);
5229 if ((autoprovisioning
== AUTOPROVISIONING_TN
) &&
5230 (!ast_strlen_zero(d
->extension_number
))) {
5231 d
->extension
= EXTENSION_TN
;
5232 if (!ast_strlen_zero(d
->id
))
5233 ast_log(LOG_WARNING
,
5234 "tn= and device= can't be used together. Ignoring device= entry\n");
5235 d
->id
[0] = 'T'; /* magic : this is a tn entry */
5236 ast_copy_string((d
->id
) + 1, d
->extension_number
, sizeof(d
->id
) - 1);
5237 d
->extension_number
[0] = '\0';
5238 } else if (ast_strlen_zero(d
->id
)) {
5239 if (strcmp(d
->name
, "template")) {
5240 ast_log(LOG_ERROR
, "You must specify the mac address with device=\n");
5241 ast_mutex_destroy(&l
->lock
);
5246 strcpy(d
->id
, "000000000000");
5249 d
->rtp_port
= 10000;
5250 if (d
->contrast
== -1)
5252 if (ast_strlen_zero(d
->maintext0
))
5253 strcpy(d
->maintext0
, "Welcome");
5254 if (ast_strlen_zero(d
->maintext1
))
5255 strcpy(d
->maintext1
, d
->name
);
5256 if (ast_strlen_zero(d
->titledefault
)) {
5257 struct ast_tm tm
= { 0, };
5258 struct timeval cur_time
= ast_tvnow();
5260 if ((ast_localtime(&cur_time
, &tm
, 0)) == 0 || ast_strlen_zero(tm
.tm_zone
)) {
5261 display_last_error("Error in ast_localtime()");
5262 ast_copy_string(d
->titledefault
, "UNISTIM for*", 12);
5264 if (strlen(tm
.tm_zone
) < 4) {
5265 strcpy(d
->titledefault
, "TimeZone ");
5266 strcat(d
->titledefault
, tm
.tm_zone
);
5267 } else if (strlen(tm
.tm_zone
) < 9) {
5268 strcpy(d
->titledefault
, "TZ ");
5269 strcat(d
->titledefault
, tm
.tm_zone
);
5271 ast_copy_string(d
->titledefault
, tm
.tm_zone
, 12);
5274 /* Update the chained link if it's a new device */
5276 ast_mutex_lock(&devicelock
);
5279 ast_mutex_unlock(&devicelock
);
5280 ast_verb(3, "Added device '%s'\n", d
->name
);
5282 ast_verb(3, "Device '%s' reloaded\n", d
->name
);
5287 /*--- reload_config: Re-read unistim.conf config file ---*/
5288 static int reload_config(void)
5290 struct ast_config
*cfg
;
5291 struct ast_variable
*v
;
5292 struct ast_hostent ahp
;
5294 struct sockaddr_in bindaddr
= { 0, };
5295 char *config
= "unistim.conf";
5297 struct unistim_device
*d
;
5298 const int reuseFlag
= 1;
5299 struct unistimsession
*s
;
5300 struct ast_flags config_flags
= { 0, };
5302 cfg
= ast_config_load(config
, config_flags
);
5303 /* We *must* have a config file otherwise stop immediately */
5305 ast_log(LOG_ERROR
, "Unable to load config %s\n", config
);
5309 /* Copy the default jb config over global_jbconf */
5310 memcpy(&global_jbconf
, &default_jbconf
, sizeof(struct ast_jb_conf
));
5312 unistim_keepalive
= 120;
5314 v
= ast_variable_browse(cfg
, "general");
5316 /* handle jb conf */
5317 if (!ast_jb_read_conf(&global_jbconf
, v
->name
, v
->value
))
5320 if (!strcasecmp(v
->name
, "keepalive"))
5321 unistim_keepalive
= atoi(v
->value
);
5322 else if (!strcasecmp(v
->name
, "port"))
5323 unistim_port
= atoi(v
->value
);
5324 else if (!strcasecmp(v
->name
, "tos")) {
5325 if (ast_str2tos(v
->value
, &qos
.tos
))
5326 ast_log(LOG_WARNING
, "Invalid tos value at line %d, refer to QoS documentation\n", v
->lineno
);
5327 } else if (!strcasecmp(v
->name
, "tos_audio")) {
5328 if (ast_str2tos(v
->value
, &qos
.tos_audio
))
5329 ast_log(LOG_WARNING
, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v
->lineno
);
5330 } else if (!strcasecmp(v
->name
, "cos")) {
5331 if (ast_str2cos(v
->value
, &qos
.cos
))
5332 ast_log(LOG_WARNING
, "Invalid cos value at line %d, refer to QoS documentation\n", v
->lineno
);
5333 } else if (!strcasecmp(v
->name
, "cos_audio")) {
5334 if (ast_str2cos(v
->value
, &qos
.cos_audio
))
5335 ast_log(LOG_WARNING
, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v
->lineno
);
5336 } else if (!strcasecmp(v
->name
, "autoprovisioning")) {
5337 if (!strcasecmp(v
->value
, "no"))
5338 autoprovisioning
= AUTOPROVISIONING_NO
;
5339 else if (!strcasecmp(v
->value
, "yes"))
5340 autoprovisioning
= AUTOPROVISIONING_YES
;
5341 else if (!strcasecmp(v
->value
, "db"))
5342 autoprovisioning
= AUTOPROVISIONING_DB
;
5343 else if (!strcasecmp(v
->value
, "tn"))
5344 autoprovisioning
= AUTOPROVISIONING_TN
;
5346 ast_log(LOG_WARNING
, "Unknown autoprovisioning option.\n");
5347 } else if (!strcasecmp(v
->name
, "public_ip")) {
5348 if (!ast_strlen_zero(v
->value
)) {
5349 if (!(hp
= ast_gethostbyname(v
->value
, &ahp
)))
5350 ast_log(LOG_WARNING
, "Invalid address: %s\n", v
->value
);
5352 memcpy(&public_ip
.sin_addr
, hp
->h_addr
, sizeof(public_ip
.sin_addr
));
5353 public_ip
.sin_family
= AF_INET
;
5359 if ((unistim_keepalive
< 10) ||
5360 (unistim_keepalive
>
5361 255 - (((NB_MAX_RETRANSMIT
+ 1) * RETRANSMIT_TIMER
) / 1000))) {
5362 ast_log(LOG_ERROR
, "keepalive is invalid in %s\n", config
);
5363 ast_config_destroy(cfg
);
5366 packet_send_ping
[4] =
5367 unistim_keepalive
+ (((NB_MAX_RETRANSMIT
+ 1) * RETRANSMIT_TIMER
) / 1000);
5368 if ((unistim_port
< 1) || (unistim_port
> 65535)) {
5369 ast_log(LOG_ERROR
, "port is not set or invalid in %s\n", config
);
5370 ast_config_destroy(cfg
);
5373 unistim_keepalive
*= 1000;
5375 ast_mutex_lock(&devicelock
);
5378 if (d
->to_delete
>= 0)
5382 ast_mutex_unlock(&devicelock
);
5383 /* load the device sections */
5384 cat
= ast_category_browse(cfg
, NULL
);
5386 if (strcasecmp(cat
, "general")) {
5387 d
= build_device(cat
, ast_variable_browse(cfg
, cat
));
5389 cat
= ast_category_browse(cfg
, cat
);
5391 ast_mutex_lock(&devicelock
);
5398 ast_verb(0, "Removing device '%s'\n", d
->name
);
5400 ast_log(LOG_ERROR
, "Device '%s' without a line !, aborting\n", d
->name
);
5401 ast_config_destroy(cfg
);
5404 if (!d
->lines
->subs
[0]) {
5405 ast_log(LOG_ERROR
, "Device '%s' without a subchannel !, aborting\n",
5407 ast_config_destroy(cfg
);
5410 if (d
->lines
->subs
[0]->owner
) {
5411 ast_log(LOG_WARNING
,
5412 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
5417 ast_mutex_destroy(&d
->lines
->subs
[0]->lock
);
5418 ast_free(d
->lines
->subs
[0]);
5419 for (i
= 1; i
< MAX_SUBS
; i
++) {
5420 if (d
->lines
->subs
[i
]) {
5421 ast_log(LOG_WARNING
,
5422 "Device '%s' with threeway call subchannels allocated, aborting.\n",
5431 ast_mutex_destroy(&d
->lines
->lock
);
5434 if (sessions
== d
->session
)
5435 sessions
= d
->session
->next
;
5439 if (s
->next
== d
->session
) {
5440 s
->next
= d
->session
->next
;
5446 ast_mutex_destroy(&d
->session
->lock
);
5447 ast_free(d
->session
);
5452 struct unistim_device
*d2
= devices
;
5454 if (d2
->next
== d
) {
5468 ast_mutex_unlock(&devicelock
);
5469 ast_config_destroy(cfg
);
5470 ast_mutex_lock(&sessionlock
);
5474 refresh_all_favorite(s
);
5477 ast_mutex_unlock(&sessionlock
);
5478 /* We don't recreate a socket when reloading (locks would be necessary). */
5479 if (unistimsock
> -1)
5481 bindaddr
.sin_addr
.s_addr
= INADDR_ANY
;
5482 bindaddr
.sin_port
= htons(unistim_port
);
5483 bindaddr
.sin_family
= AF_INET
;
5484 unistimsock
= socket(AF_INET
, SOCK_DGRAM
, 0);
5485 if (unistimsock
< 0) {
5486 ast_log(LOG_WARNING
, "Unable to create UNISTIM socket: %s\n", strerror(errno
));
5491 const int pktinfoFlag
= 1;
5492 setsockopt(unistimsock
, IPPROTO_IP
, IP_PKTINFO
, &pktinfoFlag
,
5493 sizeof(pktinfoFlag
));
5496 if (public_ip
.sin_family
== 0) {
5497 ast_log(LOG_WARNING
,
5498 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
5503 setsockopt(unistimsock
, SOL_SOCKET
, SO_REUSEADDR
, (const char *) &reuseFlag
,
5505 if (bind(unistimsock
, (struct sockaddr
*) &bindaddr
, sizeof(bindaddr
)) < 0) {
5506 ast_log(LOG_WARNING
, "Failed to bind to %s:%d: %s\n",
5507 ast_inet_ntoa(bindaddr
.sin_addr
), htons(bindaddr
.sin_port
),
5512 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr
.sin_addr
), htons(bindaddr
.sin_port
));
5513 ast_netsock_set_qos(unistimsock
, qos
.tos
, qos
.cos
, "UNISTIM");
5518 static enum ast_rtp_get_result
unistim_get_vrtp_peer(struct ast_channel
*chan
,
5519 struct ast_rtp
**rtp
)
5521 return AST_RTP_TRY_NATIVE
;
5524 static enum ast_rtp_get_result
unistim_get_rtp_peer(struct ast_channel
*chan
,
5525 struct ast_rtp
**rtp
)
5527 struct unistim_subchannel
*sub
;
5528 enum ast_rtp_get_result res
= AST_RTP_GET_FAILED
;
5531 ast_verb(0, "unistim_get_rtp_peer called\n");
5533 sub
= chan
->tech_pvt
;
5534 if (sub
&& sub
->rtp
) {
5536 res
= AST_RTP_TRY_NATIVE
;
5542 static int unistim_set_rtp_peer(struct ast_channel
*chan
, struct ast_rtp
*rtp
,
5543 struct ast_rtp
*vrtp
, struct ast_rtp
*trtp
, int codecs
, int nat_active
)
5545 struct unistim_subchannel
*sub
;
5548 ast_verb(0, "unistim_set_rtp_peer called\n");
5550 sub
= chan
->tech_pvt
;
5558 static struct ast_rtp_protocol unistim_rtp
= {
5559 .type
= channel_type
,
5560 .get_rtp_info
= unistim_get_rtp_peer
,
5561 .get_vrtp_info
= unistim_get_vrtp_peer
,
5562 .set_rtp_peer
= unistim_set_rtp_peer
,
5565 /*--- load_module: PBX load module - initialization ---*/
5566 int load_module(void)
5570 if (!(buff
= ast_malloc(SIZE_PAGE
)))
5573 io
= io_context_create();
5575 ast_log(LOG_ERROR
, "Failed to allocate IO context\n");
5579 sched
= sched_context_create();
5581 ast_log(LOG_ERROR
, "Failed to allocate scheduler context\n");
5585 res
= reload_config();
5587 return AST_MODULE_LOAD_DECLINE
;
5589 /* Make sure we can register our unistim channel type */
5590 if (ast_channel_register(&unistim_tech
)) {
5591 ast_log(LOG_ERROR
, "Unable to register channel type '%s'\n", channel_type
);
5592 goto chanreg_failed
;
5595 ast_rtp_proto_register(&unistim_rtp
);
5597 ast_cli_register_multiple(unistim_cli
, ARRAY_LEN(unistim_cli
));
5601 return AST_MODULE_LOAD_SUCCESS
;
5604 /*! XXX \todo Leaking anything allocated by reload_config() ... */
5605 sched_context_destroy(sched
);
5608 io_context_destroy(io
);
5614 return AST_MODULE_LOAD_FAILURE
;
5617 static int unload_module(void)
5619 /* First, take us out of the channel loop */
5621 sched_context_destroy(sched
);
5623 ast_cli_unregister_multiple(unistim_cli
, ARRAY_LEN(unistim_cli
));
5625 ast_channel_unregister(&unistim_tech
);
5626 ast_rtp_proto_unregister(&unistim_rtp
);
5628 ast_mutex_lock(&monlock
);
5629 if (monitor_thread
&& (monitor_thread
!= AST_PTHREADT_STOP
) && (monitor_thread
!= AST_PTHREADT_NULL
)) {
5630 pthread_cancel(monitor_thread
);
5631 pthread_kill(monitor_thread
, SIGURG
);
5632 pthread_join(monitor_thread
, NULL
);
5634 monitor_thread
= AST_PTHREADT_STOP
;
5635 ast_mutex_unlock(&monlock
);
5639 if (unistimsock
> -1)
5645 /*! reload: Part of Asterisk module interface ---*/
5648 unistim_reload(NULL
, 0, NULL
);
5652 AST_MODULE_INFO(ASTERISK_GPL_KEY
, AST_MODFLAG_DEFAULT
, "UNISTIM Protocol (USTM)",
5653 .load
= load_module
,
5654 .unload
= unload_module
,