44 #if defined(__CYGWIN__) || defined(__NetBSD__)
78 #include "asterisk/features_config.h"
80 #include "asterisk/stasis_channels.h"
83 #define DEFAULTCONTEXT "default"
84 #define DEFAULTCALLERID "Unknown"
85 #define DEFAULTCALLERNAME " "
86 #define DEFAULTHEIGHT 3
87 #define USTM_LOG_DIR "unistimHistory"
88 #define USTM_LANG_DIR "unistimLang"
91 #define MAX_BUF_SIZE 64
93 #define MAX_BUF_NUMBER 150
95 #define MAX_SCREEN_NUMBER 15
97 #define MONTH_LABEL_SIZE 3
99 #define NB_MAX_RETRANSMIT 8
101 #define IDLE_WAIT 1000
103 #define RETRANSMIT_TIMER 2000
105 #define TIMER_MWI 5000
107 #define DEFAULT_INTERDIGIT_TIMER 4000
110 #define DEFAULT_CODEC 0x00
111 #define SIZE_PAGE 4096
112 #define DEVICE_NAME_LEN 16
113 #define AST_CONFIG_MAX_PATH 255
114 #define MAX_ENTRY_LOG 30
118 #define SUB_THREEWAY 2
123 AUTOPROVISIONING_NO = 0,
124 AUTOPROVISIONING_YES,
138 #define OUTPUT_HANDSET 0xC0
139 #define OUTPUT_HEADPHONE 0xC1
140 #define OUTPUT_SPEAKER 0xC2
142 #define VOLUME_LOW 0x01
143 #define VOLUME_LOW_SPEAKER 0x03
144 #define VOLUME_NORMAL 0x02
145 #define VOLUME_INSANELY_LOUD 0x07
147 #define MUTE_OFF 0x00
149 #define MUTE_ON_DISCRET 0xCE
151 #define LED_BAR_OFF 0x00
152 #define LED_BAR_ON 0x01
153 #define LED_BAR_P2 0x02
154 #define LED_BAR_P3 0x03
155 #define LED_BAR_P4 0x04
156 #define LED_BAR_P5 0x05
157 #define LED_BAR_P6 0x06
158 #define LED_BAR_P7 0x07
159 #define LED_SPEAKER_OFF 0x08
160 #define LED_SPEAKER_ON 0x09
161 #define LED_HEADPHONE_OFF 0x010
162 #define LED_HEADPHONE_ON 0x011
163 #define LED_MUTE_OFF 0x018
164 #define LED_MUTE_ON 0x019
165 #define LED_MUTE_BLINK 0x1A
167 #define SIZE_HEADER 6
168 #define SIZE_MAC_ADDR 17
169 #define TEXT_LENGTH_MAX 24
170 #define TEXT_LINE0 0x00
171 #define TEXT_LINE1 0x20
172 #define TEXT_LINE2 0x40
173 #define TEXT_NORMAL 0x05
174 #define TEXT_INVERSE 0x25
175 #define STATUS_LENGTH_MAX 28
177 #define FAV_ICON_NONE 0x00
178 #define FAV_ICON_ONHOOK_BLACK 0x20
179 #define FAV_ICON_ONHOOK_WHITE 0x21
180 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
181 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
182 #define FAV_ICON_OFFHOOK_BLACK 0x24
183 #define FAV_ICON_OFFHOOK_WHITE 0x25
184 #define FAV_ICON_ONHOLD_BLACK 0x26
185 #define FAV_ICON_ONHOLD_WHITE 0x27
186 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
187 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
188 #define FAV_ICON_PHONE_BLACK 0x2A
189 #define FAV_ICON_PHONE_WHITE 0x2B
190 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
191 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
192 #define FAV_ICON_HEADPHONES 0x2E
193 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
194 #define FAV_ICON_HOME 0x30
195 #define FAV_ICON_CITY 0x31
196 #define FAV_ICON_SHARP 0x32
197 #define FAV_ICON_PAGER 0x33
198 #define FAV_ICON_CALL_CENTER 0x34
199 #define FAV_ICON_FAX 0x35
200 #define FAV_ICON_MAILBOX 0x36
201 #define FAV_ICON_REFLECT 0x37
202 #define FAV_ICON_COMPUTER 0x38
203 #define FAV_ICON_FORWARD 0x39
204 #define FAV_ICON_LOCKED 0x3A
205 #define FAV_ICON_TRASH 0x3B
206 #define FAV_ICON_INBOX 0x3C
207 #define FAV_ICON_OUTBOX 0x3D
208 #define FAV_ICON_MEETING 0x3E
209 #define FAV_ICON_BOX 0x3F
211 #define FAV_BLINK_FAST 0x20
212 #define FAV_BLINK_SLOW 0x40
214 #define FAV_MAX_LENGTH 0x0A
218 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
220 static void dummy(
char *unused, ...)
231 .resync_threshold = 1000,
241 #define DEBUG_TIMER dummy
244 static int unistim_port;
245 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
246 static int unistim_keepalive;
247 static int unistimsock = -1;
251 unsigned int tos_audio;
253 unsigned int cos_audio;
254 } qos = { 0, 0, 0, 0 };
258 static struct sockaddr_in public_ip = { 0, };
259 static unsigned char *buff;
261 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
285 STATE_SELECTLANGUAGE,
345 static const int dtmf_row[] = { 697, 770, 852, 941 };
346 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
355 unsigned int subtype;
364 signed char ringstyle;
402 char name[DEVICE_NAME_LEN];
410 struct unistim_line *sline[FAVNUM];
411 struct unistim_device *
sp[FAVNUM];
436 char lst_cid[TEXT_LENGTH_MAX];
437 char lst_cnm[TEXT_LENGTH_MAX];
448 char extension_number[11];
455 struct unistim_device *next;
460 struct sockaddr_in sin;
461 struct sockaddr_in sout;
476 struct unistim_device *device;
477 struct unistimsession *next;
506 static const unsigned char packet_rcv_discovery[] =
507 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
508 static const unsigned char packet_send_discovery_ack[] =
509 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
511 static const unsigned char packet_recv_firm_version[] =
512 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
513 static const unsigned char packet_recv_it_type[] =
514 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
515 static const unsigned char packet_recv_pressed_key[] =
516 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
517 static const unsigned char packet_recv_pick_up[] =
518 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
519 static const unsigned char packet_recv_hangup[] =
520 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
521 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
525 { 0x00, 0x00, 0x00, 0x13, 0x89, 0x04, 0x59 };
526 static const unsigned char packet_send_expansion_next[] = { 0x09, 0x03, 0x17 };
527 static const unsigned char packet_send_expansion_icon[] = { 0x09, 0x06, 0x59, 0x05, 0x47, 0x20 };
528 static const unsigned char packet_send_expansion_text[] = { 0x09, 0x0f, 0x57, 0x19, 0x47, 0x20,
529 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 };
534 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
535 static const unsigned char packet_recv_mac_addr[] =
536 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 };
538 static const unsigned char packet_send_date_time3[] =
539 { 0x11, 0x09, 0x02, 0x02, 0x05, 0x06, 0x07,
542 static const unsigned char packet_send_date_time[] =
543 { 0x11, 0x09, 0x02, 0x0a, 0x05, 0x06, 0x07,
544 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
545 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
546 0x05, 0x12, 0x00, 0x78
549 static const unsigned char packet_send_no_ring[] =
550 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
551 static const unsigned char packet_send_s4[] =
552 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
553 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
554 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
555 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
556 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
558 static const unsigned char packet_send_call[] =
559 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
560 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
561 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
562 0x00, 0x12, 0x12, 0x01, 0x5c, 0x00,
563 0x0f, 0xa0, 0x9c, 0x41,
564 0x0f, 0xa0, 0x9c, 0x41, 0x0a, 0x01,
567 static const unsigned char packet_send_stream_based_tone_off[] =
568 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
570 static const unsigned char packet_send_mute[] = { 0x16, 0x05, 0x04, 0x00, 0x00 };
572 static const unsigned char packet_send_CloseAudioStreamRX[] = { 0x16, 0x05, 0x31, 0x00, 0xff };
573 static const unsigned char packet_send_CloseAudioStreamTX[] = { 0x16, 0x05, 0x31, 0xff, 0x00 };
575 static const unsigned char packet_send_stream_based_tone_on[] =
576 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
577 static const unsigned char packet_send_stream_based_tone_single_freq[] =
578 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
579 static const unsigned char packet_send_stream_based_tone_dual_freq[] =
580 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
581 static const unsigned char packet_send_select_output[] =
582 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
584 static const unsigned char packet_send_ring[] =
585 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
586 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 , 0x18, 0x16, 0x04, 0x18,
587 0x20, 0x16, 0x04, 0x10, 0x00
592 static const unsigned char packet_send_end_call[] =
593 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10 };
594 static const unsigned char packet_send_s9[] =
595 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
597 static const unsigned char packet_send_rtp_packet_size[] =
598 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
599 static const unsigned char packet_send_jitter_buffer_conf[] =
600 { 0x16, 0x0e, 0x3a, 0x00, 0x02, 0x04, 0x00, 0x00,
602 0x00, 0x00, 0x3e, 0x80
608 static const unsigned char packet_send_open_audio_stream_rx[] =
609 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
610 0x0e, 0x01, 0x14, 0x50, 0x00,
611 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
613 static const unsigned char packet_send_open_audio_stream_tx[] =
614 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
615 0x0e, 0x01, 0x14, 0x50,
616 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
619 static const unsigned char packet_send_open_audio_stream_rx3[] =
620 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
621 0x06, 0x81, 0x14, 0x50,
623 0x51, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93,
626 static const unsigned char packet_send_open_audio_stream_tx3[] =
627 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
628 0x06, 0x81, 0x14, 0x50,
629 0x00, 0x00, 0x14, 0x50, 0x00, 0x00,
630 0x0a, 0x93, 0x69, 0x05
633 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
634 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
635 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, 0x05,
636 0x06, 0x07, 0x08, 0x32
638 static const unsigned char packet_send_Contrast[] =
639 { 0x17, 0x04, 0x24, 0x08 };
640 static const unsigned char packet_send_start_timer[] =
641 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16,
642 'T',
'i',
'm',
'e',
'r' };
643 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
644 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, 0x00, 0x25 };
645 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
646 static const unsigned char packet_send_set_pos_cursor[] =
647 { 0x17, 0x06, 0x10, 0x81, 0x04, 0x20 };
649 static unsigned char monthlabels[] =
650 {
'J',
'a',
'n',
'F',
'e',
'b',
'M',
'a',
'r',
'A',
'p',
'r',
'M',
'a',
'y',
'J',
'u',
'n',
651 'J',
'u',
'l',
'A',
'u',
'g',
'S',
'e',
'p',
'O',
'c',
't',
'N',
'o',
'v',
'D',
'e',
'c' };
652 static unsigned char packet_send_monthlabels_download[] =
653 { 0x17, 0x0a, 0x15,
'-',
'-',
'-',
'-',
'-',
'-', 0x20 };
654 static const unsigned char packet_send_favorite[] =
655 { 0x17, 0x0f, 0x19, 0x10, 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
656 0x20, 0x20, 0x20, 0x20, 0x19,
657 0x05, 0x0f, 0x01, 0x00
659 static const unsigned char packet_send_title[] =
660 { 0x17, 0x10, 0x19, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
661 0x20, 0x20, 0x20, 0x20 };
662 static const unsigned char packet_send_text[] =
663 { 0x17, 0x1e, 0x1b, 0x04, 0x00, 0x25, 0x20, 0x20,
664 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
665 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
666 0x17, 0x04, 0x10, 0x87
668 static const unsigned char packet_send_status[] =
669 { 0x17, 0x20, 0x19, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
670 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
671 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
673 static const unsigned char packet_send_status2[] =
674 { 0x17, 0x0b, 0x19, 0x00, 0x20, 0x20, 0x20, 0x20,
679 static const unsigned char packet_send_charset_iso_8859_1[] =
680 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
682 static const unsigned char packet_send_charset_iso_8859_2[] =
683 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
685 static const unsigned char packet_send_charset_iso_8859_4[] =
686 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
688 static const unsigned char packet_send_charset_iso_8859_5[] =
689 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
691 static const unsigned char packet_send_charset_iso_2022_jp[] =
692 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
694 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
696 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
697 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
698 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
699 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
701 static unsigned char packet_send_ping[] =
702 { 0x1e, 0x05, 0x12, 0x00, 0x78 };
704 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
706 static const char tdesc[] =
"UNISTIM Channel Driver";
707 static const char channel_type[] =
"USTM";
713 static int unload_module(
void);
714 static int reload_config(
void);
718 const char *dest,
int *cause);
719 static int unistim_call(
struct ast_channel *ast,
const char *dest,
int timeout);
720 static int unistim_hangup(
struct ast_channel *ast);
721 static int unistim_answer(
struct ast_channel *ast);
724 static int unistim_indicate(
struct ast_channel *ast,
int ind,
const void *
data,
727 static int unistim_senddigit_begin(
struct ast_channel *ast,
char digit);
728 static int unistim_senddigit_end(
struct ast_channel *ast,
char digit,
729 unsigned int duration);
730 static int unistim_sendtext(
struct ast_channel *ast,
const char *text);
732 static int write_entry_history(
struct unistimsession *pte, FILE * f,
char c,
734 static void change_callerid(
struct unistimsession *pte,
int type,
char *callerid);
737 .type = channel_type,
738 .description = tdesc,
740 .requester = unistim_request,
741 .call = unistim_call,
742 .hangup = unistim_hangup,
743 .answer = unistim_answer,
744 .read = unistim_read,
745 .write = unistim_write,
746 .indicate = unistim_indicate,
747 .fixup = unistim_fixup,
748 .send_digit_begin = unistim_senddigit_begin,
749 .send_digit_end = unistim_senddigit_end,
750 .send_text = unistim_sendtext,
760 static int find_language(
const char*);
766 {
"Change codec", STATE_SELECTCODEC, handle_select_codec},
767 {
"Language", STATE_SELECTLANGUAGE, handle_select_language},
773 {
"English",
"en", ISO_8859_1, NULL},
774 {
"French",
"fr", ISO_8859_1, NULL},
775 {
"Russian",
"ru", ISO_8859_5, NULL},
776 {NULL, NULL, 0, NULL}
779 static char ustm_strcopy[1024];
782 const char *str_orig;
783 const char *str_trans;
786 static int lang_hash_fn(
const void *obj,
const int flags)
792 static int lang_cmp_fn(
void *obj,
void *arg,
int flags)
797 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (
CMP_MATCH |
CMP_STOP) : 0;
800 static const char *ustmtext(
const char *str,
struct unistimsession *pte)
808 lang = &options_languages[find_language(pte->device->
language)];
815 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
819 lang_hash_fn, NULL, lang_cmp_fn);
821 ast_log(LOG_ERROR,
"Unable to allocate container for translation!\n");
824 snprintf(tmp,
sizeof(tmp),
"%s/%s/%s.po", ast_config_AST_VAR_DIR,
825 USTM_LANG_DIR, lang->lang_short);
828 ast_log(LOG_WARNING,
"There is no translation file for '%s'\n", lang->lang_short);
831 while (fgets(tmp,
sizeof(tmp), f)) {
832 if (!(p = strchr(tmp,
'\n'))) {
833 ast_log(LOG_ERROR,
"Too long line found in language file - truncated!\n");
837 if (!(p = strchr(tmp,
'"'))) {
840 if (tmp == strstr(tmp,
"msgid")) {
842 p = strchr(p_orig,
'"');
843 }
else if (tmp == strstr(tmp,
"msgstr")) {
845 p = strchr(p_trans,
'"');
850 if (!p_trans || !p_orig) {
853 if (ast_strlen_zero(p_trans)) {
860 if (!(lang_entry = ao2_alloc(
sizeof(*lang_entry), NULL))) {
865 lang_entry->str_trans = p_trans;
866 lang_entry->str_orig = p_orig;
875 le_search.str_orig = str;
876 if ((lang_entry = ao2_find(lang->trans, &le_search,
OBJ_POINTER))) {
877 size = strlen(lang_entry->str_trans)+1;
881 memcpy(ustm_strcopy, lang_entry->str_trans, size);
889 static void display_last_error(
const char *sz_msg)
892 ast_log(LOG_WARNING,
"%s : (%d) %s\n", sz_msg, errno, strerror(errno));
895 static unsigned int get_tick_count(
void)
899 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
903 static void send_raw_client(
int size,
const unsigned char *data,
struct sockaddr_in *addr_to,
904 const struct sockaddr_in *addr_ourip)
907 struct iovec msg_iov;
909 char buffer[CMSG_SPACE(
sizeof(
struct in_pktinfo))];
910 struct cmsghdr *ip_msg = (
struct cmsghdr *) buffer;
911 struct in_pktinfo *pki = (
struct in_pktinfo *) CMSG_DATA(ip_msg);
918 msg_iov.iov_base = (
char *) data;
919 msg_iov.iov_len = size;
921 msg.msg_name = addr_to;
922 msg.msg_namelen =
sizeof(
struct sockaddr_in);
923 msg.msg_iov = &msg_iov;
925 msg.msg_control = ip_msg;
926 msg.msg_controllen =
sizeof(buffer);
929 ip_msg->cmsg_len = CMSG_LEN(
sizeof(*pki));
930 ip_msg->cmsg_level = IPPROTO_IP;
931 ip_msg->cmsg_type = IP_PKTINFO;
932 pki->ipi_ifindex = 0;
933 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr;
939 ast_verb(0,
"\n**> From %s sending %d bytes to %s ***\n",
942 for (tmp = 0; tmp < size; tmp++)
943 ast_verb(0,
"%02hhx ", data[tmp]);
944 ast_verb(0,
"\n******************************************\n");
949 if (sendmsg(unistimsock, &msg, 0) == -1) {
950 display_last_error(
"Error sending datas");
953 if (sendto(unistimsock, data, size, 0, (
struct sockaddr *) addr_to,
sizeof(*addr_to))
955 display_last_error(
"Error sending datas");
959 static void send_client(
int size,
const unsigned char *data,
struct unistimsession *pte)
963 unsigned short seq = ntohs(++pte->
seq_server);
965 ast_mutex_lock(&pte->lock);
969 ast_log(LOG_WARNING,
"Error : send queue overflow\n");
970 ast_mutex_unlock(&pte->lock);
973 memcpy((
void *)data +
sizeof(
unsigned short), (
void *)&seq,
sizeof(
unsigned short));
975 memcpy(pte->
wsabufsend[buf_pos].buf, data, size);
977 tick = get_tick_count();
982 ast_verb(0,
"Sending datas with seq #0x%04x Using slot #%d :\n", (
unsigned)pte->
seq_server, buf_pos);
988 ast_mutex_unlock(&pte->lock);
995 ast_verb(0,
"Sending ping\n");
998 memcpy(buffsend + SIZE_HEADER, packet_send_ping,
sizeof(packet_send_ping));
999 send_client(SIZE_HEADER +
sizeof(packet_send_ping), buffsend, pte);
1002 static int get_to_address(
int fd,
struct sockaddr_in *toAddr)
1007 struct cmsghdr *cmsg;
1008 struct sockaddr_in peeraddr;
1009 struct in_addr addr;
1010 struct msghdr mh = {
1011 .msg_name = &peeraddr,
1012 .msg_namelen =
sizeof(peeraddr),
1013 .msg_control = cmbuf,
1014 .msg_controllen =
sizeof(cmbuf),
1016 memset(&addr, 0,
sizeof(addr));
1018 err = recvmsg(fd, &mh, MSG_PEEK);
1020 ast_log(LOG_WARNING,
"recvmsg returned an error: %s\n", strerror(errno));
1023 for(cmsg = CMSG_FIRSTHDR(&mh);
1025 cmsg = CMSG_NXTHDR(&mh, cmsg))
1027 if (cmsg->cmsg_level == IPPROTO_IP && cmsg->cmsg_type == IP_PKTINFO) {
1028 struct in_pktinfo *pkt = (
struct in_pktinfo*)CMSG_DATA(cmsg);
1029 addr = pkt->ipi_addr;
1031 ast_verb(0,
"message received on address %s\n",
ast_inet_ntoa(addr));
1035 memcpy(&toAddr->sin_addr, &addr,
sizeof(
struct in_addr));
1038 memcpy(toAddr, &public_ip,
sizeof(*toAddr));
1046 static struct unistimsession *create_client(
const struct sockaddr_in *addr_from)
1054 memcpy(&s->
sin, addr_from,
sizeof(
struct sockaddr_in));
1055 if (get_to_address(unistimsock, &s->
sout) < 0) {
1059 s->
sout.sin_family = AF_INET;
1061 ast_verb(0,
"Creating a new entry for the phone from %s received via server ip %s\n",
1064 ast_mutex_init(&s->lock);
1070 s->
state = STATE_INIT;
1084 ast_verb(0,
"Sending end call\n");
1086 memcpy(buffsend + SIZE_HEADER, packet_send_end_call,
sizeof(packet_send_end_call));
1087 send_client(SIZE_HEADER +
sizeof(packet_send_end_call), buffsend, pte);
1092 unsigned int tick = 0;
1095 DEBUG_TIMER(
"tick = %u next ping at %u tick\n", tick, pte->
timeout);
1106 ast_verb(0,
"Our single packet was ACKed.\n");
1109 set_ping_timer(pte);
1115 ast_verb(0,
"Our send queue is completely ACKed.\n");
1118 set_ping_timer(pte);
1122 ast_verb(0,
"We still have packets in our send queue\n");
1131 ast_verb(0,
"Sending start timer\n");
1133 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer,
sizeof(packet_send_start_timer));
1134 send_client(SIZE_HEADER +
sizeof(packet_send_start_timer), buffsend, pte);
1141 ast_verb(0,
"Sending stop timer\n");
1143 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer,
sizeof(packet_send_stop_timer));
1144 send_client(SIZE_HEADER +
sizeof(packet_send_stop_timer), buffsend, pte);
1147 static void send_icon(
unsigned char pos,
unsigned char status,
struct unistimsession *pte)
1151 ast_verb(0,
"Sending icon pos %d with status 0x%02hhx\n", pos, status);
1153 memcpy(buffsend + SIZE_HEADER, packet_send_icon,
sizeof(packet_send_icon));
1155 buffsend[10] = status;
1156 send_client(SIZE_HEADER +
sizeof(packet_send_icon), buffsend, pte);
1162 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_next,
sizeof(packet_send_expansion_next));
1163 send_client(SIZE_HEADER +
sizeof(packet_send_expansion_next), buffsend, pte);
1167 static void send_expansion_icon(
unsigned char pos,
unsigned char status,
struct unistimsession *pte)
1171 ast_verb(0,
"Sending expansion icon pos %d with status 0x%02hhx\n", pos, status);
1173 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_icon,
sizeof(packet_send_expansion_icon));
1175 buffsend[11] = status;
1176 send_client(SIZE_HEADER +
sizeof(packet_send_expansion_icon), buffsend, pte);
1180 static void send_expansion_text(
unsigned char pos,
struct unistimsession *pte,
const char *text)
1185 ast_log(LOG_ERROR,
"[expansion] Asked to display NULL text (pos %d)\n", pos);
1189 ast_verb(0,
"[expansion] Sending text at pos %d\n", pos);
1191 memcpy(buffsend + SIZE_HEADER, packet_send_expansion_text,
sizeof(packet_send_expansion_text));
1194 if (i > TEXT_LENGTH_MAX) {
1195 i = TEXT_LENGTH_MAX;
1197 memcpy(buffsend + 11, text, i);
1198 send_client(SIZE_HEADER +
sizeof(packet_send_expansion_text), buffsend, pte);
1201 static void send_tone(
struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
1206 ast_verb(0,
"Sending Stream Based Tone Off\n");
1208 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
1209 sizeof(packet_send_stream_based_tone_off));
1210 send_client(SIZE_HEADER +
sizeof(packet_send_stream_based_tone_off), buffsend, pte);
1219 ast_verb(0,
"Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
1223 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
1224 sizeof(packet_send_stream_based_tone_single_freq));
1225 put_unaligned_uint16(&buffsend[10], htons(tone1));
1226 send_client(SIZE_HEADER +
sizeof(packet_send_stream_based_tone_single_freq), buffsend,
1230 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dual_freq,
1231 sizeof(packet_send_stream_based_tone_dual_freq));
1232 put_unaligned_uint16(&buffsend[10], htons(tone1));
1233 put_unaligned_uint16(&buffsend[12], htons(tone2));
1234 send_client(SIZE_HEADER +
sizeof(packet_send_stream_based_tone_dual_freq), buffsend,
1239 ast_verb(0,
"Sending Stream Based Tone On\n");
1241 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
1242 sizeof(packet_send_stream_based_tone_on));
1243 send_client(SIZE_HEADER +
sizeof(packet_send_stream_based_tone_on), buffsend, pte);
1273 send_favorite(
unsigned char pos,
unsigned char status,
struct unistimsession *pte,
1280 ast_verb(0,
"Sending favorite pos %d with status 0x%02hhx\n", pos, status);
1282 memcpy(buffsend + SIZE_HEADER, packet_send_favorite,
sizeof(packet_send_favorite));
1285 buffsend[25] = status;
1286 i = strlen(ustmtext(text, pte));
1287 if (i > FAV_MAX_LENGTH) {
1290 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
1291 send_client(SIZE_HEADER +
sizeof(packet_send_favorite), buffsend, pte);
1294 static void send_favorite_short(
unsigned char pos,
unsigned char status,
struct unistimsession *pte) {
1295 send_favorite(pos, status, pte, pte->device->
softkeylabel[pos]);
1299 static void send_favorite_selected(
unsigned char status,
struct unistimsession *pte) {
1306 static void send_expansion_short(
unsigned char pos,
unsigned char status,
struct unistimsession *pte) {
1307 send_expansion_icon(pos, status, pte);
1308 send_expansion_text(pos, pte, ustmtext(pte->device->
expsoftkeylabel[pos], pte));
1309 send_expansion_next(pte);
1313 static int soft_key_visible(
struct unistim_device* d,
unsigned char num)
1315 if(d->
height == 1 && num % 3 == 2) {
1323 unsigned char i = 0;
1325 struct unistim_line *line;
1329 ast_verb(0,
"Refreshing all favorite\n");
1331 for (i = 0; i < FAVNUM; i++) {
1332 unsigned char status = pte->device->
softkeyicon[i];
1334 if (!soft_key_visible(pte->device, i)) {
1337 if (!strcasecmp(pte->device->
softkeylabel[i],
"DND") && line) {
1338 if (!
ast_db_get(
"DND", line->name, data,
sizeof(data))) {
1339 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
1343 send_favorite_short(i, status, pte);
1345 if (pte->device->
hasexp) {
1346 for (i = 0; i < EXPNUM; i++) {
1347 send_expansion_short(i, FAV_ICON_NONE, pte);
1352 static int is_key_favorite(
struct unistim_device *d,
int fav)
1354 if ((fav < 0) || (fav >= FAVNUM)) {
1357 if (d->sline[fav]) {
1366 static int is_key_line(
struct unistim_device *d,
int fav)
1368 if ((fav < 0) || (fav >= FAVNUM)) {
1371 if (!d->sline[fav]) {
1374 if (is_key_favorite(d, fav)) {
1385 static int get_avail_softkey(
struct unistimsession *pte,
const char* name)
1389 if (!is_key_line(pte->device, pte->device->
selected)) {
1392 for (i = 0; i < FAVNUM; i++) {
1396 if (!soft_key_visible(pte->device, i)) {
1399 if (pte->device->ssub[i]) {
1402 if (is_key_line(pte->device, i)) {
1403 if (name && strcmp(name, pte->device->sline[i]->name)) {
1407 ast_verb(0,
"Found softkey %d for device %s\n", i, name);
1418 static void change_favorite_icon(
struct unistimsession *pte,
unsigned char status)
1420 struct unistim_device *d =
devices;
1423 if (pte->
state != STATE_CLEANING) {
1424 int softkeylinepos = get_active_softkey(pte);
1425 if (softkeylinepos != -1) {
1426 send_favorite_short(softkeylinepos, status, pte);
1431 for (i = 0; i < FAVNUM; i++) {
1432 if (d->
sp[i] == pte->device) {
1436 send_favorite(i, status + 1, d->session, d->
softkeylabel[i]);
1447 struct unistim_line *line;
1450 ast_verb(0,
"Trying to register extension '%s' into context '%s' to %s\n",
1459 static int unregister_extension(
const struct unistimsession *pte)
1462 ast_verb(0,
"Trying to unregister extension '%s' context '%s'\n",
1486 s->
state = STATE_CLEANING;
1488 ast_verb(0,
"close_client session %p device %p\n", s, s->device);
1490 change_favorite_icon(s, FAV_ICON_NONE);
1491 ast_mutex_lock(&s->device->lock);
1499 ast_verb(0,
"Aborting call\n");
1504 ast_debug(1,
"Released sub %u of channel %s@%s\n", sub->subtype, sub->
parent->name, s->device->
name);
1507 unistim_free_sub(sub);
1514 unregister_extension(s);
1516 cur->device->session = NULL;
1517 ast_mutex_unlock(&s->device->lock);
1520 ast_verb(0,
"Freeing an unregistered client\n");
1524 prev->next = cur->next;
1526 sessions = cur->next;
1528 ast_mutex_destroy(&s->lock);
1531 ast_log(LOG_WARNING,
"Trying to delete non-existent session %p?\n", s);
1542 ast_mutex_lock(&pte->lock);
1545 ast_verb(0,
"Too many retransmit - freeing client\n");
1547 ast_mutex_unlock(&pte->lock);
1556 ast_log(LOG_WARNING,
1557 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%04x last_seq_ack = #0x%04x\n",
1563 unsigned short *sbuf = (
unsigned short *) pte->
wsabufsend[i].buf;
1566 seq = ntohs(sbuf[1]);
1567 ast_verb(0,
"Retransmit slot #%d (seq=#0x%04x), last ack was #0x%04x\n", i,
1573 ast_mutex_unlock(&pte->lock);
1578 static void send_text(
unsigned char pos,
unsigned char inverse,
struct unistimsession *pte,
1584 ast_log(LOG_ERROR,
"Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
1587 if (pte->device && pte->device->
height == 1 && pos != TEXT_LINE0) {
1591 ast_verb(0,
"Sending text at pos %d, inverse flag %d\n", pos, inverse);
1593 memcpy(buffsend + SIZE_HEADER, packet_send_text,
sizeof(packet_send_text));
1595 buffsend[11] = inverse;
1597 if (i > TEXT_LENGTH_MAX) {
1598 i = TEXT_LENGTH_MAX;
1600 memcpy(buffsend + 12, text, i);
1601 send_client(SIZE_HEADER +
sizeof(packet_send_text), buffsend, pte);
1604 static void send_text_status(
struct unistimsession *pte,
const char *text)
1609 ast_verb(0,
"Sending status text\n");
1613 int n = strlen(text);
1616 for (i = 0, j = 0; i < 4; i++, j += 7) {
1617 int pos = 0x08 + (i * 0x20);
1618 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
1619 sizeof(packet_send_status2));
1622 memcpy(buffsend + 10, (j < n) ? (text + j) :
" ", 7);
1623 send_client(SIZE_HEADER +
sizeof(packet_send_status2), buffsend, pte);
1629 memcpy(buffsend + SIZE_HEADER, packet_send_status,
sizeof(packet_send_status));
1631 if (i > STATUS_LENGTH_MAX) {
1632 i = STATUS_LENGTH_MAX;
1634 memcpy(buffsend + 10, text, i);
1635 send_client(SIZE_HEADER +
sizeof(packet_send_status), buffsend, pte);
1639 static void send_led_update(
struct unistimsession *pte,
unsigned char led)
1643 ast_verb(0,
"Sending led_update (%x)\n", (
unsigned)led);
1645 memcpy(buffsend + SIZE_HEADER, packet_send_led_update,
sizeof(packet_send_led_update));
1647 send_client(SIZE_HEADER +
sizeof(packet_send_led_update), buffsend, pte);
1650 static void send_mute(
struct unistimsession *pte,
unsigned char mute)
1658 ast_verb(0,
"Sending mute packet (%x)\n", (
unsigned)mute);
1660 memcpy(buffsend + SIZE_HEADER, packet_send_mute,
sizeof(packet_send_mute));
1662 send_client(SIZE_HEADER +
sizeof(packet_send_mute), buffsend, pte);
1670 send_select_output(
struct unistimsession *pte,
unsigned char output,
unsigned char volume,
1676 ast_verb(0,
"Sending select output packet output=%x volume=%x mute=%x\n",
1677 (
unsigned)output, (
unsigned)volume, (
unsigned)mute);
1679 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
1680 sizeof(packet_send_select_output));
1681 buffsend[9] = output;
1682 if (output == OUTPUT_SPEAKER && volume == VOLUME_LOW) {
1683 volume = VOLUME_LOW_SPEAKER;
1685 buffsend[10] = volume;
1686 if (mute == MUTE_ON_DISCRET) {
1687 buffsend[11] = MUTE_ON;
1689 buffsend[11] = mute;
1691 send_client(SIZE_HEADER +
sizeof(packet_send_select_output), buffsend, pte);
1692 if (output == OUTPUT_HANDSET) {
1693 mute_icon = (mute == MUTE_ON) ? FAV_ICON_ONHOLD_BLACK : FAV_ICON_OFFHOOK_BLACK;
1694 send_led_update(pte, LED_SPEAKER_OFF);
1695 send_led_update(pte, LED_HEADPHONE_OFF);
1696 }
else if (output == OUTPUT_HEADPHONE) {
1697 mute_icon = (mute == MUTE_ON)? FAV_ICON_HEADPHONES_ONHOLD : FAV_ICON_HEADPHONES;
1698 send_led_update(pte, LED_SPEAKER_OFF);
1699 send_led_update(pte, LED_HEADPHONE_ON);
1700 }
else if (output == OUTPUT_SPEAKER) {
1701 send_led_update(pte, LED_SPEAKER_ON);
1702 send_led_update(pte, LED_HEADPHONE_OFF);
1704 mute_icon = (mute == MUTE_ON)? FAV_ICON_SPEAKER_ONHOLD_BLACK : FAV_ICON_SPEAKER_ONHOOK_BLACK;
1706 mute_icon = (mute == MUTE_ON)? FAV_ICON_SPEAKER_ONHOLD_BLACK : FAV_ICON_SPEAKER_OFFHOOK_BLACK;
1709 ast_log(LOG_WARNING,
"Invalid output (%d)\n", output);
1711 if (mute_icon != -1) {
1712 change_favorite_icon(pte, mute_icon);
1714 if (output != pte->device->
output) {
1717 pte->device->
output = output;
1719 static void send_ring(
struct unistimsession *pte,
signed char volume,
signed char style)
1723 ast_verb(0,
"Sending ring packet\n");
1725 memcpy(buffsend + SIZE_HEADER, packet_send_ring,
sizeof(packet_send_ring));
1726 buffsend[24] = style + 0x10;
1727 buffsend[29] = volume * 0x10;
1728 send_client(SIZE_HEADER +
sizeof(packet_send_ring), buffsend, pte);
1735 ast_verb(0,
"Sending no ring packet\n");
1737 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring,
sizeof(packet_send_no_ring));
1738 send_client(SIZE_HEADER +
sizeof(packet_send_no_ring), buffsend, pte);
1741 static void send_texttitle(
struct unistimsession *pte,
const char *text)
1746 ast_verb(0,
"Sending title text\n");
1748 memcpy(buffsend + SIZE_HEADER, packet_send_title,
sizeof(packet_send_title));
1753 memcpy(buffsend + 10, text, i);
1754 send_client(SIZE_HEADER +
sizeof(packet_send_title), buffsend, pte);
1759 send_text(TEXT_LINE0, TEXT_NORMAL, pte,
"");
1762 static void send_month_labels(
struct unistimsession *pte,
int month)
1768 ast_verb(0,
"Sending Month Labels\n");
1771 memcpy(buffsend + SIZE_HEADER, packet_send_monthlabels_download,
sizeof(packet_send_monthlabels_download));
1773 memcpy(month_name, &monthlabels[month *
MONTH_LABEL_SIZE], MONTH_LABEL_SIZE);
1774 memcpy(buffsend + SIZE_HEADER + 3 + i*
MONTH_LABEL_SIZE, ustmtext(month_name, pte), MONTH_LABEL_SIZE);
1775 ast_log(LOG_WARNING,
"%s\n", month_name);
1776 ast_log(LOG_WARNING,
"%s\n", ustmtext(month_name, pte));
1777 month = (month + 1)%12;
1780 send_client(SIZE_HEADER +
sizeof(packet_send_monthlabels_download), buffsend, pte);
1788 struct ast_tm atm = { 0, };
1791 ast_verb(0,
"Sending Time & Date\n");
1793 memcpy(buffsend + SIZE_HEADER, packet_send_date_time,
sizeof(packet_send_date_time));
1795 buffsend[10] = (
unsigned char) atm.
tm_mon + 1;
1796 buffsend[11] = (
unsigned char) atm.
tm_mday;
1797 buffsend[12] = (
unsigned char) atm.
tm_hour;
1798 buffsend[13] = (
unsigned char) atm.
tm_min;
1799 send_client(SIZE_HEADER +
sizeof(packet_send_date_time), buffsend, pte);
1800 send_month_labels(pte, atm.
tm_mon);
1807 struct ast_tm atm = { 0, };
1810 ast_verb(0,
"Sending Time & Date #2\n");
1812 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2,
sizeof(packet_send_date_time2));
1819 buffsend[14] = (
unsigned char) atm.
tm_mon + 1;
1820 buffsend[15] = (
unsigned char) atm.
tm_mday;
1821 buffsend[16] = (
unsigned char) atm.
tm_hour;
1822 buffsend[17] = (
unsigned char) atm.
tm_min;
1823 send_client(SIZE_HEADER +
sizeof(packet_send_date_time2), buffsend, pte);
1830 struct ast_tm atm = { 0, };
1833 ast_verb(0,
"Sending Time & Date #3\n");
1835 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3,
sizeof(packet_send_date_time3));
1837 buffsend[10] = (
unsigned char) atm.
tm_mon + 1;
1838 buffsend[11] = (
unsigned char) atm.
tm_mday;
1839 buffsend[12] = (
unsigned char) atm.
tm_hour;
1840 buffsend[13] = (
unsigned char) atm.
tm_min;
1841 send_client(SIZE_HEADER +
sizeof(packet_send_date_time3), buffsend, pte);
1848 ast_verb(0,
"Sending set blink\n");
1850 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor,
sizeof(packet_send_blink_cursor));
1851 send_client(SIZE_HEADER +
sizeof(packet_send_blink_cursor), buffsend, pte);
1856 static void send_cursor_pos(
struct unistimsession *pte,
unsigned char pos)
1860 ast_verb(0,
"Sending set cursor position\n");
1862 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
1863 sizeof(packet_send_set_pos_cursor));
1865 send_client(SIZE_HEADER +
sizeof(packet_send_set_pos_cursor), buffsend, pte);
1869 static void send_charset_update(
struct unistimsession *pte,
int charset)
1871 const unsigned char* packet_send_charset;
1875 ast_verb(0,
"Sending set default charset\n");
1877 if (charset == LANG_DEFAULT) {
1878 charset = options_languages[find_language(pte->device->
language)].encoding;
1882 packet_send_charset = packet_send_charset_iso_8859_2;
1883 packet_size =
sizeof(packet_send_charset_iso_8859_2);
1886 packet_send_charset = packet_send_charset_iso_8859_4;
1887 packet_size =
sizeof(packet_send_charset_iso_8859_4);
1890 packet_send_charset = packet_send_charset_iso_8859_5;
1891 packet_size =
sizeof(packet_send_charset_iso_8859_5);
1894 packet_send_charset = packet_send_charset_iso_2022_jp;
1895 packet_size =
sizeof(packet_send_charset_iso_2022_jp);
1899 packet_send_charset = packet_send_charset_iso_8859_1;
1900 packet_size =
sizeof(packet_send_charset_iso_8859_1);
1902 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
1903 send_client(SIZE_HEADER + packet_size, buffsend, pte);
1907 static void rcv_resume_connection_with_server(
struct unistimsession *pte)
1911 ast_verb(0,
"ResumeConnectionWithServer received\n");
1912 ast_verb(0,
"Sending packet_send_query_mac_address\n");
1914 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
1915 sizeof(packet_send_query_mac_address));
1916 send_client(SIZE_HEADER +
sizeof(packet_send_query_mac_address), buffsend, pte);
1922 struct unistim_device *d;
1947 static void unistim_line_copy(
struct unistim_line *dst,
struct unistim_line *src)
1950 memcpy(dst, src,
sizeof(*dst));
1955 static struct unistim_line *unistim_line_destroy(
struct unistim_line *l)
1965 static struct unistim_line *unistim_line_alloc(
void)
1967 struct unistim_line *l;
1983 ast_mutex_destroy(&sub->lock);
1996 ast_verb(3,
"Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->
name, sub);
2003 ast_mutex_init(&sub->lock);
2007 static int unistim_unalloc_sub(
struct unistim_device *d,
struct unistim_subchannel *sub)
2020 unistim_free_sub(sub);
2027 static const char *subtype_tostr(
const int type)
2040 static const char *ptestate_tostr(
const int type)
2045 case STATE_AUTHDENY:
2047 case STATE_MAINPAGE:
2049 case STATE_EXTENSION:
2051 case STATE_DIALPAGE:
2057 case STATE_SELECTOPTION:
2058 return "SELECTOPTION";
2059 case STATE_SELECTCODEC:
2060 return "SELECTCODEC";
2061 case STATE_SELECTLANGUAGE:
2062 return "SELECTLANGUAGE";
2063 case STATE_CLEANING:
2071 static void rcv_mac_addr(
struct unistimsession *pte,
const unsigned char *buf)
2077 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
2078 sprintf(&addrmac[i],
"%02hhx", buf[tmp]);
2082 ast_verb(0,
"MAC Address received: %s\n", addrmac);
2084 strcpy(pte->
macaddr, addrmac);
2085 res = unistim_register(pte);
2087 switch (autoprovisioning) {
2088 case AUTOPROVISIONING_NO:
2089 ast_log(LOG_WARNING,
"No entry found for this phone : %s\n", addrmac);
2090 pte->
state = STATE_AUTHDENY;
2092 case AUTOPROVISIONING_YES:
2094 struct unistim_device *d = NULL, *newd = NULL;
2095 struct unistim_line *newl = NULL, *l = NULL;
2097 ast_verb(0,
"New phone, autoprovisioning on\n");
2103 if (strcasecmp(d->
name,
"template")) {
2112 memcpy(newd, d,
sizeof(*newd));
2113 ast_mutex_init(&newd->lock);
2114 newd->lines.first = NULL;
2115 newd->lines.last = NULL;
2118 if (!(newl = unistim_line_alloc())) {
2121 unistim_line_copy(l, newl);
2122 newl->parent = newd;
2125 newl->name, newd->name);
2126 snprintf(l->name,
sizeof(l->name),
"%d", atoi(l->name) + 1);
2145 newd->receiver_state = STATE_ONHOOK;
2146 newd->session = pte;
2147 newd->language[0] =
'\0';
2148 newd->to_delete = -1;
2162 ast_log(LOG_WARNING,
"No entry [template] found in unistim.conf\n");
2163 pte->
state = STATE_AUTHDENY;
2167 case AUTOPROVISIONING_TN:
2168 pte->
state = STATE_AUTHDENY;
2171 ast_log(LOG_WARNING,
"Internal error : unknown autoprovisioning value = %u\n",
2175 if (pte->
state != STATE_AUTHDENY) {
2176 struct unistim_line *line;
2179 ast_verb(3,
"Device '%s' successfuly registered\n", pte->device->
name);
2184 ast_log(LOG_ERROR,
"Subchannel lost sice reboot. Hanged channel may apear!\n");
2194 pte->
state = STATE_MAINPAGE;
2199 pte->
state = STATE_EXTENSION;
2202 if (register_extension(pte)) {
2203 pte->
state = STATE_EXTENSION;
2205 pte->
state = STATE_MAINPAGE;
2213 if (register_extension(pte)) {
2214 pte->
state = STATE_EXTENSION;
2216 pte->
state = STATE_MAINPAGE;
2221 pte->
state = STATE_MAINPAGE;
2224 ast_log(LOG_WARNING,
"Internal error, extension value unknown : %u\n",
2226 pte->
state = STATE_AUTHDENY;
2230 if (pte->
state == STATE_EXTENSION) {
2237 ast_verb(0,
"\nSending S1\n");
2239 memcpy(buffsend + SIZE_HEADER, packet_send_S1,
sizeof(packet_send_S1));
2240 send_client(SIZE_HEADER +
sizeof(packet_send_S1), buffsend, pte);
2243 ast_verb(0,
"Sending query_basic_manager_04\n");
2245 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
2246 sizeof(packet_send_query_basic_manager_04));
2247 send_client(SIZE_HEADER +
sizeof(packet_send_query_basic_manager_04), buffsend, pte);
2250 ast_verb(0,
"Sending query_basic_manager_10\n");
2252 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
2253 sizeof(packet_send_query_basic_manager_10));
2254 send_client(SIZE_HEADER +
sizeof(packet_send_query_basic_manager_10), buffsend, pte);
2256 send_date_time(pte);
2260 static int write_entry_history(
struct unistimsession *pte, FILE * f,
char c,
char *line1)
2262 if (fwrite(&c, 1, 1, f) != 1) {
2263 display_last_error(
"Unable to write history log header.");
2266 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2267 display_last_error(
"Unable to write history entry - date.");
2270 if (fwrite(pte->device->
lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
2271 display_last_error(
"Unable to write history entry - callerid.");
2274 if (fwrite(pte->device->
lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
2275 display_last_error(
"Unable to write history entry - callername.");
2281 static int write_history(
struct unistimsession *pte,
char way,
char ismissed)
2283 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
2284 char line1[TEXT_LENGTH_MAX + 1];
2285 char count = 0, *histbuf;
2289 struct ast_tm atm = { 0, };
2297 if (strchr(pte->device->
name,
'/') || (pte->device->
name[0] ==
'.')) {
2298 ast_log(LOG_WARNING,
"Account code '%s' insecure for writing file\n",
2303 snprintf(tmp,
sizeof(tmp),
"%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
2305 ast_log(LOG_WARNING,
"Unable to create directory for history\n");
2319 snprintf(line1,
sizeof(line1),
"%04d/%02d/%02d %02d:%02d:%02d %s",
2323 snprintf(tmp,
sizeof(tmp),
"%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
2324 USTM_LOG_DIR, pte->device->
name, way);
2325 if ((f = fopen(tmp,
"r"))) {
2326 struct stat bufstat;
2328 if (stat(tmp, &bufstat)) {
2329 display_last_error(
"Unable to stat history log.");
2333 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
2334 if (bufstat.st_size != size) {
2335 ast_log(LOG_WARNING,
2336 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
2337 tmp, (
int) bufstat.st_size, size);
2349 if ((errno != ENOENT) && (count == 0)) {
2350 display_last_error(
"Unable to open history log.");
2353 f = fopen(tmp,
"w");
2355 display_last_error(
"Unable to create history log.");
2358 if (write_entry_history(pte, f, c, line1)) {
2362 memset(line1,
' ', TEXT_LENGTH_MAX);
2363 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
2364 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
2365 display_last_error(
"Unable to write history entry - stuffing.");
2371 display_last_error(
"Unable to close history - creation.");
2376 if (fread(&count, 1, 1, f) != 1) {
2377 display_last_error(
"Unable to read history header.");
2381 if (count > MAX_ENTRY_LOG) {
2382 ast_log(LOG_WARNING,
"Invalid count in history header of %s (%d max %d)\n", tmp,
2383 count, MAX_ENTRY_LOG);
2387 snprintf(tmp2,
sizeof(tmp2),
"%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
2388 USTM_LOG_DIR, pte->device->
name, way);
2389 if (!(f2 = fopen(tmp2,
"w"))) {
2390 display_last_error(
"Unable to create temporary history log.");
2395 if (++count > MAX_ENTRY_LOG) {
2396 count = MAX_ENTRY_LOG;
2398 if (write_entry_history(pte, f2, count, line1)) {
2403 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
2410 if (fread(histbuf, size, 1, f) != 1) {
2414 display_last_error(
"Unable to read previous history entries.");
2417 if (fwrite(histbuf, size, 1, f2) != 1) {
2421 display_last_error(
"Unable to write previous history entries.");
2426 display_last_error(
"Unable to close history log.");
2429 display_last_error(
"Unable to close temporary history log.");
2432 display_last_error(
"Unable to remove old history log.");
2434 if (rename(tmp2, tmp)) {
2435 display_last_error(
"Unable to rename new history log.");
2446 ast_log(LOG_WARNING,
"Transfer attempted without dual ownership?\n");
2454 ast_log(LOG_WARNING,
"Transfer failed. Invalid bridge setup\n");
2457 ast_log(LOG_WARNING,
"Transfer not permitted\n");
2460 ast_log(LOG_WARNING,
"Transfer encountered internal error\n");
2472 void change_callerid(
struct unistimsession *pte,
int type,
char *callerid)
2485 memset(data,
' ', TEXT_LENGTH_MAX);
2486 size = strlen(callerid);
2487 if (size > TEXT_LENGTH_MAX) {
2488 size = TEXT_LENGTH_MAX;
2490 memcpy(data, callerid, size);
2502 if (sub->subtype == type) {
2511 static struct unistim_subchannel* get_sub_holding(
struct unistim_device *device,
int type,
int holding)
2520 if (sub->subtype == type && sub->holding == holding) {
2532 if (!pte->device->silence_generator) {
2533 pte->device->silence_generator =
2535 if (pte->device->silence_generator == NULL) {
2536 ast_log(LOG_WARNING,
"Unable to start a silence generator.\n");
2538 ast_verb(0,
"Starting silence generator\n");
2547 if (pte->device->silence_generator) {
2549 ast_verb(0,
"Stopping silence generator\n");
2554 ast_log(LOG_WARNING,
"Trying to stop silence generator on a null channel!\n");
2556 pte->device->silence_generator = NULL;
2567 send_favorite_short(sub->
softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
2568 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_ON);
2569 send_stop_timer(pte);
2580 sub_real = get_sub(pte->device,
SUB_REAL);
2582 sub_hold(pte, sub_real);
2587 send_favorite_short(sub->
softkey, FAV_ICON_OFFHOOK_BLACK, pte);
2588 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_OFF);
2589 send_start_timer(pte);
2593 send_start_rtp(sub);
2603 sub = get_sub(pte->device,
SUB_REAL);
2605 send_stop_timer(pte);
2607 ast_log(LOG_WARNING,
"Close call without sub\n");
2610 send_favorite_short(sub->
softkey, FAV_LINE_ICON, pte);
2615 if (attempt_transfer(sub, sub_transf) < 0) {
2616 ast_verb(0,
"attempt_transfer failed.\n");
2623 if (sub_transf->
owner) {
2626 ast_log(LOG_WARNING,
"threeway sub without owner\n");
2629 ast_verb(0,
"USTM(%s@%s-%d) channel already destroyed\n", sub->
parent->name,
2634 change_callerid(pte, 1,
"");
2635 write_history(pte,
'o', pte->device->
missed_call);
2637 show_main_page(pte);
2650 sub = get_sub(pte->device, SUB_RING);
2659 static void *unistim_ss(
void *data)
2663 struct unistim_line *l = sub->
parent;
2670 ast_verb(3,
"Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->
name, sub->
softkey, s->device->
phone_number);
2671 ast_channel_lock(chan);
2674 ast_channel_unlock(chan);
2679 ast_log(LOG_WARNING,
"PBX exited non-zero\n");
2680 send_tone(s, 1000, 0);
2690 struct sockaddr_in us = { 0, };
2700 if (htons(us.sin_port)) {
2701 rtp_start = htons(us.sin_port) + 1;
2715 struct sockaddr_in public = { 0, };
2716 struct sockaddr_in us = { 0, };
2717 struct sockaddr_in sin = { 0, };
2728 if (public_ip.sin_family == 0) {
2729 memcpy(&
public, &us,
sizeof(
public));
2731 memcpy(&
public, &public_ip,
sizeof(
public));
2734 ast_verb(0,
"RTP started : Our IP/port is : %s:%hd with codec %s\n",
2737 ast_verb(0,
"Starting phone RTP stack. Our public IP is %s\n",
2741 pte = sub->
parent->parent->session;
2743 1, ast_channel_readformat(sub->
owner), 0);
2747 ast_verb(0,
"Sending packet_send_rtp_packet_size for codec %d\n", codec);
2749 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
2750 sizeof(packet_send_rtp_packet_size));
2751 buffsend[10] = (int) codec & 0xffffffffLL;
2752 send_client(SIZE_HEADER +
sizeof(packet_send_rtp_packet_size), buffsend, pte);
2755 ast_verb(0,
"Sending Jitter Buffer Parameters Configuration\n");
2757 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
2758 sizeof(packet_send_jitter_buffer_conf));
2759 send_client(SIZE_HEADER +
sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
2761 uint16_t rtcpsin_port = ntohs(us.sin_port) + 1;
2764 ast_verb(0,
"Sending OpenAudioStreamTX using method #%d\n", pte->device->
rtp_method);
2767 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
2768 sizeof(packet_send_open_audio_stream_tx3));
2770 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
2771 sizeof(packet_send_open_audio_stream_tx));
2774 memcpy(buffsend + 28, &
public.sin_addr,
sizeof(
public.sin_addr));
2775 put_unaligned_uint16(&buffsend[20], sin.sin_port);
2776 put_unaligned_uint16(&buffsend[22], htons(rtcpsin_port));
2777 put_unaligned_uint16(&buffsend[24], us.sin_port);
2778 put_unaligned_uint16(&buffsend[26], htons(rtcpsin_port));
2780 memcpy(buffsend + 23, &
public.sin_addr,
sizeof(
public.sin_addr));
2781 put_unaligned_uint16(&buffsend[15], sin.sin_port);
2782 put_unaligned_uint16(&buffsend[19], us.sin_port);
2784 buffsend[11] = codec;
2785 buffsend[12] = codec;
2786 send_client(SIZE_HEADER +
sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
2789 ast_verb(0,
"Sending OpenAudioStreamRX\n");
2792 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
2793 sizeof(packet_send_open_audio_stream_rx3));
2795 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
2796 sizeof(packet_send_open_audio_stream_rx));
2799 memcpy(buffsend + 28, &
public.sin_addr,
sizeof(
public.sin_addr));
2800 put_unaligned_uint16(&buffsend[20], sin.sin_port);
2801 put_unaligned_uint16(&buffsend[22], htons(rtcpsin_port));
2802 put_unaligned_uint16(&buffsend[24], us.sin_port);
2803 put_unaligned_uint16(&buffsend[26], htons(rtcpsin_port));
2805 memcpy(buffsend + 23, &
public.sin_addr,
sizeof(
public.sin_addr));
2806 put_unaligned_uint16(&buffsend[15], sin.sin_port);
2807 put_unaligned_uint16(&buffsend[19], us.sin_port);
2809 buffsend[11] = codec;
2810 buffsend[12] = codec;
2811 send_client(SIZE_HEADER +
sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
2813 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
2816 ast_verb(0,
"Sending packet_send_call default method\n");
2819 memcpy(buffsend + SIZE_HEADER, packet_send_call,
sizeof(packet_send_call));
2820 memcpy(buffsend + 53, &
public.sin_addr,
sizeof(
public.sin_addr));
2822 put_unaligned_uint16(&buffsend[49], us.sin_port);
2824 put_unaligned_uint16(&buffsend[51], htons(rtcpsin_port));
2826 buffsend[40] = codec;
2827 buffsend[41] = codec;
2837 ast_log(LOG_WARNING,
"Unsupported codec %s!\n",
2841 put_unaligned_uint16(&buffsend[45], sin.sin_port);
2842 put_unaligned_uint16(&buffsend[47], htons(rtcpsin_port));
2843 send_client(SIZE_HEADER +
sizeof(packet_send_call), buffsend, pte);
2849 struct sockaddr_in sin = { 0, };
2850 struct sockaddr_in sout = { 0, };
2856 ast_log(LOG_WARNING,
"start_rtp with a null subchannel !\n");
2860 ast_log(LOG_WARNING,
"start_rtp with a null line!\n");
2863 if (!sub->
parent->parent) {
2864 ast_log(LOG_WARNING,
"start_rtp with a null device!\n");
2867 if (!sub->
parent->parent->session) {
2868 ast_log(LOG_WARNING,
"start_rtp with a null session!\n");
2872 ast_log(LOG_WARNING,
"start_rtp with a null asterisk channel!\n");
2876 ast_mutex_lock(&sub->lock);
2879 ast_verb(0,
"Starting RTP. Bind on %s\n",
ast_inet_ntoa(sout.sin_addr));
2884 ast_log(LOG_WARNING,
"Unable to create RTP session: %s binaddr=%s\n",
2886 ast_mutex_unlock(&sub->lock);
2897 sin.sin_family = AF_INET;
2899 memcpy(&sin.sin_addr, &sub->
parent->parent->session->
sin.sin_addr,
2900 sizeof(sin.sin_addr));
2902 sin.sin_port = htons(find_rtp_port(sub));
2910 ast_log(LOG_WARNING,
2911 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
2916 ast_channel_set_readformat(sub->
owner, tmpfmt);
2917 ast_channel_set_writeformat(sub->
owner, tmpfmt);
2920 send_start_rtp(sub);
2921 ast_mutex_unlock(&sub->lock);
2933 s = strsep(&ind,
",");
2935 send_tone(pte, tone_data.freq1, tone_data.freq2);
2937 ast_verb(0,
"Country code found (%s), freq1=%u freq2=%u\n",
2938 pte->device->
tz->
country, tone_data.freq1, tone_data.freq2);
2946 char tmp[TEXT_LENGTH_MAX + 1];
2947 const char *tmp_number = ustmtext(
"Number:", pte);
2948 int line, tmp_copy, offset = 0, i;
2953 if (offset > strlen(tmp_number)) {
2954 offset = strlen(tmp_number);
2956 tmp_copy = strlen(tmp_number) - offset + 1;
2957 if (tmp_copy >
sizeof(tmp)) {
2958 tmp_copy =
sizeof(tmp);
2960 memcpy(tmp, tmp_number + offset, tmp_copy);
2969 offset = strlen(tmp);
2971 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
2976 line = (pte->device->
height == 1) ? TEXT_LINE0 : TEXT_LINE2;
2977 send_text(line, TEXT_NORMAL, pte, tmp);
2978 send_blink_cursor(pte);
2979 send_cursor_pos(pte, (
unsigned char) (line + offset));
2980 send_led_update(pte, LED_BAR_OFF);
2985 pte->
state = STATE_DIALPAGE;
2987 send_text(TEXT_LINE0, TEXT_NORMAL, pte,
"");
2988 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"Enter forward", pte));
2989 send_text_status(pte, ustmtext(
"Fwd Cancel BackSp Erase", pte));
2993 show_phone_number(pte);
2994 send_led_update(pte, LED_BAR_OFF);
2998 if ((pte->device->
output == OUTPUT_HANDSET) &&
3000 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
3002 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_OFF);
3004 send_dial_tone(pte);
3006 if (pte->device->
height > 1) {
3007 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Enter the number to dial", pte));
3008 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"and press Call", pte));
3011 send_text_status(pte, ustmtext(
"Call BackSp Erase", pte));
3013 send_text_status(pte, ustmtext(
"Call Redial BackSp Erase", pte));
3019 show_phone_number(pte);
3020 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
3021 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
3023 send_led_update(pte, LED_BAR_OFF);
3024 pte->device->lastmsgssent = -1;
3034 ast_verb(0,
"Swapping %p and %p\n", a, b);
3037 ast_log(LOG_WARNING,
3038 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
3046 fds = ast_channel_fd(a->
owner, 0);
3047 ast_channel_internal_fd_set(a->
owner, 0, ast_channel_fd(b->
owner, 0));
3048 ast_channel_internal_fd_set(b->
owner, 0, fds);
3050 fds = ast_channel_fd(a->
owner, 1);
3051 ast_channel_internal_fd_set(a->
owner, 1, ast_channel_fd(b->
owner, 1));
3052 ast_channel_internal_fd_set(b->
owner, 1, fds);
3059 struct unistim_device *d = pte->device;
3064 if (!sub || !sub->
owner) {
3065 ast_log(LOG_WARNING,
"Unable to find subchannel for music on hold\n");
3070 ast_log(LOG_WARNING,
"Transfer with peer already listening music on hold\n");
3076 sub_start_silence(pte, sub);
3077 handle_dial_page(pte);
3083 struct unistim_device *d = pte->device;
3088 if (!sub || !sub->
owner) {
3089 ast_log(LOG_WARNING,
"Unable to find subchannel for music on hold\n");
3094 ast_verb(0,
"Transfer canceled, hangup our threeway channel\n");
3097 swap_subs(sub, sub_trans);
3104 ast_log(LOG_WARNING,
"Canceling a threeway channel without owner\n");
3117 s->
state = STATE_CALL;
3123 struct unistim_device *d = s->device;
3127 ast_log(LOG_WARNING,
"Can't transfer while active subchannel exists!\n");
3131 ast_log(LOG_WARNING,
"Unable to find subchannel with music on hold\n");
3135 sub_trans = unistim_alloc_sub(d,
SUB_REAL);
3137 ast_log(LOG_WARNING,
"Unable to allocate three-way subchannel\n");
3141 sub_stop_silence(s, sub);
3146 ast_log(LOG_WARNING,
"Cannot allocate new structure on channel %p\n", sub->
parent);
3150 swap_subs(sub, sub_trans);
3151 send_select_output(s, s->device->
output, s->device->
volume, MUTE_OFF);
3152 if (s->device->
height == 1) {
3153 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->
phone_number);
3155 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext(
"Calling (pre-transfer)", s));
3156 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->
phone_number);
3157 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"Dialing...", s));
3159 send_text_status(s, ustmtext(
"TransfrCancel", s));
3161 if (ast_pthread_create(&sub->
ss_thread, NULL, unistim_ss, c)) {
3162 ast_log(LOG_WARNING,
"Unable to start simple switch on channel %p\n", c);
3168 ast_verb(0,
"Started three way call on channel %p (%s) subchan %u\n",
3169 sub_trans->
owner, ast_channel_name(sub_trans->
owner), sub_trans->subtype);
3174 softkey = get_avail_softkey(s, NULL);
3175 if (softkey == -1) {
3176 ast_log(LOG_WARNING,
"Have no avail softkey for calling\n");
3179 sub = get_sub(s->device,
SUB_REAL);
3183 if (!(sub = unistim_alloc_sub(s->device,
SUB_REAL))) {
3184 ast_log(LOG_WARNING,
"Unable to allocate subchannel!\n");
3188 s->device->ssub[
softkey] = sub;
3192 ast_verb(0,
"Using softkey %d, line %p\n", sub->
softkey, sub->
parent);
3194 send_favorite_short(sub->
softkey, FAV_ICON_OFFHOOK_BLACK, s);
3198 const char *pickupexten;
3205 ast_channel_lock(c);
3206 pickup_cfg = ast_get_chan_features_pickup_config(c);
3208 ast_log(LOG_ERROR,
"Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
3211 pickupexten =
ast_strdupa(pickup_cfg->pickupexten);
3213 ast_channel_unlock(c);
3215 if (c && !strcmp(s->device->
phone_number, pickupexten)) {
3217 ast_verb(0,
"Try to pickup in unistim_new\n");
3219 send_text(TEXT_LINE0, TEXT_NORMAL, s,
"");
3220 send_text_status(s, ustmtext(
" Transf Hangup", s));
3221 send_start_timer(s);
3223 ast_log(LOG_NOTICE,
"Nothing to pick up\n");
3224 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
3226 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
3231 send_select_output(s, s->device->
output, s->device->
volume, MUTE_OFF);
3233 if (s->device->
height == 1) {
3235 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->
phone_number);
3237 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext(
"Calling...", s));
3240 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext(
"Calling :", s));
3241 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->
phone_number);
3242 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"Dialing...", s));
3244 send_text_status(s, ustmtext(
" Hangup", s));
3247 if (ast_pthread_create(&sub->
ss_thread, NULL, unistim_ss, c)) {
3248 ast_log(LOG_WARNING,
"Unable to create switch thread\n");
3253 ast_log(LOG_WARNING,
"Unable to create channel for %s@%s\n",
3256 ast_debug(1,
"Current sub [%s] already has owner\n", ast_channel_name(sub->
owner));
3267 s->
state = STATE_CALL;
3270 sub = get_sub(s->device, SUB_RING);
3272 ast_log(LOG_WARNING,
"No ringing lines on: %s\n", s->device->
name);
3276 for (i = 0; i < FAVNUM; i++) {
3277 if (!s->device->ssub[i]) {
3280 if (s->device->ssub[i]->subtype ==
SUB_REAL) {
3281 sub_hold(s, s->device->ssub[i]);
3283 if (s->device->ssub[i] != sub) {
3293 send_favorite_short(i, FAV_LINE_ICON, s);
3294 s->device->ssub[i] = NULL;
3297 ast_log(LOG_WARNING,
"Can not assign softkey for incoming call on: %s\n", s->device->
name);
3300 send_favorite_short(sub->
softkey, FAV_ICON_OFFHOOK_BLACK, s);
3304 ast_verb(0,
"Handle Call Incoming for %s@%s\n", sub->
parent->name,
3309 ast_log(LOG_WARNING,
"Unable to create channel for %s@%s\n", sub->
parent->name, s->device->
name);
3315 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"is on-line", s));
3316 send_text_status(s, ustmtext(
" Transf Hangup", s));
3317 send_start_timer(s);
3319 if ((s->device->
output == OUTPUT_HANDSET) &&
3321 send_select_output(s, OUTPUT_SPEAKER, s->device->
volume, MUTE_OFF);
3323 send_select_output(s, s->device->
output, s->device->
volume, MUTE_OFF);
3325 write_history(s,
'i', 0);
3329 static int send_dtmf_tone(
struct unistimsession *pte,
char digit)
3334 ast_verb(0,
"Phone Play Digit %c\n", digit);
3337 row = (digit -
'1') % 3;
3338 col = (digit -
'1' - row) / 3;
3339 if (digit >=
'1' && digit <=
'9') {
3340 send_tone(pte, dtmf_row[row], dtmf_col[col]);
3341 }
else if (digit >=
'A' && digit <=
'D') {
3342 send_tone(pte, dtmf_row[digit-
'A'], dtmf_col[3]);
3343 }
else if (digit ==
'*') {
3344 send_tone(pte, dtmf_row[3], dtmf_col[0]);
3345 }
else if (digit ==
'0') {
3346 send_tone(pte, dtmf_row[3], dtmf_col[1]);
3347 }
else if (digit ==
'#') {
3348 send_tone(pte, dtmf_row[3], dtmf_col[2]);
3350 send_tone(pte, 500, 2000);
3356 static int unistim_do_senddigit(
struct unistimsession *pte,
char digit)
3358 struct ast_frame f = { .
frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src =
"unistim" };
3361 sub = get_sub(pte->device,
SUB_REAL);
3363 ast_log(LOG_WARNING,
"Unable to find subchannel in dtmf senddigit\n");
3371 ast_verb(0,
"Send Digit %c (%i ms)\n", digit, pte->device->
dtmfduration);
3373 send_dtmf_tone(pte, digit);
3375 send_tone(pte, 0, 0);
3380 static void handle_key_fav(
struct unistimsession *pte,
char keycode)
3382 int keynum = keycode - KEY_FAV0;
3384 sub = get_sub_holding(pte->device,
SUB_REAL, 0);
3387 if (!pte->device->ssub[keynum]) {
3388 sub = get_sub_holding(pte->device,
SUB_REAL, 0);
3389 send_favorite_selected(FAV_LINE_ICON, pte);
3390 if (is_key_line(pte->device, keynum)) {
3392 ast_verb(0,
"Handle line w/o sub - dialpage\n");
3396 send_stop_timer(pte);
3397 handle_dial_page(pte);
3398 }
else if (is_key_favorite(pte->device, keynum)) {
3402 ast_verb(0,
"Handle favorite w/o sub - dialing\n");
3404 if ((pte->device->
output == OUTPUT_HANDSET) &&
3406 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
3408 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_OFF);
3410 key_favorite(pte, keycode);
3413 sub_key = pte->device->ssub[keynum];
3415 if (sub_key->subtype ==
SUB_REAL && !sub_key->holding) {
3416 sub_hold(pte, sub_key);
3417 show_main_page(pte);
3418 }
else if (sub_key->subtype ==
SUB_REAL && sub_key->holding) {
3420 if (pte->
state == STATE_DIALPAGE){
3421 send_tone(pte, 0, 0);
3424 send_callerid_screen(pte, sub_key);
3425 sub_unhold(pte, sub_key);
3426 pte->
state = STATE_CALL;
3427 }
else if (sub_key->subtype == SUB_RING) {
3430 handle_call_incoming(pte);
3443 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3444 if (keycode == KEY_SHARP) {
3446 }
else if (keycode == KEY_STAR) {
3451 unistim_do_senddigit(pte, keycode);
3464 transfer_cancel_step2(pte);
3466 transfer_call_step1(pte);
3481 handle_key_fav(pte, keycode);
3484 if (pte->device->
output == OUTPUT_HEADPHONE) {
3485 send_select_output(pte, OUTPUT_HANDSET, pte->device->
volume, MUTE_OFF);
3487 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->
volume, MUTE_OFF);
3491 if (pte->device->
output != OUTPUT_SPEAKER)
3492 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
3499 if(pte->device->ssub[pte->device->
selected]) {
3500 sub = pte->device->ssub[pte->device->
selected];
3506 sub_unhold(pte, sub);
3515 static void key_ringing(
struct unistimsession *pte,
char keycode)
3524 handle_key_fav(pte, keycode);
3534 pte->device->
output = OUTPUT_SPEAKER;
3535 handle_call_incoming(pte);
3538 pte->device->
output = OUTPUT_HEADPHONE;
3539 handle_call_incoming(pte);
3542 handle_call_incoming(pte);
3548 static void key_favorite(
struct unistimsession *pte,
char keycode)
3550 int fav = keycode - KEY_FAV0;
3551 if (!is_key_favorite(pte->device, fav)) {
3552 ast_log(LOG_WARNING,
"It's not a favorite key\n");
3557 handle_call_outgoing(pte);
3561 static void key_dial_page(
struct unistimsession *pte,
char keycode)
3566 if (keycode == KEY_FUNC3) {
3568 keycode = KEY_FUNC4;
3574 if (keycode == KEY_SHARP && pte->device->
sharp_dial == 1) {
3575 keycode = KEY_FUNC1;
3577 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
3581 send_tone(pte, 0, 0);
3583 if (keycode == KEY_SHARP) {
3585 }
else if (keycode == KEY_STAR) {
3593 show_phone_number(pte);
3597 keycode = KEY_FUNC1;
3604 if (keycode == KEY_FUNC4) {
3606 show_phone_number(pte);
3611 if (keycode == KEY_FUNC1) {
3614 show_main_page(pte);
3615 }
else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
3617 send_led_update(pte, LED_SPEAKER_OFF);
3618 send_led_update(pte, LED_HEADPHONE_OFF);
3619 show_main_page(pte);
3631 handle_call_outgoing(pte);
3634 if (sub && sub->
owner) {
3635 sub_stop_silence(pte, sub);
3636 send_tone(pte, 0, 0);
3640 pte->
state = STATE_CALL;
3642 send_text_status(pte, ustmtext(
" Transf Hangup", pte));
3643 send_callerid_screen(pte, sub);
3645 send_led_update(pte, LED_SPEAKER_OFF);
3646 send_led_update(pte, LED_HEADPHONE_OFF);
3647 show_main_page(pte);
3656 send_favorite_selected(FAV_LINE_ICON, pte);
3658 handle_key_fav(pte, keycode);
3661 if (pte->device->
output == OUTPUT_SPEAKER) {
3666 show_main_page(pte);
3669 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
3673 if (pte->device->
output == OUTPUT_HEADPHONE) {
3675 send_select_output(pte, OUTPUT_HANDSET, pte->device->
volume, MUTE_OFF);
3677 show_main_page(pte);
3680 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->
volume, MUTE_OFF);
3691 if (pte->
state != STATE_SELECTOPTION) {
3692 pte->
state = STATE_SELECTOPTION;
3696 snprintf(tmp,
sizeof(tmp),
"%d. %s", pte->
buff_entry[0] + 1, ustmtext(options_menu[(
int)pte->
buff_entry[0]].label, pte));
3697 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
3698 send_text_status(pte, ustmtext(
"Select Cancel", pte));
3702 static void key_select_option(
struct unistimsession *pte,
char keycode)
3707 if (options_menu[(
int)pte->
buff_entry[0]].label == NULL) {
3717 options_menu[(int)pte->
buff_entry[0]].handle_option(pte);
3721 show_main_page(pte);
3725 handle_select_option(pte);
3729 #define SELECTCODEC_START_ENTRY_POS 15
3730 #define SELECTCODEC_MAX_LENGTH 2
3731 #define SELECTCODEC_MSG "Codec number : .."
3734 char buf[30], buf2[6];
3736 pte->
state = STATE_SELECTCODEC;
3738 snprintf(buf2,
sizeof(buf2),
" %d", pte->device->
codec_number);
3740 strcat(buf,
" (G711u=0,");
3742 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
3743 send_text(TEXT_LINE1, TEXT_NORMAL, pte,
"G723=4,G711a=8,G729A=18)");
3744 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
3745 send_blink_cursor(pte);
3746 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
3748 send_text_status(pte, ustmtext(
"Select BackSp Erase Cancel", pte));
3752 static void key_select_codec(
struct unistimsession *pte,
char keycode)
3754 if (keycode == KEY_FUNC2) {
3756 keycode = KEY_FUNC3;
3762 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
3763 char tmpbuf[] = SELECTCODEC_MSG;
3769 while (i < pte->size_buff_entry) {
3770 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->
buff_entry[i];
3773 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
3776 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
3777 send_blink_cursor(pte);
3778 send_cursor_pos(pte,
3779 (
unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
3791 show_main_page(pte);
3795 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
3796 send_blink_cursor(pte);
3797 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
3801 show_main_page(pte);
3807 static int find_language(
const char* lang)
3810 while (options_languages[i].lang_short != NULL) {
3811 if(!strcmp(options_languages[i].lang_short, lang)) {
3821 char tmp_language[40];
3824 if (pte->
state != STATE_SELECTLANGUAGE) {
3825 pte->
state = STATE_SELECTLANGUAGE;
3829 lang = options_languages[(int)pte->
buff_entry[0]];
3832 send_charset_update(pte, lang.encoding);
3833 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(lang.label, pte));
3836 lang = options_languages[find_language(pte->device->
language)];
3837 send_charset_update(pte, lang.encoding);
3838 send_text_status(pte, ustmtext(
"Select Cancel", pte));
3842 static void key_select_language(
struct unistimsession *pte,
char keycode)
3847 if (options_languages[(
int)pte->
buff_entry[0]].label == NULL) {
3858 send_charset_update(pte, options_languages[(
int)pte->
buff_entry[0]].encoding);
3859 refresh_all_favorite(pte);
3860 show_main_page(pte);
3864 handle_select_option(pte);
3868 handle_select_language(pte);
3873 #define SELECTEXTENSION_START_ENTRY_POS 0
3874 #define SELECTEXTENSION_MAX_LENGTH 10
3875 #define SELECTEXTENSION_MSG ".........."
3878 pte->
state = STATE_EXTENSION;
3880 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Please enter a Terminal", pte));
3881 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"Number (TN) :", pte));
3882 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
3883 send_blink_cursor(pte);
3884 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
3885 send_text_status(pte, ustmtext(
"Enter BackSpcErase", pte));
3890 static void key_select_extension(
struct unistimsession *pte,
char keycode)
3892 if (keycode == KEY_FUNC2) {
3894 keycode = KEY_FUNC3;
3900 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
3901 char tmpbuf[] = SELECTEXTENSION_MSG;
3907 while (i < pte->size_buff_entry) {
3908 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->
buff_entry[i];
3911 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
3914 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
3915 send_blink_cursor(pte);
3916 send_cursor_pos(pte, (
unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 + i));
3925 if (autoprovisioning == AUTOPROVISIONING_TN) {
3926 struct unistim_device *d;
3933 if (d->
id[0] ==
'T') {
3947 show_main_page(pte);
3948 refresh_all_favorite(pte);
3955 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Invalid Terminal Number.", pte));
3956 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"Please try again :", pte));
3957 send_cursor_pos(pte, (
unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
3959 send_blink_cursor(pte);
3963 if (register_extension(pte)) {
3964 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Invalid extension.", pte));
3965 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"Please try again :", pte));
3966 send_cursor_pos(pte, (
unsigned char) (TEXT_LINE2 +
3967 SELECTEXTENSION_START_ENTRY_POS +
3969 send_blink_cursor(pte);
3971 show_main_page(pte);
3976 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
3977 send_blink_cursor(pte);
3978 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
3984 static void show_entry_history(
struct unistimsession *pte, FILE ** f)
3986 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
3990 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
3991 display_last_error(
"Can't read history date entry");
3995 line[
sizeof(line) - 1] =
'\0';
3996 if (pte->device->
height == 1) {
3998 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
4001 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
4004 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
4005 display_last_error(
"Can't read callerid entry");
4009 line[
sizeof(line) - 1] =
'\0';
4012 if (pte->device->
height == 1) {
4014 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
4017 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
4020 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
4021 display_last_error(
"Can't read callername entry");
4025 line[
sizeof(line) - 1] =
'\0';
4026 if (pte->device->
height == 1) {
4028 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
4031 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
4035 snprintf(line,
sizeof(line),
"%s %03d/%03d", ustmtext(
"Call", pte), pte->
buff_entry[2],
4037 send_texttitle(pte, line);
4049 if (strlen(pte->device->
lst_cid)) {
4054 snprintf(status,
sizeof(status),
"%s%s%s%s", func1, func2, func3, ustmtext(
"Cancel", pte));
4055 send_text_status(pte, status);
4058 static char open_history(
struct unistimsession *pte,
char way, FILE ** f)
4060 char tmp[AST_CONFIG_MAX_PATH];
4063 snprintf(tmp,
sizeof(tmp),
"%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
4064 USTM_LOG_DIR, pte->device->
name, way);
4065 *f = fopen(tmp,
"r");
4067 display_last_error(
"Unable to open history file");
4070 if (fread(&count, 1, 1, *f) != 1) {
4071 display_last_error(
"Unable to read history header - display.");
4076 if (count > MAX_ENTRY_LOG) {
4077 ast_log(LOG_WARNING,
"Invalid count in history header of %s (%d max %d)\n", tmp,
4078 count, MAX_ENTRY_LOG);
4097 count = open_history(pte, way, &f);
4105 show_entry_history(pte, &f);
4106 pte->
state = STATE_HISTORY;
4111 char tmpbuf[TEXT_LENGTH_MAX + 1];
4116 show_extension_page(pte);
4120 pte->
state = STATE_MAINPAGE;
4121 send_led_update(pte, LED_BAR_OFF);
4122 pte->device->lastmsgssent = -1;
4124 send_tone(pte, 0, 0);
4125 send_stop_timer(pte);
4126 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_ON_DISCRET);
4127 send_led_update(pte, LED_SPEAKER_OFF);
4128 send_led_update(pte, LED_HEADPHONE_OFF);
4131 if (pte->device->
height == 1) {
4132 char tmp_field[100];
4133 snprintf(tmp_field,
sizeof(tmp_field),
"%s %s", ustmtext(
"Fwd to:", pte), pte->device->
call_forward);
4134 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp_field);
4136 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Call forwarded to :", pte));
4137 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->
call_forward);
4139 send_icon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
4141 send_text_status(pte, ustmtext(
"Dial NoFwd ", pte));
4143 send_text_status(pte, ustmtext(
"Dial Redial NoFwd ", pte));
4148 send_text_status(pte, ustmtext(
"Dial Fwd Unregis", pte));
4150 send_text_status(pte, ustmtext(
"Dial Redial Fwd Unregis", pte));
4154 send_text_status(pte, ustmtext(
"Dial Fwd Pickup", pte));
4156 send_text_status(pte, ustmtext(
"Dial Redial Fwd Pickup", pte));
4159 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->
maintext1);
4161 send_date_time2(pte);
4162 send_idle_clock(pte);
4164 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(pte->device->
maintext0, pte));
4168 text = ustmtext(
"unanswered call", pte);
4170 text = ustmtext(
"unanswered calls", pte);
4172 snprintf(tmpbuf,
sizeof(tmpbuf),
"%d %s", pte->device->
missed_call, text);
4173 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
4174 send_icon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
4177 if (pte->device->
height > 1) {
4178 if (ast_strlen_zero(pte->device->
maintext2)) {
4179 strcpy(tmpbuf,
"IP : ");
4181 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
4183 send_text(TEXT_LINE2, TEXT_NORMAL, pte, ustmtext(pte->device->
maintext2, pte));
4187 send_texttitle(pte, ustmtext(pte->device->
titledefault, pte));
4188 change_favorite_icon(pte, FAV_LINE_ICON);
4191 static void key_main_page(
struct unistimsession *pte,
char keycode)
4194 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
4197 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
4198 handle_dial_page(pte);
4199 key_dial_page(pte, keycode);
4204 pte->device->
selected = get_avail_softkey(pte, NULL);
4205 handle_dial_page(pte);
4211 if ((pte->device->
output == OUTPUT_HANDSET) &&
4213 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
4215 send_select_output(pte, pte->device->
output, pte->device->
volume, MUTE_OFF);
4219 handle_call_outgoing(pte);
4227 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
4228 pte->device->
output = OUTPUT_HANDSET;
4229 show_main_page(pte);
4233 handle_dial_page(pte);
4237 unregister_extension(pte);
4239 show_extension_page(pte);
4245 pte->device->session = NULL;
4248 show_extension_page(pte);
4252 ast_get_chan_features_pickup_config(NULL), ao2_cleanup);
4255 ast_log(LOG_ERROR,
"Unable to retrieve pickup configuration options. Unable to detect call pickup extension\n");
4262 handle_call_outgoing(pte);
4271 handle_key_fav(pte, keycode);
4274 handle_select_option(pte);
4277 send_select_output(pte, OUTPUT_SPEAKER, pte->device->
volume, MUTE_OFF);
4278 handle_dial_page(pte);
4281 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->
volume, MUTE_OFF);
4282 handle_dial_page(pte);
4285 show_history(pte,
'o');
4288 show_history(pte,
'i');
4294 static void key_history(
struct unistimsession *pte,
char keycode)
4303 if (pte->device->
height == 1) {
4320 if (pte->device->
height == 1) {
4337 if (ast_strlen_zero(pte->device->
lst_cid)) {
4342 key_main_page(pte, KEY_FUNC2);
4346 show_main_page(pte);
4350 show_history(pte,
'o');
4352 show_main_page(pte);
4357 show_main_page(pte);
4359 show_history(pte,
'i');
4365 count = open_history(pte, pte->
buff_entry[0], &f);
4369 offset = ((pte->
buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
4370 if (fseek(f, offset, SEEK_CUR)) {
4371 display_last_error(
"Unable to seek history entry.");
4375 show_entry_history(pte, &f);
4385 ast_verb(0,
"Sending S4\n");
4387 memcpy(buffsend + SIZE_HEADER, packet_send_s4,
sizeof(packet_send_s4));
4388 send_client(SIZE_HEADER +
sizeof(packet_send_s4), buffsend, pte);
4389 send_date_time2(pte);
4390 send_date_time3(pte);
4392 ast_verb(0,
"Sending S7\n");
4394 memcpy(buffsend + SIZE_HEADER, packet_send_S7,
sizeof(packet_send_S7));
4395 send_client(SIZE_HEADER +
sizeof(packet_send_S7), buffsend, pte);
4397 ast_verb(0,
"Sending Contrast\n");
4399 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast,
sizeof(packet_send_Contrast));
4400 if (pte->device != NULL) {
4401 buffsend[9] = pte->device->
contrast;
4403 send_client(SIZE_HEADER +
sizeof(packet_send_Contrast), buffsend, pte);
4406 ast_verb(0,
"Sending S9\n");
4408 memcpy(buffsend + SIZE_HEADER, packet_send_s9,
sizeof(packet_send_s9));
4409 send_client(SIZE_HEADER +
sizeof(packet_send_s9), buffsend, pte);
4413 ast_verb(0,
"Sending S7\n");
4415 memcpy(buffsend + SIZE_HEADER, packet_send_S7,
sizeof(packet_send_S7));
4416 send_client(SIZE_HEADER +
sizeof(packet_send_S7), buffsend, pte);
4417 send_led_update(pte, LED_BAR_OFF);
4420 ast_verb(0,
"Sending init language\n");
4423 send_charset_update(pte, options_languages[find_language(pte->device->
language)].encoding);
4425 if (pte->
state < STATE_MAINPAGE) {
4426 if (autoprovisioning == AUTOPROVISIONING_TN) {
4427 show_extension_page(pte);
4433 for (i = 1; i < FAVNUM; i++) {
4434 send_favorite(i, 0, pte,
"");
4436 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Phone is not registered", pte));
4437 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(
"in unistim.conf", pte));
4438 strcpy(tmp,
"MAC = ");
4440 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
4441 send_text_status(pte,
"");
4442 send_texttitle(pte, ustmtext(
"UNISTIM for*", pte));
4446 show_main_page(pte);
4447 refresh_all_favorite(pte);
4449 ast_verb(0,
"Sending arrow\n");
4451 memcpy(buffsend + SIZE_HEADER, packet_send_arrow,
sizeof(packet_send_arrow));
4452 send_client(SIZE_HEADER +
sizeof(packet_send_arrow), buffsend, pte);
4461 send_led_update(pte, LED_MUTE_ON);
4462 }
else if (pte->device->
microphone == MUTE_ON) {
4464 send_led_update(pte, LED_MUTE_OFF);
4466 send_mute(pte, (pte->device->
microphone & 0x01));
4469 static void process_request(
int size,
unsigned char *buf,
struct unistimsession *pte)
4473 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
4474 sizeof(packet_recv_resume_connection_with_server)) == 0) {
4475 rcv_resume_connection_with_server(pte);
4478 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version,
sizeof(packet_recv_firm_version)) == 0) {
4481 ast_verb(0,
"Got the firmware version : '%s'\n", buf + 13);
4484 init_phone_step2(pte);
4487 if (memcmp(buf + SIZE_HEADER, packet_recv_it_type,
sizeof(packet_recv_it_type)) == 0) {
4488 char type = buf[13];
4490 ast_verb(0,
"Got the equipment type: '%d'\n", type);
4501 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr,
sizeof(packet_recv_mac_addr)) == 0) {
4502 rcv_mac_addr(pte, buf);
4505 if (memcmp(buf + SIZE_HEADER, packet_recv_r2,
sizeof(packet_recv_r2)) == 0) {
4507 ast_verb(0,
"R2 received\n");
4512 if (pte->
state < STATE_MAINPAGE) {
4514 ast_verb(0,
"Request not authorized in this state\n");
4518 if (!memcmp(buf + SIZE_HEADER, packet_recv_expansion_pressed_key,
sizeof(packet_recv_expansion_pressed_key))) {
4519 char keycode = buf[13];
4522 ast_verb(0,
"Expansion key pressed: keycode = 0x%02hhx - current state: %s\n", (
unsigned char)keycode,
4523 ptestate_tostr(pte->
state));
4526 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key,
sizeof(packet_recv_pressed_key))) {
4527 char keycode = buf[13];
4530 ast_verb(0,
"Key pressed: keycode = 0x%02hhx - current state: %s\n", (
unsigned char)keycode,
4531 ptestate_tostr(pte->
state));
4533 if (keycode == KEY_MUTE) {
4534 microphone_mute_toggle(pte);
4536 switch (pte->
state) {
4539 ast_verb(0,
"No keys allowed in the init state\n");
4542 case STATE_AUTHDENY:
4544 ast_verb(0,
"No keys allowed in authdeny state\n");
4547 case STATE_MAINPAGE:
4548 key_main_page(pte, keycode);
4550 case STATE_DIALPAGE:
4551 key_dial_page(pte, keycode);
4554 key_ringing(pte, keycode);
4557 key_call(pte, keycode);
4559 case STATE_EXTENSION:
4560 key_select_extension(pte, keycode);
4562 case STATE_SELECTOPTION:
4563 key_select_option(pte, keycode);
4565 case STATE_SELECTCODEC:
4566 key_select_codec(pte, keycode);
4568 case STATE_SELECTLANGUAGE:
4569 key_select_language(pte, keycode);
4572 key_history(pte, keycode);
4575 ast_log(LOG_WARNING,
"Key : Unknown state\n");
4579 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up,
sizeof(packet_recv_pick_up)) == 0) {
4581 ast_verb(0,
"Handset off hook, current state: %s\n", ptestate_tostr(pte->
state));
4587 if (pte->device->
output == OUTPUT_HEADPHONE) {
4588 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->
volume, MUTE_OFF);
4590 send_select_output(pte, OUTPUT_HANDSET, pte->device->
volume, MUTE_OFF);
4592 if (pte->
state == STATE_RINGING) {
4593 handle_call_incoming(pte);
4594 }
else if ((pte->
state == STATE_DIALPAGE) || (pte->
state == STATE_CALL)) {
4595 send_select_output(pte, OUTPUT_HANDSET, pte->device->
volume, MUTE_OFF);
4596 }
else if (pte->
state == STATE_EXTENSION) {
4599 pte->device->
selected = get_avail_softkey(pte, NULL);
4600 send_select_output(pte, OUTPUT_HANDSET, pte->device->
volume, MUTE_OFF);
4601 handle_dial_page(pte);
4605 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup,
sizeof(packet_recv_hangup)) == 0) {
4607 ast_verb(0,
"Handset on hook, current state: %s\n", ptestate_tostr(pte->
state));
4613 if (pte->
state == STATE_CALL) {
4614 if (pte->device->
output != OUTPUT_SPEAKER) {
4617 }
else if (pte->
state == STATE_EXTENSION) {
4621 show_main_page(pte);
4626 strcat(tmpbuf,
" Unknown request packet\n");
4633 static void parsing(
int size,
unsigned char *buf,
struct unistimsession *pte,
4634 struct sockaddr_in *addr_from)
4636 unsigned short *sbuf = (
unsigned short *) buf;
4644 ast_log(LOG_WARNING,
"%s Read error\n", tmpbuf);
4646 ast_log(LOG_NOTICE,
"%s Packet too short - ignoring\n", tmpbuf);
4650 if (sbuf[0] == 0xffff) {
4651 if (size !=
sizeof(packet_rcv_discovery)) {
4652 ast_log(LOG_NOTICE,
"%s Invalid size of a discovery packet\n", tmpbuf);
4654 if (memcmp(buf, packet_rcv_discovery,
sizeof(packet_rcv_discovery)) == 0) {
4656 ast_verb(0,
"Discovery packet received - Sending Discovery ACK\n");
4659 if (pte->
state == STATE_INIT) {
4661 ast_verb(1,
"Duplicated Discovery packet\n");
4663 send_raw_client(
sizeof(packet_send_discovery_ack),
4664 packet_send_discovery_ack, addr_from, &pte->
sout);
4668 if (create_client(addr_from)) {
4669 send_raw_client(
sizeof(packet_send_discovery_ack),
4670 packet_send_discovery_ack, addr_from, &pte->
sout);
4675 if ((pte = create_client(addr_from))) {
4676 send_raw_client(
sizeof(packet_send_discovery_ack),
4677 packet_send_discovery_ack, addr_from, &pte->
sout);
4682 ast_log(LOG_NOTICE,
"%s Invalid discovery packet\n", tmpbuf);
4688 ast_verb(0,
"%s Not a discovery packet from an unknown source : ignoring\n", tmpbuf);
4694 ast_log(LOG_NOTICE,
"Unknown packet received - ignoring\n");
4698 ast_log(LOG_NOTICE,
"%s Wrong direction : got 0x%02hhx expected 0x02\n", tmpbuf, buf[5]);
4701 seq = ntohs(sbuf[1]);
4703 ast_mutex_lock(&pte->lock);
4705 ast_verb(0,
"ACK received for packet #0x%04x\n", (
unsigned)seq);
4711 check_send_queue(pte);
4712 ast_mutex_unlock(&pte->lock);
4717 ast_verb(0,
"ACK at 0xffff, restarting counter.\n");
4721 "%s Warning : ACK received for an already ACKed packet : #0x%04x we are at #0x%04x\n",
4724 ast_mutex_unlock(&pte->lock);
4729 "%s Error : ACK received for a non-existent packet : #0x%04x\n",
4731 ast_mutex_unlock(&pte->lock);
4735 ast_verb(0,
"%s ACK gap : Received ACK #0x%04x, previous was #0x%04x\n",
4739 check_send_queue(pte);
4740 ast_mutex_unlock(&pte->lock);
4745 ast_verb(0,
"Request received\n");
4751 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->
sout);
4754 process_request(size, buf, pte);
4759 "%s Warning : received a retransmitted packet : #0x%04x (we are at #0x%04x)\n",
4760 tmpbuf, (
unsigned)seq, (
unsigned)pte->
seq_phone);
4765 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->
sout);
4769 "%s Warning : we lost a packet : received #0x%04x (we are at #0x%04x)\n",
4770 tmpbuf, (
unsigned)seq, (
unsigned)pte->
seq_phone);
4774 ast_log(LOG_NOTICE,
"%s Retransmit request for packet #0x%04x\n", tmpbuf, (
unsigned)seq);
4777 "%s Error : received a request for an already ACKed packet : #0x%04x\n",
4783 "%s Error : received a request for a non-existent packet : #0x%04x\n",
4787 send_retransmit(pte);
4790 ast_log(LOG_NOTICE,
"%s Unknown request : got 0x%02hhx expected 0x00,0x01 or 0x02\n", tmpbuf, buf[4]);
4798 ast_log(LOG_WARNING,
"Unistim callback function called with a null channel\n");
4801 if (!ast_channel_tech_pvt(ast)) {
4802 ast_log(LOG_WARNING,
"Unistim callback function called without a tech_pvt\n");
4805 sub = ast_channel_tech_pvt(ast);
4808 ast_log(LOG_WARNING,
"Unistim callback function called without a line\n");
4811 if (!sub->
parent->parent) {
4812 ast_log(LOG_WARNING,
"Unistim callback function called without a device\n");
4815 ast_mutex_lock(&sub->
parent->parent->lock);
4816 if (!sub->
parent->parent->session) {
4817 ast_log(LOG_WARNING,
"Unistim callback function called without a session\n");
4818 ast_mutex_unlock(&sub->
parent->parent->lock);
4821 ast_mutex_unlock(&sub->
parent->parent->lock);
4822 return sub->
parent->parent->session;
4837 cidnum_str = DEFAULTCALLERID;
4839 change_callerid(pte, 0, cidnum_str);
4840 if (strlen(cidnum_str) == 0) {
4841 cidnum_str = DEFAULTCALLERID;
4847 cidname_str = DEFAULTCALLERNAME;
4849 change_callerid(pte, 1, cidname_str);
4850 if (strlen(cidname_str) == 0) {
4851 cidname_str = DEFAULTCALLERNAME;
4854 if (pte->device->
height == 1) {
4856 snprintf(tmpstr,
sizeof(tmpstr),
"%s %s", cidnum_str, ustmtext(cidname_str, pte));
4857 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpstr);
4859 send_text(TEXT_LINE0, TEXT_NORMAL, pte, cidname_str);
4860 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(cidnum_str, pte));
4867 static int unistim_call(
struct ast_channel *ast,
const char *dest,
int timeout)
4874 session = channel_to_session(ast);
4876 ast_log(LOG_ERROR,
"Device not registered, cannot call %s\n", dest);
4879 sub = ast_channel_tech_pvt(ast);
4880 sub_real = get_sub(session->device,
SUB_REAL);
4882 ast_log(LOG_WARNING,
"unistim_call called on %s, neither down nor reserved\n",
4883 ast_channel_name(ast));
4888 ast_verb(3,
"unistim_call(%s)\n", ast_channel_name(ast));
4890 session->
state = STATE_RINGING;
4891 send_callerid_screen(session, sub);
4892 if (ast_strlen_zero(ast_channel_call_forward(ast))) {
4893 send_text(TEXT_LINE2, TEXT_NORMAL, session, ustmtext(
"is calling you.", session));
4894 send_text_status(session, ustmtext(
"Accept Ignore Hangup", session));
4897 ringstyle = session->device->
cwstyle;
4898 ringvolume = session->device->
cwvolume;
4900 ringstyle = (sub->ringstyle == -1) ? session->device->
ringstyle : sub->ringstyle;
4903 send_ring(session, ringvolume, ringstyle);
4904 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
4906 for (i = 0; i < FAVNUM; i++) {
4907 if (!soft_key_visible(session->device, i)) {
4910 if (session->device->ssub[i]) {
4913 if (is_key_line(session->device, i) && !strcmp(sub->
parent->name, session->device->sline[i]->name)) {
4915 ast_verb(0,
"Found softkey %d for line %s\n", i, sub->
parent->name);
4917 send_favorite_short(i, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST, session);
4918 session->device->ssub[i] = sub;
4928 ast_mutex_lock(&sub->lock);
4929 ast_channel_tech_pvt_set(ast, NULL);
4930 unistim_set_owner(sub, NULL);
4934 ast_verb(0,
"Destroying RTP session\n");
4940 ast_mutex_unlock(&sub->lock);
4945 static int unistim_hangup(
struct ast_channel *ast)
4948 struct unistim_line *l;
4949 struct unistim_device *d;
4953 s = channel_to_session(ast);
4954 sub = ast_channel_tech_pvt(ast);
4958 ast_debug(1,
"Asked to hangup channel not connected\n");
4959 unistim_hangup_clean(ast, sub);
4963 ast_verb(0,
"unistim_hangup(%s) on %s@%s (STATE_%s)\n", ast_channel_name(ast), l->name, l->parent->
name, ptestate_tostr(s->
state));
4967 if (sub_trans && (sub_trans->owner) && (sub->subtype ==
SUB_REAL)) {
4969 ast_verb(0,
"Threeway call disconnected, switching to real call\n");
4974 swap_subs(sub_trans, sub);
4975 send_text_status(s, ustmtext(
" Transf Hangup", s));
4976 send_callerid_screen(s, sub_trans);
4977 unistim_hangup_clean(ast, sub);
4978 unistim_unalloc_sub(d, sub);
4981 if (sub_real && (sub_real->owner) && (sub->subtype ==
SUB_THREEWAY) && (s->
state == STATE_CALL)) {
4983 ast_verb(0,
"Real call disconnected, stay in call\n");
4985 send_text_status(s, ustmtext(
" Transf Hangup", s));
4986 send_callerid_screen(s, sub_real);
4987 unistim_hangup_clean(ast, sub);
4988 unistim_unalloc_sub(d, sub);
4992 sub_stop_silence(s, sub);
4993 }
else if (sub->subtype == SUB_RING) {
4995 for (i = 0; i < FAVNUM; i++) {
4996 if (!soft_key_visible(s->device, i)) {
4999 if (d->ssub[i] != sub) {
5000 if (d->ssub[i] != NULL) {
5005 if (is_key_line(d, i) && !strcmp(l->name, d->sline[i]->name)) {
5006 send_favorite_short(i, FAV_LINE_ICON, s);
5017 send_favorite_short(sub->
softkey, FAV_LINE_ICON, s);
5020 for (i = 0; i < FAVNUM; i++) {
5021 if (d->ssub[i] == sub) {
5027 if (s->
state == STATE_RINGING && sub->subtype == SUB_RING) {
5029 if (ast_channel_hangupcause(ast) != AST_CAUSE_ANSWERED_ELSEWHERE) {
5031 write_history(s,
'i', 1);
5036 s->
state = STATE_CALL;
5037 send_callerid_screen(s, sub_real);
5038 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"is on-line", s));
5039 send_text_status(s, ustmtext(
" Transf Hangup", s));
5040 send_favorite_short(sub->
softkey, FAV_ICON_OFFHOOK_BLACK, s);
5048 unistim_hangup_clean(ast, sub);
5049 unistim_unalloc_sub(d, sub);
5054 static int unistim_answer(
struct ast_channel *ast)
5058 struct unistim_line *l;
5059 struct unistim_device *d;
5062 s = channel_to_session(ast);
5064 ast_log(LOG_WARNING,
"unistim_answer on a disconnected device ?\n");
5067 sub = ast_channel_tech_pvt(ast);
5072 ast_verb(0,
"unistim_answer(%s) on %s@%s-%d\n", ast_channel_name(ast), l->name,
5075 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"is now on-line", s));
5077 send_text_status(s, ustmtext(
"Transf Cancel", s));
5079 send_text_status(s, ustmtext(
" Transf Hangup", s));
5081 send_start_timer(s);
5089 static int unistimsock_read(
int *
id,
int fd,
short events,
void *ignore)
5091 struct sockaddr_in addr_from = { 0, };
5095 int dw_num_bytes_rcvd;
5096 unsigned int size_addr_from;
5098 int dw_num_bytes_rcvdd;
5101 size_addr_from =
sizeof(addr_from);
5103 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (
struct sockaddr *) &addr_from,
5105 if (dw_num_bytes_rcvd == -1) {
5106 if (errno == EAGAIN) {
5107 ast_log(LOG_NOTICE,
"UNISTIM: Received packet with bad UDP checksum\n");
5108 }
else if (errno != ECONNREFUSED) {
5109 ast_log(LOG_WARNING,
"Recv error %d (%s)\n", errno, strerror(errno));
5118 if (cur->
sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
5129 ast_verb(0,
"\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
5131 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
5132 dw_num_bytes_rcvdd++)
5133 ast_verb(0,
"%02hhx ", buff[dw_num_bytes_rcvdd]);
5134 ast_verb(0,
"\n******************************************\n");
5139 ast_verb(0,
"Received a packet from an unknown source\n");
5141 parsing(dw_num_bytes_rcvd, buff, NULL, (
struct sockaddr_in *) &addr_from);
5144 parsing(dw_num_bytes_rcvd, buff, cur, (
struct sockaddr_in *) &addr_from);
5156 ast_log(LOG_WARNING,
"Channel NULL while reading\n");
5161 ast_log(LOG_WARNING,
"RTP handle NULL while reading on subchannel %u\n",
5166 switch (ast_channel_fdno(ast)) {
5185 "Oooh, format changed from %s to %s\n",
5192 ast_channel_nativeformats_set(sub->
owner, caps);
5209 ast_mutex_lock(&sub->lock);
5210 fr = unistim_rtp_read(ast, sub);
5211 ast_mutex_unlock(&sub->lock);
5225 ast_log(LOG_WARNING,
"Can't send %u type frames with unistim_write\n",
5233 ast_log(LOG_WARNING,
5234 "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
5244 ast_mutex_lock(&sub->lock);
5248 ast_mutex_unlock(&sub->lock);
5257 struct unistim_line *l = p->
parent;
5259 ast_mutex_lock(&p->lock);
5261 ast_debug(1,
"New owner for channel USTM/%s@%s-%u is %s\n", l->name,
5262 l->parent->
name, p->subtype, ast_channel_name(newchan));
5264 if (p->
owner != oldchan) {
5265 ast_log(LOG_WARNING,
"old channel wasn't %s (%p) but was %s (%p)\n",
5266 ast_channel_name(oldchan), oldchan, ast_channel_name(p->
owner), p->
owner);
5267 ast_mutex_unlock(&p->lock);
5271 unistim_set_owner(p, newchan);
5273 ast_mutex_unlock(&p->lock);
5279 static char *control2str(
int ind)
5283 return "Other end has hungup";
5285 return "Local ring";
5287 return "Remote end is ringing";
5289 return "Remote end has answered";
5291 return "Remote end is busy";
5293 return "Make it go off hook";
5295 return "Line is off hook";
5297 return "Congestion (circuits busy)";
5299 return "Flash hook";
5303 return "Set a low-level option";
5307 return "Un-Key Radio";
5309 return "Remote end changed";
5311 return "RTP source updated";
5313 return "Source of media changed";
5321 const char *indication)
5329 ast_log(LOG_WARNING,
"Unable to get indication tone for %s\n", indication);
5333 static int unistim_indicate(
struct ast_channel *ast,
int ind,
const void *data,
size_t datalen)
5336 struct unistim_line *l;
5340 ast_verb(3,
"Asked to indicate '%s' (%d) condition on channel %s\n",
5341 control2str(ind), ind, ast_channel_name(ast));
5344 s = channel_to_session(ast);
5348 sub = ast_channel_tech_pvt(ast);
5354 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"Ringing...", s));
5355 in_band_indication(ast, l->parent->
tz,
"ring");
5363 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"Busy", s));
5364 in_band_indication(ast, l->parent->
tz,
"busy");
5376 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext(
"Congestion", s));
5377 in_band_indication(ast, l->parent->
tz,
"congestion");
5398 ast_log(LOG_NOTICE,
"Connected party is now %s <%s>\n",
5399 S_COR(ast_channel_connected(ast)->
id.name.valid, ast_channel_connected(ast)->
id.name.str,
""),
5400 S_COR(ast_channel_connected(ast)->
id.
number.valid, ast_channel_connected(ast)->
id.
number.str,
""));
5402 send_callerid_screen(s, sub);
5411 ast_log(LOG_WARNING,
"Don't know how to indicate condition %d\n", ind);
5423 struct unistim_line *l;
5424 struct unistim_device *d;
5431 at = strchr(line,
'@');
5433 ast_log(LOG_NOTICE,
"Device '%s' has no @ (at) sign!\n", dest);
5441 at = strchr(device,
'/');
5446 if (!strcasecmp(d->
name, device)) {
5448 ast_verb(0,
"Found device: %s\n", d->
name);
5454 if (!strcasecmp(l->name, line)) {
5456 ast_verb(0,
"Found line: %s\n", l->name);
5460 sub = unistim_alloc_sub(d,
SUB_REAL);
5464 sub = unistim_alloc_sub(d,
SUB_REAL);
5468 sub->ringstyle = -1;
5473 if ((*at <
'0') || (*at >
'7')) {
5474 ast_log(LOG_WARNING,
"Invalid ring selection (%s)", at);
5476 signed char ring_volume = -1;
5477 signed char ring_style = *at -
'0';
5479 if ((*at >=
'0') && (*at <=
'3')) {
5480 ring_volume = *at -
'0';
5483 ast_verb(0,
"Distinctive ring: style #%d volume %d\n",
5484 ring_style, ring_volume);
5487 sub->ringstyle = ring_style;
5509 static int unistim_senddigit_begin(
struct ast_channel *ast,
char digit)
5516 return send_dtmf_tone(pte, digit);
5519 static int unistim_senddigit_end(
struct ast_channel *ast,
char digit,
unsigned int duration)
5528 ast_verb(0,
"Send Digit off %c (duration %d)\n", digit, duration);
5530 send_tone(pte, 0, 0);
5536 static int unistim_sendtext(
struct ast_channel *ast,
const char *text)
5540 char tmp[TEXT_LENGTH_MAX + 1];
5543 ast_verb(0,
"unistim_sendtext called\n");
5546 ast_log(LOG_WARNING,
"unistim_sendtext called with a null text\n");
5554 size = strlen(text);
5555 if (text[0] ==
'@') {
5556 int pos = 0, i = 1, tok = 0, sz = 0;
5562 memset(label, 0, 11);
5563 memset(number, 0, 16);
5568 if ((cur <
'0') && (cur >
'5')) {
5569 ast_log(LOG_WARNING,
5570 "sendtext failed : position must be a number beetween 0 and 5\n");
5578 ast_log(LOG_WARNING,
"sendtext failed : invalid position\n");
5584 if ((cur <
'3') && (cur >
'6')) {
5585 ast_log(LOG_WARNING,
5586 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
5589 icon = (cur -
'0') * 10;
5593 if ((cur <
'0') && (cur >
'9')) {
5594 ast_log(LOG_WARNING,
5595 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
5598 icon += (cur -
'0');
5603 ast_log(LOG_WARNING,
5604 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
5623 ast_log(LOG_WARNING,
5624 "sendtext failed : extension too long = %d (15 car max)\n",
5634 ast_log(LOG_WARNING,
"sendtext failed : incomplet command\n");
5638 ast_log(LOG_WARNING,
"sendtext failed : no device ?\n");
5644 send_favorite(pos, icon, pte, label);
5648 if (size <= TEXT_LENGTH_MAX * 2) {
5649 if (pte->device->
height == 1) {
5650 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
5652 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(
"Message :", pte));
5653 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
5655 if (size <= TEXT_LENGTH_MAX) {
5656 send_text(TEXT_LINE2, TEXT_NORMAL, pte,
"");
5659 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
5660 tmp[
sizeof(tmp) - 1] =
'\0';
5661 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
5664 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
5665 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
5666 tmp[
sizeof(tmp) - 1] =
'\0';
5667 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
5668 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
5669 tmp[
sizeof(tmp) - 1] =
'\0';
5670 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
5675 static int unistim_send_mwi_to_peer(
struct unistim_line *peer,
unsigned int tick)
5687 ast_debug(3,
"MWI Status for mailbox %s is %d, lastmsgsent:%d\n",
5688 peer->
mailbox,
new, peer->parent->lastmsgssent);
5692 if ((peer->parent->session->
state != STATE_MAINPAGE) || (
new == peer->parent->lastmsgssent)) {
5696 peer->parent->lastmsgssent =
new;
5697 send_led_update(peer->parent->session, (
new > 0)?LED_BAR_ON:LED_BAR_OFF);
5708 struct unistim_line *l;
5712 ast_log(LOG_WARNING,
"subchannel null in unistim_new\n");
5716 ast_log(LOG_WARNING,
"no line for subchannel %p\n", sub);
5727 l->parent->
context, assignedids, requestor, l->
amaflags,
"USTM/%s@%s-%p", l->name, l->parent->
name, sub);
5729 ast_verb(0,
"unistim_new sub=%u (%p) chan=%p line=%s\n", sub->subtype, sub, tmp, l->name);
5732 ast_log(LOG_WARNING,
"Unable to allocate channel structure\n");
5744 ast_channel_nativeformats_set(tmp, caps);
5754 ast_verb(0,
"Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
5760 if ((sub->
rtp) && (sub->subtype == 0)) {
5762 ast_verb(0,
"New unistim channel with a previous rtp handle ?\n");
5773 ast_channel_rings_set(tmp, 1);
5775 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
5777 ast_channel_set_writeformat(tmp, tmpfmt);
5778 ast_channel_set_rawwriteformat(tmp, tmpfmt);
5779 ast_channel_set_readformat(tmp, tmpfmt);
5780 ast_channel_set_rawreadformat(tmp, tmpfmt);
5783 ast_channel_tech_pvt_set(tmp, sub);
5784 ast_channel_tech_set(tmp, &unistim_tech);
5786 if (!ast_strlen_zero(l->parent->
language)) {
5787 ast_channel_language_set(tmp, l->parent->
language);
5789 unistim_set_owner(sub, tmp);
5793 ast_channel_call_forward_set(tmp, l->parent->
call_forward);
5794 if (!ast_strlen_zero(l->
cid_num)) {
5795 char *name, *loc, *instr;
5800 ast_free(ast_channel_caller(tmp)->
id.number.str);
5803 ast_free(ast_channel_caller(tmp)->
id.name.str);
5808 ast_channel_priority_set(tmp, 1);
5811 ast_channel_unlock(tmp);
5815 ast_verb(0,
"Starting pbx in unistim_new\n");
5818 ast_log(LOG_WARNING,
"Unable to start PBX on %s\n", ast_channel_name(tmp));
5835 static void *do_monitor(
void *data)
5838 unsigned int dw_timeout = 0;
5844 if (unistimsock > -1) {
5851 tick = get_tick_count();
5852 dw_timeout = UINT_MAX;
5855 DEBUG_TIMER(
"checking timeout for session %p with tick = %u\n", cur, tick);
5857 DEBUG_TIMER(
"checking timeout for session %p timeout = %u\n", cur,
5861 DEBUG_TIMER(
"Event for session %p\n", cur);
5866 if (send_retransmit(cur)) {
5867 DEBUG_TIMER(
"The chained link was modified, restarting...\n");
5869 dw_timeout = UINT_MAX;
5874 if (dw_timeout > cur->
timeout - tick) {
5875 dw_timeout = cur->
timeout - tick;
5879 struct unistim_line *l;
5883 DEBUG_TIMER(
"Checking mailbox for MWI\n");
5884 unistim_send_mwi_to_peer(l, tick);
5890 handle_call_outgoing(cur);
5897 DEBUG_TIMER(
"Waiting for %dus\n", dw_timeout);
5906 ast_mutex_lock(&unistim_reload_lock);
5909 ast_mutex_unlock(&unistim_reload_lock);
5911 ast_verb(1,
"Reloading unistim.conf...\n");
5914 pthread_testcancel();
5921 static int restart_monitor(
void)
5923 pthread_attr_t attr;
5928 if (ast_mutex_lock(&
monlock)) {
5929 ast_log(LOG_WARNING,
"Unable to lock monitor\n");
5934 ast_log(LOG_WARNING,
"Cannot kill myself\n");
5941 pthread_attr_init(&attr);
5942 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
5944 if (ast_pthread_create(&
monitor_thread, &attr, do_monitor, NULL) < 0) {
5946 ast_log(LOG_ERROR,
"Unable to start monitor thread.\n");
5960 struct unistim_device *d;
5968 "Asked to get a channel of unsupported format %s while capability is %s\n",
5975 if (ast_strlen_zero(tmp)) {
5976 ast_log(LOG_NOTICE,
"Unistim channels require a device\n");
5979 sub = find_subchannel_by_name(tmp);
5981 ast_log(LOG_NOTICE,
"No available lines on: %s\n", dest);
5982 *cause = AST_CAUSE_CONGESTION;
5986 sub_ring = get_sub(d, SUB_RING);
5990 unistim_unalloc_sub(d, sub);
5991 *cause = AST_CAUSE_CONGESTION;
5994 if (sub_ring || sub_trans) {
5996 ast_verb(0,
"Can't create channel, request already in progress: Busy!\n");
5998 unistim_unalloc_sub(d, sub);
5999 *cause = AST_CAUSE_BUSY;
6002 if (d->session->
state == STATE_DIALPAGE) {
6004 ast_verb(0,
"Can't create channel, user on dialpage: Busy!\n");
6006 unistim_unalloc_sub(d, sub);
6007 *cause = AST_CAUSE_BUSY;
6011 if (get_avail_softkey(d->session, sub->
parent->name) == -1) {
6013 ast_verb(0,
"Can't create channel for line %s, all lines busy\n", sub->
parent->name);
6015 unistim_unalloc_sub(d, sub);
6016 *cause = AST_CAUSE_BUSY;
6019 sub->subtype = SUB_RING;
6025 ast_log(LOG_WARNING,
"Unable to make channel for '%s'\n", tmp);
6028 ast_verb(0,
"unistim_request owner = %p\n", sub->
owner);
6037 struct unistim_device *device =
devices;
6038 struct unistim_line *line;
6045 e->
command =
"unistim show info";
6047 "Usage: unistim show info\n"
6048 " Dump internal structures.\n\n"
6059 if (a->argc != e->
args) {
6060 return CLI_SHOWUSAGE;
6062 ast_cli(a->fd,
"Dumping internal structures:\n");
6067 ast_cli(a->fd,
"\nname=%s id=%s ha=%p sess=%p device=%p selected=%d height=%d\n",
6068 device->
name, device->
id, device->ha, device->session,
6073 "->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n",
6085 "-->subtype=%s chan=%p rtp=%p line=%p alreadygone=%d softkey=%d\n",
6091 for (i = 0; i < FAVNUM; i++) {
6092 if (!soft_key_visible(device, i)) {
6095 ast_cli(a->fd,
"==> %d. dev=%s icon=%#-4x label=%-10s number=%-5s sub=%p line=%p\n",
6097 device->ssub[i], device->sline[i]);
6099 device = device->next;
6102 ast_cli(a->fd,
"\nSessions:\n");
6107 "sin=%s timeout=%d state=%s macaddr=%s device=%p session=%p\n",
6119 struct unistim_device *device =
devices;
6123 e->
command =
"unistim show devices";
6125 "Usage: unistim show devices\n"
6126 " Lists all known Unistim devices.\n";
6132 if (a->argc != e->
args)
6133 return CLI_SHOWUSAGE;
6135 ast_cli(a->fd,
"%-20.20s %-20.20s %-15.15s %-15.15s %s\n",
"Name/username",
"MAC",
"Host",
"Firmware",
"Status");
6138 ast_cli(a->fd,
"%-20.20s %-20.20s %-15.15s %-15.15s %s\n",
6139 device->
name, device->
id,
6140 (!device->session) ?
"(Unspecified)" :
ast_inet_ntoa(device->session->
sin.sin_addr),
6141 (!device->session) ?
"(Unspecified)" : device->session->
firmware,
6142 (!device->session) ?
"UNKNOWN" :
"OK");
6143 device = device->next;
6155 unsigned char c, cc;
6160 e->
command =
"unistim send packet";
6162 "Usage: unistim send packet USTM/line@name hexa\n"
6163 " unistim send packet USTM/1000@hans 19040004\n";
6171 return CLI_SHOWUSAGE;
6173 if (strlen(a->argv[3]) < 9) {
6174 return CLI_SHOWUSAGE;
6176 len = strlen(a->argv[4]);
6178 return CLI_SHOWUSAGE;
6181 sub = find_subchannel_by_name(tmp);
6183 ast_cli(a->fd,
"Can't find '%s'\n", tmp);
6186 if (!sub->
parent->parent->session) {
6187 ast_cli(a->fd,
"'%s' is not connected\n", tmp);
6190 ast_cli(a->fd,
"Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->
parent->parent->session);
6191 for (i = 0; i < len; i++) {
6205 tmp[j++] = (c << 4) | cc;
6207 memcpy(buffsend + SIZE_HEADER, tmp, j);
6208 send_client(SIZE_HEADER + j, buffsend, sub->
parent->parent->session);
6216 e->
command =
"unistim set debug {on|off}";
6218 "Usage: unistim set debug\n"
6219 " Display debug messages.\n";
6226 if (a->argc != e->
args) {
6227 return CLI_SHOWUSAGE;
6229 if (!strcasecmp(a->argv[3],
"on")) {
6231 ast_cli(a->fd,
"UNISTIM Debugging Enabled\n");
6232 }
else if (!strcasecmp(a->argv[3],
"off")) {
6234 ast_cli(a->fd,
"UNISTIM Debugging Disabled\n");
6236 return CLI_SHOWUSAGE;
6249 e->
command =
"unistim reload";
6251 "Usage: unistim reload\n"
6252 " Reloads UNISTIM configuration from unistim.conf\n";
6259 if (e && a && a->argc != e->
args) {
6260 return CLI_SHOWUSAGE;
6269 AST_CLI_DEFINE(unistim_show_info,
"Show UNISTIM info"),
6270 AST_CLI_DEFINE(unistim_show_devices,
"Show UNISTIM devices"),
6271 AST_CLI_DEFINE(unistim_sp,
"Send packet (for reverse engineering)"),
6272 AST_CLI_DEFINE(unistim_do_debug,
"Toggle UNITSTIM debugging"),
6275 static void unquote(
char *out,
const char *src,
int maxlen)
6277 int len = strlen(src);
6281 if ((len > 1) && src[0] ==
'\"') {
6286 if (maxlen > len - 1) {
6289 memcpy(out, src, maxlen);
6290 ((
char *) out)[maxlen] =
'\0';
6292 memcpy(out, src, maxlen);
6297 static int parse_bookmark(
const char *text,
struct unistim_device *d)
6304 int len = strlen(text);
6308 if ((len > 2) && (line[1] ==
'@')) {
6310 if ((p >=
'0') && (p <=
'5')) {
6313 ast_log(LOG_WARNING,
6314 "Invalid position for bookmark : must be between 0 and 5\n");
6318 ast_log(LOG_WARNING,
"Invalid position %d for bookmark : already used:\n", p);
6321 memmove(line, line + 2,
sizeof(line) - 2);
6324 for (p = 0; p < FAVNUM; p++) {
6330 ast_log(LOG_WARNING,
"No more free bookmark position\n");
6334 at = strchr(line,
'@');
6336 ast_log(LOG_NOTICE,
"Bookmark entry '%s' has no @ (at) sign!\n", text);
6342 at = strchr(at,
'@');
6343 if (ast_strlen_zero(number)) {
6344 ast_log(LOG_NOTICE,
"Bookmark entry '%s' has no number\n", text);
6347 if (ast_strlen_zero(line)) {
6348 ast_log(LOG_NOTICE,
"Bookmark entry '%s' has no description\n", text);
6352 at = strchr(number,
'@');
6359 if (ast_strlen_zero(icon)) {
6360 ast_log(LOG_NOTICE,
"Bookmark entry '%s' has no icon value\n", text);
6363 if (strncmp(icon,
"USTM/", 5)) {
6373 ast_verb(0,
"New bookmark at pos %d label='%s' number='%s' icon=%#x\n",
6380 static void finish_bookmark(
void)
6382 struct unistim_device *d =
devices;
6386 for (i = 0; i < 6; i++) {
6388 struct unistim_device *d2 =
devices;
6397 if (d->
sp[i] == NULL) {
6398 ast_log(LOG_NOTICE,
"Bookmark entry with device %s not found\n",
6408 static struct unistim_line *find_line_by_number(
struct unistim_device *d,
const char *
val) {
6409 struct unistim_line *l, *ret = NULL;
6413 if (!strcmp(l->name, val)) {
6422 static void delete_device(
struct unistim_device *d)
6424 struct unistim_line *l;
6429 ast_verb(0,
"Removing device '%s'\n", d->
name);
6435 ast_log(LOG_WARNING,
6436 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
6443 ast_log(LOG_WARNING,
6444 "Device '%s' with threeway call subchannels allocated, aborting.\n",
6450 ast_mutex_destroy(&sub->lock);
6460 ast_mutex_destroy(&l->lock);
6461 unistim_line_destroy(l);
6467 if (sessions == d->session) {
6468 sessions = d->session->next;
6472 if (s->next == d->session) {
6473 s->next = d->session->next;
6479 ast_mutex_destroy(&d->session->lock);
6480 ast_free(d->session);
6485 struct unistim_device *d2 =
devices;
6487 if (d2->next == d) {
6497 ast_mutex_destroy(&d->lock);
6501 static struct unistim_device *build_device(
const char *cat,
const struct ast_variable *v)
6503 struct unistim_device *d;
6504 struct unistim_line *l = NULL, *lt = NULL;
6506 int nbsoftkey, dateformat, timeformat, callhistory, sharpdial, linecnt;
6508 signed char ringvolume, ringstyle, cwvolume, cwstyle;
6515 if (!strcmp(d->
name, cat)) {
6517 if (unistimsock < 0) {
6519 ast_log(LOG_WARNING,
"Duplicate entry found (%s), ignoring.\n", cat);
6537 ast_mutex_init(&d->lock);
6542 d->
output = OUTPUT_HANDSET;
6546 d->
height = DEFAULTHEIGHT;
6554 unistim_line_destroy(l);
6564 memset(d->ssub, 0,
sizeof(d->ssub));
6565 memset(d->sline, 0,
sizeof(d->sline));
6566 memset(d->
sp, 0,
sizeof(d->
sp));
6568 linelabel[0] =
'\0';
6581 if (!strcasecmp(v->
name,
"rtp_port")) {
6583 }
else if (!strcasecmp(v->
name,
"rtp_method")) {
6585 }
else if (!strcasecmp(v->
name,
"status_method")) {
6587 }
else if (!strcasecmp(v->
name,
"device")) {
6589 }
else if (!strcasecmp(v->
name,
"tn")) {
6591 }
else if (!strcasecmp(v->
name,
"permit") || !strcasecmp(v->
name,
"deny")) {
6595 ast_log(LOG_ERROR,
"Invalid ACL '%s' specified for device '%s' on line %d. Deleting device\n",
6596 v->
value, cat, v->lineno);
6600 }
else if (!strcasecmp(v->
name,
"context")) {
6602 }
else if (!strcasecmp(v->
name,
"maintext0")) {
6604 }
else if (!strcasecmp(v->
name,
"maintext1")) {
6606 }
else if (!strcasecmp(v->
name,
"maintext2")) {
6608 }
else if (!strcasecmp(v->
name,
"titledefault")) {
6610 }
else if (!strcasecmp(v->
name,
"dateformat")) {
6611 dateformat = atoi(v->
value);
6612 }
else if (!strcasecmp(v->
name,
"timeformat")) {
6613 timeformat = atoi(v->
value);
6614 }
else if (!strcasecmp(v->
name,
"contrast")) {
6617 ast_log(LOG_WARNING,
"contrast must be beetween 0 and 15\n");
6620 }
else if (!strcasecmp(v->
name,
"nat")) {
6622 }
else if (!strcasecmp(v->
name,
"hasexp")) {
6624 }
else if (!strcasecmp(v->
name,
"ringvolume")) {
6625 ringvolume = atoi(v->
value);
6626 }
else if (!strcasecmp(v->
name,
"ringstyle")) {
6627 ringstyle = atoi(v->
value);
6628 }
else if (!strcasecmp(v->
name,
"cwvolume")) {
6629 cwvolume = atoi(v->
value);
6630 }
else if (!strcasecmp(v->
name,
"cwstyle")) {
6631 cwstyle = atoi(v->
value);
6632 }
else if (!strcasecmp(v->
name,
"callhistory")) {
6633 callhistory = atoi(v->
value);
6634 }
else if (!strcasecmp(v->
name,
"sharpdial")) {
6636 }
else if (!strcasecmp(v->
name,
"interdigit_timer")) {
6638 }
else if (!strcasecmp(v->
name,
"dtmf_duration")) {
6643 }
else if (!strcasecmp(v->
name,
"callerid")) {
6644 if (!strcasecmp(v->
value,
"asreceived")) {
6645 lt->cid_num[0] =
'\0';
6649 }
else if (!strcasecmp(v->
name,
"language")) {
6651 }
else if (!strcasecmp(v->
name,
"country")) {
6653 }
else if (!strcasecmp(v->
name,
"accountcode")) {
6655 }
else if (!strcasecmp(v->
name,
"amaflags")) {
6659 ast_log(LOG_WARNING,
"Invalid AMA flags: %s at line %d\n", v->
value,
6664 }
else if (!strcasecmp(v->
name,
"musiconhold")) {
6666 }
else if (!strcasecmp(v->
name,
"callgroup")) {
6667 lt->callgroup = ast_get_group(v->
value);
6668 }
else if (!strcasecmp(v->
name,
"pickupgroup")) {
6669 lt->pickupgroup = ast_get_group(v->
value);
6670 }
else if (!strcasecmp(v->
name,
"mailbox")) {
6672 }
else if (!strcasecmp(v->
name,
"parkinglot")) {
6674 }
else if (!strcasecmp(v->
name,
"linelabel")) {
6675 unquote(linelabel, v->
value,
sizeof(linelabel) - 1);
6676 }
else if (!strcasecmp(v->
name,
"extension")) {
6677 if (!strcasecmp(v->
value,
"none")) {
6679 }
else if (!strcasecmp(v->
value,
"ask")) {
6681 }
else if (!strcasecmp(v->
value,
"line")) {
6684 ast_log(LOG_WARNING,
"Unknown extension option.\n");
6686 }
else if (!strcasecmp(v->
name,
"bookmark")) {
6687 if (nbsoftkey > 5) {
6688 ast_log(LOG_WARNING,
6689 "More than 6 softkeys defined. Ignoring new entries.\n");
6691 if (parse_bookmark(v->
value, d)) {
6695 }
else if (!strcasecmp(v->
name,
"line")) {
6696 int len = strlen(linelabel);
6697 int create_line = 0;
6699 l = find_line_by_number(d, v->
value);
6701 if (!(l = unistim_line_alloc())) {
6707 memcpy(l, lt,
sizeof(*l));
6708 ast_mutex_init(&l->lock);
6714 d->sline[nbsoftkey] = l;
6719 int softkeylinepos = 0;
6720 if ((len > 2) && (linelabel[1] ==
'@')) {
6721 softkeylinepos = linelabel[0];
6722 if ((softkeylinepos >=
'0') && (softkeylinepos <=
'5')) {
6723 softkeylinepos -=
'0';
6726 ast_log(LOG_WARNING,
6727 "Invalid position for linelabel : must be between 0 and 5\n");
6742 if (!ast_strlen_zero(l->
mailbox)) {
6744 ast_verb(3,
"Setting mailbox '%s' on %s@%s\n", l->
mailbox, d->
name, l->name);
6754 }
else if (!strcasecmp(v->
name,
"height")) {
6759 ast_log(LOG_WARNING,
"Don't know keyword '%s' at line %d\n", v->
name,
6765 ast_log(LOG_ERROR,
"An Unistim device must have at least one line!\n");
6776 if ((d->
tz == NULL) && !ast_strlen_zero(d->
country)) {
6777 ast_log(LOG_WARNING,
"Country '%s' was not found in indications.conf\n",
6782 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
6785 if (!ast_strlen_zero(d->
id)) {
6786 ast_log(LOG_WARNING,
6787 "tn= and device= can't be used together. Ignoring device= entry\n");
6792 }
else if (ast_strlen_zero(d->
id)) {
6793 if (strcmp(d->
name,
"template")) {
6794 ast_log(LOG_ERROR,
"You must specify the mac address with device=\n");
6801 strcpy(d->
id,
"000000000000");
6814 struct ast_tm tm = { 0, };
6818 ast_log(LOG_WARNING,
"Error in ast_localtime()\n");
6824 }
else if (strlen(tm.
tm_zone) < 9) {
6838 ast_verb(3,
"Added device '%s'\n", d->
name);
6840 ast_verb(3,
"Device '%s' reloaded\n", d->
name);
6846 static int reload_config(
void)
6850 struct sockaddr_in bindaddr = { 0, };
6851 char *config =
"unistim.conf";
6853 struct unistim_device *d;
6854 const int reuseFlag = 1;
6861 ast_log(LOG_ERROR,
"Unable to load config %s\n", config);
6863 }
else if (cfg == CONFIG_STATUS_FILEINVALID) {
6864 ast_log(LOG_ERROR,
"Config file %s is in an invalid format. Aborting.\n", config);
6869 memcpy(&global_jbconf, &default_jbconf,
sizeof(
struct ast_jb_conf));
6871 unistim_keepalive = 120;
6873 v = ast_variable_browse(cfg,
"general");
6879 if (!strcasecmp(v->
name,
"keepalive")) {
6880 unistim_keepalive = atoi(v->
value);
6881 }
else if (!strcasecmp(v->
name,
"port")) {
6882 unistim_port = atoi(v->
value);
6883 }
else if (!strcasecmp(v->
name,
"tos")) {
6885 ast_log(LOG_WARNING,
"Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
6887 }
else if (!strcasecmp(v->
name,
"tos_audio")) {
6889 ast_log(LOG_WARNING,
"Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
6891 }
else if (!strcasecmp(v->
name,
"cos")) {
6893 ast_log(LOG_WARNING,
"Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
6895 }
else if (!strcasecmp(v->
name,
"cos_audio")) {
6897 ast_log(LOG_WARNING,
"Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
6899 }
else if (!strcasecmp(v->
name,
"debug")) {
6900 if (!strcasecmp(v->
value,
"no")) {
6902 }
else if (!strcasecmp(v->
value,
"yes")) {
6905 }
else if (!strcasecmp(v->
name,
"autoprovisioning")) {
6906 if (!strcasecmp(v->
value,
"no")) {
6907 autoprovisioning = AUTOPROVISIONING_NO;
6908 }
else if (!strcasecmp(v->
value,
"yes")) {
6909 autoprovisioning = AUTOPROVISIONING_YES;
6910 }
else if (!strcasecmp(v->
value,
"tn")) {
6911 autoprovisioning = AUTOPROVISIONING_TN;
6913 ast_log(LOG_WARNING,
"Unknown autoprovisioning option.\n");
6915 }
else if (!strcasecmp(v->
name,
"public_ip")) {
6916 if (!ast_strlen_zero(v->
value)) {
6919 ast_log(LOG_WARNING,
"Invalid address: %s\n", v->
value);
6927 if ((unistim_keepalive < 10) ||
6928 (unistim_keepalive >
6930 ast_log(LOG_ERROR,
"keepalive is invalid in %s\n", config);
6934 packet_send_ping[4] =
6936 if ((unistim_port < 1) || (unistim_port > 65535)) {
6937 ast_log(LOG_ERROR,
"port is not set or invalid in %s\n", config);
6941 unistim_keepalive *= 1000;
6955 if (strcasecmp(cat,
"general")) {
6956 d = build_device(cat, ast_variable_browse(cfg, cat));
6977 refresh_all_favorite(s);
6978 if (ast_strlen_zero(s->device->
language)) {
6980 lang = options_languages[find_language(s->device->
language)];
6981 send_charset_update(s, lang.encoding);
6988 if (unistimsock > -1) {
6991 bindaddr.sin_addr.s_addr = INADDR_ANY;
6992 bindaddr.sin_port = htons(unistim_port);
6993 bindaddr.sin_family = AF_INET;
6994 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
6995 if (unistimsock < 0) {
6996 ast_log(LOG_WARNING,
"Unable to create UNISTIM socket: %s\n", strerror(errno));
7001 const int pktinfoFlag = 1;
7002 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
7003 sizeof(pktinfoFlag));
7006 if (public_ip.sin_family == 0) {
7007 ast_log(LOG_WARNING,
7008 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
7013 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (
const char *) &reuseFlag,
7015 if (bind(unistimsock, (
struct sockaddr *) &bindaddr,
sizeof(bindaddr)) < 0) {
7016 ast_log(LOG_WARNING,
"Failed to bind to %s:%d: %s\n",
7022 ast_verb(2,
"UNISTIM Listening on %s:%d\n",
ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
7023 ast_set_qos(unistimsock, qos.tos, qos.cos,
"UNISTIM");
7040 *instance = sub->
rtp;
7048 struct sockaddr_in them = { 0, };
7049 struct sockaddr_in us = { 0, };
7057 ast_log(LOG_ERROR,
"No Private Structure, this is bad\n");
7074 .
type = channel_type,
7075 .get_rtp_info = unistim_get_rtp_peer,
7076 .update_peer = unistim_set_rtp_peer,
7101 ast_log(LOG_ERROR,
"Failed to allocate IO context\n");
7107 ast_log(LOG_ERROR,
"Failed to allocate scheduler context\n");
7111 res = reload_config();
7121 ast_log(LOG_ERROR,
"Unable to register channel type '%s'\n", channel_type);
7122 goto chanreg_failed;
7125 ast_rtp_glue_register(&unistim_rtp_glue);
7144 ao2_cleanup(global_cap);
7151 static int unload_module(
void)
7176 if (unistimsock > -1) {
7188 ast_verb(0,
"reload unistim\n");
7190 ast_mutex_lock(&unistim_reload_lock);
7194 ast_mutex_unlock(&unistim_reload_lock);
7201 AST_MODULE_INFO(
ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT,
"UNISTIM Protocol (USTM)",
7202 .support_level = AST_MODULE_SUPPORT_EXTENDED,
7204 .unload = unload_module,
int ast_io_wait(struct io_context *ioc, int howlong)
Waits for IO.
struct ast_variable * next
struct ast_channel * owner
char call_forward[AST_MAX_EXTENSION]
int ast_queue_hangup(struct ast_channel *chan)
Queue a hangup frame.
void ast_channel_pickupgroup_set(struct ast_channel *chan, ast_group_t value)
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
struct unistim_device * sp[FAVNUM]
Main Channel structure associated with a channel.
char * str
Subscriber phone number (Malloced)
#define AST_LIST_LOCK(head)
Locks a list.
char softkeylabel[FAVNUM][11]
Asterisk main include file. File version handling, generic pbx functions.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
enum ast_transfer_result ast_bridge_transfer_attended(struct ast_channel *to_transferee, struct ast_channel *to_transfer_target)
Attended transfer.
#define AST_LIST_HEAD(name, type)
Defines a structure to be used to hold a list of specified type.
int ast_queue_control(struct ast_channel *chan, enum ast_control_frame_type control)
Queue a control frame without payload.
A device containing one or more lines.
char name[DEVICE_NAME_LEN]
static pthread_t monitor_thread
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
static struct ast_tone_zone * ast_tone_zone_unref(struct ast_tone_zone *tz)
Release a reference to an ast_tone_zone.
void ast_rtp_instance_change_source(struct ast_rtp_instance *instance)
Indicate a new source of audio has dropped in and the ssrc should change.
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static struct ast_channel * unistim_new(struct unistim_subchannel *sub, int state, const struct ast_assigned_ids *assignedids, const struct ast_channel *requestor)
struct ast_party_id id
Connected party ID.
char lst_cnm[TEXT_LENGTH_MAX]
struct ast_rtp_instance * rtp
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
#define ast_channel_unref(c)
Decrease channel reference count.
char country[MAX_TONEZONE_COUNTRY]
Country code that this set of tones is for.
struct ast_party_name name
Subscriber name.
void ast_channel_unregister(const struct ast_channel_tech *tech)
Unregister a channel technology.
int ast_queue_unhold(struct ast_channel *chan)
Queue an unhold frame.
struct ast_rtp_codecs * ast_rtp_instance_get_codecs(struct ast_rtp_instance *instance)
Get the codecs structure of an RTP instance.
struct wsabuf wsabufsend[MAX_BUF_NUMBER]
descriptor for a cli entry.
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
unsigned short seq_server
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
char phone_number[AST_MAX_EXTENSION]
int ast_jb_read_conf(struct ast_jb_conf *conf, const char *varname, const char *value)
Sets jitterbuffer configuration property.
A description of a part of a tone.
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Structure for variables, used for configurations and for channel variables.
int ast_rtp_instance_set_qos(struct ast_rtp_instance *instance, int tos, int cos, const char *desc)
Set QoS parameters on an RTP session.
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Structure to pass both assignedid values to channel drivers.
void ast_channel_callgroup_set(struct ast_channel *chan, ast_group_t value)
ast_channel_state
ast_channel states
char * str
Subscriber name (Malloced)
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
#define ast_cli_register_multiple(e, len)
Register multiple commands.
char expsoftkeylabel[EXPNUM][11]
unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
char softkeynumber[FAVNUM][AST_MAX_EXTENSION]
int ast_channel_register(const struct ast_channel_tech *tech)
Register a channel technology (a new channel driver) Called by a channel module to register the kind ...
#define ast_strdup(str)
A wrapper for strdup()
int ast_str2tos(const char *value, unsigned int *tos)
Convert a string to the appropriate TOS value.
char * ast_category_browse(struct ast_config *config, const char *prev_name)
Browse categories.
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
void ast_update_use_count(void)
Notify when usecount has been changed.
void ast_moh_stop(struct ast_channel *chan)
Turn off music on hold on a given channel.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Socket address structure.
int ast_rtp_codecs_payload_code_tx(struct ast_rtp_codecs *codecs, int asterisk_format, const struct ast_format *format, int code)
Retrieve a tx mapped payload type based on whether it is an Asterisk format and the code...
static ast_mutex_t sessionlock
static int load_module(void)
struct ast_frame_subclass subclass
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
unsigned short last_seq_ack
int ast_queue_hangup_with_cause(struct ast_channel *chan, int cause)
Queue a hangup frame with hangupcause set.
int args
This gets set in ast_cli_register()
static char * unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
— unistim_reload: Force reload of module from cli — Runs in the asterisk main thread, so don't do anything useful but setting a flag and waiting for do_monitor to do the job in our thread
#define AST_MAX_ACCOUNT_CODE
enum ama_flags ast_channel_string2amaflag(const char *flag)
Convert a string to a detail record AMA flag.
internal representation of ACL entries In principle user applications would have no need for this...
struct ast_party_id id
Caller party ID.
struct unistim_line * next
Configuration File Parser.
static ast_mutex_t devicelock
Handle unaligned data access.
unsigned long tick_next_ping
void ast_rtp_instance_stop(struct ast_rtp_instance *instance)
Stop an RTP instance.
#define ast_config_load(filename, flags)
Load a config file.
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
void io_context_destroy(struct io_context *ioc)
Destroys a context.
#define ast_sockaddr_from_sin(addr, sin)
Converts a struct sockaddr_in to a struct ast_sockaddr.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
A set of tones for a given locale.
void ast_channel_stage_snapshot_done(struct ast_channel *chan)
Clear flag to indicate channel snapshot is being staged, and publish snapshot.
#define ast_strdupa(s)
duplicate a string in memory from the stack
Access Control of various sorts.
static struct ao2_container * codecs
Registered codecs.
#define ao2_ref(o, delta)
Reference/unreference an object and return the old refcount.
Global IO variables are now in a struct in order to be made threadsafe.
#define AST_MAX_EXTENSION
struct stasis_cache * ast_mwi_state_cache(void)
Backend cache for ast_mwi_topic_cached().
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define NB_MAX_RETRANSMIT
structure to hold extensions
static struct ast_jb_conf default_jbconf
Global jitterbuffer configuration - by default, jb is disabled.
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
char mailbox[AST_MAX_EXTENSION]
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
static struct stasis_rest_handlers events
REST handler for /api-docs/events.json.
int ast_sockaddr_resolve_first_af(struct ast_sockaddr *addr, const char *name, int flag, int family)
Return the first entry from ast_sockaddr_resolve filtered by address family.
#define ast_malloc(len)
A wrapper for malloc()
#define ast_debug(level,...)
Log a DEBUG message.
int ast_set_write_format(struct ast_channel *chan, struct ast_format *format)
Sets write format on channel chan.
struct ast_tone_zone * tz
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
int ast_queue_hold(struct ast_channel *chan, const char *musicclass)
Queue a hold frame.
Structure to describe a channel "technology", ie a channel driver See for examples: ...
Core PBX routines and definitions.
int ast_queue_frame(struct ast_channel *chan, struct ast_frame *f)
Queue one or more frames to a channel's frame queue.
enum autoprov_extn extension
char cid_num[AST_MAX_EXTENSION]
char musicclass[MAX_MUSICCLASS]
Wrapper for network related headers, masking differences between various operating systems...
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
struct ast_silence_generator * ast_channel_start_silence_generator(struct ast_channel *chan)
Starts a silence generator on the given channel.
void ast_channel_stage_snapshot(struct ast_channel *chan)
Set flag to indicate channel snapshot is being staged.
struct unistim_device::@132 subs
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define ao2_container_alloc_hash(ao2_options, container_options, n_buckets, hash_fn, sort_fn, cmp_fn)
Allocate and initialize a hash container with the desired number of buckets.
int ast_pickup_call(struct ast_channel *chan)
Pickup a call.
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true". This function checks to see whether a string passed to it is an indication of an "true" value. It checks to see if the string is "yes", "true", "y", "t", "on" or "1".
Support for dynamic strings.
static const unsigned char packet_recv_resume_connection_with_server[]
#define DEFAULT_INTERDIGIT_TIMER
void * stasis_message_data(const struct stasis_message *msg)
Get the data contained in a message.
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
struct ast_tone_zone * ast_get_indication_zone(const char *country)
locate ast_tone_zone
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
char softkeydevice[FAVNUM][16]
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
struct stasis_message_type * ast_mwi_state_type(void)
Get the Stasis Message Bus API message type for MWI messages.
int ast_moh_start(struct ast_channel *chan, const char *mclass, const char *interpclass)
Turn on music on hold on a given channel.
#define MAX_SCREEN_NUMBER
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
struct ast_format_cap * capabilities
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
void ast_channel_stop_silence_generator(struct ast_channel *chan, struct ast_silence_generator *state)
Stops a previously-started silence generator on the given channel.
const char * ast_inet_ntoa(struct in_addr ia)
thread-safe replacement for inet_ntoa().
union ast_frame::@224 data
#define ast_calloc(num, len)
A wrapper for calloc()
int ast_str2cos(const char *value, unsigned int *cos)
Convert a string to the appropriate COS value.
void ast_hangup(struct ast_channel *chan)
Hang up a channel.
int ast_rtp_instance_fd(struct ast_rtp_instance *instance, int rtcp)
Get the file descriptor for an RTP session (or RTCP)
static const unsigned char packet_recv_expansion_pressed_key[]
Module has failed to load, may be in an inconsistent state.
char lst_cid[TEXT_LENGTH_MAX]
unsigned int flags
Combination of the AST_JB_ENABLED, AST_JB_FORCED and AST_JB_LOG flags.
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Structure used to handle boolean flags.
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
int ast_app_has_voicemail(const char *mailboxes, const char *folder)
Determine if a given mailbox has any voicemail If folder is NULL, defaults to "INBOX". If folder is "INBOX", includes the number of messages in the "Urgent" folder.
static int unistim_reloading
char exten[AST_MAX_EXTENSION]
void ast_jb_configure(struct ast_channel *chan, const struct ast_jb_conf *conf)
Configures a jitterbuffer on a channel.
char context[AST_MAX_EXTENSION]
struct ast_frame ast_null_frame
char accountcode[AST_MAX_ACCOUNT_CODE]
#define ast_channel_ref(c)
Increase channel reference count.
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Standard Command Line Interface.
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
struct unistim_line * parent
Channels have this property if they can accept input with jitter; i.e. most VoIP channels.
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
int ast_rtp_glue_unregister(struct ast_rtp_glue *glue)
Unregister RTP glue.
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Data structure associated with a single frame of data.
Internal Asterisk hangup causes.
struct stasis_message * stasis_cache_get(struct stasis_cache *cache, struct stasis_message_type *type, const char *id)
Retrieve an item from the cache for the ast_eid_default entity.
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
struct ast_ha * ast_append_ha(const char *sense, const char *stuff, struct ast_ha *path, int *error)
Add a new rule to a list of HAs.
char language[MAX_LANGUAGE]
const char * data
Description of a tone.
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
#define ast_sockaddr_to_sin(addr, sin)
Converts a struct ast_sockaddr to a struct sockaddr_in.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
enum ast_frame_type frametype
Channels have this property if they can create jitter; i.e. most VoIP channels.
unsigned char valid
TRUE if the name information is valid/present.
struct ast_format * format
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
int ast_softhangup_nolock(struct ast_channel *chan, int cause)
Softly hangup up a channel (no channel lock)
The structure that contains MWI state.
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
struct ast_format_cap * cap
#define ASTERISK_GPL_KEY
The text the key() function should return.
Pluggable RTP Architecture.
#define ast_channel_alloc(needqueue, state, cid_num, cid_name, acctcode, exten, context, assignedids, requestor, amaflag,...)
Create a channel structure.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Persistent data storage (akin to *doze registry)
#define ast_rtp_instance_get_remote_address(instance, address)
Get the address of the remote endpoint that we are sending RTP to.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
char extension_number[11]
unsigned char valid
TRUE if the number information is valid/present.
General jitterbuffer configuration.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
int ast_tone_zone_part_parse(const char *s, struct ast_tone_zone_part *tone_data)
Parse a tone part.
Structure for mutex and tracking information.
char redial_number[AST_MAX_EXTENSION]
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
static ast_mutex_t monlock
Configuration relating to call pickup.
static force_inline int attribute_pure ast_str_hash(const char *str)
Compute a hash value on a string.
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
int ast_callerid_parse(char *instr, char **name, char **location)
Destructively parse inbuf into name and location (or number)
struct ast_party_number number
Subscriber phone number.
#define ao2_link(container, obj)
Add an object to a container.
struct io_context * io_context_create(void)
Creates a context Create a context for I/O operations Basically mallocs an IO structure and sets up s...