00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "asterisk.h"
00040
00041 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 409761 $")
00042
00043 #include <sys/stat.h>
00044 #include <signal.h>
00045
00046 #if defined(__CYGWIN__)
00047
00048
00049
00050
00051
00052
00053
00054
00055 #ifdef HAVE_PKTINFO
00056 #undef HAVE_PKTINFO
00057 #endif
00058 #endif
00059
00060 #include "asterisk/paths.h"
00061 #include "asterisk/network.h"
00062 #include "asterisk/channel.h"
00063 #include "asterisk/config.h"
00064 #include "asterisk/module.h"
00065 #include "asterisk/pbx.h"
00066 #include "asterisk/event.h"
00067 #include "asterisk/rtp_engine.h"
00068 #include "asterisk/netsock2.h"
00069 #include "asterisk/acl.h"
00070 #include "asterisk/callerid.h"
00071 #include "asterisk/cli.h"
00072 #include "asterisk/app.h"
00073 #include "asterisk/musiconhold.h"
00074 #include "asterisk/causes.h"
00075 #include "asterisk/indications.h"
00076 #include "asterisk/features.h"
00077 #include "asterisk/astobj2.h"
00078 #include "asterisk/astdb.h"
00079
00080
00081 #define DEFAULTCONTEXT "default"
00082 #define DEFAULTCALLERID "Unknown"
00083 #define DEFAULTCALLERNAME " "
00084 #define DEFAULTHEIGHT 3
00085 #define USTM_LOG_DIR "unistimHistory"
00086 #define USTM_LANG_DIR "unistimLang"
00087
00088
00089 #define MAX_BUF_SIZE 64
00090
00091 #define MAX_BUF_NUMBER 50
00092
00093 #define MAX_SCREEN_NUMBER 15
00094
00095 #define NB_MAX_RETRANSMIT 8
00096
00097 #define IDLE_WAIT 1000
00098
00099 #define RETRANSMIT_TIMER 2000
00100
00101 #define TIMER_MWI 5000
00102
00103 #define DEFAULT_INTERDIGIT_TIMER 4000
00104
00105
00106 #define DEFAULT_CODEC 0x00
00107 #define SIZE_PAGE 4096
00108 #define DEVICE_NAME_LEN 16
00109 #define AST_CONFIG_MAX_PATH 255
00110 #define MAX_ENTRY_LOG 30
00111
00112 #define SUB_REAL 0
00113 #define SUB_RING 1
00114 #define SUB_THREEWAY 2
00115 #define SUB_ONHOLD 3
00116
00117 struct ast_format_cap *global_cap;
00118
00119 enum autoprovision {
00120 AUTOPROVISIONING_NO = 0,
00121 AUTOPROVISIONING_YES,
00122 AUTOPROVISIONING_TN
00123 };
00124
00125 enum autoprov_extn {
00126
00127 EXTENSION_NONE = 0,
00128
00129 EXTENSION_ASK,
00130
00131 EXTENSION_LINE,
00132
00133 EXTENSION_TN
00134 };
00135 #define OUTPUT_HANDSET 0xC0
00136 #define OUTPUT_HEADPHONE 0xC1
00137 #define OUTPUT_SPEAKER 0xC2
00138
00139 #define VOLUME_LOW 0x01
00140 #define VOLUME_LOW_SPEAKER 0x03
00141 #define VOLUME_NORMAL 0x02
00142 #define VOLUME_INSANELY_LOUD 0x07
00143
00144 #define MUTE_OFF 0x00
00145 #define MUTE_ON 0xFF
00146 #define MUTE_ON_DISCRET 0xCE
00147
00148 #define SIZE_HEADER 6
00149 #define SIZE_MAC_ADDR 17
00150 #define TEXT_LENGTH_MAX 24
00151 #define TEXT_LINE0 0x00
00152 #define TEXT_LINE1 0x20
00153 #define TEXT_LINE2 0x40
00154 #define TEXT_NORMAL 0x05
00155 #define TEXT_INVERSE 0x25
00156 #define STATUS_LENGTH_MAX 28
00157
00158 #define FAV_ICON_NONE 0x00
00159 #define FAV_ICON_ONHOOK_BLACK 0x20
00160 #define FAV_ICON_ONHOOK_WHITE 0x21
00161 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
00162 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
00163 #define FAV_ICON_OFFHOOK_BLACK 0x24
00164 #define FAV_ICON_OFFHOOK_WHITE 0x25
00165 #define FAV_ICON_ONHOLD_BLACK 0x26
00166 #define FAV_ICON_ONHOLD_WHITE 0x27
00167 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
00168 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
00169 #define FAV_ICON_PHONE_BLACK 0x2A
00170 #define FAV_ICON_PHONE_WHITE 0x2B
00171 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
00172 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
00173 #define FAV_ICON_HEADPHONES 0x2E
00174 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
00175 #define FAV_ICON_HOME 0x30
00176 #define FAV_ICON_CITY 0x31
00177 #define FAV_ICON_SHARP 0x32
00178 #define FAV_ICON_PAGER 0x33
00179 #define FAV_ICON_CALL_CENTER 0x34
00180 #define FAV_ICON_FAX 0x35
00181 #define FAV_ICON_MAILBOX 0x36
00182 #define FAV_ICON_REFLECT 0x37
00183 #define FAV_ICON_COMPUTER 0x38
00184 #define FAV_ICON_FORWARD 0x39
00185 #define FAV_ICON_LOCKED 0x3A
00186 #define FAV_ICON_TRASH 0x3B
00187 #define FAV_ICON_INBOX 0x3C
00188 #define FAV_ICON_OUTBOX 0x3D
00189 #define FAV_ICON_MEETING 0x3E
00190 #define FAV_ICON_BOX 0x3F
00191
00192 #define FAV_BLINK_FAST 0x20
00193 #define FAV_BLINK_SLOW 0x40
00194
00195 #define FAV_MAX_LENGTH 0x0A
00196
00197 #define FAVNUM 6
00198 #define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
00199
00200 static void dummy(char *unused, ...)
00201 {
00202 return;
00203 }
00204
00205
00206
00207 static struct ast_jb_conf default_jbconf =
00208 {
00209 .flags = 0,
00210 .max_size = 200,
00211 .resync_threshold = 1000,
00212 .impl = "fixed",
00213 .target_extra = 40,
00214 };
00215 static struct ast_jb_conf global_jbconf;
00216
00217
00218
00219
00220
00221 #define DEBUG_TIMER dummy
00222
00223 static int unistimdebug = 0;
00224 static int unistim_port;
00225 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
00226 static int unistim_keepalive;
00227 static int unistimsock = -1;
00228
00229 static struct {
00230 unsigned int tos;
00231 unsigned int tos_audio;
00232 unsigned int cos;
00233 unsigned int cos_audio;
00234 } qos = { 0, 0, 0, 0 };
00235
00236 static struct io_context *io;
00237 static struct ast_sched_context *sched;
00238 static struct sockaddr_in public_ip = { 0, };
00239 static unsigned char *buff;
00240 static int unistim_reloading = 0;
00241 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
00242
00243
00244
00245 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00246
00247
00248
00249 AST_MUTEX_DEFINE_STATIC(monlock);
00250
00251 AST_MUTEX_DEFINE_STATIC(sessionlock);
00252
00253 AST_MUTEX_DEFINE_STATIC(devicelock);
00254
00255 enum phone_state {
00256 STATE_INIT,
00257 STATE_AUTHDENY,
00258 STATE_MAINPAGE,
00259 STATE_EXTENSION,
00260 STATE_DIALPAGE,
00261 STATE_RINGING,
00262 STATE_CALL,
00263 STATE_SELECTOPTION,
00264 STATE_SELECTCODEC,
00265 STATE_SELECTLANGUAGE,
00266 STATE_CLEANING,
00267 STATE_HISTORY
00268 };
00269
00270 enum handset_state {
00271 STATE_ONHOOK,
00272 STATE_OFFHOOK,
00273 };
00274
00275 enum phone_key {
00276 KEY_0 = 0x40,
00277 KEY_1 = 0x41,
00278 KEY_2 = 0x42,
00279 KEY_3 = 0x43,
00280 KEY_4 = 0x44,
00281 KEY_5 = 0x45,
00282 KEY_6 = 0x46,
00283 KEY_7 = 0x47,
00284 KEY_8 = 0x48,
00285 KEY_9 = 0x49,
00286 KEY_STAR = 0x4a,
00287 KEY_SHARP = 0x4b,
00288 KEY_UP = 0x4c,
00289 KEY_DOWN = 0x4d,
00290 KEY_RIGHT = 0x4e,
00291 KEY_LEFT = 0x4f,
00292 KEY_QUIT = 0x50,
00293 KEY_COPY = 0x51,
00294 KEY_FUNC1 = 0x54,
00295 KEY_FUNC2 = 0x55,
00296 KEY_FUNC3 = 0x56,
00297 KEY_FUNC4 = 0x57,
00298 KEY_ONHOLD = 0x5b,
00299 KEY_HANGUP = 0x5c,
00300 KEY_MUTE = 0x5d,
00301 KEY_HEADPHN = 0x5e,
00302 KEY_LOUDSPK = 0x5f,
00303 KEY_FAV0 = 0x60,
00304 KEY_FAV1 = 0x61,
00305 KEY_FAV2 = 0x62,
00306 KEY_FAV3 = 0x63,
00307 KEY_FAV4 = 0x64,
00308 KEY_FAV5 = 0x65,
00309 KEY_COMPUTR = 0x7b,
00310 KEY_CONF = 0x7c,
00311 KEY_SNDHIST = 0x7d,
00312 KEY_RCVHIST = 0x7e,
00313 KEY_INDEX = 0x7f
00314 };
00315
00316 enum charset {
00317 LANG_DEFAULT,
00318 ISO_8859_1,
00319 ISO_8859_2,
00320 ISO_8859_4,
00321 ISO_8859_5,
00322 ISO_2022_JP,
00323 };
00324
00325 static const int dtmf_row[] = { 697, 770, 852, 941 };
00326 static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
00327
00328 struct wsabuf {
00329 u_long len;
00330 unsigned char *buf;
00331 };
00332
00333 struct unistim_subchannel {
00334 ast_mutex_t lock;
00335 unsigned int subtype;
00336 struct ast_channel *owner;
00337 struct unistim_line *parent;
00338 struct ast_rtp_instance *rtp;
00339 int softkey;
00340 pthread_t ss_thread;
00341 int alreadygone;
00342 char ringvolume;
00343 char ringstyle;
00344 int moh;
00345 AST_LIST_ENTRY(unistim_subchannel) list;
00346 };
00347
00348
00349
00350
00351 struct unistim_line {
00352 ast_mutex_t lock;
00353 char name[80];
00354 char fullname[80];
00355 char exten[AST_MAX_EXTENSION];
00356 char cid_num[AST_MAX_EXTENSION];
00357 char mailbox[AST_MAX_EXTENSION];
00358 char musicclass[MAX_MUSICCLASS];
00359 ast_group_t callgroup;
00360 ast_group_t pickupgroup;
00361 char accountcode[AST_MAX_ACCOUNT_CODE];
00362 int amaflags;
00363 struct ast_format_cap *cap;
00364 char parkinglot[AST_MAX_CONTEXT];
00365 struct unistim_line *next;
00366 struct unistim_device *parent;
00367 AST_LIST_ENTRY(unistim_line) list;
00368 };
00369
00370
00371
00372
00373 static struct unistim_device {
00374 ast_mutex_t lock;
00375 int receiver_state;
00376 int size_phone_number;
00377 char context[AST_MAX_EXTENSION];
00378 char phone_number[AST_MAX_EXTENSION];
00379 char redial_number[AST_MAX_EXTENSION];
00380 char id[18];
00381 char name[DEVICE_NAME_LEN];
00382 char softkeylabel[FAVNUM][11];
00383 char softkeynumber[FAVNUM][AST_MAX_EXTENSION];
00384 char softkeyicon[FAVNUM];
00385 char softkeydevice[FAVNUM][16];
00386 struct unistim_subchannel *ssub[FAVNUM];
00387 struct unistim_line *sline[FAVNUM];
00388 struct unistim_device *sp[FAVNUM];
00389 char language[MAX_LANGUAGE];
00390 int height;
00391 char maintext0[25];
00392 char maintext1[25];
00393 char maintext2[25];
00394 char titledefault[13];
00395 char datetimeformat;
00396 char contrast;
00397 char country[3];
00398 struct ast_tone_zone *tz;
00399 char ringvolume;
00400 char ringstyle;
00401 char cwvolume;
00402 char cwstyle;
00403 int interdigit_timer;
00404 time_t nextdial;
00405 int rtp_port;
00406 int rtp_method;
00407 int status_method;
00408 char codec_number;
00409 int missed_call;
00410 int callhistory;
00411 int sharp_dial;
00412 char lst_cid[TEXT_LENGTH_MAX];
00413 char lst_cnm[TEXT_LENGTH_MAX];
00414 char call_forward[AST_MAX_EXTENSION];
00415 int output;
00416 int previous_output;
00417 int volume;
00418 int selected;
00419 int mute;
00420 int lastmsgssent;
00421 time_t nextmsgcheck;
00422 int nat;
00423 enum autoprov_extn extension;
00424 char extension_number[11];
00425 char to_delete;
00426 struct ast_silence_generator *silence_generator;
00427 AST_LIST_HEAD(,unistim_subchannel) subs;
00428 AST_LIST_HEAD(,unistim_line) lines;
00429 struct ast_ha *ha;
00430 struct unistimsession *session;
00431 struct unistim_device *next;
00432 } *devices = NULL;
00433
00434 static struct unistimsession {
00435 ast_mutex_t lock;
00436 struct sockaddr_in sin;
00437 struct sockaddr_in sout;
00438 int timeout;
00439 unsigned short seq_phone;
00440 unsigned short seq_server;
00441 unsigned short last_seq_ack;
00442 unsigned long tick_next_ping;
00443 int last_buf_available;
00444 int nb_retransmit;
00445 int state;
00446 int size_buff_entry;
00447 char buff_entry[16];
00448 char macaddr[18];
00449 struct wsabuf wsabufsend[MAX_BUF_NUMBER];
00450 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE];
00451 struct unistim_device *device;
00452 struct unistimsession *next;
00453 } *sessions = NULL;
00454
00455
00456 struct unistim_menu_item {
00457 char *label;
00458 int state;
00459 void (*handle_option)(struct unistimsession *);
00460 };
00461
00462
00463 struct unistim_languages {
00464 char *label;
00465 char *lang_short;
00466 int encoding;
00467 struct ao2_container *trans;
00468 };
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481 static const unsigned char packet_rcv_discovery[] =
00482 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
00483 static const unsigned char packet_send_discovery_ack[] =
00484 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
00485
00486 static const unsigned char packet_recv_firm_version[] =
00487 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
00488 static const unsigned char packet_recv_it_type[] =
00489 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x04, 0x03 };
00490 static const unsigned char packet_recv_pressed_key[] =
00491 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
00492 static const unsigned char packet_recv_pick_up[] =
00493 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
00494 static const unsigned char packet_recv_hangup[] =
00495 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
00496 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
00497
00498
00499 static const unsigned char packet_recv_resume_connection_with_server[] =
00500 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
00501 static const unsigned char packet_recv_mac_addr[] =
00502 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 };
00503
00504 static const unsigned char packet_send_date_time3[] =
00505 { 0x11, 0x09, 0x02, 0x02, 0x05, 0x06, 0x07,
00506 0x08, 0x32
00507 };
00508 static const unsigned char packet_send_date_time[] =
00509 { 0x11, 0x09, 0x02, 0x0a, 0x05, 0x06, 0x07,
00510 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
00511 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
00512 0x05, 0x12, 0x00, 0x78
00513 };
00514
00515 static const unsigned char packet_send_no_ring[] =
00516 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
00517 static const unsigned char packet_send_s4[] =
00518 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
00519 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
00520 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
00521 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
00522 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
00523 };
00524 static const unsigned char packet_send_call[] =
00525 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
00526 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
00527 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
00528 0x00, 0x12, 0x12, 0x01, 0x5c, 0x00,
00529 0x0f, 0xa0, 0x9c, 0x41,
00530 0x0f, 0xa0, 0x9c, 0x41, 0x0a, 0x01,
00531 0x16, 0x66
00532 };
00533 static const unsigned char packet_send_stream_based_tone_off[] =
00534 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
00535
00536
00537
00538
00539 static const unsigned char packet_send_stream_based_tone_on[] =
00540 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
00541 static const unsigned char packet_send_stream_based_tone_single_freq[] =
00542 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
00543 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
00544 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
00545 static const unsigned char packet_send_select_output[] =
00546 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
00547 static const unsigned char packet_send_ring[] =
00548 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
00549 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 , 0x18, 0x16, 0x04, 0x18,
00550 0x20, 0x16, 0x04, 0x10, 0x00
00551 };
00552 static const unsigned char packet_send_end_call[] =
00553 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
00554 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
00555 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
00556 };
00557 static const unsigned char packet_send_s9[] =
00558 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
00559 0x00 };
00560 static const unsigned char packet_send_rtp_packet_size[] =
00561 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
00562 static const unsigned char packet_send_jitter_buffer_conf[] =
00563 { 0x16, 0x0e, 0x3a, 0x00, 0x02, 0x04, 0x00, 0x00,
00564 0x3e, 0x80,
00565 0x00, 0x00, 0x3e, 0x80
00566 };
00567
00568
00569
00570
00571 static const unsigned char packet_send_open_audio_stream_rx[] =
00572 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
00573 0x0e, 0x01, 0x14, 0x50, 0x00,
00574 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
00575 };
00576 static const unsigned char packet_send_open_audio_stream_tx[] =
00577 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
00578 0x0e, 0x01, 0x14, 0x50,
00579 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
00580 };
00581
00582 static const unsigned char packet_send_open_audio_stream_rx3[] =
00583 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
00584 0x06, 0x81, 0x14, 0x50,
00585 0x14,
00586 0x51, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93,
00587 0x69, 0x05
00588 };
00589 static const unsigned char packet_send_open_audio_stream_tx3[] =
00590 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
00591 0x06, 0x81, 0x14, 0x50,
00592 0x00, 0x00, 0x14, 0x50, 0x00, 0x00,
00593 0x0a, 0x93, 0x69, 0x05
00594 };
00595
00596 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
00597 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
00598 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, 0x05,
00599 0x06, 0x07, 0x08, 0x32
00600 };
00601 static const unsigned char packet_send_Contrast[] =
00602 { 0x17, 0x04, 0x24, 0x08 };
00603 static const unsigned char packet_send_start_timer[] =
00604 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16,
00605 0x44, 0x75, 0x72, 0xe9, 0x65 };
00606 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
00607 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, 0x00, 0x25 };
00608 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
00609 static const unsigned char packet_send_set_pos_cursor[] =
00610 { 0x17, 0x06, 0x10, 0x81, 0x04, 0x20 };
00611
00612
00613
00614 static const unsigned char packet_send_favorite[] =
00615 { 0x17, 0x0f, 0x19, 0x10, 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00616 0x20, 0x20, 0x20, 0x20, 0x19,
00617 0x05, 0x0f, 0x01, 0x00
00618 };
00619 static const unsigned char packet_send_title[] =
00620 { 0x17, 0x10, 0x19, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00621 0x20, 0x20, 0x20, 0x20 };
00622 static const unsigned char packet_send_text[] =
00623 { 0x17, 0x1e, 0x1b, 0x04, 0x00, 0x25, 0x20, 0x20,
00624 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00625 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00626 0x17, 0x04, 0x10, 0x87
00627 };
00628 static const unsigned char packet_send_status[] =
00629 { 0x17, 0x20, 0x19, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00630 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00631 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
00632 };
00633 static const unsigned char packet_send_status2[] =
00634 { 0x17, 0x0b, 0x19, 0x00, 0x20, 0x20, 0x20, 0x20,
00635 0x20, 0x20, 0x20 };
00636
00637
00638
00639 static const unsigned char packet_send_charset_iso_8859_1[] =
00640 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
00641
00642 static const unsigned char packet_send_charset_iso_8859_2[] =
00643 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
00644
00645 static const unsigned char packet_send_charset_iso_8859_4[] =
00646 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
00647
00648 static const unsigned char packet_send_charset_iso_8859_5[] =
00649 { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
00650
00651 static const unsigned char packet_send_charset_iso_2022_jp[] =
00652 { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
00653
00654 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
00655
00656 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
00657 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
00658 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
00659 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
00660
00661 static unsigned char packet_send_ping[] =
00662 { 0x1e, 0x05, 0x12, 0x00, 0x78 };
00663
00664 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
00665
00666 static const char tdesc[] = "UNISTIM Channel Driver";
00667 static const char channel_type[] = "USTM";
00668
00669
00670 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
00671 static int load_module(void);
00672 static int reload(void);
00673 static int unload_module(void);
00674 static int reload_config(void);
00675 static void show_main_page(struct unistimsession *pte);
00676 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor,
00677 const char *dest, int *cause);
00678 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout);
00679 static int unistim_hangup(struct ast_channel *ast);
00680 static int unistim_answer(struct ast_channel *ast);
00681 static struct ast_frame *unistim_read(struct ast_channel *ast);
00682 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
00683 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
00684 size_t datalen);
00685 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00686 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
00687 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
00688 unsigned int duration);
00689 static int unistim_sendtext(struct ast_channel *ast, const char *text);
00690
00691 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
00692 char *line1);
00693 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
00694
00695 static struct ast_channel_tech unistim_tech = {
00696 .type = channel_type,
00697 .description = tdesc,
00698 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00699 .requester = unistim_request,
00700 .call = unistim_call,
00701 .hangup = unistim_hangup,
00702 .answer = unistim_answer,
00703 .read = unistim_read,
00704 .write = unistim_write,
00705 .indicate = unistim_indicate,
00706 .fixup = unistim_fixup,
00707 .send_digit_begin = unistim_senddigit_begin,
00708 .send_digit_end = unistim_senddigit_end,
00709 .send_text = unistim_sendtext,
00710 .bridge = ast_rtp_instance_bridge,
00711 };
00712
00713 static void send_start_rtp(struct unistim_subchannel *);
00714
00715 static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *);
00716 static void key_favorite(struct unistimsession *, char);
00717
00718 static void handle_select_codec(struct unistimsession *);
00719 static void handle_select_language(struct unistimsession *);
00720 static int find_language(const char*);
00721
00722 static int unistim_free_sub(struct unistim_subchannel *);
00723
00724 static struct unistim_menu_item options_menu[] =
00725 {
00726 {"Change codec", STATE_SELECTCODEC, handle_select_codec},
00727 {"Language", STATE_SELECTLANGUAGE, handle_select_language},
00728 {NULL, 0, NULL}
00729 };
00730
00731 static struct unistim_languages options_languages[] =
00732 {
00733 {"English", "en", ISO_8859_1, NULL},
00734 {"French", "fr", ISO_8859_1, NULL},
00735 {"Russian", "ru", ISO_8859_5, NULL},
00736 {NULL, NULL, 0, NULL}
00737 };
00738
00739 static char ustm_strcopy[1024];
00740
00741 struct ustm_lang_entry {
00742 const char *str_orig;
00743 const char *str_trans;
00744 };
00745
00746 static int lang_hash_fn(const void *obj, const int flags)
00747 {
00748 const struct ustm_lang_entry *entry = obj;
00749 return ast_str_hash(entry->str_orig);
00750 }
00751
00752 static int lang_cmp_fn(void *obj, void *arg, int flags)
00753 {
00754 struct ustm_lang_entry *entry1 = obj;
00755 struct ustm_lang_entry *entry2 = arg;
00756
00757 return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
00758 }
00759
00760 static const char *ustmtext(const char *str, struct unistimsession *pte)
00761 {
00762 struct ustm_lang_entry *lang_entry;
00763 struct ustm_lang_entry le_search;
00764 struct unistim_languages *lang = NULL;
00765 int size;
00766
00767 if (pte->device) {
00768 lang = &options_languages[find_language(pte->device->language)];
00769 }
00770 if (!lang) {
00771 return str;
00772 }
00773
00774 if (!lang->trans) {
00775 char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
00776 FILE *f;
00777
00778 if (!(lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn))) {
00779 ast_log(LOG_ERROR, "Unable to allocate container for translation!\n");
00780 return str;
00781 }
00782 snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
00783 USTM_LANG_DIR, lang->lang_short);
00784 f = fopen(tmp, "r");
00785 if (!f) {
00786 ast_log(LOG_WARNING, "There is no translation file for '%s'\n", lang->lang_short);
00787 return str;
00788 }
00789 while (fgets(tmp, sizeof(tmp), f)) {
00790 if (!(p = strchr(tmp, '\n'))) {
00791 ast_log(LOG_ERROR, "Too long line found in language file - truncated!\n");
00792 continue;
00793 }
00794 *p = '\0';
00795 if (!(p = strchr(tmp, '"'))) {
00796 continue;
00797 }
00798 if (tmp == strstr(tmp, "msgid")) {
00799 p_orig = ast_strdup(p + 1);
00800 p = strchr(p_orig, '"');
00801 } else if (tmp == strstr(tmp, "msgstr")) {
00802 p_trans = ast_strdup(p + 1);
00803 p = strchr(p_trans, '"');
00804 } else {
00805 continue;
00806 }
00807 *p = '\0';
00808 if (!p_trans || !p_orig) {
00809 continue;
00810 }
00811 if (ast_strlen_zero(p_trans)) {
00812 ast_free(p_trans);
00813 ast_free(p_orig);
00814 p_trans = NULL;
00815 p_orig = NULL;
00816 continue;
00817 }
00818 if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), NULL))) {
00819 fclose(f);
00820 return str;
00821 }
00822
00823 lang_entry->str_trans = p_trans;
00824 lang_entry->str_orig = p_orig;
00825 ao2_link(lang->trans, lang_entry);
00826 p_trans = NULL;
00827 p_orig = NULL;
00828 }
00829
00830 fclose(f);
00831 }
00832
00833 le_search.str_orig = str;
00834 if ((lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER))) {
00835 size = strlen(lang_entry->str_trans)+1;
00836 if (size > 1024) {
00837 size = 1024;
00838 }
00839 memcpy(ustm_strcopy, lang_entry->str_trans, size);
00840 ao2_ref(lang_entry, -1);
00841 return ustm_strcopy;
00842 }
00843
00844 return str;
00845 }
00846
00847 static void display_last_error(const char *sz_msg)
00848 {
00849
00850 ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
00851 }
00852
00853 static unsigned int get_tick_count(void)
00854 {
00855 struct timeval now = ast_tvnow();
00856
00857 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
00858 }
00859
00860
00861 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
00862 const struct sockaddr_in *addr_ourip)
00863 {
00864 #ifdef HAVE_PKTINFO
00865 struct iovec msg_iov;
00866 struct msghdr msg;
00867 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
00868 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
00869 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
00870
00871
00872
00873
00874
00875
00876 msg_iov.iov_base = (char *) data;
00877 msg_iov.iov_len = size;
00878
00879 msg.msg_name = addr_to;
00880 msg.msg_namelen = sizeof(struct sockaddr_in);
00881 msg.msg_iov = &msg_iov;
00882 msg.msg_iovlen = 1;
00883 msg.msg_control = ip_msg;
00884 msg.msg_controllen = sizeof(buffer);
00885 msg.msg_flags = 0;
00886
00887 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
00888 ip_msg->cmsg_level = IPPROTO_IP;
00889 ip_msg->cmsg_type = IP_PKTINFO;
00890 pki->ipi_ifindex = 0;
00891 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr;
00892
00893
00894 #ifdef DUMP_PACKET
00895 if (unistimdebug) {
00896 int tmp;
00897 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
00898 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
00899 ast_inet_ntoa(addr_to->sin_addr));
00900 for (tmp = 0; tmp < size; tmp++)
00901 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
00902 ast_verb(0, "\n******************************************\n");
00903
00904 }
00905 #endif
00906
00907 if (sendmsg(unistimsock, &msg, 0) == -1) {
00908 display_last_error("Error sending datas");
00909 }
00910 #else
00911 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
00912 == -1)
00913 display_last_error("Error sending datas");
00914 #endif
00915 }
00916
00917 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
00918 {
00919 unsigned int tick;
00920 int buf_pos;
00921 unsigned short seq = ntohs(++pte->seq_server);
00922
00923 ast_mutex_lock(&pte->lock);
00924 buf_pos = pte->last_buf_available;
00925
00926 if (buf_pos >= MAX_BUF_NUMBER) {
00927 ast_log(LOG_WARNING, "Error : send queue overflow\n");
00928 ast_mutex_unlock(&pte->lock);
00929 return;
00930 }
00931 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
00932 pte->wsabufsend[buf_pos].len = size;
00933 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
00934
00935 tick = get_tick_count();
00936 pte->timeout = tick + RETRANSMIT_TIMER;
00937
00938
00939 if (unistimdebug) {
00940 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
00941 }
00942
00943 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
00944 &(pte->sout));
00945 pte->last_buf_available++;
00946 ast_mutex_unlock(&pte->lock);
00947 }
00948
00949 static void send_ping(struct unistimsession *pte)
00950 {
00951 BUFFSEND;
00952 if (unistimdebug) {
00953 ast_verb(6, "Sending ping\n");
00954 }
00955 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
00956 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
00957 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
00958 }
00959
00960 static int get_to_address(int fd, struct sockaddr_in *toAddr)
00961 {
00962 #ifdef HAVE_PKTINFO
00963 int err;
00964 struct msghdr msg;
00965 struct {
00966 struct cmsghdr cm;
00967 int len;
00968 struct in_addr address;
00969 } ip_msg;
00970
00971
00972
00973 memset(&msg, 0, sizeof(msg));
00974 memset(&ip_msg, 0, sizeof(ip_msg));
00975
00976
00977 msg.msg_control = &ip_msg;
00978 msg.msg_controllen = sizeof(ip_msg);
00979
00980 err = recvmsg(fd, &msg, MSG_PEEK);
00981 if (err == -1) {
00982 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
00983 }
00984 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
00985 return err;
00986 #else
00987 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
00988 return 0;
00989 #endif
00990 }
00991
00992
00993
00994 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
00995 {
00996 int tmp;
00997 struct unistimsession *s;
00998
00999 if (!(s = ast_calloc(1, sizeof(*s))))
01000 return NULL;
01001
01002 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
01003 get_to_address(unistimsock, &s->sout);
01004 s->sout.sin_family = AF_INET;
01005 if (unistimdebug) {
01006 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
01007 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
01008 }
01009 ast_mutex_init(&s->lock);
01010 ast_mutex_lock(&sessionlock);
01011 s->next = sessions;
01012 sessions = s;
01013
01014 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
01015 s->state = STATE_INIT;
01016 s->tick_next_ping = get_tick_count() + unistim_keepalive;
01017
01018 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
01019 s->wsabufsend[tmp].buf = s->buf[tmp];
01020 }
01021 ast_mutex_unlock(&sessionlock);
01022 return s;
01023 }
01024
01025 static void send_end_call(struct unistimsession *pte)
01026 {
01027 BUFFSEND;
01028 if (unistimdebug) {
01029 ast_verb(0, "Sending end call\n");
01030 }
01031 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
01032 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
01033 }
01034
01035 static void set_ping_timer(struct unistimsession *pte)
01036 {
01037 unsigned int tick = 0;
01038
01039 pte->timeout = pte->tick_next_ping;
01040 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
01041 return;
01042 }
01043
01044
01045
01046 static void check_send_queue(struct unistimsession *pte)
01047 {
01048
01049 if (pte->last_buf_available == 1) {
01050 if (unistimdebug) {
01051 ast_verb(6, "Our single packet was ACKed.\n");
01052 }
01053 pte->last_buf_available--;
01054 set_ping_timer(pte);
01055 return;
01056 }
01057
01058 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
01059 if (unistimdebug) {
01060 ast_verb(6, "Our send queue is completely ACKed.\n");
01061 }
01062 pte->last_buf_available = 0;
01063 set_ping_timer(pte);
01064 return;
01065 }
01066 if (unistimdebug) {
01067 ast_verb(6, "We still have packets in our send queue\n");
01068 }
01069 return;
01070 }
01071
01072 static void send_start_timer(struct unistimsession *pte)
01073 {
01074 BUFFSEND;
01075 if (unistimdebug) {
01076 ast_verb(0, "Sending start timer\n");
01077 }
01078 memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
01079 send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
01080 }
01081
01082 static void send_stop_timer(struct unistimsession *pte)
01083 {
01084 BUFFSEND;
01085 if (unistimdebug) {
01086 ast_verb(0, "Sending stop timer\n");
01087 }
01088 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
01089 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
01090 }
01091
01092 static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
01093 {
01094 BUFFSEND;
01095 if (unistimdebug) {
01096 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
01097 }
01098 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
01099 buffsend[9] = pos;
01100 buffsend[10] = status;
01101 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
01102 }
01103
01104 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
01105 {
01106 BUFFSEND;
01107 if (!tone1) {
01108 if (unistimdebug) {
01109 ast_verb(0, "Sending Stream Based Tone Off\n");
01110 }
01111 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
01112 sizeof(packet_send_stream_based_tone_off));
01113 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
01114 return;
01115 }
01116
01117
01118
01119
01120
01121 if (unistimdebug) {
01122 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
01123 }
01124 tone1 *= 8;
01125 if (!tone2) {
01126 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
01127 sizeof(packet_send_stream_based_tone_single_freq));
01128 buffsend[10] = (tone1 & 0xff00) >> 8;
01129 buffsend[11] = (tone1 & 0x00ff);
01130 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
01131 pte);
01132 } else {
01133 tone2 *= 8;
01134 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
01135 sizeof(packet_send_stream_based_tone_dial_freq));
01136 buffsend[10] = (tone1 & 0xff00) >> 8;
01137 buffsend[11] = (tone1 & 0x00ff);
01138 buffsend[12] = (tone2 & 0xff00) >> 8;
01139 buffsend[13] = (tone2 & 0x00ff);
01140 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
01141 pte);
01142 }
01143
01144 if (unistimdebug) {
01145 ast_verb(0, "Sending Stream Based Tone On\n");
01146 }
01147 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
01148 sizeof(packet_send_stream_based_tone_on));
01149 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160 static void
01161 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
01162 const char *text)
01163 {
01164 BUFFSEND;
01165 int i;
01166
01167 if (unistimdebug) {
01168 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
01169 }
01170 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
01171 buffsend[10] = pos;
01172 buffsend[24] = pos;
01173 buffsend[25] = status;
01174 i = strlen(ustmtext(text, pte));
01175 if (i > FAV_MAX_LENGTH) {
01176 i = FAV_MAX_LENGTH;
01177 }
01178 memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
01179 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
01180 }
01181
01182 static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
01183 send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
01184 return;
01185 }
01186
01187 static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
01188 if (pte->device->selected != -1) {
01189 send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
01190 }
01191 return;
01192 }
01193
01194 static int soft_key_visible(struct unistim_device* d, unsigned char num)
01195 {
01196 if(d->height == 1 && num % 3 == 2) {
01197 return 0;
01198 }
01199 return 1;
01200 }
01201
01202 static void refresh_all_favorite(struct unistimsession *pte)
01203 {
01204 unsigned char i = 0;
01205 char data[256];
01206 struct unistim_line *line;
01207 line = AST_LIST_FIRST(&pte->device->lines);
01208
01209 if (unistimdebug) {
01210 ast_verb(0, "Refreshing all favorite\n");
01211 }
01212 for (i = 0; i < FAVNUM; i++) {
01213 unsigned char status = pte->device->softkeyicon[i];
01214
01215 if (!soft_key_visible(pte->device, i)) {
01216 continue;
01217 }
01218 if (!strcasecmp(pte->device->softkeylabel[i], "DND") && line) {
01219 if (!ast_db_get("DND", line->name, data, sizeof(data))) {
01220 status = FAV_ICON_SPEAKER_ONHOOK_WHITE;
01221 }
01222 }
01223
01224 send_favorite_short(i, status, pte);
01225 }
01226 }
01227
01228 static int is_key_favorite(struct unistim_device *d, int fav)
01229 {
01230 if ((fav < 0) && (fav > 5)) {
01231 return 0;
01232 }
01233 if (d->sline[fav]) {
01234 return 0;
01235 }
01236 if (d->softkeynumber[fav][0] == '\0') {
01237 return 0;
01238 }
01239 return 1;
01240 }
01241
01242 static int is_key_line(struct unistim_device *d, int fav)
01243 {
01244 if ((fav < 0) && (fav > 5)) {
01245 return 0;
01246 }
01247 if (!d->sline[fav]) {
01248 return 0;
01249 }
01250 if (is_key_favorite(d, fav)) {
01251 return 0;
01252 }
01253 return 1;
01254 }
01255
01256 static int get_active_softkey(struct unistimsession *pte)
01257 {
01258 return pte->device->selected;
01259 }
01260
01261 static int get_avail_softkey(struct unistimsession *pte, const char* name)
01262 {
01263 int i;
01264
01265 if (!is_key_line(pte->device, pte->device->selected)) {
01266 pte->device->selected = -1;
01267 }
01268 for (i = 0; i < FAVNUM; i++) {
01269 if (pte->device->selected != -1 && pte->device->selected != i) {
01270 continue;
01271 }
01272 if (!soft_key_visible(pte->device, i)) {
01273 continue;
01274 }
01275 if (pte->device->ssub[i]) {
01276 continue;
01277 }
01278 if (is_key_line(pte->device, i)) {
01279 if (name && strcmp(name, pte->device->sline[i]->name)) {
01280 continue;
01281 }
01282 if (unistimdebug) {
01283 ast_verb(0, "Found softkey %d for device %s\n", i, name);
01284 }
01285 return i;
01286 }
01287 }
01288 return -1;
01289 }
01290
01291
01292
01293
01294 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
01295 {
01296 struct unistim_device *d = devices;
01297 int i;
01298
01299 if (pte->state != STATE_CLEANING) {
01300 int softkeylinepos = get_active_softkey(pte);
01301 if (softkeylinepos != -1) {
01302 send_favorite_short(softkeylinepos, status, pte);
01303 }
01304 }
01305
01306 while (d) {
01307 for (i = 0; i < FAVNUM; i++) {
01308 if (d->sp[i] == pte->device) {
01309 if (d->softkeyicon[i] != status) {
01310 d->softkeyicon[i] = status;
01311 if (d->session) {
01312 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
01313 }
01314 }
01315 }
01316 }
01317 d = d->next;
01318 }
01319 }
01320
01321 static int register_extension(const struct unistimsession *pte)
01322 {
01323 struct unistim_line *line;
01324 line = AST_LIST_FIRST(&pte->device->lines);
01325 if (unistimdebug) {
01326 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
01327 pte->device->extension_number, pte->device->context,
01328 line->fullname);
01329 }
01330 return ast_add_extension(pte->device->context, 0,
01331 pte->device->extension_number, 1, NULL, NULL, "Dial",
01332 line->fullname, 0, "Unistim");
01333 }
01334
01335 static int unregister_extension(const struct unistimsession *pte)
01336 {
01337 if (unistimdebug) {
01338 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
01339 pte->device->extension_number, pte->device->context);
01340 }
01341 return ast_context_remove_extension(pte->device->context,
01342 pte->device->extension_number, 1, "Unistim");
01343 }
01344
01345
01346 static void close_client(struct unistimsession *s)
01347 {
01348 struct unistim_subchannel *sub = NULL;
01349 struct unistimsession *cur, *prev = NULL;
01350 ast_mutex_lock(&sessionlock);
01351 cur = sessions;
01352
01353 while (cur) {
01354 if (cur == s) {
01355 break;
01356 }
01357 prev = cur;
01358 cur = cur->next;
01359 }
01360 if (cur) {
01361 if (cur->device) {
01362 s->state = STATE_CLEANING;
01363 if (unistimdebug) {
01364 ast_verb(0, "close_client session %p device %p\n", s, s->device);
01365 }
01366 change_favorite_icon(s, FAV_ICON_NONE);
01367 ast_mutex_lock(&s->device->lock);
01368 AST_LIST_LOCK(&s->device->subs);
01369 AST_LIST_TRAVERSE_SAFE_BEGIN(&s->device->subs, sub, list) {
01370 if (!sub) {
01371 continue;
01372 }
01373 if (sub->owner) {
01374 if (unistimdebug) {
01375 ast_verb(0, "Aborting call\n");
01376 }
01377 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
01378 } else {
01379 if (unistimdebug) {
01380 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, s->device->name);
01381 }
01382 AST_LIST_REMOVE_CURRENT(list);
01383 unistim_free_sub(sub);
01384 }
01385 }
01386 AST_LIST_TRAVERSE_SAFE_END;
01387 AST_LIST_UNLOCK(&s->device->subs);
01388
01389 if (!ast_strlen_zero(s->device->extension_number)) {
01390 unregister_extension(s);
01391 }
01392 cur->device->session = NULL;
01393 ast_mutex_unlock(&s->device->lock);
01394 } else {
01395 if (unistimdebug) {
01396 ast_verb(0, "Freeing an unregistered client\n");
01397 }
01398 }
01399 if (prev) {
01400 prev->next = cur->next;
01401 } else {
01402 sessions = cur->next;
01403 }
01404 ast_mutex_destroy(&s->lock);
01405 ast_free(s);
01406 } else {
01407 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
01408 }
01409 ast_mutex_unlock(&sessionlock);
01410 return;
01411 }
01412
01413
01414 static int send_retransmit(struct unistimsession *pte)
01415 {
01416 int i;
01417
01418 ast_mutex_lock(&pte->lock);
01419 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
01420 if (unistimdebug) {
01421 ast_verb(0, "Too many retransmit - freeing client\n");
01422 }
01423 ast_mutex_unlock(&pte->lock);
01424 close_client(pte);
01425 return 1;
01426 }
01427 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
01428
01429 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
01430 i < pte->last_buf_available; i++) {
01431 if (i < 0) {
01432 ast_log(LOG_WARNING,
01433 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
01434 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
01435 continue;
01436 }
01437
01438 if (unistimdebug) {
01439 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
01440 unsigned short seq;
01441
01442 seq = ntohs(sbuf[1]);
01443 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
01444 seq, pte->last_seq_ack);
01445 }
01446 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
01447 &pte->sout);
01448 }
01449 ast_mutex_unlock(&pte->lock);
01450 return 0;
01451 }
01452
01453
01454 static void
01455 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
01456 const char *text)
01457 {
01458 int i;
01459 BUFFSEND;
01460 if (!text) {
01461 ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
01462 return;
01463 }
01464 if (pte->device && pte->device->height == 1 && pos != TEXT_LINE0) {
01465 return;
01466 }
01467 if (unistimdebug) {
01468 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
01469 }
01470 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
01471 buffsend[10] = pos;
01472 buffsend[11] = inverse;
01473 i = strlen(text);
01474 if (i > TEXT_LENGTH_MAX) {
01475 i = TEXT_LENGTH_MAX;
01476 }
01477 memcpy(buffsend + 12, text, i);
01478 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
01479 }
01480
01481 static void send_text_status(struct unistimsession *pte, const char *text)
01482 {
01483 BUFFSEND;
01484 int i;
01485 if (unistimdebug) {
01486 ast_verb(0, "Sending status text\n");
01487 }
01488 if (pte->device) {
01489 if (pte->device->status_method == 1) {
01490 int n = strlen(text);
01491
01492 int j;
01493 for (i = 0, j = 0; i < 4; i++, j += 7) {
01494 int pos = 0x08 + (i * 0x20);
01495 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
01496 sizeof(packet_send_status2));
01497
01498 buffsend[9] = pos;
01499 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
01500 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
01501 }
01502 return;
01503 }
01504 }
01505
01506
01507 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
01508 i = strlen(text);
01509 if (i > STATUS_LENGTH_MAX) {
01510 i = STATUS_LENGTH_MAX;
01511 }
01512 memcpy(buffsend + 10, text, i);
01513 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
01514
01515 }
01516
01517
01518
01519
01520
01521 static void send_led_update(struct unistimsession *pte, unsigned char led)
01522 {
01523 BUFFSEND;
01524 if (unistimdebug) {
01525 ast_verb(0, "Sending led_update (%x)\n", led);
01526 }
01527 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
01528 buffsend[9] = led;
01529 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
01530 }
01531
01532
01533
01534
01535 static void
01536 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
01537 unsigned char mute)
01538 {
01539 BUFFSEND;
01540 if (unistimdebug) {
01541 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
01542 volume, mute);
01543 }
01544 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
01545 sizeof(packet_send_select_output));
01546 buffsend[9] = output;
01547 if (output == OUTPUT_SPEAKER) {
01548 volume = VOLUME_LOW_SPEAKER;
01549 } else {
01550 volume = VOLUME_LOW;
01551 }
01552 buffsend[10] = volume;
01553 if (mute == MUTE_ON_DISCRET) {
01554 buffsend[11] = MUTE_ON;
01555 } else {
01556 buffsend[11] = mute;
01557 }
01558 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
01559 if (mute == MUTE_OFF) {
01560 send_led_update(pte, 0x18);
01561 } else if (mute == MUTE_ON) {
01562 send_led_update(pte, 0x19);
01563 }
01564 pte->device->mute = mute;
01565 if (output == OUTPUT_HANDSET) {
01566 if (mute == MUTE_ON) {
01567 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
01568 } else {
01569 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
01570 }
01571 send_led_update(pte, 0x08);
01572 send_led_update(pte, 0x10);
01573 } else if (output == OUTPUT_HEADPHONE) {
01574 if (mute == MUTE_ON) {
01575 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
01576 } else {
01577 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
01578 }
01579 send_led_update(pte, 0x08);
01580 send_led_update(pte, 0x11);
01581 } else if (output == OUTPUT_SPEAKER) {
01582 send_led_update(pte, 0x10);
01583 send_led_update(pte, 0x09);
01584 if (pte->device->receiver_state == STATE_OFFHOOK) {
01585 if (mute == MUTE_ON) {
01586 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01587 } else {
01588 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
01589 }
01590 } else {
01591 if (mute == MUTE_ON) {
01592 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01593 } else {
01594 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
01595 }
01596 }
01597 } else {
01598 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
01599 }
01600 if (output != pte->device->output) {
01601 pte->device->previous_output = pte->device->output;
01602 }
01603 pte->device->output = output;
01604 }
01605
01606 static void send_ring(struct unistimsession *pte, char volume, char style)
01607 {
01608 BUFFSEND;
01609 if (unistimdebug) {
01610 ast_verb(0, "Sending ring packet\n");
01611 }
01612 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
01613 buffsend[24] = style + 0x10;
01614 buffsend[29] = volume * 0x10;
01615 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
01616 }
01617
01618 static void send_no_ring(struct unistimsession *pte)
01619 {
01620 BUFFSEND;
01621 if (unistimdebug) {
01622 ast_verb(0, "Sending no ring packet\n");
01623 }
01624 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
01625 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
01626 }
01627
01628 static void send_texttitle(struct unistimsession *pte, const char *text)
01629 {
01630 BUFFSEND;
01631 int i;
01632 if (unistimdebug) {
01633 ast_verb(0, "Sending title text\n");
01634 }
01635 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
01636 i = strlen(text);
01637 if (i > 12) {
01638 i = 12;
01639 }
01640 memcpy(buffsend + 10, text, i);
01641 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
01642
01643 }
01644
01645 static void send_idle_clock(struct unistimsession *pte)
01646 {
01647 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
01648 }
01649
01650 static void send_date_time(struct unistimsession *pte)
01651 {
01652 BUFFSEND;
01653 struct timeval now = ast_tvnow();
01654 struct ast_tm atm = { 0, };
01655
01656 if (unistimdebug) {
01657 ast_verb(0, "Sending Time & Date\n");
01658 }
01659 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
01660 ast_localtime(&now, &atm, NULL);
01661 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01662 buffsend[11] = (unsigned char) atm.tm_mday;
01663 buffsend[12] = (unsigned char) atm.tm_hour;
01664 buffsend[13] = (unsigned char) atm.tm_min;
01665 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
01666 }
01667
01668 static void send_date_time2(struct unistimsession *pte)
01669 {
01670 BUFFSEND;
01671 struct timeval now = ast_tvnow();
01672 struct ast_tm atm = { 0, };
01673
01674 if (unistimdebug) {
01675 ast_verb(0, "Sending Time & Date #2\n");
01676 }
01677 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
01678 ast_localtime(&now, &atm, NULL);
01679 if (pte->device) {
01680 buffsend[9] = pte->device->datetimeformat;
01681 } else {
01682 buffsend[9] = 61;
01683 }
01684 buffsend[14] = (unsigned char) atm.tm_mon + 1;
01685 buffsend[15] = (unsigned char) atm.tm_mday;
01686 buffsend[16] = (unsigned char) atm.tm_hour;
01687 buffsend[17] = (unsigned char) atm.tm_min;
01688 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
01689 }
01690
01691 static void send_date_time3(struct unistimsession *pte)
01692 {
01693 BUFFSEND;
01694 struct timeval now = ast_tvnow();
01695 struct ast_tm atm = { 0, };
01696
01697 if (unistimdebug) {
01698 ast_verb(0, "Sending Time & Date #3\n");
01699 }
01700 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
01701 ast_localtime(&now, &atm, NULL);
01702 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01703 buffsend[11] = (unsigned char) atm.tm_mday;
01704 buffsend[12] = (unsigned char) atm.tm_hour;
01705 buffsend[13] = (unsigned char) atm.tm_min;
01706 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
01707 }
01708
01709 static void send_blink_cursor(struct unistimsession *pte)
01710 {
01711 BUFFSEND;
01712 if (unistimdebug) {
01713 ast_verb(0, "Sending set blink\n");
01714 }
01715 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
01716 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
01717 return;
01718 }
01719
01720
01721 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
01722 {
01723 BUFFSEND;
01724 if (unistimdebug) {
01725 ast_verb(0, "Sending set cursor position\n");
01726 }
01727 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
01728 sizeof(packet_send_set_pos_cursor));
01729 buffsend[11] = pos;
01730 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
01731 return;
01732 }
01733
01734 static void send_charset_update(struct unistimsession *pte, int charset)
01735 {
01736 const unsigned char* packet_send_charset;
01737 int packet_size;
01738 BUFFSEND;
01739 if (unistimdebug) {
01740 ast_verb(0, "Sending set default charset\n");
01741 }
01742 if (charset == LANG_DEFAULT) {
01743 charset = options_languages[find_language(pte->device->language)].encoding;
01744 }
01745 switch (charset) {
01746 case ISO_8859_2:
01747 packet_send_charset = packet_send_charset_iso_8859_2;
01748 packet_size = sizeof(packet_send_charset_iso_8859_2);
01749 break;
01750 case ISO_8859_4:
01751 packet_send_charset = packet_send_charset_iso_8859_4;
01752 packet_size = sizeof(packet_send_charset_iso_8859_4);
01753 break;
01754 case ISO_8859_5:
01755 packet_send_charset = packet_send_charset_iso_8859_5;
01756 packet_size = sizeof(packet_send_charset_iso_8859_5);
01757 break;
01758 case ISO_2022_JP:
01759 packet_send_charset = packet_send_charset_iso_2022_jp;
01760 packet_size = sizeof(packet_send_charset_iso_2022_jp);
01761 break;
01762 case ISO_8859_1:
01763 default:
01764 packet_send_charset = packet_send_charset_iso_8859_1;
01765 packet_size = sizeof(packet_send_charset_iso_8859_1);
01766 }
01767 memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
01768 send_client(SIZE_HEADER + packet_size, buffsend, pte);
01769 return;
01770 }
01771
01772 static void rcv_resume_connection_with_server(struct unistimsession *pte)
01773 {
01774 BUFFSEND;
01775 if (unistimdebug) {
01776 ast_verb(0, "ResumeConnectionWithServer received\n");
01777 ast_verb(0, "Sending packet_send_query_mac_address\n");
01778 }
01779 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
01780 sizeof(packet_send_query_mac_address));
01781 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
01782 return;
01783 }
01784
01785 static int unistim_register(struct unistimsession *s)
01786 {
01787 struct unistim_device *d;
01788
01789 ast_mutex_lock(&devicelock);
01790 d = devices;
01791 while (d) {
01792 if (!strcasecmp(s->macaddr, d->id)) {
01793
01794 s->device = d;
01795 d->session = s;
01796 d->codec_number = DEFAULT_CODEC;
01797 d->missed_call = 0;
01798 d->receiver_state = STATE_ONHOOK;
01799 break;
01800 }
01801 d = d->next;
01802 }
01803 ast_mutex_unlock(&devicelock);
01804
01805 if (!d) {
01806 return 0;
01807 }
01808
01809 return 1;
01810 }
01811
01812 static void unistim_line_copy(struct unistim_line *dst, struct unistim_line *src)
01813 {
01814 struct ast_format_cap *tmp = src->cap;
01815 memcpy(dst, src, sizeof(*dst));
01816 src->cap = tmp;
01817 ast_format_cap_copy(src->cap, dst->cap);
01818 }
01819
01820 static struct unistim_line *unistim_line_destroy(struct unistim_line *l)
01821 {
01822 if (!l) {
01823 return NULL;
01824 }
01825 l->cap = ast_format_cap_destroy(l->cap);
01826 ast_free(l);
01827 return NULL;
01828 }
01829
01830 static struct unistim_line *unistim_line_alloc(void)
01831 {
01832 struct unistim_line *l;
01833 if (!(l = ast_calloc(1, sizeof(*l)))) {
01834 return NULL;
01835 }
01836
01837 if (!(l->cap = ast_format_cap_alloc_nolock())) {
01838 ast_free(l);
01839 return NULL;
01840 }
01841 return l;
01842 }
01843
01844 static int unistim_free_sub(struct unistim_subchannel *sub) {
01845 if (unistimdebug) {
01846 ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, sub->parent->parent->name);
01847 }
01848 ast_mutex_destroy(&sub->lock);
01849 ast_free(sub);
01850 return 0;
01851 }
01852
01853 static struct unistim_subchannel *unistim_alloc_sub(struct unistim_device *d, int x)
01854 {
01855 struct unistim_subchannel *sub;
01856 if (!(sub = ast_calloc(1, sizeof(*sub)))) {
01857 return NULL;
01858 }
01859
01860 if (unistimdebug) {
01861 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
01862 }
01863 sub->ss_thread = AST_PTHREADT_NULL;
01864 sub->subtype = x;
01865 AST_LIST_LOCK(&d->subs);
01866 AST_LIST_INSERT_TAIL(&d->subs, sub, list);
01867 AST_LIST_UNLOCK(&d->subs);
01868 ast_mutex_init(&sub->lock);
01869 return sub;
01870 }
01871
01872 static int unistim_unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
01873 {
01874 struct unistim_subchannel *s;
01875
01876 AST_LIST_LOCK(&d->subs);
01877 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
01878 if (!s) {
01879 continue;
01880 }
01881 if (s != sub) {
01882 continue;
01883 }
01884 AST_LIST_REMOVE_CURRENT(list);
01885 unistim_free_sub(sub);
01886 }
01887 AST_LIST_TRAVERSE_SAFE_END;
01888 AST_LIST_UNLOCK(&d->subs);
01889 return 0;
01890 }
01891
01892 static const char *subtype_tostr(const int type)
01893 {
01894 switch (type) {
01895 case SUB_REAL:
01896 return "REAL";
01897 case SUB_ONHOLD:
01898 return "ONHOLD";
01899 case SUB_RING:
01900 return "RINGING";
01901 case SUB_THREEWAY:
01902 return "THREEWAY";
01903 }
01904 return "UNKNOWN";
01905 }
01906
01907 static const char *ptestate_tostr(const int type)
01908 {
01909 switch (type) {
01910 case STATE_INIT:
01911 return "INIT";
01912 case STATE_AUTHDENY:
01913 return "AUTHDENY";
01914 case STATE_MAINPAGE:
01915 return "MAINPAGE";
01916 case STATE_EXTENSION:
01917 return "EXTENSION";
01918 case STATE_DIALPAGE:
01919 return "DIALPAGE";
01920 case STATE_RINGING:
01921 return "RINGING";
01922 case STATE_CALL:
01923 return "CALL";
01924 case STATE_SELECTOPTION:
01925 return "SELECTOPTION";
01926 case STATE_SELECTCODEC:
01927 return "SELECTCODEC";
01928 case STATE_SELECTLANGUAGE:
01929 return "SELECTLANGUAGE";
01930 case STATE_CLEANING:
01931 return "CLEARING";
01932 case STATE_HISTORY:
01933 return "HISTORY";
01934 }
01935 return "UNKNOWN";
01936 }
01937
01938 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
01939 {
01940 BUFFSEND;
01941 int tmp, i = 0;
01942 char addrmac[19];
01943 int res = 0;
01944 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
01945 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
01946 i += 2;
01947 }
01948 if (unistimdebug) {
01949 ast_verb(0, "MAC Address received: %s\n", addrmac);
01950 }
01951 strcpy(pte->macaddr, addrmac);
01952 res = unistim_register(pte);
01953 if (!res) {
01954 switch (autoprovisioning) {
01955 case AUTOPROVISIONING_NO:
01956 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
01957 pte->state = STATE_AUTHDENY;
01958 break;
01959 case AUTOPROVISIONING_YES:
01960 {
01961 struct unistim_device *d = NULL, *newd = NULL;
01962 struct unistim_line *newl = NULL, *l = NULL;
01963 if (unistimdebug) {
01964 ast_verb(0, "New phone, autoprovisioning on\n");
01965 }
01966
01967 ast_mutex_lock(&devicelock);
01968 d = devices;
01969 while (d) {
01970 if (strcasecmp(d->name, "template")) {
01971 d = d->next;
01972 continue;
01973 }
01974
01975 if (!(newd = ast_malloc(sizeof(*newd)))) {
01976 ast_mutex_unlock(&devicelock);
01977 return;
01978 }
01979 memcpy(newd, d, sizeof(*newd));
01980 ast_mutex_init(&newd->lock);
01981 newd->lines.first = NULL;
01982 newd->lines.last = NULL;
01983 AST_LIST_LOCK(&d->lines);
01984 AST_LIST_TRAVERSE(&d->lines, l, list) {
01985 if (!(newl = unistim_line_alloc())) {
01986 break;
01987 }
01988 unistim_line_copy(l, newl);
01989 newl->parent = newd;
01990 ast_copy_string(newl->name, l->name, sizeof(newl->name));
01991 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
01992 newl->name, newd->name);
01993 snprintf(l->name, sizeof(l->name), "%d", atoi(l->name) + 1);
01994
01995 AST_LIST_LOCK(&newd->lines);
01996 AST_LIST_INSERT_TAIL(&newd->lines, newl, list);
01997 AST_LIST_UNLOCK(&newd->lines);
01998 }
01999 AST_LIST_UNLOCK(&d->lines);
02000 if (!newl) {
02001 ast_free(newd);
02002 ast_mutex_unlock(&devicelock);
02003 }
02004
02005
02006 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
02007 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
02008 if (newd->extension == EXTENSION_NONE) {
02009 newd->extension = EXTENSION_ASK;
02010 }
02011
02012 newd->receiver_state = STATE_ONHOOK;
02013 newd->session = pte;
02014 newd->language[0] = '\0';
02015 newd->to_delete = -1;
02016 newd->next = NULL;
02017 pte->device = newd;
02018
02019
02020 while (d->next) {
02021 d = d->next;
02022 }
02023 d->next = newd;
02024 d = newd;
02025 break;
02026 }
02027 ast_mutex_unlock(&devicelock);
02028 if (!d) {
02029 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
02030 pte->state = STATE_AUTHDENY;
02031 }
02032 }
02033 break;
02034 case AUTOPROVISIONING_TN:
02035 pte->state = STATE_AUTHDENY;
02036 break;
02037 default:
02038 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
02039 autoprovisioning);
02040 }
02041 }
02042 if (pte->state != STATE_AUTHDENY) {
02043 struct unistim_line *line;
02044 struct unistim_subchannel *sub;
02045
02046 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
02047
02048 AST_LIST_LOCK(&pte->device->subs);
02049 AST_LIST_TRAVERSE_SAFE_BEGIN(&pte->device->subs, sub, list) {
02050 if (sub) {
02051 ast_log(LOG_ERROR, "Subchannel lost sice reboot. Hanged channel may apear!\n");
02052 AST_LIST_REMOVE_CURRENT(list);
02053 ast_free(sub);
02054 }
02055 }
02056 AST_LIST_TRAVERSE_SAFE_END;
02057 AST_LIST_UNLOCK(&pte->device->subs);
02058
02059 switch (pte->device->extension) {
02060 case EXTENSION_NONE:
02061 pte->state = STATE_MAINPAGE;
02062 break;
02063 case EXTENSION_ASK:
02064
02065 if (ast_strlen_zero(pte->device->extension_number)) {
02066 pte->state = STATE_EXTENSION;
02067 } else {
02068
02069 if (register_extension(pte)) {
02070 pte->state = STATE_EXTENSION;
02071 } else {
02072 pte->state = STATE_MAINPAGE;
02073 }
02074 }
02075 break;
02076 case EXTENSION_LINE:
02077 line = AST_LIST_FIRST(&pte->device->lines);
02078 ast_copy_string(pte->device->extension_number, line->name,
02079 sizeof(pte->device->extension_number));
02080 if (register_extension(pte)) {
02081 pte->state = STATE_EXTENSION;
02082 } else {
02083 pte->state = STATE_MAINPAGE;
02084 }
02085 break;
02086 case EXTENSION_TN:
02087
02088 pte->state = STATE_MAINPAGE;
02089 break;
02090 default:
02091 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
02092 pte->device->extension);
02093 pte->state = STATE_AUTHDENY;
02094 break;
02095 }
02096 }
02097 if (pte->state == STATE_EXTENSION) {
02098 if (pte->device->extension != EXTENSION_TN) {
02099 pte->device->extension = EXTENSION_ASK;
02100 }
02101 pte->device->extension_number[0] = '\0';
02102 }
02103 if (unistimdebug) {
02104 ast_verb(0, "\nSending S1\n");
02105 }
02106 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
02107 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
02108
02109 if (unistimdebug) {
02110 ast_verb(0, "Sending query_basic_manager_04\n");
02111 }
02112 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
02113 sizeof(packet_send_query_basic_manager_04));
02114 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
02115
02116 if (unistimdebug) {
02117 ast_verb(0, "Sending query_basic_manager_10\n");
02118 }
02119 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
02120 sizeof(packet_send_query_basic_manager_10));
02121 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
02122
02123 send_date_time(pte);
02124 return;
02125 }
02126
02127 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
02128 {
02129 if (fwrite(&c, 1, 1, f) != 1) {
02130 display_last_error("Unable to write history log header.");
02131 return -1;
02132 }
02133 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
02134 display_last_error("Unable to write history entry - date.");
02135 return -1;
02136 }
02137 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
02138 display_last_error("Unable to write history entry - callerid.");
02139 return -1;
02140 }
02141 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
02142 display_last_error("Unable to write history entry - callername.");
02143 return -1;
02144 }
02145 return 0;
02146 }
02147
02148 static int write_history(struct unistimsession *pte, char way, char ismissed)
02149 {
02150 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
02151 char line1[TEXT_LENGTH_MAX + 1];
02152 char count = 0, *histbuf;
02153 int size;
02154 FILE *f, *f2;
02155 struct timeval now = ast_tvnow();
02156 struct ast_tm atm = { 0, };
02157
02158 if (!pte->device) {
02159 return -1;
02160 }
02161 if (!pte->device->callhistory) {
02162 return 0;
02163 }
02164 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
02165 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
02166 pte->device->name);
02167 return -1;
02168 }
02169
02170 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
02171 if (ast_mkdir(tmp, 0770)) {
02172 ast_log(LOG_WARNING, "Unable to create directory for history\n");
02173 return -1;
02174 }
02175
02176 ast_localtime(&now, &atm, NULL);
02177 if (ismissed) {
02178 if (way == 'i') {
02179 ast_copy_string(tmp2, ustmtext("Miss", pte), sizeof(tmp2));
02180 } else {
02181 ast_copy_string(tmp2, ustmtext("Fail", pte), sizeof(tmp2));
02182 }
02183 } else {
02184 ast_copy_string(tmp2, ustmtext("Answ", pte), sizeof(tmp2));
02185 }
02186 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
02187 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
02188 atm.tm_min, atm.tm_sec, tmp2);
02189
02190 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
02191 USTM_LOG_DIR, pte->device->name, way);
02192 if ((f = fopen(tmp, "r"))) {
02193 struct stat bufstat;
02194
02195 if (stat(tmp, &bufstat)) {
02196 display_last_error("Unable to stat history log.");
02197 fclose(f);
02198 return -1;
02199 }
02200 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
02201 if (bufstat.st_size != size) {
02202 ast_log(LOG_WARNING,
02203 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
02204 tmp, (int) bufstat.st_size, size);
02205 fclose(f);
02206 f = NULL;
02207 count = 1;
02208 }
02209 }
02210
02211
02212 if (!f) {
02213 char c = 1;
02214 int i;
02215
02216 if ((errno != ENOENT) && (count == 0)) {
02217 display_last_error("Unable to open history log.");
02218 return -1;
02219 }
02220 f = fopen(tmp, "w");
02221 if (!f) {
02222 display_last_error("Unable to create history log.");
02223 return -1;
02224 }
02225 if (write_entry_history(pte, f, c, line1)) {
02226 fclose(f);
02227 return -1;
02228 }
02229 memset(line1, ' ', TEXT_LENGTH_MAX);
02230 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
02231 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
02232 display_last_error("Unable to write history entry - stuffing.");
02233 fclose(f);
02234 return -1;
02235 }
02236 }
02237 if (fclose(f)) {
02238 display_last_error("Unable to close history - creation.");
02239 }
02240 return 0;
02241 }
02242
02243 if (fread(&count, 1, 1, f) != 1) {
02244 display_last_error("Unable to read history header.");
02245 fclose(f);
02246 return -1;
02247 }
02248 if (count > MAX_ENTRY_LOG) {
02249 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
02250 count, MAX_ENTRY_LOG);
02251 fclose(f);
02252 return -1;
02253 }
02254 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
02255 USTM_LOG_DIR, pte->device->name, way);
02256 if (!(f2 = fopen(tmp2, "w"))) {
02257 display_last_error("Unable to create temporary history log.");
02258 fclose(f);
02259 return -1;
02260 }
02261
02262 if (++count > MAX_ENTRY_LOG) {
02263 count = MAX_ENTRY_LOG;
02264 }
02265 if (write_entry_history(pte, f2, count, line1)) {
02266 fclose(f);
02267 fclose(f2);
02268 return -1;
02269 }
02270 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
02271 if (!(histbuf = ast_malloc(size))) {
02272 fclose(f);
02273 fclose(f2);
02274 return -1;
02275 }
02276
02277 if (fread(histbuf, size, 1, f) != 1) {
02278 ast_free(histbuf);
02279 fclose(f);
02280 fclose(f2);
02281 display_last_error("Unable to read previous history entries.");
02282 return -1;
02283 }
02284 if (fwrite(histbuf, size, 1, f2) != 1) {
02285 ast_free(histbuf);
02286 fclose(f);
02287 fclose(f2);
02288 display_last_error("Unable to write previous history entries.");
02289 return -1;
02290 }
02291 ast_free(histbuf);
02292 if (fclose(f)) {
02293 display_last_error("Unable to close history log.");
02294 }
02295 if (fclose(f2)) {
02296 display_last_error("Unable to close temporary history log.");
02297 }
02298 if (unlink(tmp)) {
02299 display_last_error("Unable to remove old history log.");
02300 }
02301 if (rename(tmp2, tmp)) {
02302 display_last_error("Unable to rename new history log.");
02303 }
02304 return 0;
02305 }
02306
02307 static void unistim_quiet_chan(struct ast_channel *chan)
02308 {
02309 if (chan && ast_channel_state(chan) == AST_STATE_UP) {
02310 if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_MOH)) {
02311 ast_moh_stop(chan);
02312 } else if (ast_channel_generatordata(chan)) {
02313 ast_deactivate_generator(chan);
02314 }
02315 }
02316 }
02317
02318 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
02319 {
02320 int res = 0;
02321 struct ast_channel
02322 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
02323 NULL, *peerb = NULL, *peerc = NULL, *peerd = NULL;
02324
02325 if (!p1->owner || !p2->owner) {
02326 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
02327 return -1;
02328 }
02329 chana = p1->owner;
02330 chanb = p2->owner;
02331 bridgea = ast_bridged_channel(chana);
02332 bridgeb = ast_bridged_channel(chanb);
02333
02334 if (bridgea) {
02335 peera = chana;
02336 peerb = chanb;
02337 peerc = bridgea;
02338 peerd = bridgeb;
02339 } else if (bridgeb) {
02340 peera = chanb;
02341 peerb = chana;
02342 peerc = bridgeb;
02343 peerd = bridgea;
02344 }
02345
02346 if (peera && peerb && peerc && (peerb != peerc)) {
02347 unistim_quiet_chan(peera);
02348 unistim_quiet_chan(peerb);
02349 unistim_quiet_chan(peerc);
02350 if (peerd) {
02351 unistim_quiet_chan(peerd);
02352 }
02353
02354 ast_log(LOG_NOTICE, "UNISTIM transfer: trying to masquerade %s into %s\n", ast_channel_name(peerc), ast_channel_name(peerb));
02355 if (ast_channel_masquerade(peerb, peerc)) {
02356 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", ast_channel_name(peerb),
02357 ast_channel_name(peerc));
02358 res = -1;
02359 }
02360 return res;
02361 } else {
02362 ast_log(LOG_NOTICE,
02363 "Transfer attempted with no appropriate bridged calls to transfer\n");
02364 if (chana) {
02365 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
02366 }
02367 if (chanb) {
02368 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
02369 }
02370 return -1;
02371 }
02372 return 0;
02373 }
02374
02375 void change_callerid(struct unistimsession *pte, int type, char *callerid)
02376 {
02377 char *data;
02378 int size;
02379
02380 if (type) {
02381 data = pte->device->lst_cnm;
02382 } else {
02383 data = pte->device->lst_cid;
02384 }
02385
02386
02387
02388 memset(data, ' ', TEXT_LENGTH_MAX);
02389 size = strlen(callerid);
02390 if (size > TEXT_LENGTH_MAX) {
02391 size = TEXT_LENGTH_MAX;
02392 }
02393 memcpy(data, callerid, size);
02394 }
02395
02396 static struct unistim_subchannel* get_sub(struct unistim_device *device, int type)
02397 {
02398 struct unistim_subchannel *sub = NULL;
02399
02400 AST_LIST_LOCK(&device->subs);
02401 AST_LIST_TRAVERSE(&device->subs, sub, list) {
02402 if (!sub) {
02403 continue;
02404 }
02405 if (sub->subtype == type) {
02406 break;
02407 }
02408 }
02409 AST_LIST_UNLOCK(&device->subs);
02410
02411 return sub;
02412 }
02413
02414 static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
02415 {
02416
02417 if (!pte->device->silence_generator) {
02418 pte->device->silence_generator =
02419 ast_channel_start_silence_generator(sub->owner);
02420 if (pte->device->silence_generator == NULL) {
02421 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
02422 } else if (unistimdebug) {
02423 ast_verb(0, "Starting silence generator\n");
02424 }
02425 }
02426
02427 }
02428
02429 static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub)
02430 {
02431
02432 if (pte->device->silence_generator) {
02433 if (unistimdebug) {
02434 ast_verb(0, "Stopping silence generator\n");
02435 }
02436 if (sub->owner) {
02437 ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
02438 } else {
02439 ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel!\n");
02440 }
02441 pte->device->silence_generator = NULL;
02442 }
02443 }
02444
02445 static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub)
02446 {
02447 if (!sub) {
02448 return;
02449 }
02450 sub->moh = 1;
02451 sub->subtype = SUB_ONHOLD;
02452 send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
02453 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
02454 send_stop_timer(pte);
02455 if (sub->owner) {
02456 ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, NULL, 0);
02457 send_end_call(pte);
02458 }
02459 return;
02460 }
02461
02462 static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub)
02463 {
02464 struct unistim_subchannel *sub_real;
02465
02466 sub_real = get_sub(pte->device, SUB_REAL);
02467 if (sub_real) {
02468 sub_hold(pte, sub_real);
02469 }
02470
02471 sub->moh = 0;
02472 sub->subtype = SUB_REAL;
02473 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
02474 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02475 send_start_timer(pte);
02476 if (sub->owner) {
02477 ast_queue_control_data(sub->owner, AST_CONTROL_UNHOLD, NULL, 0);
02478 if (sub->rtp) {
02479 send_start_rtp(sub);
02480 }
02481 }
02482 return;
02483 }
02484
02485 static void close_call(struct unistimsession *pte)
02486 {
02487 struct unistim_subchannel *sub, *sub_transf;
02488
02489 sub = get_sub(pte->device, SUB_REAL);
02490 sub_transf = get_sub(pte->device, SUB_THREEWAY);
02491 send_stop_timer(pte);
02492 if (!sub) {
02493 ast_log(LOG_WARNING, "Close call without sub\n");
02494 return;
02495 }
02496 send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
02497 if (sub->owner) {
02498 sub->alreadygone = 1;
02499 if (sub_transf) {
02500 sub_transf->alreadygone = 1;
02501 if (attempt_transfer(sub, sub_transf) < 0) {
02502 ast_verb(0, "attempt_transfer failed.\n");
02503 }
02504 } else {
02505 ast_queue_hangup(sub->owner);
02506 }
02507 } else {
02508 if (sub_transf) {
02509 if (sub_transf->owner) {
02510 ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
02511 } else {
02512 ast_log(LOG_WARNING, "threeway sub without owner\n");
02513 }
02514 } else {
02515 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
02516 pte->device->name, sub->softkey);
02517 }
02518 }
02519 change_callerid(pte, 0, pte->device->redial_number);
02520 change_callerid(pte, 1, "");
02521 write_history(pte, 'o', pte->device->missed_call);
02522 pte->device->missed_call = 0;
02523 show_main_page(pte);
02524 return;
02525 }
02526
02527 static void ignore_call(struct unistimsession *pte)
02528 {
02529 send_no_ring(pte);
02530 return;
02531 }
02532
02533 static void discard_call(struct unistimsession *pte)
02534 {
02535 struct unistim_subchannel* sub;
02536 sub = get_sub(pte->device, SUB_RING);
02537 if (!sub) {
02538 return;
02539 }
02540
02541 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
02542 return;
02543 }
02544
02545 static void *unistim_ss(void *data)
02546 {
02547 struct ast_channel *chan = data;
02548 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
02549 struct unistim_line *l = sub->parent;
02550 struct unistimsession *s = l->parent->session;
02551 int res;
02552
02553 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
02554 ast_channel_exten_set(chan, s->device->phone_number);
02555 ast_copy_string(s->device->redial_number, s->device->phone_number,
02556 sizeof(s->device->redial_number));
02557 ast_setstate(chan, AST_STATE_RING);
02558 res = ast_pbx_run(chan);
02559 if (res) {
02560 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02561 send_tone(s, 1000, 0);
02562 }
02563 return NULL;
02564 }
02565
02566 static int find_rtp_port(struct unistim_subchannel *s)
02567 {
02568 struct unistim_subchannel *sub = NULL;
02569 int rtp_start = s->parent->parent->rtp_port;
02570 struct ast_sockaddr us_tmp;
02571 struct sockaddr_in us = { 0, };
02572
02573 AST_LIST_LOCK(&s->parent->parent->subs);
02574 AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
02575 if (!sub) {
02576 continue;
02577 }
02578 if (sub->rtp) {
02579 ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
02580 ast_sockaddr_to_sin(&us_tmp, &us);
02581 if (htons(us.sin_port)) {
02582 rtp_start = htons(us.sin_port) + 1;
02583 break;
02584 }
02585 }
02586 }
02587 AST_LIST_UNLOCK(&s->parent->parent->subs);
02588 return rtp_start;
02589 }
02590
02591 static void send_start_rtp(struct unistim_subchannel *sub)
02592 {
02593 BUFFSEND;
02594
02595 int codec;
02596 struct sockaddr_in public = { 0, };
02597 struct sockaddr_in us = { 0, };
02598 struct sockaddr_in sin = { 0, };
02599 struct ast_sockaddr us_tmp;
02600 struct ast_sockaddr sin_tmp;
02601 struct unistimsession *pte;
02602
02603 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
02604 ast_sockaddr_to_sin(&us_tmp, &us);
02605 ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
02606 ast_sockaddr_to_sin(&sin_tmp, &sin);
02607
02608
02609 if (public_ip.sin_family == 0) {
02610 memcpy(&public, &us, sizeof(public));
02611 } else {
02612 memcpy(&public, &public_ip, sizeof(public));
02613 }
02614 if (unistimdebug) {
02615 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
02616 ast_inet_ntoa(us.sin_addr),
02617 htons(us.sin_port), ast_getformatname(ast_channel_readformat(sub->owner)));
02618 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
02619 ast_inet_ntoa(public.sin_addr));
02620 }
02621
02622 pte = sub->parent->parent->session;
02623 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, ast_channel_readformat(sub->owner), 0);
02624 if ((ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) ||
02625 (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW)) {
02626 if (unistimdebug) {
02627 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %d\n", codec);
02628 }
02629 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
02630 sizeof(packet_send_rtp_packet_size));
02631 buffsend[10] = (int) codec & 0xffffffffLL;
02632 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
02633 }
02634 if (unistimdebug) {
02635 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
02636 }
02637 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
02638 sizeof(packet_send_jitter_buffer_conf));
02639 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
02640 if (pte->device->rtp_method != 0) {
02641 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02642
02643 if (unistimdebug) {
02644 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
02645 }
02646 if (pte->device->rtp_method == 3) {
02647 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
02648 sizeof(packet_send_open_audio_stream_tx3));
02649 } else {
02650 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
02651 sizeof(packet_send_open_audio_stream_tx));
02652 }
02653 if (pte->device->rtp_method != 2) {
02654 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02655 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02656 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02657 buffsend[23] = (rtcpsin_port & 0x00ff);
02658 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02659 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02660 buffsend[24] = (us.sin_port & 0x00ff);
02661 buffsend[27] = (rtcpsin_port & 0x00ff);
02662 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02663 } else {
02664 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02665 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02666 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02667 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02668 buffsend[19] = (us.sin_port & 0x00ff);
02669 }
02670 buffsend[11] = codec;
02671 buffsend[12] = codec;
02672 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
02673
02674 if (unistimdebug) {
02675 ast_verb(0, "Sending OpenAudioStreamRX\n");
02676 }
02677 if (pte->device->rtp_method == 3) {
02678 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
02679 sizeof(packet_send_open_audio_stream_rx3));
02680 } else {
02681 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
02682 sizeof(packet_send_open_audio_stream_rx));
02683 }
02684 if (pte->device->rtp_method != 2) {
02685 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02686 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02687 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02688 buffsend[23] = (rtcpsin_port & 0x00ff);
02689 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02690 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02691 buffsend[24] = (us.sin_port & 0x00ff);
02692 buffsend[27] = (rtcpsin_port & 0x00ff);
02693 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02694 } else {
02695 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02696 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02697 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02698 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02699 buffsend[19] = (us.sin_port & 0x00ff);
02700 }
02701 buffsend[11] = codec;
02702 buffsend[12] = codec;
02703 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
02704 } else {
02705 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02706
02707 if (unistimdebug) {
02708 ast_verb(0, "Sending packet_send_call default method\n");
02709 }
02710
02711 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
02712 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
02713
02714 buffsend[49] = (us.sin_port & 0x00ff);
02715 buffsend[50] = (us.sin_port & 0xff00) >> 8;
02716
02717 buffsend[52] = (rtcpsin_port & 0x00ff);
02718 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
02719
02720 buffsend[40] = codec;
02721 buffsend[41] = codec;
02722 if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ULAW) {
02723 buffsend[42] = 1;
02724 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_ALAW) {
02725 buffsend[42] = 1;
02726 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G723_1) {
02727 buffsend[42] = 2;
02728 } else if (ast_channel_readformat(sub->owner)->id == AST_FORMAT_G729A) {
02729 buffsend[42] = 2;
02730 } else {
02731 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
02732 ast_getformatname(ast_channel_readformat(sub->owner)));
02733 }
02734
02735 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
02736 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
02737 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
02738 buffsend[48] = (rtcpsin_port & 0x00ff);
02739 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
02740 }
02741 }
02742
02743 static void start_rtp(struct unistim_subchannel *sub)
02744 {
02745 struct sockaddr_in sin = { 0, };
02746 struct sockaddr_in sout = { 0, };
02747 struct ast_sockaddr sin_tmp;
02748 struct ast_sockaddr sout_tmp;
02749
02750
02751 if (!sub) {
02752 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
02753 return;
02754 }
02755 if (!sub->parent) {
02756 ast_log(LOG_WARNING, "start_rtp with a null line!\n");
02757 return;
02758 }
02759 if (!sub->parent->parent) {
02760 ast_log(LOG_WARNING, "start_rtp with a null device!\n");
02761 return;
02762 }
02763 if (!sub->parent->parent->session) {
02764 ast_log(LOG_WARNING, "start_rtp with a null session!\n");
02765 return;
02766 }
02767 if (!sub->owner) {
02768 ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
02769 return;
02770 }
02771 sout = sub->parent->parent->session->sout;
02772 ast_mutex_lock(&sub->lock);
02773
02774 if (unistimdebug) {
02775 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
02776 }
02777 ast_sockaddr_from_sin(&sout_tmp, &sout);
02778 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
02779 if (!sub->rtp) {
02780 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
02781 strerror(errno), ast_inet_ntoa(sout.sin_addr));
02782 ast_mutex_unlock(&sub->lock);
02783 return;
02784 }
02785 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
02786 ast_channel_internal_fd_set(sub->owner, 0, ast_rtp_instance_fd(sub->rtp, 0));
02787 ast_channel_internal_fd_set(sub->owner, 1, ast_rtp_instance_fd(sub->rtp, 1));
02788 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
02789 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
02790
02791
02792 sin.sin_family = AF_INET;
02793
02794 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
02795 sizeof(sin.sin_addr));
02796
02797 sin.sin_port = htons(find_rtp_port(sub));
02798 ast_sockaddr_from_sin(&sin_tmp, &sin);
02799 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
02800 if (!ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), ast_channel_readformat(sub->owner))) {
02801 struct ast_format tmpfmt;
02802 char tmp[256];
02803 ast_best_codec(ast_channel_nativeformats(sub->owner), &tmpfmt);
02804 ast_log(LOG_WARNING,
02805 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
02806 ast_getformatname(ast_channel_readformat(sub->owner)),
02807 ast_getformatname(&tmpfmt),
02808 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)));
02809
02810 ast_format_copy(ast_channel_readformat(sub->owner), &tmpfmt);
02811 ast_format_copy(ast_channel_writeformat(sub->owner), &tmpfmt);
02812 }
02813 send_start_rtp(sub);
02814 ast_mutex_unlock(&sub->lock);
02815 }
02816
02817 static void send_dial_tone(struct unistimsession *pte)
02818 {
02819 struct ast_tone_zone_sound *ts = NULL;
02820 struct ast_tone_zone_part tone_data;
02821 char *s = NULL;
02822 char *ind;
02823
02824 if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
02825 ind = ast_strdupa(ts->data);
02826 s = strsep(&ind, ",");
02827 ast_tone_zone_part_parse(s, &tone_data);
02828 if (tone_data.modulate) {
02829 tone_data.freq2 = 0;
02830 }
02831 send_tone(pte, tone_data.freq1, tone_data.freq2);
02832 if (unistimdebug) {
02833 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
02834 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
02835 }
02836 ts = ast_tone_zone_sound_unref(ts);
02837 }
02838 }
02839
02840 static void show_phone_number(struct unistimsession *pte)
02841 {
02842 char tmp[TEXT_LENGTH_MAX + 1];
02843 const char *tmp_number = ustmtext("Number:", pte);
02844 int line, tmp_copy, offset = 0, i;
02845
02846 pte->device->phone_number[pte->device->size_phone_number] = '\0';
02847 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
02848 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
02849 if (offset > strlen(tmp_number)) {
02850 offset = strlen(tmp_number);
02851 }
02852 tmp_copy = strlen(tmp_number) - offset + 1;
02853 if (tmp_copy > sizeof(tmp)) {
02854 tmp_copy = sizeof(tmp);
02855 }
02856 memcpy(tmp, tmp_number + offset, tmp_copy);
02857 } else {
02858 ast_copy_string(tmp, tmp_number, sizeof(tmp));
02859 }
02860
02861 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
02862 if (pte->device->size_phone_number) {
02863 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
02864 }
02865 offset = strlen(tmp);
02866
02867 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
02868 tmp[i] = '.';
02869 }
02870 tmp[i] = '\0';
02871
02872 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
02873 send_text(line, TEXT_NORMAL, pte, tmp);
02874 send_blink_cursor(pte);
02875 send_cursor_pos(pte, (unsigned char) (line + offset));
02876 send_led_update(pte, 0);
02877 }
02878
02879 static void handle_dial_page(struct unistimsession *pte)
02880 {
02881 pte->state = STATE_DIALPAGE;
02882 if (pte->device->call_forward[0] == -1) {
02883 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
02884 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
02885 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
02886 if (pte->device->call_forward[1] != 0) {
02887 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
02888 sizeof(pte->device->phone_number));
02889 show_phone_number(pte);
02890 send_led_update(pte, 0);
02891 return;
02892 }
02893 } else {
02894 if ((pte->device->output == OUTPUT_HANDSET) &&
02895 (pte->device->receiver_state == STATE_ONHOOK)) {
02896 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02897 } else {
02898 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02899 }
02900 send_dial_tone(pte);
02901
02902 if (pte->device->height > 1) {
02903 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
02904 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
02905 }
02906 if (ast_strlen_zero(pte->device->redial_number)) {
02907 send_text_status(pte, ustmtext("Call BackSp Erase", pte));
02908 } else {
02909 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
02910 }
02911 }
02912
02913 pte->device->size_phone_number = 0;
02914 pte->device->phone_number[0] = 0;
02915 show_phone_number(pte);
02916 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
02917 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
02918 pte->device->missed_call = 0;
02919 send_led_update(pte, 0);
02920 pte->device->lastmsgssent = -1;
02921 return;
02922 }
02923
02924 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
02925 {
02926 struct ast_rtp_instance *rtp;
02927 int fds;
02928
02929 if (unistimdebug) {
02930 ast_verb(0, "Swapping %p and %p\n", a, b);
02931 }
02932 if ((!a->owner) || (!b->owner)) {
02933 ast_log(LOG_WARNING,
02934 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
02935 a, a->owner, b, b->owner);
02936 return;
02937 }
02938 rtp = a->rtp;
02939 a->rtp = b->rtp;
02940 b->rtp = rtp;
02941
02942 fds = ast_channel_fd(a->owner, 0);
02943 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
02944 ast_channel_internal_fd_set(b->owner, 0, fds);
02945
02946 fds = ast_channel_fd(a->owner, 1);
02947 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
02948 ast_channel_internal_fd_set(b->owner, 1, fds);
02949 }
02950
02951
02952 static void transfer_call_step1(struct unistimsession *pte)
02953 {
02954 struct unistim_subchannel *sub ;
02955 struct unistim_device *d = pte->device;
02956
02957 sub = get_sub(d, SUB_REAL);
02958
02959
02960 if (!sub || !sub->owner) {
02961 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02962 return;
02963 }
02964
02965 if (sub->moh) {
02966 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
02967 } else {
02968 if (ast_bridged_channel(sub->owner)) {
02969 ast_moh_start(ast_bridged_channel(sub->owner),
02970 sub->parent->musicclass, NULL);
02971 sub->moh = 1;
02972 sub->subtype = SUB_THREEWAY;
02973 } else {
02974 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
02975 return;
02976 }
02977 }
02978 sub_start_silence(pte, sub);
02979 handle_dial_page(pte);
02980 }
02981
02982 static void transfer_cancel_step2(struct unistimsession *pte)
02983 {
02984 struct unistim_subchannel *sub, *sub_trans;
02985 struct unistim_device *d = pte->device;
02986
02987 sub = get_sub(d, SUB_REAL);
02988 sub_trans = get_sub(d, SUB_THREEWAY);
02989
02990 if (!sub || !sub->owner) {
02991 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02992 return;
02993 }
02994 if (sub_trans) {
02995 if (unistimdebug) {
02996 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
02997 }
02998 if (sub->owner) {
02999 swap_subs(sub, sub_trans);
03000 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
03001 sub_trans->moh = 0;
03002 sub_trans->subtype = SUB_REAL;
03003 sub->subtype = SUB_THREEWAY;
03004 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
03005 } else {
03006 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
03007 }
03008 return;
03009 }
03010 }
03011
03012
03013 static void handle_call_outgoing(struct unistimsession *s)
03014 {
03015 struct ast_channel *c;
03016 struct unistim_subchannel *sub;
03017 int softkey;
03018
03019 s->state = STATE_CALL;
03020
03021 sub = get_sub(s->device, SUB_THREEWAY);
03022 if (sub) {
03023
03024 struct unistim_subchannel *sub_trans = NULL;
03025 struct unistim_device *d = s->device;
03026
03027 sub_trans = get_sub(d, SUB_REAL);
03028 if (sub_trans) {
03029 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
03030 return;
03031 }
03032 if (!sub->owner) {
03033 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
03034 return;
03035 }
03036
03037 sub_trans = unistim_alloc_sub(d, SUB_REAL);
03038 if (!sub_trans) {
03039 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
03040 return;
03041 }
03042 sub_trans->parent = sub->parent;
03043 sub_stop_silence(s, sub);
03044 send_tone(s, 0, 0);
03045
03046 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
03047 if (!c) {
03048 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
03049 return;
03050 }
03051
03052 swap_subs(sub, sub_trans);
03053 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03054 if (s->device->height == 1) {
03055 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03056 } else {
03057 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
03058 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03059 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03060 }
03061 send_text_status(s, ustmtext("TransfrCancel", s));
03062
03063 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03064 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
03065 sub->ss_thread = AST_PTHREADT_NULL;
03066 ast_hangup(c);
03067 return;
03068 }
03069 if (unistimdebug) {
03070 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
03071 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
03072 }
03073 return;
03074 }
03075
03076 softkey = get_avail_softkey(s, NULL);
03077 if (softkey == -1) {
03078 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
03079 return;
03080 }
03081 sub = get_sub(s->device, SUB_REAL);
03082 if (sub) {
03083 sub_hold(s, sub);
03084 }
03085 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
03086 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
03087 return;
03088 }
03089 sub->parent = s->device->sline[softkey];
03090 s->device->ssub[softkey] = sub;
03091 sub->softkey = softkey;
03092
03093 if (unistimdebug) {
03094 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
03095 }
03096 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03097 s->device->selected = -1;
03098 if (!sub->owner) {
03099 c = unistim_new(sub, AST_STATE_DOWN, NULL);
03100 if (!sub->rtp) {
03101 start_rtp(sub);
03102 }
03103 if (c && !strcmp(s->device->phone_number, ast_pickup_ext())) {
03104 if (unistimdebug) {
03105 ast_verb(0, "Try to pickup in unistim_new\n");
03106 }
03107 send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
03108 send_text_status(s, ustmtext(" Transf Hangup", s));
03109 send_start_timer(s);
03110 if (ast_pickup_call(c)) {
03111 ast_log(LOG_NOTICE, "Nothing to pick up\n");
03112 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
03113 } else {
03114 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
03115 }
03116 ast_hangup(c);
03117 c = NULL;
03118 } else if (c) {
03119 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03120 send_tone(s, 0, 0);
03121 if (s->device->height == 1) {
03122 if (strlen(s->device->phone_number) > 0) {
03123 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03124 } else {
03125 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
03126 }
03127 } else {
03128 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
03129 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03130 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03131 }
03132 send_text_status(s, ustmtext(" Hangup", s));
03133
03134
03135 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03136 ast_log(LOG_WARNING, "Unable to create switch thread\n");
03137 sub->ss_thread = AST_PTHREADT_NULL;
03138 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
03139 }
03140 } else
03141 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
03142 sub->parent->name, s->device->name);
03143 } else {
03144 ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
03145 }
03146 return;
03147 }
03148
03149
03150 static void handle_call_incoming(struct unistimsession *s)
03151 {
03152 struct unistim_subchannel *sub = NULL;
03153 int i;
03154
03155 s->state = STATE_CALL;
03156 s->device->missed_call = 0;
03157 send_no_ring(s);
03158 sub = get_sub(s->device, SUB_RING);
03159 if (!sub) {
03160 ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
03161 return;
03162 }
03163
03164 for (i = 0; i < FAVNUM; i++) {
03165 if (!s->device->ssub[i]) {
03166 continue;
03167 }
03168 if (s->device->ssub[i]->subtype == SUB_REAL) {
03169 sub_hold(s, s->device->ssub[i]);
03170 }
03171 if (s->device->ssub[i] != sub) {
03172 continue;
03173 }
03174 if (sub->softkey == i) {
03175 continue;
03176 }
03177 if (sub->softkey < 0) {
03178 sub->softkey = i;
03179 continue;
03180 }
03181 send_favorite_short(i, FAV_LINE_ICON, s);
03182 s->device->ssub[i] = NULL;
03183 }
03184 if (sub->softkey < 0) {
03185 ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
03186 return;
03187 }
03188 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03189 sub->parent = s->device->sline[sub->softkey];
03190 sub->subtype = SUB_REAL;
03191 if (unistimdebug) {
03192 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
03193 s->device->name);
03194 }
03195 start_rtp(sub);
03196 if (!sub->rtp) {
03197 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
03198 return;
03199 }
03200 if (sub->owner) {
03201 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
03202 }
03203 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
03204 send_text_status(s, ustmtext(" Transf Hangup", s));
03205 send_start_timer(s);
03206
03207 if ((s->device->output == OUTPUT_HANDSET) &&
03208 (s->device->receiver_state == STATE_ONHOOK)) {
03209 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
03210 } else {
03211 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03212 }
03213 write_history(s, 'i', 0);
03214 return;
03215 }
03216
03217 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
03218 {
03219 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
03220 struct unistim_subchannel *sub;
03221 int row, col;
03222
03223 sub = get_sub(pte->device, SUB_REAL);
03224 if (!sub || !sub->owner || sub->alreadygone) {
03225 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
03226 return -1;
03227 }
03228
03229
03230 ast_queue_frame(sub->owner, &f);
03231
03232 if (unistimdebug) {
03233 ast_verb(0, "Send Digit %c\n", digit);
03234 }
03235 row = (digit - '1') % 3;
03236 col = (digit - '1' - row) / 3;
03237 if (digit >= '1' && digit <='9') {
03238 send_tone(pte, dtmf_row[row], dtmf_col[col]);
03239 } else if (digit >= 'A' && digit <= 'D') {
03240 send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
03241 } else if (digit == '*') {
03242 send_tone(pte, dtmf_row[3], dtmf_col[0]);
03243 } else if (digit == '0') {
03244 send_tone(pte, dtmf_row[3], dtmf_col[1]);
03245 } else if (digit == '#') {
03246 send_tone(pte, dtmf_row[3], dtmf_col[2]);
03247 } else {
03248 send_tone(pte, 500, 2000);
03249 }
03250 usleep(150000);
03251 send_tone(pte, 0, 0);
03252 return 0;
03253 }
03254
03255 static void handle_key_fav(struct unistimsession *pte, char keycode)
03256 {
03257 int keynum = keycode - KEY_FAV0;
03258 struct unistim_subchannel *sub;
03259
03260 sub = get_sub(pte->device, SUB_REAL);
03261
03262
03263 if (!pte->device->ssub[keynum]) {
03264 send_favorite_selected(FAV_LINE_ICON, pte);
03265 if (is_key_line(pte->device, keynum)) {
03266 if (unistimdebug) {
03267 ast_verb(0, "Handle line w/o sub - dialpage\n");
03268 }
03269 pte->device->selected = keynum;
03270 sub_hold(pte, sub);
03271 send_stop_timer(pte);
03272 handle_dial_page(pte);
03273 } else if (is_key_favorite(pte->device, keynum)) {
03274
03275
03276 if (unistimdebug) {
03277 ast_verb(0, "Handle favorite w/o sub - dialing\n");
03278 }
03279 if ((pte->device->output == OUTPUT_HANDSET) &&
03280 (pte->device->receiver_state == STATE_ONHOOK)) {
03281 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03282 } else {
03283 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03284 }
03285 key_favorite(pte, keycode);
03286 }
03287 } else {
03288 sub = pte->device->ssub[keynum];
03289
03290 if (sub->subtype == SUB_REAL) {
03291 sub_hold(pte, sub);
03292 show_main_page(pte);
03293 } else if (sub->subtype == SUB_RING) {
03294 sub->softkey = keynum;
03295 handle_call_incoming(pte);
03296 } else if (sub->subtype == SUB_ONHOLD) {
03297 if (pte->state == STATE_DIALPAGE){
03298 send_tone(pte, 0, 0);
03299 }
03300 send_callerid_screen(pte, sub);
03301 sub_unhold(pte, sub);
03302 pte->state = STATE_CALL;
03303 }
03304 }
03305 }
03306
03307 static void key_call(struct unistimsession *pte, char keycode)
03308 {
03309 struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
03310 struct unistim_subchannel *sub_3way = get_sub(pte->device, SUB_THREEWAY);
03311
03312 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03313 if (keycode == KEY_SHARP) {
03314 keycode = '#';
03315 } else if (keycode == KEY_STAR) {
03316 keycode = '*';
03317 } else {
03318 keycode -= 0x10;
03319 }
03320 unistim_do_senddigit(pte, keycode);
03321 return;
03322 }
03323 switch (keycode) {
03324 case KEY_FUNC1:
03325 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
03326 if (sub_3way) {
03327 close_call(pte);
03328 }
03329 }
03330 break;
03331 case KEY_FUNC2:
03332 if (sub_3way) {
03333 transfer_cancel_step2(pte);
03334 } else if (ast_channel_state(sub->owner) == AST_STATE_UP) {
03335 transfer_call_step1(pte);
03336 }
03337 break;
03338 case KEY_HANGUP:
03339 case KEY_FUNC4:
03340 if (!sub_3way) {
03341 close_call(pte);
03342 }
03343 break;
03344 case KEY_FAV0:
03345 case KEY_FAV1:
03346 case KEY_FAV2:
03347 case KEY_FAV3:
03348 case KEY_FAV4:
03349 case KEY_FAV5:
03350 handle_key_fav(pte, keycode);
03351 break;
03352 case KEY_HEADPHN:
03353 if (pte->device->output == OUTPUT_HEADPHONE) {
03354 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03355 } else {
03356 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03357 }
03358 break;
03359 case KEY_LOUDSPK:
03360 if (pte->device->output != OUTPUT_SPEAKER)
03361 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03362 else
03363 send_select_output(pte, pte->device->previous_output, pte->device->volume,
03364 MUTE_OFF);
03365 break;
03366 case KEY_MUTE:
03367 if (!sub || !sub->owner) {
03368 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
03369 return;
03370 }
03371 if (!sub->moh) {
03372 if (pte->device->mute == MUTE_ON) {
03373 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03374 } else {
03375 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
03376 }
03377 break;
03378 }
03379 break;
03380 case KEY_ONHOLD:
03381 if (!sub) {
03382 if(pte->device->ssub[pte->device->selected]) {
03383 sub_hold(pte, pte->device->ssub[pte->device->selected]);
03384 }
03385 } else {
03386 sub_hold(pte, sub);
03387 }
03388 break;
03389 }
03390 return;
03391 }
03392
03393 static void key_ringing(struct unistimsession *pte, char keycode)
03394 {
03395 switch (keycode) {
03396 case KEY_FAV0:
03397 case KEY_FAV1:
03398 case KEY_FAV2:
03399 case KEY_FAV3:
03400 case KEY_FAV4:
03401 case KEY_FAV5:
03402 handle_key_fav(pte, keycode);
03403 break;
03404 case KEY_FUNC3:
03405 ignore_call(pte);
03406 break;
03407 case KEY_HANGUP:
03408 case KEY_FUNC4:
03409 discard_call(pte);
03410 break;
03411 case KEY_LOUDSPK:
03412 pte->device->output = OUTPUT_SPEAKER;
03413 handle_call_incoming(pte);
03414 break;
03415 case KEY_HEADPHN:
03416 pte->device->output = OUTPUT_HEADPHONE;
03417 handle_call_incoming(pte);
03418 break;
03419 case KEY_FUNC1:
03420 handle_call_incoming(pte);
03421 break;
03422 }
03423 return;
03424 }
03425
03426 static void key_favorite(struct unistimsession *pte, char keycode)
03427 {
03428 int fav = keycode - KEY_FAV0;
03429 if (!is_key_favorite(pte->device, fav)) {
03430 ast_log(LOG_WARNING, "It's not a favorite key\n");
03431 return;
03432 }
03433 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
03434 sizeof(pte->device->phone_number));
03435 handle_call_outgoing(pte);
03436 return;
03437 }
03438
03439 static void key_dial_page(struct unistimsession *pte, char keycode)
03440 {
03441 struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
03442
03443 pte->device->nextdial = 0;
03444 if (keycode == KEY_FUNC3) {
03445 if (pte->device->size_phone_number <= 1) {
03446 keycode = KEY_FUNC4;
03447 } else {
03448 pte->device->size_phone_number -= 2;
03449 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
03450 }
03451 }
03452 if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
03453 keycode = KEY_FUNC1;
03454 }
03455 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03456 int i = pte->device->size_phone_number;
03457
03458 if (pte->device->size_phone_number == 0) {
03459 send_tone(pte, 0, 0);
03460 }
03461 if (keycode == KEY_SHARP) {
03462 keycode = '#';
03463 } else if (keycode == KEY_STAR) {
03464 keycode = '*';
03465 } else {
03466 keycode -= 0x10;
03467 }
03468 pte->device->phone_number[i] = keycode;
03469 pte->device->size_phone_number++;
03470 pte->device->phone_number[i + 1] = 0;
03471 show_phone_number(pte);
03472
03473 if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
03474 !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
03475 keycode = KEY_FUNC1;
03476 } else {
03477 if (pte->device->interdigit_timer) {
03478 pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
03479 }
03480 }
03481 }
03482 if (keycode == KEY_FUNC4) {
03483 pte->device->size_phone_number = 0;
03484 show_phone_number(pte);
03485 return;
03486 }
03487
03488 if (pte->device->call_forward[0] == -1) {
03489 if (keycode == KEY_FUNC1) {
03490 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
03491 sizeof(pte->device->call_forward));
03492 show_main_page(pte);
03493 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
03494 pte->device->call_forward[0] = '\0';
03495 send_led_update(pte, 0x08);
03496 send_led_update(pte, 0x10);
03497 show_main_page(pte);
03498 }
03499 return;
03500 }
03501 switch (keycode) {
03502 case KEY_FUNC2:
03503 if (ast_strlen_zero(pte->device->redial_number)) {
03504 break;
03505 }
03506 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03507 sizeof(pte->device->phone_number));
03508 case KEY_FUNC1:
03509 handle_call_outgoing(pte);
03510 break;
03511 case KEY_HANGUP:
03512 if (sub && sub->owner) {
03513 struct ast_channel *bridgepeer = NULL;
03514
03515 sub_stop_silence(pte, sub);
03516 send_tone(pte, 0, 0);
03517 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
03518 ast_moh_stop(bridgepeer);
03519 }
03520 sub->moh = 0;
03521 sub->subtype = SUB_REAL;
03522 pte->state = STATE_CALL;
03523
03524 send_text_status(pte, ustmtext(" Transf Hangup", pte));
03525 send_callerid_screen(pte, sub);
03526 } else {
03527 send_led_update(pte, 0x08);
03528 send_led_update(pte, 0x10);
03529 show_main_page(pte);
03530 }
03531 break;
03532 case KEY_FAV0:
03533 case KEY_FAV1:
03534 case KEY_FAV2:
03535 case KEY_FAV3:
03536 case KEY_FAV4:
03537 case KEY_FAV5:
03538 send_favorite_selected(FAV_LINE_ICON, pte);
03539 pte->device->selected = -1;
03540 handle_key_fav(pte, keycode);
03541 break;
03542 case KEY_LOUDSPK:
03543 if (pte->device->output == OUTPUT_SPEAKER) {
03544 if (pte->device->receiver_state == STATE_OFFHOOK) {
03545 send_select_output(pte, pte->device->previous_output, pte->device->volume,
03546 MUTE_OFF);
03547 } else {
03548 show_main_page(pte);
03549 }
03550 } else {
03551 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03552 }
03553 break;
03554 case KEY_HEADPHN:
03555 if (pte->device->output == OUTPUT_HEADPHONE) {
03556 if (pte->device->receiver_state == STATE_OFFHOOK) {
03557 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03558 } else {
03559 show_main_page(pte);
03560 }
03561 } else {
03562 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03563 }
03564 break;
03565 }
03566 return;
03567 }
03568
03569 static void handle_select_option(struct unistimsession *pte)
03570 {
03571 char tmp[128];
03572
03573 if (pte->state != STATE_SELECTOPTION) {
03574 pte->state = STATE_SELECTOPTION;
03575 pte->size_buff_entry = 1;
03576 pte->buff_entry[0] = 0;
03577 }
03578 snprintf(tmp, sizeof(tmp), "%d. %s", pte->buff_entry[0] + 1, ustmtext(options_menu[(int)pte->buff_entry[0]].label, pte));
03579 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
03580 send_text_status(pte, ustmtext("Select Cancel", pte));
03581 return;
03582 }
03583
03584 static void key_select_option(struct unistimsession *pte, char keycode)
03585 {
03586 switch (keycode) {
03587 case KEY_DOWN:
03588 pte->buff_entry[0]++;
03589 if (options_menu[(int)pte->buff_entry[0]].label == NULL) {
03590 pte->buff_entry[0]--;
03591 }
03592 break;
03593 case KEY_UP:
03594 if (pte->buff_entry[0] > 0) {
03595 pte->buff_entry[0]--;
03596 }
03597 break;
03598 case KEY_FUNC1:
03599 options_menu[(int)pte->buff_entry[0]].handle_option(pte);
03600 return;
03601 case KEY_HANGUP:
03602 case KEY_FUNC4:
03603 show_main_page(pte);
03604 return;
03605 }
03606
03607 handle_select_option(pte);
03608 return;
03609 }
03610
03611 #define SELECTCODEC_START_ENTRY_POS 15
03612 #define SELECTCODEC_MAX_LENGTH 2
03613 #define SELECTCODEC_MSG "Codec number : .."
03614 static void handle_select_codec(struct unistimsession *pte)
03615 {
03616 char buf[30], buf2[5];
03617
03618 pte->state = STATE_SELECTCODEC;
03619 ast_copy_string(buf, ustmtext("Using codec", pte), sizeof(buf));
03620 snprintf(buf2, sizeof(buf2), " %d", pte->device->codec_number);
03621 strcat(buf, buf2);
03622 strcat(buf, " (G711u=0,");
03623
03624 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
03625 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
03626 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03627 send_blink_cursor(pte);
03628 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03629 pte->size_buff_entry = 0;
03630 send_text_status(pte, ustmtext("Select BackSp Erase Cancel", pte));
03631 return;
03632 }
03633
03634 static void key_select_codec(struct unistimsession *pte, char keycode)
03635 {
03636 if (keycode == KEY_FUNC2) {
03637 if (pte->size_buff_entry <= 1) {
03638 keycode = KEY_FUNC3;
03639 } else {
03640 pte->size_buff_entry -= 2;
03641 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03642 }
03643 }
03644 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03645 char tmpbuf[] = SELECTCODEC_MSG;
03646 int i = 0;
03647
03648 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH) {
03649 return;
03650 }
03651 while (i < pte->size_buff_entry) {
03652 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
03653 i++;
03654 }
03655 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
03656 pte->buff_entry[i] = keycode - 0x10;
03657 pte->size_buff_entry++;
03658 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
03659 send_blink_cursor(pte);
03660 send_cursor_pos(pte,
03661 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
03662 return;
03663 }
03664
03665 switch (keycode) {
03666 case KEY_FUNC1:
03667 if (pte->size_buff_entry == 1) {
03668 pte->device->codec_number = pte->buff_entry[0] - 48;
03669 } else if (pte->size_buff_entry == 2) {
03670 pte->device->codec_number =
03671 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
03672 }
03673 show_main_page(pte);
03674 break;
03675 case KEY_FUNC3:
03676 pte->size_buff_entry = 0;
03677 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03678 send_blink_cursor(pte);
03679 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03680 break;
03681 case KEY_HANGUP:
03682 case KEY_FUNC4:
03683 show_main_page(pte);
03684 break;
03685 }
03686 return;
03687 }
03688
03689 static int find_language(const char* lang)
03690 {
03691 int i = 0;
03692 while (options_languages[i].lang_short != NULL) {
03693 if(!strcmp(options_languages[i].lang_short, lang)) {
03694 return i;
03695 }
03696 i++;
03697 }
03698 return 0;
03699 }
03700
03701 static void handle_select_language(struct unistimsession *pte)
03702 {
03703 char tmp_language[40];
03704 struct unistim_languages lang;
03705
03706 if (pte->state != STATE_SELECTLANGUAGE) {
03707 pte->state = STATE_SELECTLANGUAGE;
03708 pte->size_buff_entry = 1;
03709 pte->buff_entry[0] = find_language(pte->device->language);
03710 }
03711 lang = options_languages[(int)pte->buff_entry[0]];
03712 ast_copy_string(tmp_language, pte->device->language, sizeof(tmp_language));
03713 ast_copy_string(pte->device->language, lang.lang_short, sizeof(pte->device->language));
03714 send_charset_update(pte, lang.encoding);
03715 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(lang.label, pte));
03716
03717 ast_copy_string(pte->device->language, tmp_language, sizeof(pte->device->language));
03718 lang = options_languages[find_language(pte->device->language)];
03719 send_charset_update(pte, lang.encoding);
03720 send_text_status(pte, ustmtext("Select Cancel", pte));
03721 return;
03722 }
03723
03724 static void key_select_language(struct unistimsession *pte, char keycode)
03725 {
03726 switch (keycode) {
03727 case KEY_DOWN:
03728 pte->buff_entry[0]++;
03729 if (options_languages[(int)pte->buff_entry[0]].label == NULL) {
03730 pte->buff_entry[0]--;
03731 }
03732 break;
03733 case KEY_UP:
03734 if (pte->buff_entry[0] > 0) {
03735 pte->buff_entry[0]--;
03736 }
03737 break;
03738 case KEY_FUNC1:
03739 ast_copy_string(pte->device->language, options_languages[(int)pte->buff_entry[0]].lang_short, sizeof(pte->device->language));
03740 send_charset_update(pte, options_languages[(int)pte->buff_entry[0]].encoding);
03741 refresh_all_favorite(pte);
03742 show_main_page(pte);
03743 return;
03744 case KEY_HANGUP:
03745 case KEY_FUNC4:
03746 handle_select_option(pte);
03747 return;
03748 }
03749
03750 handle_select_language(pte);
03751 return;
03752 }
03753
03754
03755 #define SELECTEXTENSION_START_ENTRY_POS 0
03756 #define SELECTEXTENSION_MAX_LENGTH 10
03757 #define SELECTEXTENSION_MSG ".........."
03758 static void show_extension_page(struct unistimsession *pte)
03759 {
03760 pte->state = STATE_EXTENSION;
03761
03762 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Please enter a Terminal", pte));
03763 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Number (TN) :", pte));
03764 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03765 send_blink_cursor(pte);
03766 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03767 send_text_status(pte, ustmtext("Enter BackSpcErase", pte));
03768 pte->size_buff_entry = 0;
03769 return;
03770 }
03771
03772 static void key_select_extension(struct unistimsession *pte, char keycode)
03773 {
03774 if (keycode == KEY_FUNC2) {
03775 if (pte->size_buff_entry <= 1) {
03776 keycode = KEY_FUNC3;
03777 } else {
03778 pte->size_buff_entry -= 2;
03779 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03780 }
03781 }
03782 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03783 char tmpbuf[] = SELECTEXTENSION_MSG;
03784 int i = 0;
03785
03786 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH) {
03787 return;
03788 }
03789 while (i < pte->size_buff_entry) {
03790 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
03791 i++;
03792 }
03793 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
03794 pte->buff_entry[i] = keycode - 0x10;
03795 pte->size_buff_entry++;
03796 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03797 send_blink_cursor(pte);
03798 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 + i));
03799 return;
03800 }
03801
03802 switch (keycode) {
03803 case KEY_FUNC1:
03804 if (pte->size_buff_entry < 1) {
03805 return;
03806 }
03807 if (autoprovisioning == AUTOPROVISIONING_TN) {
03808 struct unistim_device *d;
03809
03810
03811 ast_mutex_lock(&devicelock);
03812 d = devices;
03813 pte->buff_entry[pte->size_buff_entry] = '\0';
03814 while (d) {
03815 if (d->id[0] == 'T') {
03816
03817 if (!strcmp((d->id) + 1, pte->buff_entry)) {
03818 pte->device = d;
03819 d->session = pte;
03820 d->codec_number = DEFAULT_CODEC;
03821 d->missed_call = 0;
03822 d->receiver_state = STATE_ONHOOK;
03823 strcpy(d->id, pte->macaddr);
03824 pte->device->extension_number[0] = 'T';
03825 pte->device->extension = EXTENSION_TN;
03826 ast_copy_string((pte->device->extension_number) + 1,
03827 pte->buff_entry, pte->size_buff_entry + 1);
03828 ast_mutex_unlock(&devicelock);
03829 show_main_page(pte);
03830 refresh_all_favorite(pte);
03831 return;
03832 }
03833 }
03834 d = d->next;
03835 }
03836 ast_mutex_unlock(&devicelock);
03837 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid Terminal Number.", pte));
03838 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03839 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
03840 pte->size_buff_entry));
03841 send_blink_cursor(pte);
03842 } else {
03843 ast_copy_string(pte->device->extension_number, pte->buff_entry,
03844 pte->size_buff_entry + 1);
03845 if (register_extension(pte)) {
03846 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid extension.", pte));
03847 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03848 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 +
03849 SELECTEXTENSION_START_ENTRY_POS +
03850 pte->size_buff_entry));
03851 send_blink_cursor(pte);
03852 } else
03853 show_main_page(pte);
03854 }
03855 break;
03856 case KEY_FUNC3:
03857 pte->size_buff_entry = 0;
03858 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03859 send_blink_cursor(pte);
03860 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03861 break;
03862 }
03863 return;
03864 }
03865
03866 static void show_entry_history(struct unistimsession *pte, FILE ** f)
03867 {
03868 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
03869 func3[10];
03870
03871
03872 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03873 display_last_error("Can't read history date entry");
03874 fclose(*f);
03875 return;
03876 }
03877 line[sizeof(line) - 1] = '\0';
03878 if (pte->device->height == 1) {
03879 if (pte->buff_entry[3] == 1) {
03880 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03881 }
03882 } else {
03883 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03884 }
03885
03886 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03887 display_last_error("Can't read callerid entry");
03888 fclose(*f);
03889 return;
03890 }
03891 line[sizeof(line) - 1] = '\0';
03892 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
03893 ast_trim_blanks(pte->device->lst_cid);
03894 if (pte->device->height == 1) {
03895 if (pte->buff_entry[3] == 2) {
03896 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03897 }
03898 } else {
03899 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
03900 }
03901
03902 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03903 display_last_error("Can't read callername entry");
03904 fclose(*f);
03905 return;
03906 }
03907 line[sizeof(line) - 1] = '\0';
03908 if (pte->device->height == 1) {
03909 if (pte->buff_entry[3] == 3) {
03910 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03911 }
03912 } else {
03913 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
03914 }
03915 fclose(*f);
03916
03917 snprintf(line, sizeof(line), "%s %03d/%03d", ustmtext("Call", pte), pte->buff_entry[2],
03918 pte->buff_entry[1]);
03919 send_texttitle(pte, line);
03920
03921 if (pte->buff_entry[2] == 1) {
03922 ast_copy_string(func1, " ", sizeof(func1));
03923 } else {
03924 ast_copy_string(func1, ustmtext("Prev ", pte), sizeof(func1));
03925 }
03926 if (pte->buff_entry[2] >= pte->buff_entry[1]) {
03927 ast_copy_string(func2, " ", sizeof(func2));
03928 } else {
03929 ast_copy_string(func2, ustmtext("Next ", pte), sizeof(func2));
03930 }
03931 if (strlen(pte->device->lst_cid)) {
03932 ast_copy_string(func3, ustmtext("Redial ", pte), sizeof(func3));
03933 } else {
03934 ast_copy_string(func3, " ", sizeof(func3));
03935 }
03936 snprintf(status, sizeof(status), "%s%s%s%s", func1, func2, func3, ustmtext("Cancel", pte));
03937 send_text_status(pte, status);
03938 }
03939
03940 static char open_history(struct unistimsession *pte, char way, FILE ** f)
03941 {
03942 char tmp[AST_CONFIG_MAX_PATH];
03943 char count;
03944
03945 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
03946 USTM_LOG_DIR, pte->device->name, way);
03947 *f = fopen(tmp, "r");
03948 if (!*f) {
03949 display_last_error("Unable to open history file");
03950 return 0;
03951 }
03952 if (fread(&count, 1, 1, *f) != 1) {
03953 display_last_error("Unable to read history header - display.");
03954 fclose(*f);
03955 *f = NULL;
03956 return 0;
03957 }
03958 if (count > MAX_ENTRY_LOG) {
03959 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
03960 count, MAX_ENTRY_LOG);
03961 fclose(*f);
03962 *f = NULL;
03963 return 0;
03964 }
03965 return count;
03966 }
03967
03968 static void show_history(struct unistimsession *pte, char way)
03969 {
03970 FILE *f;
03971 char count;
03972
03973 if (!pte->device) {
03974 return;
03975 }
03976 if (!pte->device->callhistory) {
03977 return;
03978 }
03979 count = open_history(pte, way, &f);
03980 if (!count) {
03981 return;
03982 }
03983 pte->buff_entry[0] = way;
03984 pte->buff_entry[1] = count;
03985 pte->buff_entry[2] = 1;
03986 pte->buff_entry[3] = 1;
03987 show_entry_history(pte, &f);
03988 pte->state = STATE_HISTORY;
03989 }
03990
03991 static void show_main_page(struct unistimsession *pte)
03992 {
03993 char tmpbuf[TEXT_LENGTH_MAX + 1];
03994 const char *text;
03995
03996 if ((pte->device->extension == EXTENSION_ASK) &&
03997 (ast_strlen_zero(pte->device->extension_number))) {
03998 show_extension_page(pte);
03999 return;
04000 }
04001
04002 pte->state = STATE_MAINPAGE;
04003 send_led_update(pte, 0);
04004 pte->device->lastmsgssent = -1;
04005
04006 send_tone(pte, 0, 0);
04007 send_stop_timer(pte);
04008 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
04009 send_led_update(pte, 0x08);
04010 send_led_update(pte, 0x10);
04011
04012 if (!ast_strlen_zero(pte->device->call_forward)) {
04013 if (pte->device->height == 1) {
04014 char tmp_field[100];
04015 snprintf(tmp_field, sizeof(tmp_field), "%s %s", ustmtext("Fwd to:", pte), pte->device->call_forward);
04016 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp_field);
04017 } else {
04018 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Call forwarded to :", pte));
04019 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
04020 }
04021 send_icon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
04022 if (ast_strlen_zero(pte->device->redial_number)) {
04023 send_text_status(pte, ustmtext("Dial NoFwd ", pte));
04024 } else {
04025 send_text_status(pte, ustmtext("Dial Redial NoFwd ", pte));
04026 }
04027 } else {
04028 if ((pte->device->extension == EXTENSION_ASK) || (pte->device->extension == EXTENSION_TN)) {
04029 if (ast_strlen_zero(pte->device->redial_number)) {
04030 send_text_status(pte, ustmtext("Dial Fwd Unregis", pte));
04031 } else {
04032 send_text_status(pte, ustmtext("Dial Redial Fwd Unregis", pte));
04033 }
04034 } else {
04035 if (ast_strlen_zero(pte->device->redial_number)) {
04036 send_text_status(pte, ustmtext("Dial Fwd Pickup", pte));
04037 } else {
04038 send_text_status(pte, ustmtext("Dial Redial Fwd Pickup", pte));
04039 }
04040 }
04041 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
04042 if (pte->device->missed_call == 0) {
04043 send_date_time2(pte);
04044 send_idle_clock(pte);
04045 if (strlen(pte->device->maintext0)) {
04046 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
04047 }
04048 } else {
04049 if (pte->device->missed_call == 1) {
04050 text = ustmtext("unanswered call", pte);
04051 } else {
04052 text = ustmtext("unanswered calls", pte);
04053 }
04054 snprintf(tmpbuf, sizeof(tmpbuf), "%d %s", pte->device->missed_call, text);
04055 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
04056 send_icon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
04057 }
04058 }
04059 if (pte->device->height > 1) {
04060 if (ast_strlen_zero(pte->device->maintext2)) {
04061 strcpy(tmpbuf, "IP : ");
04062 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
04063 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
04064 } else {
04065 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
04066 }
04067 }
04068
04069 send_texttitle(pte, pte->device->titledefault);
04070 change_favorite_icon(pte, FAV_LINE_ICON);
04071 }
04072
04073 static void key_main_page(struct unistimsession *pte, char keycode)
04074 {
04075 if (pte->device->missed_call) {
04076 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04077 pte->device->missed_call = 0;
04078 }
04079 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
04080 handle_dial_page(pte);
04081 key_dial_page(pte, keycode);
04082 return;
04083 }
04084 switch (keycode) {
04085 case KEY_FUNC1:
04086 pte->device->selected = get_avail_softkey(pte, NULL);
04087 handle_dial_page(pte);
04088 break;
04089 case KEY_FUNC2:
04090 if (ast_strlen_zero(pte->device->redial_number)) {
04091 break;
04092 }
04093 if ((pte->device->output == OUTPUT_HANDSET) &&
04094 (pte->device->receiver_state == STATE_ONHOOK)) {
04095 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04096 } else {
04097 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
04098 }
04099 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
04100 sizeof(pte->device->phone_number));
04101 handle_call_outgoing(pte);
04102 break;
04103 case KEY_FUNC3:
04104 if (!ast_strlen_zero(pte->device->call_forward)) {
04105
04106 memmove(pte->device->call_forward + 1, pte->device->call_forward,
04107 sizeof(pte->device->call_forward) - 1);
04108 pte->device->call_forward[0] = '\0';
04109 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04110 pte->device->output = OUTPUT_HANDSET;
04111 show_main_page(pte);
04112 break;
04113 }
04114 pte->device->call_forward[0] = -1;
04115 handle_dial_page(pte);
04116 break;
04117 case KEY_FUNC4:
04118 if (pte->device->extension == EXTENSION_ASK) {
04119 unregister_extension(pte);
04120 pte->device->extension_number[0] = '\0';
04121 show_extension_page(pte);
04122 } else if (pte->device->extension == EXTENSION_TN) {
04123 ast_mutex_lock(&devicelock);
04124 strcpy(pte->device->id, pte->device->extension_number);
04125 pte->buff_entry[0] = '\0';
04126 pte->size_buff_entry = 0;
04127 pte->device->session = NULL;
04128 pte->device = NULL;
04129 ast_mutex_unlock(&devicelock);
04130 show_extension_page(pte);
04131 } else {
04132 pte->device->selected = -1;
04133 ast_copy_string(pte->device->phone_number, ast_pickup_ext(),
04134 sizeof(pte->device->phone_number));
04135 handle_call_outgoing(pte);
04136 }
04137 break;
04138 case KEY_FAV0:
04139 case KEY_FAV1:
04140 case KEY_FAV2:
04141 case KEY_FAV3:
04142 case KEY_FAV4:
04143 case KEY_FAV5:
04144 handle_key_fav(pte, keycode);
04145 break;
04146 case KEY_CONF:
04147 handle_select_option(pte);
04148 break;
04149 case KEY_LOUDSPK:
04150 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04151 handle_dial_page(pte);
04152 break;
04153 case KEY_HEADPHN:
04154 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04155 handle_dial_page(pte);
04156 break;
04157 case KEY_SNDHIST:
04158 show_history(pte, 'o');
04159 break;
04160 case KEY_RCVHIST:
04161 show_history(pte, 'i');
04162 break;
04163 }
04164 return;
04165 }
04166
04167 static void key_history(struct unistimsession *pte, char keycode)
04168 {
04169 FILE *f;
04170 char count;
04171 long offset;
04172 int flag = 0;
04173
04174 switch (keycode) {
04175 case KEY_LEFT:
04176 if (pte->device->height == 1) {
04177 if (pte->buff_entry[3] <= 1) {
04178 return;
04179 }
04180 pte->buff_entry[3]--;
04181 flag = 1;
04182 break;
04183 }
04184 case KEY_UP:
04185 case KEY_FUNC1:
04186 if (pte->buff_entry[2] <= 1) {
04187 return;
04188 }
04189 pte->buff_entry[2]--;
04190 flag = 1;
04191 break;
04192 case KEY_RIGHT:
04193 if (pte->device->height == 1) {
04194 if (pte->buff_entry[3] == 3) {
04195 return;
04196 }
04197 pte->buff_entry[3]++;
04198 flag = 1;
04199 break;
04200 }
04201 case KEY_DOWN:
04202 case KEY_FUNC2:
04203 if (pte->buff_entry[2] >= pte->buff_entry[1]) {
04204 return;
04205 }
04206 pte->buff_entry[2]++;
04207 flag = 1;
04208 break;
04209 case KEY_FUNC3:
04210 if (ast_strlen_zero(pte->device->lst_cid)) {
04211 break;
04212 }
04213 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
04214 sizeof(pte->device->redial_number));
04215 key_main_page(pte, KEY_FUNC2);
04216 break;
04217 case KEY_FUNC4:
04218 case KEY_HANGUP:
04219 show_main_page(pte);
04220 break;
04221 case KEY_SNDHIST:
04222 if (pte->buff_entry[0] == 'i') {
04223 show_history(pte, 'o');
04224 } else {
04225 show_main_page(pte);
04226 }
04227 break;
04228 case KEY_RCVHIST:
04229 if (pte->buff_entry[0] == 'i') {
04230 show_main_page(pte);
04231 } else {
04232 show_history(pte, 'i');
04233 }
04234 break;
04235 }
04236
04237 if (flag) {
04238 count = open_history(pte, pte->buff_entry[0], &f);
04239 if (!count) {
04240 return;
04241 }
04242 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
04243 if (fseek(f, offset, SEEK_CUR)) {
04244 display_last_error("Unable to seek history entry.");
04245 fclose(f);
04246 return;
04247 }
04248 show_entry_history(pte, &f);
04249 }
04250
04251 return;
04252 }
04253
04254 static void init_phone_step2(struct unistimsession *pte)
04255 {
04256 BUFFSEND;
04257 if (unistimdebug) {
04258 ast_verb(0, "Sending S4\n");
04259 }
04260 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
04261 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
04262 send_date_time2(pte);
04263 send_date_time3(pte);
04264 if (unistimdebug) {
04265 ast_verb(0, "Sending S7\n");
04266 }
04267 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04268 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04269 if (unistimdebug) {
04270 ast_verb(0, "Sending Contrast\n");
04271 }
04272 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
04273 if (pte->device != NULL) {
04274 buffsend[9] = pte->device->contrast;
04275 }
04276 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
04277
04278 if (unistimdebug) {
04279 ast_verb(0, "Sending S9\n");
04280 }
04281 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
04282 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
04283 send_no_ring(pte);
04284
04285 if (unistimdebug) {
04286 ast_verb(0, "Sending S7\n");
04287 }
04288 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04289 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04290 send_led_update(pte, 0);
04291 send_ping(pte);
04292 if (unistimdebug) {
04293 ast_verb(0, "Sending init language\n");
04294 }
04295 if (pte->device) {
04296 send_charset_update(pte, options_languages[find_language(pte->device->language)].encoding);
04297 }
04298 if (pte->state < STATE_MAINPAGE) {
04299 if (autoprovisioning == AUTOPROVISIONING_TN) {
04300 show_extension_page(pte);
04301 return;
04302 } else {
04303 int i;
04304 char tmp[30];
04305
04306 for (i = 1; i < FAVNUM; i++) {
04307 send_favorite(i, 0, pte, "");
04308 }
04309 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Phone is not registered", pte));
04310 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("in unistim.conf", pte));
04311 strcpy(tmp, "MAC = ");
04312 strcat(tmp, pte->macaddr);
04313 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04314 send_text_status(pte, "");
04315 send_texttitle(pte, "UNISTIM for*");
04316 return;
04317 }
04318 }
04319 show_main_page(pte);
04320 refresh_all_favorite(pte);
04321 if (unistimdebug) {
04322 ast_verb(0, "Sending arrow\n");
04323 }
04324 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
04325 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
04326 return;
04327 }
04328
04329 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
04330 {
04331 char tmpbuf[255];
04332 if (memcmp
04333 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
04334 sizeof(packet_recv_resume_connection_with_server)) == 0) {
04335 rcv_resume_connection_with_server(pte);
04336 return;
04337 }
04338 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) == 0) {
04339 buf[size] = 0;
04340 if (unistimdebug) {
04341 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
04342 }
04343 init_phone_step2(pte);
04344 return;
04345 }
04346 if (memcmp(buf + SIZE_HEADER, packet_recv_it_type, sizeof(packet_recv_it_type)) == 0) {
04347 char type = buf[13];
04348 if (unistimdebug) {
04349 ast_verb(0, "Got the equipment type: '%d'\n", type);
04350 }
04351 switch (type) {
04352 case 0x03:
04353 if (pte->device) {
04354 pte->device->height = 1;
04355 }
04356 break;
04357 }
04358 return;
04359 }
04360 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
04361 rcv_mac_addr(pte, buf);
04362 return;
04363 }
04364 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
04365 if (unistimdebug) {
04366 ast_verb(0, "R2 received\n");
04367 }
04368 return;
04369 }
04370
04371 if (pte->state < STATE_MAINPAGE) {
04372 if (unistimdebug) {
04373 ast_verb(0, "Request not authorized in this state\n");
04374 }
04375 return;
04376 }
04377 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
04378 char keycode = buf[13];
04379
04380 if (unistimdebug) {
04381 ast_verb(0, "Key pressed: keycode = 0x%.2x - current state: %s\n", keycode,
04382 ptestate_tostr(pte->state));
04383 }
04384 switch (pte->state) {
04385 case STATE_INIT:
04386 if (unistimdebug) {
04387 ast_verb(0, "No keys allowed in the init state\n");
04388 }
04389 break;
04390 case STATE_AUTHDENY:
04391 if (unistimdebug) {
04392 ast_verb(0, "No keys allowed in authdeny state\n");
04393 }
04394 break;
04395 case STATE_MAINPAGE:
04396 key_main_page(pte, keycode);
04397 break;
04398 case STATE_DIALPAGE:
04399 key_dial_page(pte, keycode);
04400 break;
04401 case STATE_RINGING:
04402 key_ringing(pte, keycode);
04403 break;
04404 case STATE_CALL:
04405 key_call(pte, keycode);
04406 break;
04407 case STATE_EXTENSION:
04408 key_select_extension(pte, keycode);
04409 break;
04410 case STATE_SELECTOPTION:
04411 key_select_option(pte, keycode);
04412 break;
04413 case STATE_SELECTCODEC:
04414 key_select_codec(pte, keycode);
04415 break;
04416 case STATE_SELECTLANGUAGE:
04417 key_select_language(pte, keycode);
04418 break;
04419 case STATE_HISTORY:
04420 key_history(pte, keycode);
04421 break;
04422 default:
04423 ast_log(LOG_WARNING, "Key : Unknown state\n");
04424 }
04425 return;
04426 }
04427 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
04428 if (unistimdebug) {
04429 ast_verb(0, "Handset off hook, current state: %s\n", ptestate_tostr(pte->state));
04430 }
04431 if (!pte->device) {
04432 return;
04433 }
04434 pte->device->receiver_state = STATE_OFFHOOK;
04435 if (pte->device->output == OUTPUT_HEADPHONE) {
04436 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04437 } else {
04438 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04439 }
04440 if (pte->state == STATE_RINGING) {
04441 handle_call_incoming(pte);
04442 } else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL)) {
04443 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04444 } else if (pte->state == STATE_EXTENSION) {
04445 return;
04446 } else {
04447 pte->device->selected = get_avail_softkey(pte, NULL);
04448 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04449 handle_dial_page(pte);
04450 }
04451 return;
04452 }
04453 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
04454 if (unistimdebug) {
04455 ast_verb(0, "Handset on hook, current state: %s\n", ptestate_tostr(pte->state));
04456 }
04457 if (!pte->device) {
04458 return;
04459 }
04460 pte->device->receiver_state = STATE_ONHOOK;
04461 if (pte->state == STATE_CALL) {
04462 if (pte->device->output != OUTPUT_SPEAKER) {
04463 close_call(pte);
04464 }
04465 } else if (pte->state == STATE_EXTENSION) {
04466 return;
04467 } else {
04468 pte->device->nextdial = 0;
04469 show_main_page(pte);
04470 }
04471 return;
04472 }
04473 strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
04474 strcat(tmpbuf, " Unknown request packet\n");
04475 if (unistimdebug) {
04476 ast_debug(1, "%s", tmpbuf);
04477 }
04478 return;
04479 }
04480
04481 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
04482 struct sockaddr_in *addr_from)
04483 {
04484 unsigned short *sbuf = (unsigned short *) buf;
04485 unsigned short seq;
04486 char tmpbuf[255];
04487
04488 strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
04489
04490 if (size < 10) {
04491 if (size == 0) {
04492 ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
04493 } else {
04494 ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
04495 }
04496 return;
04497 }
04498 if (sbuf[0] == 0xffff) {
04499 if (size != sizeof(packet_rcv_discovery)) {
04500 ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
04501 } else {
04502 if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
04503 if (unistimdebug) {
04504 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
04505 }
04506 if (pte) {
04507 if (pte->state == STATE_INIT) {
04508 if (unistimdebug) {
04509 ast_verb(1, "Duplicated Discovery packet\n");
04510 }
04511 send_raw_client(sizeof(packet_send_discovery_ack),
04512 packet_send_discovery_ack, addr_from, &pte->sout);
04513 pte->seq_phone = (short) 0x0000;
04514 } else {
04515 close_client(pte);
04516 if (create_client(addr_from)) {
04517 send_raw_client(sizeof(packet_send_discovery_ack),
04518 packet_send_discovery_ack, addr_from, &pte->sout);
04519 }
04520 }
04521 } else {
04522
04523 if ((pte = create_client(addr_from))) {
04524 send_raw_client(sizeof(packet_send_discovery_ack),
04525 packet_send_discovery_ack, addr_from, &pte->sout);
04526 }
04527 }
04528 return;
04529 }
04530 ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
04531 }
04532 return;
04533 }
04534 if (!pte) {
04535 if (unistimdebug) {
04536 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n", tmpbuf);
04537 }
04538 return;
04539 }
04540
04541 if (sbuf[0] != 0) {
04542 ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
04543 return;
04544 }
04545 if (buf[5] != 2) {
04546 ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
04547 buf[5]);
04548 return;
04549 }
04550 seq = ntohs(sbuf[1]);
04551 if (buf[4] == 1) {
04552 ast_mutex_lock(&pte->lock);
04553 if (unistimdebug) {
04554 ast_verb(6, "ACK received for packet #0x%.4x\n", seq);
04555 }
04556 pte->nb_retransmit = 0;
04557
04558 if ((pte->last_seq_ack) + 1 == seq) {
04559 pte->last_seq_ack++;
04560 check_send_queue(pte);
04561 ast_mutex_unlock(&pte->lock);
04562 return;
04563 }
04564 if (pte->last_seq_ack > seq) {
04565 if (pte->last_seq_ack == 0xffff) {
04566 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
04567 pte->last_seq_ack = 0;
04568 } else {
04569 ast_log(LOG_NOTICE,
04570 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
04571 tmpbuf, seq, pte->last_seq_ack);
04572 }
04573 ast_mutex_unlock(&pte->lock);
04574 return;
04575 }
04576 if (pte->seq_server < seq) {
04577 ast_log(LOG_NOTICE,
04578 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
04579 tmpbuf, pte->seq_server);
04580 ast_mutex_unlock(&pte->lock);
04581 return;
04582 }
04583 if (unistimdebug) {
04584 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
04585 tmpbuf, seq, pte->last_seq_ack);
04586 }
04587 pte->last_seq_ack = seq;
04588 check_send_queue(pte);
04589 ast_mutex_unlock(&pte->lock);
04590 return;
04591 }
04592 if (buf[4] == 2) {
04593 if (unistimdebug) {
04594 ast_verb(0, "Request received\n");
04595 }
04596 if (pte->seq_phone == seq) {
04597
04598 buf[4] = 1;
04599 buf[5] = 1;
04600 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04601 pte->seq_phone++;
04602
04603 process_request(size, buf, pte);
04604 return;
04605 }
04606 if (pte->seq_phone > seq) {
04607 ast_log(LOG_NOTICE,
04608 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
04609 tmpbuf, seq, pte->seq_phone);
04610
04611
04612 buf[4] = 1;
04613 buf[5] = 1;
04614 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04615 return;
04616 }
04617 ast_log(LOG_NOTICE,
04618 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
04619 tmpbuf, seq, pte->seq_phone);
04620 return;
04621 }
04622 if (buf[4] == 0) {
04623 ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, seq);
04624 if (pte->last_seq_ack > seq) {
04625 ast_log(LOG_NOTICE,
04626 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
04627 tmpbuf, pte->last_seq_ack);
04628 return;
04629 }
04630 if (pte->seq_server < seq) {
04631 ast_log(LOG_NOTICE,
04632 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
04633 tmpbuf, pte->seq_server);
04634 return;
04635 }
04636 send_retransmit(pte);
04637 return;
04638 }
04639 ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
04640 tmpbuf, buf[4]);
04641 return;
04642 }
04643
04644 static struct unistimsession *channel_to_session(struct ast_channel *ast)
04645 {
04646 struct unistim_subchannel *sub;
04647 if (!ast) {
04648 ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
04649 return NULL;
04650 }
04651 if (!ast_channel_tech_pvt(ast)) {
04652 ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
04653 return NULL;
04654 }
04655 sub = ast_channel_tech_pvt(ast);
04656
04657 if (!sub->parent) {
04658 ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
04659 return NULL;
04660 }
04661 if (!sub->parent->parent) {
04662 ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
04663 return NULL;
04664 }
04665 ast_mutex_lock(&sub->parent->parent->lock);
04666 if (!sub->parent->parent->session) {
04667 ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
04668 ast_mutex_unlock(&sub->parent->parent->lock);
04669 return NULL;
04670 }
04671 ast_mutex_unlock(&sub->parent->parent->lock);
04672 return sub->parent->parent->session;
04673 }
04674
04675 static void send_callerid_screen(struct unistimsession *pte, struct unistim_subchannel *sub)
04676 {
04677 char *cidname_str;
04678 char *cidnum_str;
04679
04680 if (!sub) {
04681 return;
04682 }
04683 if (sub->owner) {
04684 if (ast_channel_connected(sub->owner)->id.number.valid && ast_channel_connected(sub->owner)->id.number.str) {
04685 cidnum_str = ast_channel_connected(sub->owner)->id.number.str;
04686 } else {
04687 cidnum_str = DEFAULTCALLERID;
04688 }
04689 change_callerid(pte, 0, cidnum_str);
04690 if (strlen(cidnum_str) == 0) {
04691 cidnum_str = DEFAULTCALLERID;
04692 }
04693
04694 if (ast_channel_connected(sub->owner)->id.name.valid && ast_channel_connected(sub->owner)->id.name.str) {
04695 cidname_str = ast_channel_connected(sub->owner)->id.name.str;
04696 } else {
04697 cidname_str = DEFAULTCALLERNAME;
04698 }
04699 change_callerid(pte, 1, cidname_str);
04700 if (strlen(cidname_str) == 0) {
04701 cidname_str = DEFAULTCALLERNAME;
04702 }
04703
04704 if (pte->device->height == 1) {
04705 char tmpstr[256];
04706 snprintf(tmpstr, sizeof(tmpstr), "%s %s", cidnum_str, ustmtext(cidname_str, pte));
04707 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpstr);
04708 } else {
04709 send_text(TEXT_LINE0, TEXT_NORMAL, pte, cidname_str);
04710 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(cidnum_str, pte));
04711 }
04712 }
04713 }
04714
04715
04716
04717 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout)
04718 {
04719 int res = 0, i;
04720 struct unistim_subchannel *sub, *sub_real;
04721 struct unistimsession *session;
04722 char ringstyle, ringvolume;
04723
04724 session = channel_to_session(ast);
04725 if (!session) {
04726 ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
04727 return -1;
04728 }
04729 sub = ast_channel_tech_pvt(ast);
04730 sub_real = get_sub(session->device, SUB_REAL);
04731 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
04732 ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
04733 ast_channel_name(ast));
04734 return -1;
04735 }
04736
04737 if (unistimdebug) {
04738 ast_verb(3, "unistim_call(%s)\n", ast_channel_name(ast));
04739 }
04740 session->state = STATE_RINGING;
04741 send_callerid_screen(session, sub);
04742 if (ast_strlen_zero(ast_channel_call_forward(ast))) {
04743 send_text(TEXT_LINE2, TEXT_NORMAL, session, ustmtext("is calling you.", session));
04744 send_text_status(session, ustmtext("Accept Ignore Hangup", session));
04745
04746 if (sub_real) {
04747 ringstyle = session->device->cwstyle;
04748 ringvolume = session->device->cwvolume;
04749 } else {
04750 ringstyle = (sub->ringstyle == -1) ? session->device->ringstyle : sub->ringstyle;
04751 ringvolume = (sub->ringvolume == -1) ? session->device->ringvolume : sub->ringvolume;
04752 }
04753 send_ring(session, ringvolume, ringstyle);
04754 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
04755
04756 for (i = 0; i < FAVNUM; i++) {
04757 if (!soft_key_visible(session->device, i)) {
04758 continue;
04759 }
04760 if (session->device->ssub[i]) {
04761 continue;
04762 }
04763 if (is_key_line(session->device, i) && !strcmp(sub->parent->name, session->device->sline[i]->name)) {
04764 if (unistimdebug) {
04765 ast_verb(0, "Found softkey %d for line %s\n", i, sub->parent->name);
04766 }
04767 send_favorite_short(i, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST, session);
04768 session->device->ssub[i] = sub;
04769 }
04770 }
04771 }
04772 ast_setstate(ast, AST_STATE_RINGING);
04773 ast_queue_control(ast, AST_CONTROL_RINGING);
04774 return res;
04775 }
04776
04777 static int unistim_hangup_clean(struct ast_channel *ast, struct unistim_subchannel *sub) {
04778 ast_mutex_lock(&sub->lock);
04779 ast_channel_tech_pvt_set(ast, NULL);
04780 sub->owner = NULL;
04781 sub->alreadygone = 0;
04782 ast_mutex_unlock(&sub->lock);
04783 if (sub->rtp) {
04784 if (unistimdebug) {
04785 ast_verb(0, "Destroying RTP session\n");
04786 }
04787 ast_rtp_instance_destroy(sub->rtp);
04788 sub->rtp = NULL;
04789 }
04790 return 0;
04791 }
04792
04793
04794 static int unistim_hangup(struct ast_channel *ast)
04795 {
04796 struct unistim_subchannel *sub = NULL, *sub_real = NULL, *sub_trans = NULL;
04797 struct unistim_line *l;
04798 struct unistim_device *d;
04799 struct unistimsession *s;
04800 int i,end_call = 1;
04801
04802 s = channel_to_session(ast);
04803 sub = ast_channel_tech_pvt(ast);
04804 l = sub->parent;
04805 d = l->parent;
04806 if (!s) {
04807 ast_debug(1, "Asked to hangup channel not connected\n");
04808 unistim_hangup_clean(ast, sub);
04809 return 0;
04810 }
04811 if (unistimdebug) {
04812 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));
04813 }
04814 sub_trans = get_sub(d, SUB_THREEWAY);
04815 sub_real = get_sub(d, SUB_REAL);
04816 if (sub_trans && (sub_trans->owner) && (sub->subtype == SUB_REAL)) {
04817 if (unistimdebug) {
04818 ast_verb(0, "Threeway call disconnected, switching to real call\n");
04819 }
04820 if (ast_bridged_channel(sub_trans->owner)) {
04821 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
04822 }
04823 sub_trans->moh = 0;
04824 sub_trans->subtype = SUB_REAL;
04825 swap_subs(sub_trans, sub);
04826 send_text_status(s, ustmtext(" Transf Hangup", s));
04827 send_callerid_screen(s, sub_trans);
04828 unistim_hangup_clean(ast, sub);
04829 unistim_unalloc_sub(d, sub);
04830 return 0;
04831 }
04832 if (sub_real && (sub_real->owner) && (sub->subtype == SUB_THREEWAY) && (s->state == STATE_CALL)) {
04833 if (unistimdebug) {
04834 ast_verb(0, "Real call disconnected, stay in call\n");
04835 }
04836 send_text_status(s, ustmtext(" Transf Hangup", s));
04837 send_callerid_screen(s, sub_real);
04838 unistim_hangup_clean(ast, sub);
04839 unistim_unalloc_sub(d, sub);
04840 return 0;
04841 }
04842 if (sub->subtype == SUB_REAL) {
04843 sub_stop_silence(s, sub);
04844 } else if (sub->subtype == SUB_RING) {
04845 send_no_ring(s);
04846 for (i = 0; i < FAVNUM; i++) {
04847 if (!soft_key_visible(s->device, i))
04848 continue;
04849 if (d->ssub[i] != sub)
04850 continue;
04851 if (is_key_line(d, i) && !strcmp(l->name, d->sline[i]->name)) {
04852 send_favorite_short(i, FAV_LINE_ICON, s);
04853 d->ssub[i] = NULL;
04854 continue;
04855 }
04856 if (d->ssub[i] != NULL) {
04857 end_call = 0;
04858 }
04859 }
04860 }
04861 if (end_call) {
04862 send_end_call(s);
04863 }
04864 sub->moh = 0;
04865 if (sub->softkey >= 0) {
04866 send_favorite_short(sub->softkey, FAV_LINE_ICON, s);
04867 }
04868
04869 for (i = 0; i < FAVNUM; i++) {
04870 if (d->ssub[i] == sub) {
04871 d->ssub[i] = NULL;
04872 break;
04873 }
04874 }
04875
04876 if (s->state == STATE_RINGING && sub->subtype == SUB_RING) {
04877 send_no_ring(s);
04878 if (ast_channel_hangupcause(ast) != AST_CAUSE_ANSWERED_ELSEWHERE) {
04879 d->missed_call++;
04880 write_history(s, 'i', 1);
04881 }
04882 if (!sub_real) {
04883 show_main_page(s);
04884 } else {
04885 s->state = STATE_CALL;
04886 send_callerid_screen(s, sub_real);
04887 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
04888 send_text_status(s, ustmtext(" Transf Hangup", s));
04889 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
04890
04891 }
04892 }
04893 if (s->state == STATE_CALL && sub->subtype == SUB_REAL) {
04894 close_call(s);
04895 }
04896 sub->softkey = -1;
04897 unistim_hangup_clean(ast, sub);
04898 unistim_unalloc_sub(d, sub);
04899 return 0;
04900 }
04901
04902
04903 static int unistim_answer(struct ast_channel *ast)
04904 {
04905 int res = 0;
04906 struct unistim_subchannel *sub;
04907 struct unistim_line *l;
04908 struct unistim_device *d;
04909 struct unistimsession *s;
04910
04911 s = channel_to_session(ast);
04912 if (!s) {
04913 ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
04914 return -1;
04915 }
04916 sub = ast_channel_tech_pvt(ast);
04917 l = sub->parent;
04918 d = l->parent;
04919
04920 if (unistimdebug) {
04921 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast_channel_name(ast), l->name,
04922 l->parent->name, sub->softkey);
04923 }
04924 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is now on-line", s));
04925 if (get_sub(d, SUB_THREEWAY)) {
04926 send_text_status(s, ustmtext("Transf Cancel", s));
04927 } else {
04928 send_text_status(s, ustmtext(" Transf Hangup", s));
04929 }
04930 send_start_timer(s);
04931 if (ast_channel_state(ast) != AST_STATE_UP)
04932 ast_setstate(ast, AST_STATE_UP);
04933 return res;
04934 }
04935
04936
04937
04938 static int unistimsock_read(int *id, int fd, short events, void *ignore)
04939 {
04940 struct sockaddr_in addr_from = { 0, };
04941 struct unistimsession *cur = NULL;
04942 int found = 0;
04943 int tmp = 0;
04944 int dw_num_bytes_rcvd;
04945 unsigned int size_addr_from;
04946 #ifdef DUMP_PACKET
04947 int dw_num_bytes_rcvdd;
04948 #endif
04949
04950 size_addr_from = sizeof(addr_from);
04951 dw_num_bytes_rcvd =
04952 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
04953 &size_addr_from);
04954 if (dw_num_bytes_rcvd == -1) {
04955 if (errno == EAGAIN) {
04956 ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
04957 } else if (errno != ECONNREFUSED) {
04958 ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
04959 }
04960 return 1;
04961 }
04962
04963
04964 ast_mutex_lock(&sessionlock);
04965 cur = sessions;
04966 while (cur) {
04967 if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
04968 found = 1;
04969 break;
04970 }
04971 tmp++;
04972 cur = cur->next;
04973 }
04974 ast_mutex_unlock(&sessionlock);
04975
04976 #ifdef DUMP_PACKET
04977 if (unistimdebug)
04978 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
04979 dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
04980 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
04981 dw_num_bytes_rcvdd++)
04982 ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
04983 ast_verb(0, "\n******************************************\n");
04984 #endif
04985
04986 if (!found) {
04987 if (unistimdebug) {
04988 ast_verb(0, "Received a packet from an unknown source\n");
04989 }
04990 parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
04991
04992 } else {
04993 parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
04994 }
04995 return 1;
04996 }
04997
04998 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
04999 const struct unistim_subchannel *sub)
05000 {
05001
05002 struct ast_frame *f;
05003
05004 if (!ast) {
05005 ast_log(LOG_WARNING, "Channel NULL while reading\n");
05006 return &ast_null_frame;
05007 }
05008
05009 if (!sub->rtp) {
05010 ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %d\n",
05011 sub->subtype);
05012 return &ast_null_frame;
05013 }
05014
05015 switch (ast_channel_fdno(ast)) {
05016 case 0:
05017 f = ast_rtp_instance_read(sub->rtp, 0);
05018 break;
05019 case 1:
05020 f = ast_rtp_instance_read(sub->rtp, 1);
05021 break;
05022 default:
05023 f = &ast_null_frame;
05024 }
05025
05026 if (sub->owner) {
05027
05028 if (f->frametype == AST_FRAME_VOICE) {
05029 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format))) {
05030 char tmp[256];
05031 ast_debug(1,
05032 "Oooh, format changed from %s to %s\n",
05033 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)),
05034 ast_getformatname(&f->subclass.format));
05035
05036 ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
05037 ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
05038 ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
05039 }
05040 }
05041 }
05042
05043 return f;
05044 }
05045
05046 static struct ast_frame *unistim_read(struct ast_channel *ast)
05047 {
05048 struct ast_frame *fr;
05049 struct unistim_subchannel *sub = ast_channel_tech_pvt(ast);
05050
05051 ast_mutex_lock(&sub->lock);
05052 fr = unistim_rtp_read(ast, sub);
05053 ast_mutex_unlock(&sub->lock);
05054
05055 return fr;
05056 }
05057
05058 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
05059 {
05060 struct unistim_subchannel *sub = ast_channel_tech_pvt(ast);
05061 int res = 0;
05062
05063 if (frame->frametype != AST_FRAME_VOICE) {
05064 if (frame->frametype == AST_FRAME_IMAGE) {
05065 return 0;
05066 } else {
05067 ast_log(LOG_WARNING, "Can't send %d type frames with unistim_write\n",
05068 frame->frametype);
05069 return 0;
05070 }
05071 } else {
05072 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
05073 char tmp[256];
05074 ast_log(LOG_WARNING,
05075 "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
05076 ast_getformatname(&frame->subclass.format),
05077 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(ast)),
05078 ast_getformatname(ast_channel_readformat(ast)),
05079 ast_getformatname(ast_channel_writeformat(ast)));
05080 return -1;
05081 }
05082 }
05083
05084 if (sub) {
05085 ast_mutex_lock(&sub->lock);
05086 if (sub->rtp) {
05087 res = ast_rtp_instance_write(sub->rtp, frame);
05088 }
05089 ast_mutex_unlock(&sub->lock);
05090 }
05091
05092 return res;
05093 }
05094
05095 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05096 {
05097 struct unistim_subchannel *p = ast_channel_tech_pvt(newchan);
05098 struct unistim_line *l = p->parent;
05099
05100 ast_mutex_lock(&p->lock);
05101
05102 ast_debug(1, "New owner for channel USTM/%s@%s-%d is %s\n", l->name,
05103 l->parent->name, p->subtype, ast_channel_name(newchan));
05104
05105 if (p->owner != oldchan) {
05106 ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
05107 ast_channel_name(oldchan), oldchan, ast_channel_name(p->owner), p->owner);
05108 ast_mutex_unlock(&p->lock);
05109 return -1;
05110 }
05111
05112 p->owner = newchan;
05113
05114 ast_mutex_unlock(&p->lock);
05115
05116 return 0;
05117
05118 }
05119
05120 static char *control2str(int ind)
05121 {
05122 switch (ind) {
05123 case AST_CONTROL_HANGUP:
05124 return "Other end has hungup";
05125 case AST_CONTROL_RING:
05126 return "Local ring";
05127 case AST_CONTROL_RINGING:
05128 return "Remote end is ringing";
05129 case AST_CONTROL_ANSWER:
05130 return "Remote end has answered";
05131 case AST_CONTROL_BUSY:
05132 return "Remote end is busy";
05133 case AST_CONTROL_TAKEOFFHOOK:
05134 return "Make it go off hook";
05135 case AST_CONTROL_OFFHOOK:
05136 return "Line is off hook";
05137 case AST_CONTROL_CONGESTION:
05138 return "Congestion (circuits busy)";
05139 case AST_CONTROL_FLASH:
05140 return "Flash hook";
05141 case AST_CONTROL_WINK:
05142 return "Wink";
05143 case AST_CONTROL_OPTION:
05144 return "Set a low-level option";
05145 case AST_CONTROL_RADIO_KEY:
05146 return "Key Radio";
05147 case AST_CONTROL_RADIO_UNKEY:
05148 return "Un-Key Radio";
05149 case AST_CONTROL_CONNECTED_LINE:
05150 return "Remote end changed";
05151 case AST_CONTROL_SRCCHANGE:
05152 return "RTP source updated";
05153 case AST_CONTROL_SRCUPDATE:
05154 return "Source of media changed";
05155 case -1:
05156 return "Stop tone";
05157 }
05158 return "UNKNOWN";
05159 }
05160
05161 static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
05162 const char *indication)
05163 {
05164 struct ast_tone_zone_sound *ts = NULL;
05165
05166 if ((ts = ast_get_indication_tone(tz, indication))) {
05167 ast_playtones_start(ast, 0, ts->data, 1);
05168 ts = ast_tone_zone_sound_unref(ts);
05169 } else {
05170 ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
05171 }
05172 }
05173
05174 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
05175 size_t datalen)
05176 {
05177 struct unistim_subchannel *sub;
05178 struct unistim_line *l;
05179 struct unistimsession *s;
05180
05181 if (unistimdebug) {
05182 ast_verb(3, "Asked to indicate '%s' (%d) condition on channel %s\n",
05183 control2str(ind), ind, ast_channel_name(ast));
05184 }
05185
05186 s = channel_to_session(ast);
05187 if (!s) {
05188 return -1;
05189 }
05190 sub = ast_channel_tech_pvt(ast);
05191 l = sub->parent;
05192
05193 switch (ind) {
05194 case AST_CONTROL_RINGING:
05195 if (ast_channel_state(ast) != AST_STATE_UP) {
05196 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Ringing...", s));
05197 in_band_indication(ast, l->parent->tz, "ring");
05198 s->device->missed_call = -1;
05199 break;
05200 }
05201 return -1;
05202 case AST_CONTROL_BUSY:
05203 if (ast_channel_state(ast) != AST_STATE_UP) {
05204 sub->alreadygone = 1;
05205 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Busy", s));
05206 in_band_indication(ast, l->parent->tz, "busy");
05207 s->device->missed_call = -1;
05208 break;
05209 }
05210 return -1;
05211 case AST_CONTROL_INCOMPLETE:
05212
05213
05214
05215 case AST_CONTROL_CONGESTION:
05216 if (ast_channel_state(ast) != AST_STATE_UP) {
05217 sub->alreadygone = 1;
05218 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Congestion", s));
05219 in_band_indication(ast, l->parent->tz, "congestion");
05220 s->device->missed_call = -1;
05221 break;
05222 }
05223 return -1;
05224 case AST_CONTROL_HOLD:
05225 ast_moh_start(ast, data, NULL);
05226 break;
05227 case AST_CONTROL_UNHOLD:
05228 ast_moh_stop(ast);
05229 break;
05230 case AST_CONTROL_PROGRESS:
05231 case AST_CONTROL_SRCUPDATE:
05232 case AST_CONTROL_PROCEEDING:
05233 break;
05234 case -1:
05235 ast_playtones_stop(ast);
05236 s->device->missed_call = 0;
05237 break;
05238 case AST_CONTROL_CONNECTED_LINE:
05239 ast_log(LOG_NOTICE, "Connected party is now %s <%s>\n",
05240 S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""),
05241 S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""));
05242 if (sub->subtype == SUB_REAL) {
05243 send_callerid_screen(s, sub);
05244 }
05245 case AST_CONTROL_UPDATE_RTP_PEER:
05246 break;
05247 case AST_CONTROL_SRCCHANGE:
05248 if (sub->rtp) {
05249 ast_rtp_instance_change_source(sub->rtp);
05250 }
05251 break;
05252 default:
05253 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
05254
05255 case AST_CONTROL_PVT_CAUSE_CODE:
05256 return -1;
05257 }
05258
05259 return 0;
05260 }
05261
05262 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
05263 {
05264 struct unistim_line *l;
05265 struct unistim_device *d;
05266 struct unistim_subchannel *sub = NULL;
05267 char line[256];
05268 char *at;
05269 char *device;
05270
05271 ast_copy_string(line, dest, sizeof(line));
05272 at = strchr(line, '@');
05273 if (!at) {
05274 ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
05275 return NULL;
05276 }
05277 *at = '\0';
05278 at++;
05279 device = at;
05280 ast_mutex_lock(&devicelock);
05281 d = devices;
05282 at = strchr(device, '/');
05283 if (at) {
05284 *at = '\0';
05285 }
05286 while (d) {
05287 if (!strcasecmp(d->name, device)) {
05288 if (unistimdebug) {
05289 ast_verb(0, "Found device: %s\n", d->name);
05290 }
05291
05292 AST_LIST_LOCK(&d->lines);
05293 AST_LIST_TRAVERSE(&d->lines, l, list) {
05294
05295 if (!strcasecmp(l->name, line)) {
05296 if (unistimdebug) {
05297 ast_verb(0, "Found line: %s\n", l->name);
05298 }
05299 sub = get_sub(d, SUB_REAL);
05300 if (!sub) {
05301 sub = unistim_alloc_sub(d, SUB_REAL);
05302 }
05303 if (sub->owner) {
05304
05305 sub = unistim_alloc_sub(d, SUB_ONHOLD);
05306 }
05307 sub->ringvolume = -1;
05308 sub->ringstyle = -1;
05309 if (at) {
05310 at++;
05311 if (*at == 'r') {
05312 at++;
05313 if ((*at < '0') || (*at > '7')) {
05314 ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
05315 } else {
05316 char ring_volume = -1;
05317 char ring_style = *at - '0';
05318 at++;
05319 if ((*at >= '0') && (*at <= '3')) {
05320 ring_volume = *at - '0';
05321 }
05322 if (unistimdebug) {
05323 ast_verb(0, "Distinctive ring: style #%d volume %d\n",
05324 ring_style, ring_volume);
05325 }
05326 sub->ringvolume = ring_volume;
05327 sub->ringstyle = ring_style;
05328 }
05329 }
05330 }
05331 sub->parent = l;
05332 break;
05333 }
05334 }
05335 AST_LIST_UNLOCK(&d->lines);
05336 if (sub) {
05337 ast_mutex_unlock(&devicelock);
05338 return sub;
05339 }
05340 }
05341 d = d->next;
05342 }
05343
05344 ast_mutex_unlock(&devicelock);
05345
05346 return NULL;
05347 }
05348
05349 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
05350 {
05351 struct unistimsession *pte = channel_to_session(ast);
05352
05353 if (!pte) {
05354 return -1;
05355 }
05356 return unistim_do_senddigit(pte, digit);
05357 }
05358
05359 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
05360 {
05361 struct unistimsession *pte = channel_to_session(ast);
05362 struct ast_frame f = { 0, };
05363 struct unistim_subchannel *sub;
05364
05365 sub = get_sub(pte->device, SUB_REAL);
05366
05367 if (!sub || !sub->owner || sub->alreadygone) {
05368 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
05369 return -1;
05370 }
05371
05372 if (unistimdebug) {
05373 ast_verb(0, "Send Digit off %c\n", digit);
05374 }
05375 if (!pte) {
05376 return -1;
05377 }
05378 send_tone(pte, 0, 0);
05379 f.frametype = AST_FRAME_DTMF;
05380 f.subclass.integer = digit;
05381 f.src = "unistim";
05382 ast_queue_frame(sub->owner, &f);
05383
05384 return 0;
05385 }
05386
05387
05388
05389 static int unistim_sendtext(struct ast_channel *ast, const char *text)
05390 {
05391 struct unistimsession *pte = channel_to_session(ast);
05392 int size;
05393 char tmp[TEXT_LENGTH_MAX + 1];
05394
05395 if (unistimdebug) {
05396 ast_verb(0, "unistim_sendtext called\n");
05397 }
05398 if (!text) {
05399 ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
05400 return -1;
05401 }
05402
05403 if (!pte) {
05404 return -1;
05405 }
05406
05407 size = strlen(text);
05408 if (text[0] == '@') {
05409 int pos = 0, i = 1, tok = 0, sz = 0;
05410 char label[11];
05411 char number[16];
05412 char icon = '\0';
05413 char cur = '\0';
05414
05415 memset(label, 0, 11);
05416 memset(number, 0, 16);
05417 while (text[i]) {
05418 cur = text[i++];
05419 switch (tok) {
05420 case 0:
05421 if ((cur < '0') && (cur > '5')) {
05422 ast_log(LOG_WARNING,
05423 "sendtext failed : position must be a number beetween 0 and 5\n");
05424 return 1;
05425 }
05426 pos = cur - '0';
05427 tok = 1;
05428 continue;
05429 case 1:
05430 if (cur != '@') {
05431 ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
05432 return 1;
05433 }
05434 tok = 2;
05435 continue;
05436 case 2:
05437 if ((cur < '3') && (cur > '6')) {
05438 ast_log(LOG_WARNING,
05439 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
05440 return 1;
05441 }
05442 icon = (cur - '0') * 10;
05443 tok = 3;
05444 continue;
05445 case 3:
05446 if ((cur < '0') && (cur > '9')) {
05447 ast_log(LOG_WARNING,
05448 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
05449 return 1;
05450 }
05451 icon += (cur - '0');
05452 tok = 4;
05453 continue;
05454 case 4:
05455 if (cur != '@') {
05456 ast_log(LOG_WARNING,
05457 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
05458 return 1;
05459 }
05460 tok = 5;
05461 continue;
05462 case 5:
05463 if (cur == '@') {
05464 tok = 6;
05465 sz = 0;
05466 continue;
05467 }
05468 if (sz > 10) {
05469 continue;
05470 }
05471 label[sz] = cur;
05472 sz++;
05473 continue;
05474 case 6:
05475 if (sz > 15) {
05476 ast_log(LOG_WARNING,
05477 "sendtext failed : extension too long = %d (15 car max)\n",
05478 sz);
05479 return 1;
05480 }
05481 number[sz] = cur;
05482 sz++;
05483 continue;
05484 }
05485 }
05486 if (tok != 6) {
05487 ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
05488 return 1;
05489 }
05490 if (!pte->device) {
05491 ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
05492 return 1;
05493 }
05494 strcpy(pte->device->softkeylabel[pos], label);
05495 strcpy(pte->device->softkeynumber[pos], number);
05496 pte->device->softkeyicon[pos] = icon;
05497 send_favorite(pos, icon, pte, label);
05498 return 0;
05499 }
05500
05501 if (size <= TEXT_LENGTH_MAX * 2) {
05502 if (pte->device->height == 1) {
05503 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
05504 } else {
05505 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Message :", pte));
05506 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
05507 }
05508 if (size <= TEXT_LENGTH_MAX) {
05509 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
05510 return 0;
05511 }
05512 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
05513 tmp[sizeof(tmp) - 1] = '\0';
05514 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
05515 return 0;
05516 }
05517 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
05518 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
05519 tmp[sizeof(tmp) - 1] = '\0';
05520 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
05521 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
05522 tmp[sizeof(tmp) - 1] = '\0';
05523 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
05524 return 0;
05525 }
05526
05527
05528 static int unistim_send_mwi_to_peer(struct unistim_line *peer, unsigned int tick)
05529 {
05530 struct ast_event *event;
05531 int new;
05532 char *mailbox, *context;
05533
05534 context = mailbox = ast_strdupa(peer->mailbox);
05535 strsep(&context, "@");
05536 if (ast_strlen_zero(context)) {
05537 context = "default";
05538 }
05539 event = ast_event_get_cached(AST_EVENT_MWI,
05540 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05541 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05542 AST_EVENT_IE_END);
05543
05544 if (event) {
05545 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05546 ast_event_destroy(event);
05547 } else {
05548 new = ast_app_has_voicemail(peer->mailbox, "INBOX");
05549 }
05550 ast_debug(3, "MWI Status for mailbox %s is %d, lastmsgsent:%d\n",mailbox,new,peer->parent->lastmsgssent);
05551 peer->parent->nextmsgcheck = tick + TIMER_MWI;
05552
05553
05554 if ((peer->parent->session->state != STATE_MAINPAGE) || (new == peer->parent->lastmsgssent)) {
05555 return 0;
05556 }
05557
05558 peer->parent->lastmsgssent = new;
05559 send_led_update(peer->parent->session, (new > 0));
05560
05561 return 0;
05562 }
05563
05564
05565
05566 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
05567 {
05568 struct ast_channel *tmp;
05569 struct unistim_line *l;
05570 struct ast_format tmpfmt;
05571
05572 if (!sub) {
05573 ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
05574 return NULL;
05575 }
05576 if (!sub->parent) {
05577 ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
05578 return NULL;
05579 }
05580 l = sub->parent;
05581 tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
05582 l->parent->context, linkedid, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub);
05583 if (unistimdebug) {
05584 ast_verb(0, "unistim_new sub=%d (%p) chan=%p line=%s\n", sub->subtype, sub, tmp, l->name);
05585 }
05586 if (!tmp) {
05587 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
05588 return NULL;
05589 }
05590
05591 ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
05592 if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
05593 ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap);
05594 }
05595 ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
05596
05597 if (unistimdebug) {
05598 char tmp1[256], tmp2[256], tmp3[256];
05599 ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
05600 ast_getformatname(&tmpfmt),
05601 ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(tmp)),
05602 ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap),
05603 ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap));
05604 }
05605 if ((sub->rtp) && (sub->subtype == 0)) {
05606 if (unistimdebug) {
05607 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
05608 }
05609 ast_channel_internal_fd_set(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
05610 ast_channel_internal_fd_set(tmp, 1, ast_rtp_instance_fd(sub->rtp, 1));
05611 }
05612 if (sub->rtp) {
05613 ast_jb_configure(tmp, &global_jbconf);
05614 }
05615
05616 ast_setstate(tmp, state);
05617 if (state == AST_STATE_RING) {
05618 ast_channel_rings_set(tmp, 1);
05619 }
05620 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
05621 ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
05622 ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
05623 ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
05624 ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
05625 ast_channel_tech_pvt_set(tmp, sub);
05626 ast_channel_tech_set(tmp, &unistim_tech);
05627
05628 if (!ast_strlen_zero(l->parent->language)) {
05629 ast_channel_language_set(tmp, l->parent->language);
05630 }
05631 sub->owner = tmp;
05632 ast_update_use_count();
05633 ast_channel_callgroup_set(tmp, l->callgroup);
05634 ast_channel_pickupgroup_set(tmp, l->pickupgroup);
05635 ast_channel_call_forward_set(tmp, l->parent->call_forward);
05636 if (!ast_strlen_zero(l->cid_num)) {
05637 char *name, *loc, *instr;
05638 instr = ast_strdup(l->cid_num);
05639 if (instr) {
05640 ast_callerid_parse(instr, &name, &loc);
05641 ast_channel_caller(tmp)->id.number.valid = 1;
05642 ast_free(ast_channel_caller(tmp)->id.number.str);
05643 ast_channel_caller(tmp)->id.number.str = ast_strdup(loc);
05644 ast_channel_caller(tmp)->id.name.valid = 1;
05645 ast_free(ast_channel_caller(tmp)->id.name.str);
05646 ast_channel_caller(tmp)->id.name.str = ast_strdup(name);
05647 ast_free(instr);
05648 }
05649 }
05650 ast_channel_priority_set(tmp, 1);
05651 if (state != AST_STATE_DOWN) {
05652 if (unistimdebug) {
05653 ast_verb(0, "Starting pbx in unistim_new\n");
05654 }
05655 if (ast_pbx_start(tmp)) {
05656 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
05657 ast_hangup(tmp);
05658 tmp = NULL;
05659 }
05660 }
05661
05662 return tmp;
05663 }
05664
05665 static void *do_monitor(void *data)
05666 {
05667 struct unistimsession *cur = NULL;
05668 unsigned int dw_timeout = 0;
05669 unsigned int tick;
05670 int res;
05671 int reloading;
05672
05673
05674 if (unistimsock > -1) {
05675 ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
05676 }
05677
05678 for (;;) {
05679
05680
05681 tick = get_tick_count();
05682 dw_timeout = UINT_MAX;
05683 ast_mutex_lock(&sessionlock);
05684 cur = sessions;
05685 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
05686 while (cur) {
05687 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
05688 cur->timeout);
05689
05690 if (cur->timeout <= tick) {
05691 DEBUG_TIMER("Event for session %p\n", cur);
05692
05693 if (cur->last_buf_available == 0) {
05694 send_ping(cur);
05695 } else {
05696 if (send_retransmit(cur)) {
05697 DEBUG_TIMER("The chained link was modified, restarting...\n");
05698 cur = sessions;
05699 dw_timeout = UINT_MAX;
05700 continue;
05701 }
05702 }
05703 }
05704 if (dw_timeout > cur->timeout - tick) {
05705 dw_timeout = cur->timeout - tick;
05706 }
05707
05708 if (cur->device) {
05709 struct unistim_line *l;
05710 AST_LIST_LOCK(&cur->device->lines);
05711 AST_LIST_TRAVERSE(&cur->device->lines, l, list) {
05712 if ((!ast_strlen_zero(l->mailbox)) && (tick >= l->parent->nextmsgcheck)) {
05713 DEBUG_TIMER("Checking mailbox for MWI\n");
05714 unistim_send_mwi_to_peer(l, tick);
05715 break;
05716 }
05717 }
05718 AST_LIST_UNLOCK(&cur->device->lines);
05719 if (cur->device->nextdial && tick >= cur->device->nextdial) {
05720 handle_call_outgoing(cur);
05721 cur->device->nextdial = 0;
05722 }
05723 }
05724 cur = cur->next;
05725 }
05726 ast_mutex_unlock(&sessionlock);
05727 DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
05728 res = dw_timeout;
05729
05730 if ((res < 0) || (res > IDLE_WAIT)) {
05731 res = IDLE_WAIT;
05732 }
05733
05734 res = ast_io_wait(io, res);
05735
05736 ast_mutex_lock(&unistim_reload_lock);
05737 reloading = unistim_reloading;
05738 unistim_reloading = 0;
05739 ast_mutex_unlock(&unistim_reload_lock);
05740 if (reloading) {
05741 ast_verb(1, "Reloading unistim.conf...\n");
05742 reload_config();
05743 }
05744 pthread_testcancel();
05745 }
05746
05747 return NULL;
05748 }
05749
05750
05751 static int restart_monitor(void)
05752 {
05753 pthread_attr_t attr;
05754
05755 if (monitor_thread == AST_PTHREADT_STOP) {
05756 return 0;
05757 }
05758 if (ast_mutex_lock(&monlock)) {
05759 ast_log(LOG_WARNING, "Unable to lock monitor\n");
05760 return -1;
05761 }
05762 if (monitor_thread == pthread_self()) {
05763 ast_mutex_unlock(&monlock);
05764 ast_log(LOG_WARNING, "Cannot kill myself\n");
05765 return -1;
05766 }
05767 if (monitor_thread != AST_PTHREADT_NULL) {
05768
05769 pthread_kill(monitor_thread, SIGURG);
05770 } else {
05771 pthread_attr_init(&attr);
05772 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
05773
05774 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
05775 ast_mutex_unlock(&monlock);
05776 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
05777 return -1;
05778 }
05779 }
05780 ast_mutex_unlock(&monlock);
05781 return 0;
05782 }
05783
05784
05785
05786 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest,
05787 int *cause)
05788 {
05789 struct unistim_subchannel *sub, *sub_ring, *sub_trans;
05790 struct unistim_device *d;
05791 struct ast_channel *tmpc = NULL;
05792 char tmp[256];
05793 char tmp2[256];
05794
05795 if (!(ast_format_cap_has_joint(cap, global_cap))) {
05796 ast_log(LOG_NOTICE,
05797 "Asked to get a channel of unsupported format %s while capability is %s\n",
05798 ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap));
05799 return NULL;
05800 }
05801
05802 ast_copy_string(tmp, dest, sizeof(tmp));
05803 if (ast_strlen_zero(tmp)) {
05804 ast_log(LOG_NOTICE, "Unistim channels require a device\n");
05805 return NULL;
05806 }
05807 sub = find_subchannel_by_name(tmp);
05808 if (!sub) {
05809 ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
05810 *cause = AST_CAUSE_CONGESTION;
05811 return NULL;
05812 }
05813 d = sub->parent->parent;
05814 sub_ring = get_sub(d, SUB_RING);
05815 sub_trans = get_sub(d, SUB_THREEWAY);
05816
05817 if (!d->session) {
05818 unistim_unalloc_sub(d, sub);
05819 *cause = AST_CAUSE_CONGESTION;
05820 return NULL;
05821 }
05822 if (sub_ring || sub_trans) {
05823 if (unistimdebug) {
05824 ast_verb(0, "Can't create channel, request already in progress: Busy!\n");
05825 }
05826 unistim_unalloc_sub(d, sub);
05827 *cause = AST_CAUSE_BUSY;
05828 return NULL;
05829 }
05830 if (d->session->state == STATE_DIALPAGE) {
05831 if (unistimdebug) {
05832 ast_verb(0, "Can't create channel, user on dialpage: Busy!\n");
05833 }
05834 unistim_unalloc_sub(d, sub);
05835 *cause = AST_CAUSE_BUSY;
05836 return NULL;
05837 }
05838
05839 if (get_avail_softkey(d->session, sub->parent->name) == -1) {
05840 if (unistimdebug) {
05841 ast_verb(0, "Can't create channel for line %s, all lines busy\n", sub->parent->name);
05842 }
05843 unistim_unalloc_sub(d, sub);
05844 *cause = AST_CAUSE_BUSY;
05845 return NULL;
05846 }
05847 sub->subtype = SUB_RING;
05848 sub->softkey = -1;
05849 ast_format_cap_copy(sub->parent->cap, cap);
05850 tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
05851 if (!tmpc) {
05852 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
05853 }
05854 if (unistimdebug) {
05855 ast_verb(0, "unistim_request owner = %p\n", sub->owner);
05856 }
05857 restart_monitor();
05858
05859 return tmpc;
05860 }
05861
05862 static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05863 {
05864 struct unistim_device *device = devices;
05865 struct unistim_line *line;
05866 struct unistim_subchannel *sub;
05867 struct unistimsession *s;
05868 struct ast_channel *tmp;
05869
05870 switch (cmd) {
05871 case CLI_INIT:
05872 e->command = "unistim show info";
05873 e->usage =
05874 "Usage: unistim show info\n"
05875 " Dump internal structures.\n\n"
05876 " device\n"
05877 " ->line\n"
05878 " -->sub\n"
05879 " ==>key\n";
05880 return NULL;
05881
05882 case CLI_GENERATE:
05883 return NULL;
05884 }
05885
05886 if (a->argc != e->args) {
05887 return CLI_SHOWUSAGE;
05888 }
05889 ast_cli(a->fd, "Dumping internal structures:\n");
05890 ast_mutex_lock(&devicelock);
05891 while (device) {
05892 int i;
05893
05894 ast_cli(a->fd, "\nname=%s id=%s ha=%p sess=%p device=%p selected=%d height=%d\n",
05895 device->name, device->id, device->ha, device->session,
05896 device, device->selected, device->height);
05897 AST_LIST_LOCK(&device->lines);
05898 AST_LIST_TRAVERSE(&device->lines,line,list) {
05899 char tmp2[256];
05900 ast_cli(a->fd,
05901 "->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n",
05902 line->name, line->fullname, line->exten, line->cid_num,
05903 ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line);
05904 }
05905 AST_LIST_UNLOCK(&device->lines);
05906
05907 AST_LIST_LOCK(&device->subs);
05908 AST_LIST_TRAVERSE(&device->subs, sub, list) {
05909 if (!sub) {
05910 continue;
05911 }
05912 if (!sub->owner) {
05913 tmp = (void *) -42;
05914 } else {
05915 tmp = ast_channel_internal_bridged_channel(sub->owner);
05916 }
05917 ast_cli(a->fd,
05918 "-->subtype=%s chan=%p rtp=%p bridge=%p line=%p alreadygone=%d softkey=%d\n",
05919 subtype_tostr(sub->subtype), sub->owner, sub->rtp, tmp, sub->parent,
05920 sub->alreadygone, sub->softkey);
05921 }
05922 AST_LIST_UNLOCK(&device->subs);
05923
05924 for (i = 0; i < FAVNUM; i++) {
05925 if (!soft_key_visible(device, i)) {
05926 continue;
05927 }
05928 ast_cli(a->fd, "==> %d. dev=%s icon=%#-4x label=%-10s number=%-5s sub=%p line=%p\n",
05929 i, device->softkeydevice[i], device->softkeyicon[i], device->softkeylabel[i], device->softkeynumber[i],
05930 device->ssub[i], device->sline[i]);
05931 }
05932 device = device->next;
05933 }
05934 ast_mutex_unlock(&devicelock);
05935 ast_cli(a->fd, "\nSessions:\n");
05936 ast_mutex_lock(&sessionlock);
05937 s = sessions;
05938 while (s) {
05939 ast_cli(a->fd,
05940 "sin=%s timeout=%u state=%s macaddr=%s device=%p session=%p\n",
05941 ast_inet_ntoa(s->sin.sin_addr), s->timeout, ptestate_tostr(s->state), s->macaddr,
05942 s->device, s);
05943 s = s->next;
05944 }
05945 ast_mutex_unlock(&sessionlock);
05946
05947 return CLI_SUCCESS;
05948 }
05949
05950 static char *unistim_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05951 {
05952 struct unistim_device *device = devices;
05953
05954 switch (cmd) {
05955 case CLI_INIT:
05956 e->command = "unistim show devices";
05957 e->usage =
05958 "Usage: unistim show devices\n"
05959 " Lists all known Unistim devices.\n";
05960 return NULL;
05961 case CLI_GENERATE:
05962 return NULL;
05963 }
05964
05965 if (a->argc != e->args)
05966 return CLI_SHOWUSAGE;
05967
05968 ast_cli(a->fd, "%-20.20s %-20.20s %-15.15s %s\n", "Name/username", "MAC", "Host", "Status");
05969 ast_mutex_lock(&devicelock);
05970 while (device) {
05971 ast_cli(a->fd, "%-20.20s %-20.20s %-15.15s %s\n",
05972 device->name, device->id,
05973 (!device->session) ? "(Unspecified)" : ast_inet_ntoa(device->session->sin.sin_addr),
05974 (!device->session) ? "UNKNOWN" : "OK");
05975 device = device->next;
05976 }
05977 ast_mutex_unlock(&devicelock);
05978
05979 return CLI_SUCCESS;
05980 }
05981
05982 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05983 {
05984 BUFFSEND;
05985 struct unistim_subchannel *sub;
05986 int i, j = 0, len;
05987 unsigned char c, cc;
05988 char tmp[256];
05989
05990 switch (cmd) {
05991 case CLI_INIT:
05992 e->command = "unistim send packet";
05993 e->usage =
05994 "Usage: unistim send packet USTM/line@name hexa\n"
05995 " unistim send packet USTM/1000@hans 19040004\n";
05996 return NULL;
05997
05998 case CLI_GENERATE:
05999 return NULL;
06000 }
06001
06002 if (a->argc < 5) {
06003 return CLI_SHOWUSAGE;
06004 }
06005 if (strlen(a->argv[3]) < 9) {
06006 return CLI_SHOWUSAGE;
06007 }
06008 len = strlen(a->argv[4]);
06009 if (len % 2) {
06010 return CLI_SHOWUSAGE;
06011 }
06012 ast_copy_string(tmp, a->argv[3] + 5, sizeof(tmp));
06013 sub = find_subchannel_by_name(tmp);
06014 if (!sub) {
06015 ast_cli(a->fd, "Can't find '%s'\n", tmp);
06016 return CLI_SUCCESS;
06017 }
06018 if (!sub->parent->parent->session) {
06019 ast_cli(a->fd, "'%s' is not connected\n", tmp);
06020 return CLI_SUCCESS;
06021 }
06022 ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->parent->parent->session);
06023 for (i = 0; i < len; i++) {
06024 c = a->argv[4][i];
06025 if (c >= 'a') {
06026 c -= 'a' - 10;
06027 } else {
06028 c -= '0';
06029 }
06030 i++;
06031 cc = a->argv[4][i];
06032 if (cc >= 'a') {
06033 cc -= 'a' - 10;
06034 } else {
06035 cc -= '0';
06036 }
06037 tmp[j++] = (c << 4) | cc;
06038 }
06039 memcpy(buffsend + SIZE_HEADER, tmp, j);
06040 send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
06041 return CLI_SUCCESS;
06042 }
06043
06044 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06045 {
06046 switch (cmd) {
06047 case CLI_INIT:
06048 e->command = "unistim set debug {on|off}";
06049 e->usage =
06050 "Usage: unistim set debug\n"
06051 " Display debug messages.\n";
06052 return NULL;
06053
06054 case CLI_GENERATE:
06055 return NULL;
06056 }
06057
06058 if (a->argc != e->args) {
06059 return CLI_SHOWUSAGE;
06060 }
06061 if (!strcasecmp(a->argv[3], "on")) {
06062 unistimdebug = 1;
06063 ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
06064 } else if (!strcasecmp(a->argv[3], "off")) {
06065 unistimdebug = 0;
06066 ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
06067 } else {
06068 return CLI_SHOWUSAGE;
06069 }
06070 return CLI_SUCCESS;
06071 }
06072
06073
06074
06075
06076
06077 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06078 {
06079 switch (cmd) {
06080 case CLI_INIT:
06081 e->command = "unistim reload";
06082 e->usage =
06083 "Usage: unistim reload\n"
06084 " Reloads UNISTIM configuration from unistim.conf\n";
06085 return NULL;
06086
06087 case CLI_GENERATE:
06088 return NULL;
06089 }
06090
06091 if (e && a && a->argc != e->args) {
06092 return CLI_SHOWUSAGE;
06093 }
06094 reload();
06095
06096 return CLI_SUCCESS;
06097 }
06098
06099 static struct ast_cli_entry unistim_cli[] = {
06100 AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
06101 AST_CLI_DEFINE(unistim_show_info, "Show UNISTIM info"),
06102 AST_CLI_DEFINE(unistim_show_devices, "Show UNISTIM devices"),
06103 AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
06104 AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
06105 };
06106
06107 static void unquote(char *out, const char *src, int maxlen)
06108 {
06109 int len = strlen(src);
06110 if (!len) {
06111 return;
06112 }
06113 if ((len > 1) && src[0] == '\"') {
06114
06115 src++;
06116
06117 len--;
06118 if (maxlen > len - 1) {
06119 maxlen = len - 1;
06120 }
06121 memcpy(out, src, maxlen);
06122 ((char *) out)[maxlen] = '\0';
06123 } else {
06124 memcpy(out, src, maxlen);
06125 }
06126 return;
06127 }
06128
06129 static int parse_bookmark(const char *text, struct unistim_device *d)
06130 {
06131 char line[256];
06132 char *at;
06133 char *number;
06134 char *icon;
06135 int p;
06136 int len = strlen(text);
06137
06138 ast_copy_string(line, text, sizeof(line));
06139
06140 if ((len > 2) && (line[1] == '@')) {
06141 p = line[0];
06142 if ((p >= '0') && (p <= '5')) {
06143 p -= '0';
06144 } else {
06145 ast_log(LOG_WARNING,
06146 "Invalid position for bookmark : must be between 0 and 5\n");
06147 return 0;
06148 }
06149 if (d->softkeyicon[p] != 0) {
06150 ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used:\n", p);
06151 return 0;
06152 }
06153 memmove(line, line + 2, sizeof(line) - 2);
06154 } else {
06155
06156 for (p = 0; p <= 5; p++) {
06157 if (!d->softkeyicon[p]) {
06158 break;
06159 }
06160 }
06161 if (p > 5) {
06162 ast_log(LOG_WARNING, "No more free bookmark position\n");
06163 return 0;
06164 }
06165 }
06166 at = strchr(line, '@');
06167 if (!at) {
06168 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
06169 return 0;
06170 }
06171 *at = '\0';
06172 at++;
06173 number = at;
06174 at = strchr(at, '@');
06175 if (ast_strlen_zero(number)) {
06176 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
06177 return 0;
06178 }
06179 if (ast_strlen_zero(line)) {
06180 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
06181 return 0;
06182 }
06183
06184 at = strchr(number, '@');
06185 if (!at) {
06186 d->softkeyicon[p] = FAV_ICON_SHARP;
06187 } else {
06188 *at = '\0';
06189 at++;
06190 icon = at;
06191 if (ast_strlen_zero(icon)) {
06192 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
06193 return 0;
06194 }
06195 if (strncmp(icon, "USTM/", 5)) {
06196 d->softkeyicon[p] = atoi(icon);
06197 } else {
06198 d->softkeyicon[p] = 1;
06199 ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
06200 }
06201 }
06202 ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
06203 ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
06204 if (unistimdebug) {
06205 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%#x\n",
06206 p, d->softkeylabel[p], d->softkeynumber[p], d->softkeyicon[p]);
06207 }
06208 return 1;
06209 }
06210
06211
06212 static void finish_bookmark(void)
06213 {
06214 struct unistim_device *d = devices;
06215 int i;
06216 ast_mutex_lock(&devicelock);
06217 while (d) {
06218 for (i = 0; i < 6; i++) {
06219 if (d->softkeyicon[i] == 1) {
06220 struct unistim_device *d2 = devices;
06221 while (d2) {
06222 if (!strcmp(d->softkeydevice[i], d2->name)) {
06223 d->sp[i] = d2;
06224 d->softkeyicon[i] = 0;
06225 break;
06226 }
06227 d2 = d2->next;
06228 }
06229 if (d->sp[i] == NULL) {
06230 ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
06231 d->softkeydevice[i]);
06232 }
06233 }
06234 }
06235 d = d->next;
06236 }
06237 ast_mutex_unlock(&devicelock);
06238 }
06239
06240 static struct unistim_line *find_line_by_number(struct unistim_device *d, const char *val) {
06241 struct unistim_line *l, *ret = NULL;
06242
06243 AST_LIST_LOCK(&d->lines);
06244 AST_LIST_TRAVERSE(&d->lines, l, list) {
06245 if (!strcmp(l->name, val)) {
06246 ret = l;
06247 break;
06248 }
06249 }
06250 AST_LIST_UNLOCK(&d->lines);
06251 return ret;
06252 }
06253
06254 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
06255 {
06256 struct unistim_device *d;
06257 struct unistim_line *l = NULL, *lt = NULL;
06258 int create = 1;
06259 int nbsoftkey, dateformat, timeformat, callhistory, sharpdial, linecnt;
06260 char linelabel[AST_MAX_EXTENSION];
06261 char ringvolume, ringstyle, cwvolume, cwstyle;
06262
06263
06264
06265 ast_mutex_lock(&devicelock);
06266 d = devices;
06267 while (d) {
06268 if (!strcmp(d->name, cat)) {
06269
06270 if (unistimsock < 0) {
06271
06272 ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
06273 ast_mutex_unlock(&devicelock);
06274 return NULL;
06275 }
06276
06277 create = 0;
06278 break;
06279 }
06280 d = d->next;
06281 }
06282 if (!(lt = ast_calloc(1, sizeof(*lt)))) {
06283 return NULL;
06284 }
06285 ast_mutex_unlock(&devicelock);
06286 if (create) {
06287 if (!(d = ast_calloc(1, sizeof(*d)))) {
06288 return NULL;
06289 }
06290 ast_mutex_init(&d->lock);
06291 ast_copy_string(d->name, cat, sizeof(d->name));
06292 d->contrast = -1;
06293 d->output = OUTPUT_HANDSET;
06294 d->previous_output = OUTPUT_HANDSET;
06295 d->volume = VOLUME_LOW;
06296 d->mute = MUTE_OFF;
06297 d->height = DEFAULTHEIGHT;
06298 d->selected = -1;
06299 } else {
06300
06301 AST_LIST_LOCK(&d->lines);
06302 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06303 AST_LIST_REMOVE_CURRENT(list);
06304 unistim_line_destroy(l);
06305 }
06306 AST_LIST_TRAVERSE_SAFE_END
06307 AST_LIST_UNLOCK(&d->lines);
06308
06309
06310 memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
06311 memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
06312 memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
06313 memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
06314 memset(d->ssub, 0, sizeof(d->ssub));
06315 memset(d->sline, 0, sizeof(d->sline));
06316 memset(d->sp, 0, sizeof(d->sp));
06317 }
06318 ast_copy_string(d->context, DEFAULTCONTEXT, sizeof(d->context));
06319 d->selected = -1;
06320 d->interdigit_timer = DEFAULT_INTERDIGIT_TIMER;
06321 linelabel[0] = '\0';
06322 dateformat = 1;
06323 timeformat = 1;
06324 ringvolume = 2;
06325 cwvolume = 1;
06326 callhistory = 1;
06327 sharpdial = 0;
06328 ringstyle = 3;
06329 cwstyle = 2;
06330 nbsoftkey = 0;
06331 linecnt = 0;
06332 while (v) {
06333 if (!strcasecmp(v->name, "rtp_port")) {
06334 d->rtp_port = atoi(v->value);
06335 } else if (!strcasecmp(v->name, "rtp_method")) {
06336 d->rtp_method = atoi(v->value);
06337 } else if (!strcasecmp(v->name, "status_method")) {
06338 d->status_method = atoi(v->value);
06339 } else if (!strcasecmp(v->name, "device")) {
06340 ast_copy_string(d->id, v->value, sizeof(d->id));
06341 } else if (!strcasecmp(v->name, "tn")) {
06342 ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
06343 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06344 d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
06345 } else if (!strcasecmp(v->name, "context")) {
06346 ast_copy_string(d->context, v->value, sizeof(d->context));
06347 } else if (!strcasecmp(v->name, "maintext0")) {
06348 unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
06349 } else if (!strcasecmp(v->name, "maintext1")) {
06350 unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
06351 } else if (!strcasecmp(v->name, "maintext2")) {
06352 unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
06353 } else if (!strcasecmp(v->name, "titledefault")) {
06354 unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
06355 } else if (!strcasecmp(v->name, "dateformat")) {
06356 dateformat = atoi(v->value);
06357 } else if (!strcasecmp(v->name, "timeformat")) {
06358 timeformat = atoi(v->value);
06359 } else if (!strcasecmp(v->name, "contrast")) {
06360 d->contrast = atoi(v->value);
06361 if ((d->contrast < 0) || (d->contrast > 15)) {
06362 ast_log(LOG_WARNING, "contrast must be beetween 0 and 15\n");
06363 d->contrast = 8;
06364 }
06365 } else if (!strcasecmp(v->name, "nat")) {
06366 d->nat = ast_true(v->value);
06367 } else if (!strcasecmp(v->name, "ringvolume")) {
06368 ringvolume = atoi(v->value);
06369 } else if (!strcasecmp(v->name, "ringstyle")) {
06370 ringstyle = atoi(v->value);
06371 } else if (!strcasecmp(v->name, "cwvolume")) {
06372 cwvolume = atoi(v->value);
06373 } else if (!strcasecmp(v->name, "cwstyle")) {
06374 cwstyle = atoi(v->value);
06375 } else if (!strcasecmp(v->name, "callhistory")) {
06376 callhistory = atoi(v->value);
06377 } else if (!strcasecmp(v->name, "sharpdial")) {
06378 sharpdial = ast_true(v->value) ? 1 : 0;
06379 } else if (!strcasecmp(v->name, "interdigit_timer")) {
06380 d->interdigit_timer = atoi(v->value);
06381 } else if (!strcasecmp(v->name, "callerid")) {
06382 if (!strcasecmp(v->value, "asreceived")) {
06383 lt->cid_num[0] = '\0';
06384 } else {
06385 ast_copy_string(lt->cid_num, v->value, sizeof(lt->cid_num));
06386 }
06387 } else if (!strcasecmp(v->name, "language")) {
06388 ast_copy_string(d->language, v->value, sizeof(d->language));
06389 } else if (!strcasecmp(v->name, "country")) {
06390 ast_copy_string(d->country, v->value, sizeof(d->country));
06391 } else if (!strcasecmp(v->name, "accountcode")) {
06392 ast_copy_string(lt->accountcode, v->value, sizeof(lt->accountcode));
06393 } else if (!strcasecmp(v->name, "amaflags")) {
06394 int y;
06395 y = ast_cdr_amaflags2int(v->value);
06396 if (y < 0) {
06397 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
06398 v->lineno);
06399 } else {
06400 lt->amaflags = y;
06401 }
06402 } else if (!strcasecmp(v->name, "musiconhold")) {
06403 ast_copy_string(lt->musicclass, v->value, sizeof(lt->musicclass));
06404 } else if (!strcasecmp(v->name, "callgroup")) {
06405 lt->callgroup = ast_get_group(v->value);
06406 } else if (!strcasecmp(v->name, "pickupgroup")) {
06407 lt->pickupgroup = ast_get_group(v->value);
06408 } else if (!strcasecmp(v->name, "mailbox")) {
06409 ast_copy_string(lt->mailbox, v->value, sizeof(lt->mailbox));
06410 } else if (!strcasecmp(v->name, "parkinglot")) {
06411 ast_copy_string(lt->parkinglot, v->value, sizeof(lt->parkinglot));
06412 } else if (!strcasecmp(v->name, "linelabel")) {
06413 unquote(linelabel, v->value, sizeof(linelabel) - 1);
06414 } else if (!strcasecmp(v->name, "extension")) {
06415 if (!strcasecmp(v->value, "none")) {
06416 d->extension = EXTENSION_NONE;
06417 } else if (!strcasecmp(v->value, "ask")) {
06418 d->extension = EXTENSION_ASK;
06419 } else if (!strcasecmp(v->value, "line")) {
06420 d->extension = EXTENSION_LINE;
06421 } else {
06422 ast_log(LOG_WARNING, "Unknown extension option.\n");
06423 }
06424 } else if (!strcasecmp(v->name, "bookmark")) {
06425 if (nbsoftkey > 5) {
06426 ast_log(LOG_WARNING,
06427 "More than 6 softkeys defined. Ignoring new entries.\n");
06428 } else {
06429 if (parse_bookmark(v->value, d)) {
06430 nbsoftkey++;
06431 }
06432 }
06433 } else if (!strcasecmp(v->name, "line")) {
06434 int len = strlen(linelabel);
06435 int create_line = 0;
06436
06437 l = find_line_by_number(d, v->value);
06438 if (!l) {
06439 if (!(l = unistim_line_alloc())) {
06440 ast_free(d);
06441 ast_free(lt);
06442 return NULL;
06443 }
06444 lt->cap = l->cap;
06445 memcpy(l, lt, sizeof(*l));
06446 ast_mutex_init(&l->lock);
06447 create_line = 1;
06448 }
06449 d->to_delete = 0;
06450
06451
06452 d->sline[nbsoftkey] = l;
06453 d->softkeyicon[nbsoftkey] = FAV_LINE_ICON;
06454 if (!len) {
06455 ast_copy_string(d->softkeylabel[nbsoftkey], v->value, sizeof(d->softkeylabel[nbsoftkey]));
06456 } else {
06457 int softkeylinepos = 0;
06458 if ((len > 2) && (linelabel[1] == '@')) {
06459 softkeylinepos = linelabel[0];
06460 if ((softkeylinepos >= '0') && (softkeylinepos <= '5')) {
06461 softkeylinepos -= '0';
06462 d->softkeyicon[nbsoftkey] = FAV_ICON_NONE;
06463 } else {
06464 ast_log(LOG_WARNING,
06465 "Invalid position for linelabel : must be between 0 and 5\n");
06466 }
06467 ast_copy_string(d->softkeylabel[softkeylinepos], linelabel + 2,
06468 sizeof(d->softkeylabel[softkeylinepos]));
06469 d->softkeyicon[softkeylinepos] = FAV_LINE_ICON;
06470 } else {
06471 ast_copy_string(d->softkeylabel[nbsoftkey], linelabel,
06472 sizeof(d->softkeylabel[nbsoftkey]));
06473 }
06474 }
06475 nbsoftkey++;
06476
06477 if (create_line) {
06478 ast_copy_string(l->name, v->value, sizeof(l->name));
06479 snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
06480 if (!ast_strlen_zero(l->mailbox)) {
06481 if (unistimdebug) {
06482 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
06483 }
06484 }
06485 ast_format_cap_copy(l->cap, global_cap);
06486 l->parent = d;
06487 linecnt++;
06488 AST_LIST_LOCK(&d->lines);
06489 AST_LIST_INSERT_TAIL(&d->lines, l, list);
06490 AST_LIST_UNLOCK(&d->lines);
06491 }
06492 } else if (!strcasecmp(v->name, "height")) {
06493
06494
06495 d->height = atoi(v->value);
06496 } else
06497 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
06498 v->lineno);
06499 v = v->next;
06500 }
06501 ast_free(lt);
06502 if (linecnt == 0) {
06503 ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
06504 ast_free(d);
06505 return NULL;
06506 }
06507 d->ringvolume = ringvolume;
06508 d->ringstyle = ringstyle;
06509 d->cwvolume = cwvolume;
06510 d->cwstyle = cwstyle;
06511 d->callhistory = callhistory;
06512 d->sharp_dial = sharpdial;
06513 d->tz = ast_get_indication_zone(d->country);
06514 if ((d->tz == NULL) && !ast_strlen_zero(d->country)) {
06515 ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
06516 d->country);
06517 }
06518 d->datetimeformat = 56 + (dateformat * 4);
06519 d->datetimeformat += timeformat;
06520 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
06521 (!ast_strlen_zero(d->extension_number))) {
06522 d->extension = EXTENSION_TN;
06523 if (!ast_strlen_zero(d->id)) {
06524 ast_log(LOG_WARNING,
06525 "tn= and device= can't be used together. Ignoring device= entry\n");
06526 }
06527 d->id[0] = 'T';
06528 ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
06529 d->extension_number[0] = '\0';
06530 } else if (ast_strlen_zero(d->id)) {
06531 if (strcmp(d->name, "template")) {
06532 ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
06533 if (d->tz) {
06534 d->tz = ast_tone_zone_unref(d->tz);
06535 }
06536 ast_free(d);
06537 return NULL;
06538 } else {
06539 strcpy(d->id, "000000000000");
06540 }
06541 }
06542 if (!d->rtp_port) {
06543 d->rtp_port = 10000;
06544 }
06545 if (d->contrast == -1) {
06546 d->contrast = 8;
06547 }
06548 if (ast_strlen_zero(d->maintext1)) {
06549 strcpy(d->maintext1, d->name);
06550 }
06551 if (ast_strlen_zero(d->titledefault)) {
06552 struct ast_tm tm = { 0, };
06553 struct timeval cur_time = ast_tvnow();
06554
06555 if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
06556 ast_log(LOG_WARNING, "Error in ast_localtime()\n");
06557 ast_copy_string(d->titledefault, "UNISTIM for*", 12);
06558 } else {
06559 if (strlen(tm.tm_zone) < 4) {
06560 strcpy(d->titledefault, "TimeZone ");
06561 strcat(d->titledefault, tm.tm_zone);
06562 } else if (strlen(tm.tm_zone) < 9) {
06563 strcpy(d->titledefault, "TZ ");
06564 strcat(d->titledefault, tm.tm_zone);
06565 } else {
06566 ast_copy_string(d->titledefault, tm.tm_zone, 12);
06567 }
06568 }
06569 }
06570
06571 if (create) {
06572 ast_mutex_lock(&devicelock);
06573 d->next = devices;
06574 devices = d;
06575 ast_mutex_unlock(&devicelock);
06576 ast_verb(3, "Added device '%s'\n", d->name);
06577 } else {
06578 ast_verb(3, "Device '%s' reloaded\n", d->name);
06579 }
06580 return d;
06581 }
06582
06583
06584 static int reload_config(void)
06585 {
06586 struct ast_config *cfg;
06587 struct ast_variable *v;
06588 struct ast_hostent ahp;
06589 struct hostent *hp;
06590 struct sockaddr_in bindaddr = { 0, };
06591 char *config = "unistim.conf";
06592 char *cat;
06593 struct unistim_device *d;
06594 const int reuseFlag = 1;
06595 struct unistimsession *s;
06596 struct ast_flags config_flags = { 0, };
06597
06598 cfg = ast_config_load(config, config_flags);
06599
06600 if (!cfg) {
06601 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
06602 return -1;
06603 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
06604 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
06605 return -1;
06606 }
06607
06608
06609 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
06610
06611 unistim_keepalive = 120;
06612 unistim_port = 0;
06613 v = ast_variable_browse(cfg, "general");
06614 while (v) {
06615
06616 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06617 continue;
06618 }
06619 if (!strcasecmp(v->name, "keepalive")) {
06620 unistim_keepalive = atoi(v->value);
06621 } else if (!strcasecmp(v->name, "port")) {
06622 unistim_port = atoi(v->value);
06623 } else if (!strcasecmp(v->name, "tos")) {
06624 if (ast_str2tos(v->value, &qos.tos)) {
06625 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06626 }
06627 } else if (!strcasecmp(v->name, "tos_audio")) {
06628 if (ast_str2tos(v->value, &qos.tos_audio)) {
06629 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06630 }
06631 } else if (!strcasecmp(v->name, "cos")) {
06632 if (ast_str2cos(v->value, &qos.cos)) {
06633 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06634 }
06635 } else if (!strcasecmp(v->name, "cos_audio")) {
06636 if (ast_str2cos(v->value, &qos.cos_audio)) {
06637 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06638 }
06639 } else if (!strcasecmp(v->name, "debug")) {
06640 if (!strcasecmp(v->value, "no")) {
06641 unistimdebug = 0;
06642 } else if (!strcasecmp(v->value, "yes")) {
06643 unistimdebug = 1;
06644 }
06645 } else if (!strcasecmp(v->name, "autoprovisioning")) {
06646 if (!strcasecmp(v->value, "no")) {
06647 autoprovisioning = AUTOPROVISIONING_NO;
06648 } else if (!strcasecmp(v->value, "yes")) {
06649 autoprovisioning = AUTOPROVISIONING_YES;
06650 } else if (!strcasecmp(v->value, "tn")) {
06651 autoprovisioning = AUTOPROVISIONING_TN;
06652 } else {
06653 ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
06654 }
06655 } else if (!strcasecmp(v->name, "public_ip")) {
06656 if (!ast_strlen_zero(v->value)) {
06657 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06658 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06659 } else {
06660 memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
06661 public_ip.sin_family = AF_INET;
06662 }
06663 }
06664 }
06665 v = v->next;
06666 }
06667 if ((unistim_keepalive < 10) ||
06668 (unistim_keepalive >
06669 255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
06670 ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
06671 ast_config_destroy(cfg);
06672 return -1;
06673 }
06674 packet_send_ping[4] =
06675 unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
06676 if ((unistim_port < 1) || (unistim_port > 65535)) {
06677 ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
06678 ast_config_destroy(cfg);
06679 return -1;
06680 }
06681 unistim_keepalive *= 1000;
06682
06683 ast_mutex_lock(&devicelock);
06684 d = devices;
06685 while (d) {
06686 if (d->to_delete >= 0) {
06687 d->to_delete = 1;
06688 }
06689 d = d->next;
06690 }
06691 ast_mutex_unlock(&devicelock);
06692
06693 cat = ast_category_browse(cfg, NULL);
06694 while (cat) {
06695 if (strcasecmp(cat, "general")) {
06696 d = build_device(cat, ast_variable_browse(cfg, cat));
06697 }
06698 cat = ast_category_browse(cfg, cat);
06699 }
06700 ast_mutex_lock(&devicelock);
06701 d = devices;
06702 while (d) {
06703 if (d->to_delete) {
06704 struct unistim_line *l;
06705 struct unistim_subchannel *sub;
06706
06707 if (unistimdebug) {
06708 ast_verb(0, "Removing device '%s'\n", d->name);
06709 }
06710 AST_LIST_LOCK(&d->subs);
06711 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, sub, list){
06712 if (sub->subtype == SUB_REAL) {
06713 if (!sub) {
06714 ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
06715 d->name);
06716 ast_config_destroy(cfg);
06717 return 0;
06718 }
06719 if (sub->owner) {
06720 ast_log(LOG_WARNING,
06721 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
06722 d->name);
06723 d = d->next;
06724 continue;
06725 }
06726 }
06727 if (sub->subtype == SUB_THREEWAY) {
06728 ast_log(LOG_WARNING,
06729 "Device '%s' with threeway call subchannels allocated, aborting.\n",
06730 d->name);
06731 break;
06732 }
06733 AST_LIST_REMOVE_CURRENT(list);
06734 ast_mutex_destroy(&sub->lock);
06735 ast_free(sub);
06736 }
06737 AST_LIST_TRAVERSE_SAFE_END
06738 AST_LIST_UNLOCK(&d->subs);
06739
06740
06741 AST_LIST_LOCK(&d->lines);
06742 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06743 AST_LIST_REMOVE_CURRENT(list);
06744 ast_mutex_destroy(&l->lock);
06745 unistim_line_destroy(l);
06746 }
06747 AST_LIST_TRAVERSE_SAFE_END
06748 AST_LIST_UNLOCK(&d->lines);
06749
06750 if (d->session) {
06751 if (sessions == d->session) {
06752 sessions = d->session->next;
06753 } else {
06754 s = sessions;
06755 while (s) {
06756 if (s->next == d->session) {
06757 s->next = d->session->next;
06758 break;
06759 }
06760 s = s->next;
06761 }
06762 }
06763 ast_mutex_destroy(&d->session->lock);
06764 ast_free(d->session);
06765 }
06766 if (devices == d) {
06767 devices = d->next;
06768 } else {
06769 struct unistim_device *d2 = devices;
06770 while (d2) {
06771 if (d2->next == d) {
06772 d2->next = d->next;
06773 break;
06774 }
06775 d2 = d2->next;
06776 }
06777 }
06778 if (d->tz) {
06779 d->tz = ast_tone_zone_unref(d->tz);
06780 }
06781 ast_mutex_destroy(&d->lock);
06782 ast_free(d);
06783 d = devices;
06784 continue;
06785 }
06786 d = d->next;
06787 }
06788 finish_bookmark();
06789 ast_mutex_unlock(&devicelock);
06790 ast_config_destroy(cfg);
06791 ast_mutex_lock(&sessionlock);
06792 s = sessions;
06793 while (s) {
06794 if (s->device) {
06795 refresh_all_favorite(s);
06796 if (ast_strlen_zero(s->device->language)) {
06797 struct unistim_languages lang;
06798 lang = options_languages[find_language(s->device->language)];
06799 send_charset_update(s, lang.encoding);
06800 }
06801 }
06802 s = s->next;
06803 }
06804 ast_mutex_unlock(&sessionlock);
06805
06806 if (unistimsock > -1) {
06807 return 0;
06808 }
06809 bindaddr.sin_addr.s_addr = INADDR_ANY;
06810 bindaddr.sin_port = htons(unistim_port);
06811 bindaddr.sin_family = AF_INET;
06812 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
06813 if (unistimsock < 0) {
06814 ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
06815 return -1;
06816 }
06817 #ifdef HAVE_PKTINFO
06818 {
06819 const int pktinfoFlag = 1;
06820 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
06821 sizeof(pktinfoFlag));
06822 }
06823 #else
06824 if (public_ip.sin_family == 0) {
06825 ast_log(LOG_WARNING,
06826 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
06827 unistimsock = -1;
06828 return -1;
06829 }
06830 #endif
06831 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
06832 sizeof(reuseFlag));
06833 if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
06834 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
06835 ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
06836 strerror(errno));
06837 close(unistimsock);
06838 unistimsock = -1;
06839 } else {
06840 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
06841 ast_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
06842 }
06843 return 0;
06844 }
06845
06846 static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
06847 {
06848 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
06849
06850 if (!sub) {
06851 return AST_RTP_GLUE_RESULT_FORBID;
06852 }
06853 if (!sub->rtp) {
06854 return AST_RTP_GLUE_RESULT_FORBID;
06855 }
06856
06857 ao2_ref(sub->rtp, +1);
06858 *instance = sub->rtp;
06859
06860 return AST_RTP_GLUE_RESULT_LOCAL;
06861 }
06862
06863 static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance *rtp, struct ast_rtp_instance *vrtp, struct ast_rtp_instance *trtp, const struct ast_format_cap *codecs, int nat_active)
06864 {
06865 struct unistim_subchannel *sub;
06866 struct sockaddr_in them = { 0, };
06867 struct sockaddr_in us = { 0, };
06868
06869 if (!rtp) {
06870 return 0;
06871 }
06872
06873 sub = ast_channel_tech_pvt(chan);
06874 if (!sub) {
06875 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
06876 return -1;
06877 }
06878 {
06879 struct ast_sockaddr tmp;
06880 ast_rtp_instance_get_remote_address(rtp, &tmp);
06881 ast_sockaddr_to_sin(&tmp, &them);
06882 ast_rtp_instance_get_local_address(rtp, &tmp);
06883 ast_sockaddr_to_sin(&tmp, &us);
06884 }
06885
06886
06887
06888 return 0;
06889 }
06890
06891 static struct ast_rtp_glue unistim_rtp_glue = {
06892 .type = channel_type,
06893 .get_rtp_info = unistim_get_rtp_peer,
06894 .update_peer = unistim_set_rtp_peer,
06895 };
06896
06897
06898 int load_module(void)
06899 {
06900 int res;
06901 struct ast_format tmpfmt;
06902 if (!(global_cap = ast_format_cap_alloc())) {
06903 goto buff_failed;
06904 }
06905 if (!(unistim_tech.capabilities = ast_format_cap_alloc())) {
06906 goto buff_failed;
06907 }
06908
06909 ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
06910 ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
06911 ast_format_cap_copy(unistim_tech.capabilities, global_cap);
06912 if (!(buff = ast_malloc(SIZE_PAGE))) {
06913 goto buff_failed;
06914 }
06915
06916 io = io_context_create();
06917 if (!io) {
06918 ast_log(LOG_ERROR, "Failed to allocate IO context\n");
06919 goto io_failed;
06920 }
06921
06922 sched = ast_sched_context_create();
06923 if (!sched) {
06924 ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
06925 goto sched_failed;
06926 }
06927
06928 res = reload_config();
06929 if (res) {
06930 return AST_MODULE_LOAD_DECLINE;
06931 }
06932
06933 if (ast_channel_register(&unistim_tech)) {
06934 ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
06935 goto chanreg_failed;
06936 }
06937
06938 ast_rtp_glue_register(&unistim_rtp_glue);
06939
06940 ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
06941
06942 restart_monitor();
06943
06944 return AST_MODULE_LOAD_SUCCESS;
06945
06946 chanreg_failed:
06947
06948 ast_sched_context_destroy(sched);
06949 sched = NULL;
06950 sched_failed:
06951 io_context_destroy(io);
06952 io = NULL;
06953 io_failed:
06954 ast_free(buff);
06955 buff = NULL;
06956 global_cap = ast_format_cap_destroy(global_cap);
06957 unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
06958 buff_failed:
06959 return AST_MODULE_LOAD_FAILURE;
06960 }
06961
06962 static int unload_module(void)
06963 {
06964
06965 if (sched) {
06966 ast_sched_context_destroy(sched);
06967 }
06968
06969 ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
06970
06971 ast_channel_unregister(&unistim_tech);
06972 ast_rtp_glue_unregister(&unistim_rtp_glue);
06973
06974 ast_mutex_lock(&monlock);
06975 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
06976 pthread_cancel(monitor_thread);
06977 pthread_kill(monitor_thread, SIGURG);
06978 pthread_join(monitor_thread, NULL);
06979 }
06980 monitor_thread = AST_PTHREADT_STOP;
06981 ast_mutex_unlock(&monlock);
06982
06983 if (buff) {
06984 ast_free(buff);
06985 }
06986 if (unistimsock > -1) {
06987 close(unistimsock);
06988 }
06989 global_cap = ast_format_cap_destroy(global_cap);
06990 unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
06991
06992 return 0;
06993 }
06994
06995
06996 int reload(void)
06997 {
06998 if (unistimdebug) {
06999 ast_verb(0, "reload unistim\n");
07000 }
07001 ast_mutex_lock(&unistim_reload_lock);
07002 if (!unistim_reloading) {
07003 unistim_reloading = 1;
07004 }
07005 ast_mutex_unlock(&unistim_reload_lock);
07006
07007 restart_monitor();
07008
07009 return 0;
07010 }
07011
07012 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
07013 .load = load_module,
07014 .unload = unload_module,
07015 .reload = reload,
07016 );