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: 414677 $")
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 : (%d) %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", (unsigned)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, (unsigned)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, (unsigned)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 %u 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, (unsigned)pte->seq_server, (unsigned)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 (unsigned)seq, (unsigned)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", (unsigned)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",
01542 (unsigned)output, (unsigned)volume, (unsigned)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 %u 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) 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 = %u\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 : %u\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 send_tone(pte, tone_data.freq1, tone_data.freq2);
02829 if (unistimdebug) {
02830 ast_verb(0, "Country code found (%s), freq1=%u freq2=%u\n",
02831 pte->device->tz->country, tone_data.freq1, tone_data.freq2);
02832 }
02833 ts = ast_tone_zone_sound_unref(ts);
02834 }
02835 }
02836
02837 static void show_phone_number(struct unistimsession *pte)
02838 {
02839 char tmp[TEXT_LENGTH_MAX + 1];
02840 const char *tmp_number = ustmtext("Number:", pte);
02841 int line, tmp_copy, offset = 0, i;
02842
02843 pte->device->phone_number[pte->device->size_phone_number] = '\0';
02844 if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
02845 offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
02846 if (offset > strlen(tmp_number)) {
02847 offset = strlen(tmp_number);
02848 }
02849 tmp_copy = strlen(tmp_number) - offset + 1;
02850 if (tmp_copy > sizeof(tmp)) {
02851 tmp_copy = sizeof(tmp);
02852 }
02853 memcpy(tmp, tmp_number + offset, tmp_copy);
02854 } else {
02855 ast_copy_string(tmp, tmp_number, sizeof(tmp));
02856 }
02857
02858 offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
02859 if (pte->device->size_phone_number) {
02860 memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
02861 }
02862 offset = strlen(tmp);
02863
02864 for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
02865 tmp[i] = '.';
02866 }
02867 tmp[i] = '\0';
02868
02869 line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
02870 send_text(line, TEXT_NORMAL, pte, tmp);
02871 send_blink_cursor(pte);
02872 send_cursor_pos(pte, (unsigned char) (line + offset));
02873 send_led_update(pte, 0);
02874 }
02875
02876 static void handle_dial_page(struct unistimsession *pte)
02877 {
02878 pte->state = STATE_DIALPAGE;
02879 if (pte->device->call_forward[0] == -1) {
02880 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
02881 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
02882 send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
02883 if (pte->device->call_forward[1] != 0) {
02884 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
02885 sizeof(pte->device->phone_number));
02886 show_phone_number(pte);
02887 send_led_update(pte, 0);
02888 return;
02889 }
02890 } else {
02891 if ((pte->device->output == OUTPUT_HANDSET) &&
02892 (pte->device->receiver_state == STATE_ONHOOK)) {
02893 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02894 } else {
02895 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02896 }
02897 send_dial_tone(pte);
02898
02899 if (pte->device->height > 1) {
02900 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
02901 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
02902 }
02903 if (ast_strlen_zero(pte->device->redial_number)) {
02904 send_text_status(pte, ustmtext("Call BackSp Erase", pte));
02905 } else {
02906 send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
02907 }
02908 }
02909
02910 pte->device->size_phone_number = 0;
02911 pte->device->phone_number[0] = 0;
02912 show_phone_number(pte);
02913 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
02914 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
02915 pte->device->missed_call = 0;
02916 send_led_update(pte, 0);
02917 pte->device->lastmsgssent = -1;
02918 return;
02919 }
02920
02921 static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
02922 {
02923 struct ast_rtp_instance *rtp;
02924 int fds;
02925
02926 if (unistimdebug) {
02927 ast_verb(0, "Swapping %p and %p\n", a, b);
02928 }
02929 if ((!a->owner) || (!b->owner)) {
02930 ast_log(LOG_WARNING,
02931 "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
02932 a, a->owner, b, b->owner);
02933 return;
02934 }
02935 rtp = a->rtp;
02936 a->rtp = b->rtp;
02937 b->rtp = rtp;
02938
02939 fds = ast_channel_fd(a->owner, 0);
02940 ast_channel_internal_fd_set(a->owner, 0, ast_channel_fd(b->owner, 0));
02941 ast_channel_internal_fd_set(b->owner, 0, fds);
02942
02943 fds = ast_channel_fd(a->owner, 1);
02944 ast_channel_internal_fd_set(a->owner, 1, ast_channel_fd(b->owner, 1));
02945 ast_channel_internal_fd_set(b->owner, 1, fds);
02946 }
02947
02948
02949 static void transfer_call_step1(struct unistimsession *pte)
02950 {
02951 struct unistim_subchannel *sub ;
02952 struct unistim_device *d = pte->device;
02953
02954 sub = get_sub(d, SUB_REAL);
02955
02956
02957 if (!sub || !sub->owner) {
02958 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02959 return;
02960 }
02961
02962 if (sub->moh) {
02963 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
02964 } else {
02965 if (ast_bridged_channel(sub->owner)) {
02966 ast_moh_start(ast_bridged_channel(sub->owner),
02967 sub->parent->musicclass, NULL);
02968 sub->moh = 1;
02969 sub->subtype = SUB_THREEWAY;
02970 } else {
02971 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
02972 return;
02973 }
02974 }
02975 sub_start_silence(pte, sub);
02976 handle_dial_page(pte);
02977 }
02978
02979 static void transfer_cancel_step2(struct unistimsession *pte)
02980 {
02981 struct unistim_subchannel *sub, *sub_trans;
02982 struct unistim_device *d = pte->device;
02983
02984 sub = get_sub(d, SUB_REAL);
02985 sub_trans = get_sub(d, SUB_THREEWAY);
02986
02987 if (!sub || !sub->owner) {
02988 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02989 return;
02990 }
02991 if (sub_trans) {
02992 if (unistimdebug) {
02993 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
02994 }
02995 if (sub->owner) {
02996 swap_subs(sub, sub_trans);
02997 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
02998 sub_trans->moh = 0;
02999 sub_trans->subtype = SUB_REAL;
03000 sub->subtype = SUB_THREEWAY;
03001 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
03002 } else {
03003 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
03004 }
03005 return;
03006 }
03007 }
03008
03009
03010 static void handle_call_outgoing(struct unistimsession *s)
03011 {
03012 struct ast_channel *c;
03013 struct unistim_subchannel *sub;
03014 int softkey;
03015
03016 s->state = STATE_CALL;
03017
03018 sub = get_sub(s->device, SUB_THREEWAY);
03019 if (sub) {
03020
03021 struct unistim_subchannel *sub_trans = NULL;
03022 struct unistim_device *d = s->device;
03023
03024 sub_trans = get_sub(d, SUB_REAL);
03025 if (sub_trans) {
03026 ast_log(LOG_WARNING, "Can't transfer while active subchannel exists!\n");
03027 return;
03028 }
03029 if (!sub->owner) {
03030 ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
03031 return;
03032 }
03033
03034 sub_trans = unistim_alloc_sub(d, SUB_REAL);
03035 if (!sub_trans) {
03036 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
03037 return;
03038 }
03039 sub_trans->parent = sub->parent;
03040 sub_stop_silence(s, sub);
03041 send_tone(s, 0, 0);
03042
03043 c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
03044 if (!c) {
03045 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
03046 return;
03047 }
03048
03049 swap_subs(sub, sub_trans);
03050 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03051 if (s->device->height == 1) {
03052 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03053 } else {
03054 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
03055 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03056 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03057 }
03058 send_text_status(s, ustmtext("TransfrCancel", s));
03059
03060 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03061 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
03062 sub->ss_thread = AST_PTHREADT_NULL;
03063 ast_hangup(c);
03064 return;
03065 }
03066 if (unistimdebug) {
03067 ast_verb(0, "Started three way call on channel %p (%s) subchan %u\n",
03068 sub_trans->owner, ast_channel_name(sub_trans->owner), sub_trans->subtype);
03069 }
03070 return;
03071 }
03072
03073 softkey = get_avail_softkey(s, NULL);
03074 if (softkey == -1) {
03075 ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
03076 return;
03077 }
03078 sub = get_sub(s->device, SUB_REAL);
03079 if (sub) {
03080 sub_hold(s, sub);
03081 }
03082 if (!(sub = unistim_alloc_sub(s->device, SUB_REAL))) {
03083 ast_log(LOG_WARNING, "Unable to allocate subchannel!\n");
03084 return;
03085 }
03086 sub->parent = s->device->sline[softkey];
03087 s->device->ssub[softkey] = sub;
03088 sub->softkey = softkey;
03089
03090 if (unistimdebug) {
03091 ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
03092 }
03093 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03094 s->device->selected = -1;
03095 if (!sub->owner) {
03096 c = unistim_new(sub, AST_STATE_DOWN, NULL);
03097 if (!sub->rtp) {
03098 start_rtp(sub);
03099 }
03100 if (c && !strcmp(s->device->phone_number, ast_pickup_ext())) {
03101 if (unistimdebug) {
03102 ast_verb(0, "Try to pickup in unistim_new\n");
03103 }
03104 send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
03105 send_text_status(s, ustmtext(" Transf Hangup", s));
03106 send_start_timer(s);
03107 if (ast_pickup_call(c)) {
03108 ast_log(LOG_NOTICE, "Nothing to pick up\n");
03109 ast_channel_hangupcause_set(c, AST_CAUSE_CALL_REJECTED);
03110 } else {
03111 ast_channel_hangupcause_set(c, AST_CAUSE_NORMAL_CLEARING);
03112 }
03113 ast_hangup(c);
03114 c = NULL;
03115 } else if (c) {
03116 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03117 send_tone(s, 0, 0);
03118 if (s->device->height == 1) {
03119 if (strlen(s->device->phone_number) > 0) {
03120 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
03121 } else {
03122 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
03123 }
03124 } else {
03125 send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
03126 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
03127 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
03128 }
03129 send_text_status(s, ustmtext(" Hangup", s));
03130
03131
03132 if (ast_pthread_create(&sub->ss_thread, NULL, unistim_ss, c)) {
03133 ast_log(LOG_WARNING, "Unable to create switch thread\n");
03134 sub->ss_thread = AST_PTHREADT_NULL;
03135 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
03136 }
03137 } else
03138 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
03139 sub->parent->name, s->device->name);
03140 } else {
03141 ast_debug(1, "Current sub [%s] already has owner\n", ast_channel_name(sub->owner));
03142 }
03143 return;
03144 }
03145
03146
03147 static void handle_call_incoming(struct unistimsession *s)
03148 {
03149 struct unistim_subchannel *sub = NULL;
03150 int i;
03151
03152 s->state = STATE_CALL;
03153 s->device->missed_call = 0;
03154 send_no_ring(s);
03155 sub = get_sub(s->device, SUB_RING);
03156 if (!sub) {
03157 ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
03158 return;
03159 }
03160
03161 for (i = 0; i < FAVNUM; i++) {
03162 if (!s->device->ssub[i]) {
03163 continue;
03164 }
03165 if (s->device->ssub[i]->subtype == SUB_REAL) {
03166 sub_hold(s, s->device->ssub[i]);
03167 }
03168 if (s->device->ssub[i] != sub) {
03169 continue;
03170 }
03171 if (sub->softkey == i) {
03172 continue;
03173 }
03174 if (sub->softkey < 0) {
03175 sub->softkey = i;
03176 continue;
03177 }
03178 send_favorite_short(i, FAV_LINE_ICON, s);
03179 s->device->ssub[i] = NULL;
03180 }
03181 if (sub->softkey < 0) {
03182 ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
03183 return;
03184 }
03185 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
03186 sub->parent = s->device->sline[sub->softkey];
03187 sub->subtype = SUB_REAL;
03188 if (unistimdebug) {
03189 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
03190 s->device->name);
03191 }
03192 start_rtp(sub);
03193 if (!sub->rtp) {
03194 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name, s->device->name);
03195 return;
03196 }
03197 if (sub->owner) {
03198 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
03199 }
03200 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
03201 send_text_status(s, ustmtext(" Transf Hangup", s));
03202 send_start_timer(s);
03203
03204 if ((s->device->output == OUTPUT_HANDSET) &&
03205 (s->device->receiver_state == STATE_ONHOOK)) {
03206 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
03207 } else {
03208 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
03209 }
03210 write_history(s, 'i', 0);
03211 return;
03212 }
03213
03214 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
03215 {
03216 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
03217 struct unistim_subchannel *sub;
03218 int row, col;
03219
03220 sub = get_sub(pte->device, SUB_REAL);
03221 if (!sub || !sub->owner || sub->alreadygone) {
03222 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
03223 return -1;
03224 }
03225
03226
03227 ast_queue_frame(sub->owner, &f);
03228
03229 if (unistimdebug) {
03230 ast_verb(0, "Send Digit %c\n", digit);
03231 }
03232 row = (digit - '1') % 3;
03233 col = (digit - '1' - row) / 3;
03234 if (digit >= '1' && digit <='9') {
03235 send_tone(pte, dtmf_row[row], dtmf_col[col]);
03236 } else if (digit >= 'A' && digit <= 'D') {
03237 send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
03238 } else if (digit == '*') {
03239 send_tone(pte, dtmf_row[3], dtmf_col[0]);
03240 } else if (digit == '0') {
03241 send_tone(pte, dtmf_row[3], dtmf_col[1]);
03242 } else if (digit == '#') {
03243 send_tone(pte, dtmf_row[3], dtmf_col[2]);
03244 } else {
03245 send_tone(pte, 500, 2000);
03246 }
03247 usleep(150000);
03248 send_tone(pte, 0, 0);
03249 return 0;
03250 }
03251
03252 static void handle_key_fav(struct unistimsession *pte, char keycode)
03253 {
03254 int keynum = keycode - KEY_FAV0;
03255 struct unistim_subchannel *sub;
03256
03257 sub = get_sub(pte->device, SUB_REAL);
03258
03259
03260 if (!pte->device->ssub[keynum]) {
03261 send_favorite_selected(FAV_LINE_ICON, pte);
03262 if (is_key_line(pte->device, keynum)) {
03263 if (unistimdebug) {
03264 ast_verb(0, "Handle line w/o sub - dialpage\n");
03265 }
03266 pte->device->selected = keynum;
03267 sub_hold(pte, sub);
03268 send_stop_timer(pte);
03269 handle_dial_page(pte);
03270 } else if (is_key_favorite(pte->device, keynum)) {
03271
03272
03273 if (unistimdebug) {
03274 ast_verb(0, "Handle favorite w/o sub - dialing\n");
03275 }
03276 if ((pte->device->output == OUTPUT_HANDSET) &&
03277 (pte->device->receiver_state == STATE_ONHOOK)) {
03278 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03279 } else {
03280 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03281 }
03282 key_favorite(pte, keycode);
03283 }
03284 } else {
03285 sub = pte->device->ssub[keynum];
03286
03287 if (sub->subtype == SUB_REAL) {
03288 sub_hold(pte, sub);
03289 show_main_page(pte);
03290 } else if (sub->subtype == SUB_RING) {
03291 sub->softkey = keynum;
03292 handle_call_incoming(pte);
03293 } else if (sub->subtype == SUB_ONHOLD) {
03294 if (pte->state == STATE_DIALPAGE){
03295 send_tone(pte, 0, 0);
03296 }
03297 send_callerid_screen(pte, sub);
03298 sub_unhold(pte, sub);
03299 pte->state = STATE_CALL;
03300 }
03301 }
03302 }
03303
03304 static void key_call(struct unistimsession *pte, char keycode)
03305 {
03306 struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
03307 struct unistim_subchannel *sub_3way = get_sub(pte->device, SUB_THREEWAY);
03308
03309 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03310 if (keycode == KEY_SHARP) {
03311 keycode = '#';
03312 } else if (keycode == KEY_STAR) {
03313 keycode = '*';
03314 } else {
03315 keycode -= 0x10;
03316 }
03317 unistim_do_senddigit(pte, keycode);
03318 return;
03319 }
03320 switch (keycode) {
03321 case KEY_FUNC1:
03322 if (ast_channel_state(sub->owner) == AST_STATE_UP) {
03323 if (sub_3way) {
03324 close_call(pte);
03325 }
03326 }
03327 break;
03328 case KEY_FUNC2:
03329 if (sub_3way) {
03330 transfer_cancel_step2(pte);
03331 } else if (ast_channel_state(sub->owner) == AST_STATE_UP) {
03332 transfer_call_step1(pte);
03333 }
03334 break;
03335 case KEY_HANGUP:
03336 case KEY_FUNC4:
03337 if (!sub_3way) {
03338 close_call(pte);
03339 }
03340 break;
03341 case KEY_FAV0:
03342 case KEY_FAV1:
03343 case KEY_FAV2:
03344 case KEY_FAV3:
03345 case KEY_FAV4:
03346 case KEY_FAV5:
03347 handle_key_fav(pte, keycode);
03348 break;
03349 case KEY_HEADPHN:
03350 if (pte->device->output == OUTPUT_HEADPHONE) {
03351 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03352 } else {
03353 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03354 }
03355 break;
03356 case KEY_LOUDSPK:
03357 if (pte->device->output != OUTPUT_SPEAKER)
03358 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03359 else
03360 send_select_output(pte, pte->device->previous_output, pte->device->volume,
03361 MUTE_OFF);
03362 break;
03363 case KEY_MUTE:
03364 if (!sub || !sub->owner) {
03365 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
03366 return;
03367 }
03368 if (!sub->moh) {
03369 if (pte->device->mute == MUTE_ON) {
03370 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03371 } else {
03372 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
03373 }
03374 break;
03375 }
03376 break;
03377 case KEY_ONHOLD:
03378 if (!sub) {
03379 if(pte->device->ssub[pte->device->selected]) {
03380 sub_hold(pte, pte->device->ssub[pte->device->selected]);
03381 }
03382 } else {
03383 sub_hold(pte, sub);
03384 }
03385 break;
03386 }
03387 return;
03388 }
03389
03390 static void key_ringing(struct unistimsession *pte, char keycode)
03391 {
03392 switch (keycode) {
03393 case KEY_FAV0:
03394 case KEY_FAV1:
03395 case KEY_FAV2:
03396 case KEY_FAV3:
03397 case KEY_FAV4:
03398 case KEY_FAV5:
03399 handle_key_fav(pte, keycode);
03400 break;
03401 case KEY_FUNC3:
03402 ignore_call(pte);
03403 break;
03404 case KEY_HANGUP:
03405 case KEY_FUNC4:
03406 discard_call(pte);
03407 break;
03408 case KEY_LOUDSPK:
03409 pte->device->output = OUTPUT_SPEAKER;
03410 handle_call_incoming(pte);
03411 break;
03412 case KEY_HEADPHN:
03413 pte->device->output = OUTPUT_HEADPHONE;
03414 handle_call_incoming(pte);
03415 break;
03416 case KEY_FUNC1:
03417 handle_call_incoming(pte);
03418 break;
03419 }
03420 return;
03421 }
03422
03423 static void key_favorite(struct unistimsession *pte, char keycode)
03424 {
03425 int fav = keycode - KEY_FAV0;
03426 if (!is_key_favorite(pte->device, fav)) {
03427 ast_log(LOG_WARNING, "It's not a favorite key\n");
03428 return;
03429 }
03430 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
03431 sizeof(pte->device->phone_number));
03432 handle_call_outgoing(pte);
03433 return;
03434 }
03435
03436 static void key_dial_page(struct unistimsession *pte, char keycode)
03437 {
03438 struct unistim_subchannel *sub = get_sub(pte->device, SUB_THREEWAY);
03439
03440 pte->device->nextdial = 0;
03441 if (keycode == KEY_FUNC3) {
03442 if (pte->device->size_phone_number <= 1) {
03443 keycode = KEY_FUNC4;
03444 } else {
03445 pte->device->size_phone_number -= 2;
03446 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
03447 }
03448 }
03449 if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
03450 keycode = KEY_FUNC1;
03451 }
03452 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03453 int i = pte->device->size_phone_number;
03454
03455 if (pte->device->size_phone_number == 0) {
03456 send_tone(pte, 0, 0);
03457 }
03458 if (keycode == KEY_SHARP) {
03459 keycode = '#';
03460 } else if (keycode == KEY_STAR) {
03461 keycode = '*';
03462 } else {
03463 keycode -= 0x10;
03464 }
03465 pte->device->phone_number[i] = keycode;
03466 pte->device->size_phone_number++;
03467 pte->device->phone_number[i + 1] = 0;
03468 show_phone_number(pte);
03469
03470 if (ast_exists_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL) &&
03471 !ast_matchmore_extension(NULL, pte->device->context, pte->device->phone_number, 1, NULL)) {
03472 keycode = KEY_FUNC1;
03473 } else {
03474 if (pte->device->interdigit_timer) {
03475 pte->device->nextdial = get_tick_count() + pte->device->interdigit_timer;
03476 }
03477 }
03478 }
03479 if (keycode == KEY_FUNC4) {
03480 pte->device->size_phone_number = 0;
03481 show_phone_number(pte);
03482 return;
03483 }
03484
03485 if (pte->device->call_forward[0] == -1) {
03486 if (keycode == KEY_FUNC1) {
03487 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
03488 sizeof(pte->device->call_forward));
03489 show_main_page(pte);
03490 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
03491 pte->device->call_forward[0] = '\0';
03492 send_led_update(pte, 0x08);
03493 send_led_update(pte, 0x10);
03494 show_main_page(pte);
03495 }
03496 return;
03497 }
03498 switch (keycode) {
03499 case KEY_FUNC2:
03500 if (ast_strlen_zero(pte->device->redial_number)) {
03501 break;
03502 }
03503 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03504 sizeof(pte->device->phone_number));
03505 case KEY_FUNC1:
03506 handle_call_outgoing(pte);
03507 break;
03508 case KEY_HANGUP:
03509 if (sub && sub->owner) {
03510 struct ast_channel *bridgepeer = NULL;
03511
03512 sub_stop_silence(pte, sub);
03513 send_tone(pte, 0, 0);
03514 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
03515 ast_moh_stop(bridgepeer);
03516 }
03517 sub->moh = 0;
03518 sub->subtype = SUB_REAL;
03519 pte->state = STATE_CALL;
03520
03521 send_text_status(pte, ustmtext(" Transf Hangup", pte));
03522 send_callerid_screen(pte, sub);
03523 } else {
03524 send_led_update(pte, 0x08);
03525 send_led_update(pte, 0x10);
03526 show_main_page(pte);
03527 }
03528 break;
03529 case KEY_FAV0:
03530 case KEY_FAV1:
03531 case KEY_FAV2:
03532 case KEY_FAV3:
03533 case KEY_FAV4:
03534 case KEY_FAV5:
03535 send_favorite_selected(FAV_LINE_ICON, pte);
03536 pte->device->selected = -1;
03537 handle_key_fav(pte, keycode);
03538 break;
03539 case KEY_LOUDSPK:
03540 if (pte->device->output == OUTPUT_SPEAKER) {
03541 if (pte->device->receiver_state == STATE_OFFHOOK) {
03542 send_select_output(pte, pte->device->previous_output, pte->device->volume,
03543 MUTE_OFF);
03544 } else {
03545 show_main_page(pte);
03546 }
03547 } else {
03548 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03549 }
03550 break;
03551 case KEY_HEADPHN:
03552 if (pte->device->output == OUTPUT_HEADPHONE) {
03553 if (pte->device->receiver_state == STATE_OFFHOOK) {
03554 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03555 } else {
03556 show_main_page(pte);
03557 }
03558 } else {
03559 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03560 }
03561 break;
03562 }
03563 return;
03564 }
03565
03566 static void handle_select_option(struct unistimsession *pte)
03567 {
03568 char tmp[128];
03569
03570 if (pte->state != STATE_SELECTOPTION) {
03571 pte->state = STATE_SELECTOPTION;
03572 pte->size_buff_entry = 1;
03573 pte->buff_entry[0] = 0;
03574 }
03575 snprintf(tmp, sizeof(tmp), "%d. %s", pte->buff_entry[0] + 1, ustmtext(options_menu[(int)pte->buff_entry[0]].label, pte));
03576 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
03577 send_text_status(pte, ustmtext("Select Cancel", pte));
03578 return;
03579 }
03580
03581 static void key_select_option(struct unistimsession *pte, char keycode)
03582 {
03583 switch (keycode) {
03584 case KEY_DOWN:
03585 pte->buff_entry[0]++;
03586 if (options_menu[(int)pte->buff_entry[0]].label == NULL) {
03587 pte->buff_entry[0]--;
03588 }
03589 break;
03590 case KEY_UP:
03591 if (pte->buff_entry[0] > 0) {
03592 pte->buff_entry[0]--;
03593 }
03594 break;
03595 case KEY_FUNC1:
03596 options_menu[(int)pte->buff_entry[0]].handle_option(pte);
03597 return;
03598 case KEY_HANGUP:
03599 case KEY_FUNC4:
03600 show_main_page(pte);
03601 return;
03602 }
03603
03604 handle_select_option(pte);
03605 return;
03606 }
03607
03608 #define SELECTCODEC_START_ENTRY_POS 15
03609 #define SELECTCODEC_MAX_LENGTH 2
03610 #define SELECTCODEC_MSG "Codec number : .."
03611 static void handle_select_codec(struct unistimsession *pte)
03612 {
03613 char buf[30], buf2[5];
03614
03615 pte->state = STATE_SELECTCODEC;
03616 ast_copy_string(buf, ustmtext("Using codec", pte), sizeof(buf));
03617 snprintf(buf2, sizeof(buf2), " %d", pte->device->codec_number);
03618 strcat(buf, buf2);
03619 strcat(buf, " (G711u=0,");
03620
03621 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
03622 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
03623 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03624 send_blink_cursor(pte);
03625 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03626 pte->size_buff_entry = 0;
03627 send_text_status(pte, ustmtext("Select BackSp Erase Cancel", pte));
03628 return;
03629 }
03630
03631 static void key_select_codec(struct unistimsession *pte, char keycode)
03632 {
03633 if (keycode == KEY_FUNC2) {
03634 if (pte->size_buff_entry <= 1) {
03635 keycode = KEY_FUNC3;
03636 } else {
03637 pte->size_buff_entry -= 2;
03638 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03639 }
03640 }
03641 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03642 char tmpbuf[] = SELECTCODEC_MSG;
03643 int i = 0;
03644
03645 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH) {
03646 return;
03647 }
03648 while (i < pte->size_buff_entry) {
03649 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
03650 i++;
03651 }
03652 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
03653 pte->buff_entry[i] = keycode - 0x10;
03654 pte->size_buff_entry++;
03655 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
03656 send_blink_cursor(pte);
03657 send_cursor_pos(pte,
03658 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
03659 return;
03660 }
03661
03662 switch (keycode) {
03663 case KEY_FUNC1:
03664 if (pte->size_buff_entry == 1) {
03665 pte->device->codec_number = pte->buff_entry[0] - 48;
03666 } else if (pte->size_buff_entry == 2) {
03667 pte->device->codec_number =
03668 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
03669 }
03670 show_main_page(pte);
03671 break;
03672 case KEY_FUNC3:
03673 pte->size_buff_entry = 0;
03674 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
03675 send_blink_cursor(pte);
03676 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
03677 break;
03678 case KEY_HANGUP:
03679 case KEY_FUNC4:
03680 show_main_page(pte);
03681 break;
03682 }
03683 return;
03684 }
03685
03686 static int find_language(const char* lang)
03687 {
03688 int i = 0;
03689 while (options_languages[i].lang_short != NULL) {
03690 if(!strcmp(options_languages[i].lang_short, lang)) {
03691 return i;
03692 }
03693 i++;
03694 }
03695 return 0;
03696 }
03697
03698 static void handle_select_language(struct unistimsession *pte)
03699 {
03700 char tmp_language[40];
03701 struct unistim_languages lang;
03702
03703 if (pte->state != STATE_SELECTLANGUAGE) {
03704 pte->state = STATE_SELECTLANGUAGE;
03705 pte->size_buff_entry = 1;
03706 pte->buff_entry[0] = find_language(pte->device->language);
03707 }
03708 lang = options_languages[(int)pte->buff_entry[0]];
03709 ast_copy_string(tmp_language, pte->device->language, sizeof(tmp_language));
03710 ast_copy_string(pte->device->language, lang.lang_short, sizeof(pte->device->language));
03711 send_charset_update(pte, lang.encoding);
03712 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(lang.label, pte));
03713
03714 ast_copy_string(pte->device->language, tmp_language, sizeof(pte->device->language));
03715 lang = options_languages[find_language(pte->device->language)];
03716 send_charset_update(pte, lang.encoding);
03717 send_text_status(pte, ustmtext("Select Cancel", pte));
03718 return;
03719 }
03720
03721 static void key_select_language(struct unistimsession *pte, char keycode)
03722 {
03723 switch (keycode) {
03724 case KEY_DOWN:
03725 pte->buff_entry[0]++;
03726 if (options_languages[(int)pte->buff_entry[0]].label == NULL) {
03727 pte->buff_entry[0]--;
03728 }
03729 break;
03730 case KEY_UP:
03731 if (pte->buff_entry[0] > 0) {
03732 pte->buff_entry[0]--;
03733 }
03734 break;
03735 case KEY_FUNC1:
03736 ast_copy_string(pte->device->language, options_languages[(int)pte->buff_entry[0]].lang_short, sizeof(pte->device->language));
03737 send_charset_update(pte, options_languages[(int)pte->buff_entry[0]].encoding);
03738 refresh_all_favorite(pte);
03739 show_main_page(pte);
03740 return;
03741 case KEY_HANGUP:
03742 case KEY_FUNC4:
03743 handle_select_option(pte);
03744 return;
03745 }
03746
03747 handle_select_language(pte);
03748 return;
03749 }
03750
03751
03752 #define SELECTEXTENSION_START_ENTRY_POS 0
03753 #define SELECTEXTENSION_MAX_LENGTH 10
03754 #define SELECTEXTENSION_MSG ".........."
03755 static void show_extension_page(struct unistimsession *pte)
03756 {
03757 pte->state = STATE_EXTENSION;
03758
03759 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Please enter a Terminal", pte));
03760 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Number (TN) :", pte));
03761 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03762 send_blink_cursor(pte);
03763 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03764 send_text_status(pte, ustmtext("Enter BackSpcErase", pte));
03765 pte->size_buff_entry = 0;
03766 return;
03767 }
03768
03769 static void key_select_extension(struct unistimsession *pte, char keycode)
03770 {
03771 if (keycode == KEY_FUNC2) {
03772 if (pte->size_buff_entry <= 1) {
03773 keycode = KEY_FUNC3;
03774 } else {
03775 pte->size_buff_entry -= 2;
03776 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
03777 }
03778 }
03779 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
03780 char tmpbuf[] = SELECTEXTENSION_MSG;
03781 int i = 0;
03782
03783 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH) {
03784 return;
03785 }
03786 while (i < pte->size_buff_entry) {
03787 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
03788 i++;
03789 }
03790 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
03791 pte->buff_entry[i] = keycode - 0x10;
03792 pte->size_buff_entry++;
03793 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03794 send_blink_cursor(pte);
03795 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 + i));
03796 return;
03797 }
03798
03799 switch (keycode) {
03800 case KEY_FUNC1:
03801 if (pte->size_buff_entry < 1) {
03802 return;
03803 }
03804 if (autoprovisioning == AUTOPROVISIONING_TN) {
03805 struct unistim_device *d;
03806
03807
03808 ast_mutex_lock(&devicelock);
03809 d = devices;
03810 pte->buff_entry[pte->size_buff_entry] = '\0';
03811 while (d) {
03812 if (d->id[0] == 'T') {
03813
03814 if (!strcmp((d->id) + 1, pte->buff_entry)) {
03815 pte->device = d;
03816 d->session = pte;
03817 d->codec_number = DEFAULT_CODEC;
03818 d->missed_call = 0;
03819 d->receiver_state = STATE_ONHOOK;
03820 strcpy(d->id, pte->macaddr);
03821 pte->device->extension_number[0] = 'T';
03822 pte->device->extension = EXTENSION_TN;
03823 ast_copy_string((pte->device->extension_number) + 1,
03824 pte->buff_entry, pte->size_buff_entry + 1);
03825 ast_mutex_unlock(&devicelock);
03826 show_main_page(pte);
03827 refresh_all_favorite(pte);
03828 return;
03829 }
03830 }
03831 d = d->next;
03832 }
03833 ast_mutex_unlock(&devicelock);
03834 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid Terminal Number.", pte));
03835 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03836 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
03837 pte->size_buff_entry));
03838 send_blink_cursor(pte);
03839 } else {
03840 ast_copy_string(pte->device->extension_number, pte->buff_entry,
03841 pte->size_buff_entry + 1);
03842 if (register_extension(pte)) {
03843 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid extension.", pte));
03844 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
03845 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 +
03846 SELECTEXTENSION_START_ENTRY_POS +
03847 pte->size_buff_entry));
03848 send_blink_cursor(pte);
03849 } else
03850 show_main_page(pte);
03851 }
03852 break;
03853 case KEY_FUNC3:
03854 pte->size_buff_entry = 0;
03855 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03856 send_blink_cursor(pte);
03857 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03858 break;
03859 }
03860 return;
03861 }
03862
03863 static void show_entry_history(struct unistimsession *pte, FILE ** f)
03864 {
03865 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
03866 func3[10];
03867
03868
03869 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03870 display_last_error("Can't read history date entry");
03871 fclose(*f);
03872 return;
03873 }
03874 line[sizeof(line) - 1] = '\0';
03875 if (pte->device->height == 1) {
03876 if (pte->buff_entry[3] == 1) {
03877 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03878 }
03879 } else {
03880 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03881 }
03882
03883 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03884 display_last_error("Can't read callerid entry");
03885 fclose(*f);
03886 return;
03887 }
03888 line[sizeof(line) - 1] = '\0';
03889 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
03890 ast_trim_blanks(pte->device->lst_cid);
03891 if (pte->device->height == 1) {
03892 if (pte->buff_entry[3] == 2) {
03893 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03894 }
03895 } else {
03896 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
03897 }
03898
03899 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03900 display_last_error("Can't read callername entry");
03901 fclose(*f);
03902 return;
03903 }
03904 line[sizeof(line) - 1] = '\0';
03905 if (pte->device->height == 1) {
03906 if (pte->buff_entry[3] == 3) {
03907 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03908 }
03909 } else {
03910 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
03911 }
03912 fclose(*f);
03913
03914 snprintf(line, sizeof(line), "%s %03d/%03d", ustmtext("Call", pte), pte->buff_entry[2],
03915 pte->buff_entry[1]);
03916 send_texttitle(pte, line);
03917
03918 if (pte->buff_entry[2] == 1) {
03919 ast_copy_string(func1, " ", sizeof(func1));
03920 } else {
03921 ast_copy_string(func1, ustmtext("Prev ", pte), sizeof(func1));
03922 }
03923 if (pte->buff_entry[2] >= pte->buff_entry[1]) {
03924 ast_copy_string(func2, " ", sizeof(func2));
03925 } else {
03926 ast_copy_string(func2, ustmtext("Next ", pte), sizeof(func2));
03927 }
03928 if (strlen(pte->device->lst_cid)) {
03929 ast_copy_string(func3, ustmtext("Redial ", pte), sizeof(func3));
03930 } else {
03931 ast_copy_string(func3, " ", sizeof(func3));
03932 }
03933 snprintf(status, sizeof(status), "%s%s%s%s", func1, func2, func3, ustmtext("Cancel", pte));
03934 send_text_status(pte, status);
03935 }
03936
03937 static char open_history(struct unistimsession *pte, char way, FILE ** f)
03938 {
03939 char tmp[AST_CONFIG_MAX_PATH];
03940 char count;
03941
03942 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
03943 USTM_LOG_DIR, pte->device->name, way);
03944 *f = fopen(tmp, "r");
03945 if (!*f) {
03946 display_last_error("Unable to open history file");
03947 return 0;
03948 }
03949 if (fread(&count, 1, 1, *f) != 1) {
03950 display_last_error("Unable to read history header - display.");
03951 fclose(*f);
03952 *f = NULL;
03953 return 0;
03954 }
03955 if (count > MAX_ENTRY_LOG) {
03956 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
03957 count, MAX_ENTRY_LOG);
03958 fclose(*f);
03959 *f = NULL;
03960 return 0;
03961 }
03962 return count;
03963 }
03964
03965 static void show_history(struct unistimsession *pte, char way)
03966 {
03967 FILE *f;
03968 char count;
03969
03970 if (!pte->device) {
03971 return;
03972 }
03973 if (!pte->device->callhistory) {
03974 return;
03975 }
03976 count = open_history(pte, way, &f);
03977 if (!count) {
03978 return;
03979 }
03980 pte->buff_entry[0] = way;
03981 pte->buff_entry[1] = count;
03982 pte->buff_entry[2] = 1;
03983 pte->buff_entry[3] = 1;
03984 show_entry_history(pte, &f);
03985 pte->state = STATE_HISTORY;
03986 }
03987
03988 static void show_main_page(struct unistimsession *pte)
03989 {
03990 char tmpbuf[TEXT_LENGTH_MAX + 1];
03991 const char *text;
03992
03993 if ((pte->device->extension == EXTENSION_ASK) &&
03994 (ast_strlen_zero(pte->device->extension_number))) {
03995 show_extension_page(pte);
03996 return;
03997 }
03998
03999 pte->state = STATE_MAINPAGE;
04000 send_led_update(pte, 0);
04001 pte->device->lastmsgssent = -1;
04002
04003 send_tone(pte, 0, 0);
04004 send_stop_timer(pte);
04005 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
04006 send_led_update(pte, 0x08);
04007 send_led_update(pte, 0x10);
04008
04009 if (!ast_strlen_zero(pte->device->call_forward)) {
04010 if (pte->device->height == 1) {
04011 char tmp_field[100];
04012 snprintf(tmp_field, sizeof(tmp_field), "%s %s", ustmtext("Fwd to:", pte), pte->device->call_forward);
04013 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp_field);
04014 } else {
04015 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Call forwarded to :", pte));
04016 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
04017 }
04018 send_icon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
04019 if (ast_strlen_zero(pte->device->redial_number)) {
04020 send_text_status(pte, ustmtext("Dial NoFwd ", pte));
04021 } else {
04022 send_text_status(pte, ustmtext("Dial Redial NoFwd ", pte));
04023 }
04024 } else {
04025 if ((pte->device->extension == EXTENSION_ASK) || (pte->device->extension == EXTENSION_TN)) {
04026 if (ast_strlen_zero(pte->device->redial_number)) {
04027 send_text_status(pte, ustmtext("Dial Fwd Unregis", pte));
04028 } else {
04029 send_text_status(pte, ustmtext("Dial Redial Fwd Unregis", pte));
04030 }
04031 } else {
04032 if (ast_strlen_zero(pte->device->redial_number)) {
04033 send_text_status(pte, ustmtext("Dial Fwd Pickup", pte));
04034 } else {
04035 send_text_status(pte, ustmtext("Dial Redial Fwd Pickup", pte));
04036 }
04037 }
04038 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
04039 if (pte->device->missed_call == 0) {
04040 send_date_time2(pte);
04041 send_idle_clock(pte);
04042 if (strlen(pte->device->maintext0)) {
04043 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
04044 }
04045 } else {
04046 if (pte->device->missed_call == 1) {
04047 text = ustmtext("unanswered call", pte);
04048 } else {
04049 text = ustmtext("unanswered calls", pte);
04050 }
04051 snprintf(tmpbuf, sizeof(tmpbuf), "%d %s", pte->device->missed_call, text);
04052 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
04053 send_icon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
04054 }
04055 }
04056 if (pte->device->height > 1) {
04057 if (ast_strlen_zero(pte->device->maintext2)) {
04058 strcpy(tmpbuf, "IP : ");
04059 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
04060 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
04061 } else {
04062 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
04063 }
04064 }
04065
04066 send_texttitle(pte, pte->device->titledefault);
04067 change_favorite_icon(pte, FAV_LINE_ICON);
04068 }
04069
04070 static void key_main_page(struct unistimsession *pte, char keycode)
04071 {
04072 if (pte->device->missed_call) {
04073 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04074 pte->device->missed_call = 0;
04075 }
04076 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
04077 handle_dial_page(pte);
04078 key_dial_page(pte, keycode);
04079 return;
04080 }
04081 switch (keycode) {
04082 case KEY_FUNC1:
04083 pte->device->selected = get_avail_softkey(pte, NULL);
04084 handle_dial_page(pte);
04085 break;
04086 case KEY_FUNC2:
04087 if (ast_strlen_zero(pte->device->redial_number)) {
04088 break;
04089 }
04090 if ((pte->device->output == OUTPUT_HANDSET) &&
04091 (pte->device->receiver_state == STATE_ONHOOK)) {
04092 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04093 } else {
04094 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
04095 }
04096 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
04097 sizeof(pte->device->phone_number));
04098 handle_call_outgoing(pte);
04099 break;
04100 case KEY_FUNC3:
04101 if (!ast_strlen_zero(pte->device->call_forward)) {
04102
04103 memmove(pte->device->call_forward + 1, pte->device->call_forward,
04104 sizeof(pte->device->call_forward) - 1);
04105 pte->device->call_forward[0] = '\0';
04106 send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
04107 pte->device->output = OUTPUT_HANDSET;
04108 show_main_page(pte);
04109 break;
04110 }
04111 pte->device->call_forward[0] = -1;
04112 handle_dial_page(pte);
04113 break;
04114 case KEY_FUNC4:
04115 if (pte->device->extension == EXTENSION_ASK) {
04116 unregister_extension(pte);
04117 pte->device->extension_number[0] = '\0';
04118 show_extension_page(pte);
04119 } else if (pte->device->extension == EXTENSION_TN) {
04120 ast_mutex_lock(&devicelock);
04121 strcpy(pte->device->id, pte->device->extension_number);
04122 pte->buff_entry[0] = '\0';
04123 pte->size_buff_entry = 0;
04124 pte->device->session = NULL;
04125 pte->device = NULL;
04126 ast_mutex_unlock(&devicelock);
04127 show_extension_page(pte);
04128 } else {
04129 pte->device->selected = -1;
04130 ast_copy_string(pte->device->phone_number, ast_pickup_ext(),
04131 sizeof(pte->device->phone_number));
04132 handle_call_outgoing(pte);
04133 }
04134 break;
04135 case KEY_FAV0:
04136 case KEY_FAV1:
04137 case KEY_FAV2:
04138 case KEY_FAV3:
04139 case KEY_FAV4:
04140 case KEY_FAV5:
04141 handle_key_fav(pte, keycode);
04142 break;
04143 case KEY_CONF:
04144 handle_select_option(pte);
04145 break;
04146 case KEY_LOUDSPK:
04147 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
04148 handle_dial_page(pte);
04149 break;
04150 case KEY_HEADPHN:
04151 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04152 handle_dial_page(pte);
04153 break;
04154 case KEY_SNDHIST:
04155 show_history(pte, 'o');
04156 break;
04157 case KEY_RCVHIST:
04158 show_history(pte, 'i');
04159 break;
04160 }
04161 return;
04162 }
04163
04164 static void key_history(struct unistimsession *pte, char keycode)
04165 {
04166 FILE *f;
04167 char count;
04168 long offset;
04169 int flag = 0;
04170
04171 switch (keycode) {
04172 case KEY_LEFT:
04173 if (pte->device->height == 1) {
04174 if (pte->buff_entry[3] <= 1) {
04175 return;
04176 }
04177 pte->buff_entry[3]--;
04178 flag = 1;
04179 break;
04180 }
04181 case KEY_UP:
04182 case KEY_FUNC1:
04183 if (pte->buff_entry[2] <= 1) {
04184 return;
04185 }
04186 pte->buff_entry[2]--;
04187 flag = 1;
04188 break;
04189 case KEY_RIGHT:
04190 if (pte->device->height == 1) {
04191 if (pte->buff_entry[3] == 3) {
04192 return;
04193 }
04194 pte->buff_entry[3]++;
04195 flag = 1;
04196 break;
04197 }
04198 case KEY_DOWN:
04199 case KEY_FUNC2:
04200 if (pte->buff_entry[2] >= pte->buff_entry[1]) {
04201 return;
04202 }
04203 pte->buff_entry[2]++;
04204 flag = 1;
04205 break;
04206 case KEY_FUNC3:
04207 if (ast_strlen_zero(pte->device->lst_cid)) {
04208 break;
04209 }
04210 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
04211 sizeof(pte->device->redial_number));
04212 key_main_page(pte, KEY_FUNC2);
04213 break;
04214 case KEY_FUNC4:
04215 case KEY_HANGUP:
04216 show_main_page(pte);
04217 break;
04218 case KEY_SNDHIST:
04219 if (pte->buff_entry[0] == 'i') {
04220 show_history(pte, 'o');
04221 } else {
04222 show_main_page(pte);
04223 }
04224 break;
04225 case KEY_RCVHIST:
04226 if (pte->buff_entry[0] == 'i') {
04227 show_main_page(pte);
04228 } else {
04229 show_history(pte, 'i');
04230 }
04231 break;
04232 }
04233
04234 if (flag) {
04235 count = open_history(pte, pte->buff_entry[0], &f);
04236 if (!count) {
04237 return;
04238 }
04239 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
04240 if (fseek(f, offset, SEEK_CUR)) {
04241 display_last_error("Unable to seek history entry.");
04242 fclose(f);
04243 return;
04244 }
04245 show_entry_history(pte, &f);
04246 }
04247
04248 return;
04249 }
04250
04251 static void init_phone_step2(struct unistimsession *pte)
04252 {
04253 BUFFSEND;
04254 if (unistimdebug) {
04255 ast_verb(0, "Sending S4\n");
04256 }
04257 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
04258 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
04259 send_date_time2(pte);
04260 send_date_time3(pte);
04261 if (unistimdebug) {
04262 ast_verb(0, "Sending S7\n");
04263 }
04264 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04265 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04266 if (unistimdebug) {
04267 ast_verb(0, "Sending Contrast\n");
04268 }
04269 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
04270 if (pte->device != NULL) {
04271 buffsend[9] = pte->device->contrast;
04272 }
04273 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
04274
04275 if (unistimdebug) {
04276 ast_verb(0, "Sending S9\n");
04277 }
04278 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
04279 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
04280 send_no_ring(pte);
04281
04282 if (unistimdebug) {
04283 ast_verb(0, "Sending S7\n");
04284 }
04285 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
04286 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
04287 send_led_update(pte, 0);
04288 send_ping(pte);
04289 if (unistimdebug) {
04290 ast_verb(0, "Sending init language\n");
04291 }
04292 if (pte->device) {
04293 send_charset_update(pte, options_languages[find_language(pte->device->language)].encoding);
04294 }
04295 if (pte->state < STATE_MAINPAGE) {
04296 if (autoprovisioning == AUTOPROVISIONING_TN) {
04297 show_extension_page(pte);
04298 return;
04299 } else {
04300 int i;
04301 char tmp[30];
04302
04303 for (i = 1; i < FAVNUM; i++) {
04304 send_favorite(i, 0, pte, "");
04305 }
04306 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Phone is not registered", pte));
04307 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("in unistim.conf", pte));
04308 strcpy(tmp, "MAC = ");
04309 strcat(tmp, pte->macaddr);
04310 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04311 send_text_status(pte, "");
04312 send_texttitle(pte, "UNISTIM for*");
04313 return;
04314 }
04315 }
04316 show_main_page(pte);
04317 refresh_all_favorite(pte);
04318 if (unistimdebug) {
04319 ast_verb(0, "Sending arrow\n");
04320 }
04321 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
04322 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
04323 return;
04324 }
04325
04326 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
04327 {
04328 char tmpbuf[255];
04329 if (memcmp
04330 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
04331 sizeof(packet_recv_resume_connection_with_server)) == 0) {
04332 rcv_resume_connection_with_server(pte);
04333 return;
04334 }
04335 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) == 0) {
04336 buf[size] = 0;
04337 if (unistimdebug) {
04338 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
04339 }
04340 init_phone_step2(pte);
04341 return;
04342 }
04343 if (memcmp(buf + SIZE_HEADER, packet_recv_it_type, sizeof(packet_recv_it_type)) == 0) {
04344 char type = buf[13];
04345 if (unistimdebug) {
04346 ast_verb(0, "Got the equipment type: '%d'\n", type);
04347 }
04348 switch (type) {
04349 case 0x03:
04350 if (pte->device) {
04351 pte->device->height = 1;
04352 }
04353 break;
04354 }
04355 return;
04356 }
04357 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
04358 rcv_mac_addr(pte, buf);
04359 return;
04360 }
04361 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
04362 if (unistimdebug) {
04363 ast_verb(0, "R2 received\n");
04364 }
04365 return;
04366 }
04367
04368 if (pte->state < STATE_MAINPAGE) {
04369 if (unistimdebug) {
04370 ast_verb(0, "Request not authorized in this state\n");
04371 }
04372 return;
04373 }
04374 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
04375 char keycode = buf[13];
04376
04377 if (unistimdebug) {
04378 ast_verb(0, "Key pressed: keycode = 0x%.2x - current state: %s\n", (unsigned)keycode,
04379 ptestate_tostr(pte->state));
04380 }
04381 switch (pte->state) {
04382 case STATE_INIT:
04383 if (unistimdebug) {
04384 ast_verb(0, "No keys allowed in the init state\n");
04385 }
04386 break;
04387 case STATE_AUTHDENY:
04388 if (unistimdebug) {
04389 ast_verb(0, "No keys allowed in authdeny state\n");
04390 }
04391 break;
04392 case STATE_MAINPAGE:
04393 key_main_page(pte, keycode);
04394 break;
04395 case STATE_DIALPAGE:
04396 key_dial_page(pte, keycode);
04397 break;
04398 case STATE_RINGING:
04399 key_ringing(pte, keycode);
04400 break;
04401 case STATE_CALL:
04402 key_call(pte, keycode);
04403 break;
04404 case STATE_EXTENSION:
04405 key_select_extension(pte, keycode);
04406 break;
04407 case STATE_SELECTOPTION:
04408 key_select_option(pte, keycode);
04409 break;
04410 case STATE_SELECTCODEC:
04411 key_select_codec(pte, keycode);
04412 break;
04413 case STATE_SELECTLANGUAGE:
04414 key_select_language(pte, keycode);
04415 break;
04416 case STATE_HISTORY:
04417 key_history(pte, keycode);
04418 break;
04419 default:
04420 ast_log(LOG_WARNING, "Key : Unknown state\n");
04421 }
04422 return;
04423 }
04424 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
04425 if (unistimdebug) {
04426 ast_verb(0, "Handset off hook, current state: %s\n", ptestate_tostr(pte->state));
04427 }
04428 if (!pte->device) {
04429 return;
04430 }
04431 pte->device->receiver_state = STATE_OFFHOOK;
04432 if (pte->device->output == OUTPUT_HEADPHONE) {
04433 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
04434 } else {
04435 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04436 }
04437 if (pte->state == STATE_RINGING) {
04438 handle_call_incoming(pte);
04439 } else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL)) {
04440 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04441 } else if (pte->state == STATE_EXTENSION) {
04442 return;
04443 } else {
04444 pte->device->selected = get_avail_softkey(pte, NULL);
04445 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
04446 handle_dial_page(pte);
04447 }
04448 return;
04449 }
04450 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
04451 if (unistimdebug) {
04452 ast_verb(0, "Handset on hook, current state: %s\n", ptestate_tostr(pte->state));
04453 }
04454 if (!pte->device) {
04455 return;
04456 }
04457 pte->device->receiver_state = STATE_ONHOOK;
04458 if (pte->state == STATE_CALL) {
04459 if (pte->device->output != OUTPUT_SPEAKER) {
04460 close_call(pte);
04461 }
04462 } else if (pte->state == STATE_EXTENSION) {
04463 return;
04464 } else {
04465 pte->device->nextdial = 0;
04466 show_main_page(pte);
04467 }
04468 return;
04469 }
04470 strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
04471 strcat(tmpbuf, " Unknown request packet\n");
04472 if (unistimdebug) {
04473 ast_debug(1, "%s", tmpbuf);
04474 }
04475 return;
04476 }
04477
04478 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
04479 struct sockaddr_in *addr_from)
04480 {
04481 unsigned short *sbuf = (unsigned short *) buf;
04482 unsigned short seq;
04483 char tmpbuf[255];
04484
04485 strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
04486
04487 if (size < 10) {
04488 if (size == 0) {
04489 ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
04490 } else {
04491 ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
04492 }
04493 return;
04494 }
04495 if (sbuf[0] == 0xffff) {
04496 if (size != sizeof(packet_rcv_discovery)) {
04497 ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
04498 } else {
04499 if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
04500 if (unistimdebug) {
04501 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
04502 }
04503 if (pte) {
04504 if (pte->state == STATE_INIT) {
04505 if (unistimdebug) {
04506 ast_verb(1, "Duplicated Discovery packet\n");
04507 }
04508 send_raw_client(sizeof(packet_send_discovery_ack),
04509 packet_send_discovery_ack, addr_from, &pte->sout);
04510 pte->seq_phone = (short) 0x0000;
04511 } else {
04512 close_client(pte);
04513 if (create_client(addr_from)) {
04514 send_raw_client(sizeof(packet_send_discovery_ack),
04515 packet_send_discovery_ack, addr_from, &pte->sout);
04516 }
04517 }
04518 } else {
04519
04520 if ((pte = create_client(addr_from))) {
04521 send_raw_client(sizeof(packet_send_discovery_ack),
04522 packet_send_discovery_ack, addr_from, &pte->sout);
04523 }
04524 }
04525 return;
04526 }
04527 ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
04528 }
04529 return;
04530 }
04531 if (!pte) {
04532 if (unistimdebug) {
04533 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n", tmpbuf);
04534 }
04535 return;
04536 }
04537
04538 if (sbuf[0] != 0) {
04539 ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
04540 return;
04541 }
04542 if (buf[5] != 2) {
04543 ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
04544 (unsigned)buf[5]);
04545 return;
04546 }
04547 seq = ntohs(sbuf[1]);
04548 if (buf[4] == 1) {
04549 ast_mutex_lock(&pte->lock);
04550 if (unistimdebug) {
04551 ast_verb(6, "ACK received for packet #0x%.4x\n", (unsigned)seq);
04552 }
04553 pte->nb_retransmit = 0;
04554
04555 if ((pte->last_seq_ack) + 1 == seq) {
04556 pte->last_seq_ack++;
04557 check_send_queue(pte);
04558 ast_mutex_unlock(&pte->lock);
04559 return;
04560 }
04561 if (pte->last_seq_ack > seq) {
04562 if (pte->last_seq_ack == 0xffff) {
04563 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
04564 pte->last_seq_ack = 0;
04565 } else {
04566 ast_log(LOG_NOTICE,
04567 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
04568 tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
04569 }
04570 ast_mutex_unlock(&pte->lock);
04571 return;
04572 }
04573 if (pte->seq_server < seq) {
04574 ast_log(LOG_NOTICE,
04575 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
04576 tmpbuf, (unsigned)pte->seq_server);
04577 ast_mutex_unlock(&pte->lock);
04578 return;
04579 }
04580 if (unistimdebug) {
04581 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
04582 tmpbuf, (unsigned)seq, (unsigned)pte->last_seq_ack);
04583 }
04584 pte->last_seq_ack = seq;
04585 check_send_queue(pte);
04586 ast_mutex_unlock(&pte->lock);
04587 return;
04588 }
04589 if (buf[4] == 2) {
04590 if (unistimdebug) {
04591 ast_verb(0, "Request received\n");
04592 }
04593 if (pte->seq_phone == seq) {
04594
04595 buf[4] = 1;
04596 buf[5] = 1;
04597 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04598 pte->seq_phone++;
04599
04600 process_request(size, buf, pte);
04601 return;
04602 }
04603 if (pte->seq_phone > seq) {
04604 ast_log(LOG_NOTICE,
04605 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
04606 tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
04607
04608
04609 buf[4] = 1;
04610 buf[5] = 1;
04611 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
04612 return;
04613 }
04614 ast_log(LOG_NOTICE,
04615 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
04616 tmpbuf, (unsigned)seq, (unsigned)pte->seq_phone);
04617 return;
04618 }
04619 if (buf[4] == 0) {
04620 ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, (unsigned)seq);
04621 if (pte->last_seq_ack > seq) {
04622 ast_log(LOG_NOTICE,
04623 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
04624 tmpbuf, (unsigned)pte->last_seq_ack);
04625 return;
04626 }
04627 if (pte->seq_server < seq) {
04628 ast_log(LOG_NOTICE,
04629 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
04630 tmpbuf, (unsigned)pte->seq_server);
04631 return;
04632 }
04633 send_retransmit(pte);
04634 return;
04635 }
04636 ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
04637 tmpbuf, (unsigned)buf[4]);
04638 return;
04639 }
04640
04641 static struct unistimsession *channel_to_session(struct ast_channel *ast)
04642 {
04643 struct unistim_subchannel *sub;
04644 if (!ast) {
04645 ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
04646 return NULL;
04647 }
04648 if (!ast_channel_tech_pvt(ast)) {
04649 ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
04650 return NULL;
04651 }
04652 sub = ast_channel_tech_pvt(ast);
04653
04654 if (!sub->parent) {
04655 ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
04656 return NULL;
04657 }
04658 if (!sub->parent->parent) {
04659 ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
04660 return NULL;
04661 }
04662 ast_mutex_lock(&sub->parent->parent->lock);
04663 if (!sub->parent->parent->session) {
04664 ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
04665 ast_mutex_unlock(&sub->parent->parent->lock);
04666 return NULL;
04667 }
04668 ast_mutex_unlock(&sub->parent->parent->lock);
04669 return sub->parent->parent->session;
04670 }
04671
04672 static void send_callerid_screen(struct unistimsession *pte, struct unistim_subchannel *sub)
04673 {
04674 char *cidname_str;
04675 char *cidnum_str;
04676
04677 if (!sub) {
04678 return;
04679 }
04680 if (sub->owner) {
04681 if (ast_channel_connected(sub->owner)->id.number.valid && ast_channel_connected(sub->owner)->id.number.str) {
04682 cidnum_str = ast_channel_connected(sub->owner)->id.number.str;
04683 } else {
04684 cidnum_str = DEFAULTCALLERID;
04685 }
04686 change_callerid(pte, 0, cidnum_str);
04687 if (strlen(cidnum_str) == 0) {
04688 cidnum_str = DEFAULTCALLERID;
04689 }
04690
04691 if (ast_channel_connected(sub->owner)->id.name.valid && ast_channel_connected(sub->owner)->id.name.str) {
04692 cidname_str = ast_channel_connected(sub->owner)->id.name.str;
04693 } else {
04694 cidname_str = DEFAULTCALLERNAME;
04695 }
04696 change_callerid(pte, 1, cidname_str);
04697 if (strlen(cidname_str) == 0) {
04698 cidname_str = DEFAULTCALLERNAME;
04699 }
04700
04701 if (pte->device->height == 1) {
04702 char tmpstr[256];
04703 snprintf(tmpstr, sizeof(tmpstr), "%s %s", cidnum_str, ustmtext(cidname_str, pte));
04704 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpstr);
04705 } else {
04706 send_text(TEXT_LINE0, TEXT_NORMAL, pte, cidname_str);
04707 send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(cidnum_str, pte));
04708 }
04709 }
04710 }
04711
04712
04713
04714 static int unistim_call(struct ast_channel *ast, const char *dest, int timeout)
04715 {
04716 int res = 0, i;
04717 struct unistim_subchannel *sub, *sub_real;
04718 struct unistimsession *session;
04719 char ringstyle, ringvolume;
04720
04721 session = channel_to_session(ast);
04722 if (!session) {
04723 ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
04724 return -1;
04725 }
04726 sub = ast_channel_tech_pvt(ast);
04727 sub_real = get_sub(session->device, SUB_REAL);
04728 if ((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) {
04729 ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
04730 ast_channel_name(ast));
04731 return -1;
04732 }
04733
04734 if (unistimdebug) {
04735 ast_verb(3, "unistim_call(%s)\n", ast_channel_name(ast));
04736 }
04737 session->state = STATE_RINGING;
04738 send_callerid_screen(session, sub);
04739 if (ast_strlen_zero(ast_channel_call_forward(ast))) {
04740 send_text(TEXT_LINE2, TEXT_NORMAL, session, ustmtext("is calling you.", session));
04741 send_text_status(session, ustmtext("Accept Ignore Hangup", session));
04742
04743 if (sub_real) {
04744 ringstyle = session->device->cwstyle;
04745 ringvolume = session->device->cwvolume;
04746 } else {
04747 ringstyle = (sub->ringstyle == -1) ? session->device->ringstyle : sub->ringstyle;
04748 ringvolume = (sub->ringvolume == -1) ? session->device->ringvolume : sub->ringvolume;
04749 }
04750 send_ring(session, ringvolume, ringstyle);
04751 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
04752
04753 for (i = 0; i < FAVNUM; i++) {
04754 if (!soft_key_visible(session->device, i)) {
04755 continue;
04756 }
04757 if (session->device->ssub[i]) {
04758 continue;
04759 }
04760 if (is_key_line(session->device, i) && !strcmp(sub->parent->name, session->device->sline[i]->name)) {
04761 if (unistimdebug) {
04762 ast_verb(0, "Found softkey %d for line %s\n", i, sub->parent->name);
04763 }
04764 send_favorite_short(i, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST, session);
04765 session->device->ssub[i] = sub;
04766 }
04767 }
04768 }
04769 ast_setstate(ast, AST_STATE_RINGING);
04770 ast_queue_control(ast, AST_CONTROL_RINGING);
04771 return res;
04772 }
04773
04774 static int unistim_hangup_clean(struct ast_channel *ast, struct unistim_subchannel *sub) {
04775 ast_mutex_lock(&sub->lock);
04776 ast_channel_tech_pvt_set(ast, NULL);
04777 sub->owner = NULL;
04778 sub->alreadygone = 0;
04779 ast_mutex_unlock(&sub->lock);
04780 if (sub->rtp) {
04781 if (unistimdebug) {
04782 ast_verb(0, "Destroying RTP session\n");
04783 }
04784 ast_rtp_instance_destroy(sub->rtp);
04785 sub->rtp = NULL;
04786 }
04787 return 0;
04788 }
04789
04790
04791 static int unistim_hangup(struct ast_channel *ast)
04792 {
04793 struct unistim_subchannel *sub = NULL, *sub_real = NULL, *sub_trans = NULL;
04794 struct unistim_line *l;
04795 struct unistim_device *d;
04796 struct unistimsession *s;
04797 int i,end_call = 1;
04798
04799 s = channel_to_session(ast);
04800 sub = ast_channel_tech_pvt(ast);
04801 l = sub->parent;
04802 d = l->parent;
04803 if (!s) {
04804 ast_debug(1, "Asked to hangup channel not connected\n");
04805 unistim_hangup_clean(ast, sub);
04806 return 0;
04807 }
04808 if (unistimdebug) {
04809 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));
04810 }
04811 sub_trans = get_sub(d, SUB_THREEWAY);
04812 sub_real = get_sub(d, SUB_REAL);
04813 if (sub_trans && (sub_trans->owner) && (sub->subtype == SUB_REAL)) {
04814 if (unistimdebug) {
04815 ast_verb(0, "Threeway call disconnected, switching to real call\n");
04816 }
04817 if (ast_bridged_channel(sub_trans->owner)) {
04818 ast_moh_stop(ast_bridged_channel(sub_trans->owner));
04819 }
04820 sub_trans->moh = 0;
04821 sub_trans->subtype = SUB_REAL;
04822 swap_subs(sub_trans, sub);
04823 send_text_status(s, ustmtext(" Transf Hangup", s));
04824 send_callerid_screen(s, sub_trans);
04825 unistim_hangup_clean(ast, sub);
04826 unistim_unalloc_sub(d, sub);
04827 return 0;
04828 }
04829 if (sub_real && (sub_real->owner) && (sub->subtype == SUB_THREEWAY) && (s->state == STATE_CALL)) {
04830 if (unistimdebug) {
04831 ast_verb(0, "Real call disconnected, stay in call\n");
04832 }
04833 send_text_status(s, ustmtext(" Transf Hangup", s));
04834 send_callerid_screen(s, sub_real);
04835 unistim_hangup_clean(ast, sub);
04836 unistim_unalloc_sub(d, sub);
04837 return 0;
04838 }
04839 if (sub->subtype == SUB_REAL) {
04840 sub_stop_silence(s, sub);
04841 } else if (sub->subtype == SUB_RING) {
04842 send_no_ring(s);
04843 for (i = 0; i < FAVNUM; i++) {
04844 if (!soft_key_visible(s->device, i))
04845 continue;
04846 if (d->ssub[i] != sub)
04847 continue;
04848 if (is_key_line(d, i) && !strcmp(l->name, d->sline[i]->name)) {
04849 send_favorite_short(i, FAV_LINE_ICON, s);
04850 d->ssub[i] = NULL;
04851 continue;
04852 }
04853 if (d->ssub[i] != NULL) {
04854 end_call = 0;
04855 }
04856 }
04857 }
04858 if (end_call) {
04859 send_end_call(s);
04860 }
04861 sub->moh = 0;
04862 if (sub->softkey >= 0) {
04863 send_favorite_short(sub->softkey, FAV_LINE_ICON, s);
04864 }
04865
04866 for (i = 0; i < FAVNUM; i++) {
04867 if (d->ssub[i] == sub) {
04868 d->ssub[i] = NULL;
04869 break;
04870 }
04871 }
04872
04873 if (s->state == STATE_RINGING && sub->subtype == SUB_RING) {
04874 send_no_ring(s);
04875 if (ast_channel_hangupcause(ast) != AST_CAUSE_ANSWERED_ELSEWHERE) {
04876 d->missed_call++;
04877 write_history(s, 'i', 1);
04878 }
04879 if (!sub_real) {
04880 show_main_page(s);
04881 } else {
04882 s->state = STATE_CALL;
04883 send_callerid_screen(s, sub_real);
04884 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
04885 send_text_status(s, ustmtext(" Transf Hangup", s));
04886 send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
04887
04888 }
04889 }
04890 if (s->state == STATE_CALL && sub->subtype == SUB_REAL) {
04891 close_call(s);
04892 }
04893 sub->softkey = -1;
04894 unistim_hangup_clean(ast, sub);
04895 unistim_unalloc_sub(d, sub);
04896 return 0;
04897 }
04898
04899
04900 static int unistim_answer(struct ast_channel *ast)
04901 {
04902 int res = 0;
04903 struct unistim_subchannel *sub;
04904 struct unistim_line *l;
04905 struct unistim_device *d;
04906 struct unistimsession *s;
04907
04908 s = channel_to_session(ast);
04909 if (!s) {
04910 ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
04911 return -1;
04912 }
04913 sub = ast_channel_tech_pvt(ast);
04914 l = sub->parent;
04915 d = l->parent;
04916
04917 if (unistimdebug) {
04918 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast_channel_name(ast), l->name,
04919 l->parent->name, sub->softkey);
04920 }
04921 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is now on-line", s));
04922 if (get_sub(d, SUB_THREEWAY)) {
04923 send_text_status(s, ustmtext("Transf Cancel", s));
04924 } else {
04925 send_text_status(s, ustmtext(" Transf Hangup", s));
04926 }
04927 send_start_timer(s);
04928 if (ast_channel_state(ast) != AST_STATE_UP)
04929 ast_setstate(ast, AST_STATE_UP);
04930 return res;
04931 }
04932
04933
04934
04935 static int unistimsock_read(int *id, int fd, short events, void *ignore)
04936 {
04937 struct sockaddr_in addr_from = { 0, };
04938 struct unistimsession *cur = NULL;
04939 int found = 0;
04940 int tmp = 0;
04941 int dw_num_bytes_rcvd;
04942 unsigned int size_addr_from;
04943 #ifdef DUMP_PACKET
04944 int dw_num_bytes_rcvdd;
04945 #endif
04946
04947 size_addr_from = sizeof(addr_from);
04948 dw_num_bytes_rcvd =
04949 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
04950 &size_addr_from);
04951 if (dw_num_bytes_rcvd == -1) {
04952 if (errno == EAGAIN) {
04953 ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
04954 } else if (errno != ECONNREFUSED) {
04955 ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
04956 }
04957 return 1;
04958 }
04959
04960
04961 ast_mutex_lock(&sessionlock);
04962 cur = sessions;
04963 while (cur) {
04964 if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
04965 found = 1;
04966 break;
04967 }
04968 tmp++;
04969 cur = cur->next;
04970 }
04971 ast_mutex_unlock(&sessionlock);
04972
04973 #ifdef DUMP_PACKET
04974 if (unistimdebug)
04975 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
04976 dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
04977 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
04978 dw_num_bytes_rcvdd++)
04979 ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
04980 ast_verb(0, "\n******************************************\n");
04981 #endif
04982
04983 if (!found) {
04984 if (unistimdebug) {
04985 ast_verb(0, "Received a packet from an unknown source\n");
04986 }
04987 parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
04988
04989 } else {
04990 parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
04991 }
04992 return 1;
04993 }
04994
04995 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
04996 const struct unistim_subchannel *sub)
04997 {
04998
04999 struct ast_frame *f;
05000
05001 if (!ast) {
05002 ast_log(LOG_WARNING, "Channel NULL while reading\n");
05003 return &ast_null_frame;
05004 }
05005
05006 if (!sub->rtp) {
05007 ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %u\n",
05008 sub->subtype);
05009 return &ast_null_frame;
05010 }
05011
05012 switch (ast_channel_fdno(ast)) {
05013 case 0:
05014 f = ast_rtp_instance_read(sub->rtp, 0);
05015 break;
05016 case 1:
05017 f = ast_rtp_instance_read(sub->rtp, 1);
05018 break;
05019 default:
05020 f = &ast_null_frame;
05021 }
05022
05023 if (sub->owner) {
05024
05025 if (f->frametype == AST_FRAME_VOICE) {
05026 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(sub->owner), &f->subclass.format))) {
05027 char tmp[256];
05028 ast_debug(1,
05029 "Oooh, format changed from %s to %s\n",
05030 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(sub->owner)),
05031 ast_getformatname(&f->subclass.format));
05032
05033 ast_format_cap_set(ast_channel_nativeformats(sub->owner), &f->subclass.format);
05034 ast_set_read_format(sub->owner, ast_channel_readformat(sub->owner));
05035 ast_set_write_format(sub->owner, ast_channel_writeformat(sub->owner));
05036 }
05037 }
05038 }
05039
05040 return f;
05041 }
05042
05043 static struct ast_frame *unistim_read(struct ast_channel *ast)
05044 {
05045 struct ast_frame *fr;
05046 struct unistim_subchannel *sub = ast_channel_tech_pvt(ast);
05047
05048 ast_mutex_lock(&sub->lock);
05049 fr = unistim_rtp_read(ast, sub);
05050 ast_mutex_unlock(&sub->lock);
05051
05052 return fr;
05053 }
05054
05055 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
05056 {
05057 struct unistim_subchannel *sub = ast_channel_tech_pvt(ast);
05058 int res = 0;
05059
05060 if (frame->frametype != AST_FRAME_VOICE) {
05061 if (frame->frametype == AST_FRAME_IMAGE) {
05062 return 0;
05063 } else {
05064 ast_log(LOG_WARNING, "Can't send %u type frames with unistim_write\n",
05065 frame->frametype);
05066 return 0;
05067 }
05068 } else {
05069 if (!(ast_format_cap_iscompatible(ast_channel_nativeformats(ast), &frame->subclass.format))) {
05070 char tmp[256];
05071 ast_log(LOG_WARNING,
05072 "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
05073 ast_getformatname(&frame->subclass.format),
05074 ast_getformatname_multiple(tmp, sizeof(tmp), ast_channel_nativeformats(ast)),
05075 ast_getformatname(ast_channel_readformat(ast)),
05076 ast_getformatname(ast_channel_writeformat(ast)));
05077 return -1;
05078 }
05079 }
05080
05081 if (sub) {
05082 ast_mutex_lock(&sub->lock);
05083 if (sub->rtp) {
05084 res = ast_rtp_instance_write(sub->rtp, frame);
05085 }
05086 ast_mutex_unlock(&sub->lock);
05087 }
05088
05089 return res;
05090 }
05091
05092 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
05093 {
05094 struct unistim_subchannel *p = ast_channel_tech_pvt(newchan);
05095 struct unistim_line *l = p->parent;
05096
05097 ast_mutex_lock(&p->lock);
05098
05099 ast_debug(1, "New owner for channel USTM/%s@%s-%u is %s\n", l->name,
05100 l->parent->name, p->subtype, ast_channel_name(newchan));
05101
05102 if (p->owner != oldchan) {
05103 ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
05104 ast_channel_name(oldchan), oldchan, ast_channel_name(p->owner), p->owner);
05105 ast_mutex_unlock(&p->lock);
05106 return -1;
05107 }
05108
05109 p->owner = newchan;
05110
05111 ast_mutex_unlock(&p->lock);
05112
05113 return 0;
05114
05115 }
05116
05117 static char *control2str(int ind)
05118 {
05119 switch (ind) {
05120 case AST_CONTROL_HANGUP:
05121 return "Other end has hungup";
05122 case AST_CONTROL_RING:
05123 return "Local ring";
05124 case AST_CONTROL_RINGING:
05125 return "Remote end is ringing";
05126 case AST_CONTROL_ANSWER:
05127 return "Remote end has answered";
05128 case AST_CONTROL_BUSY:
05129 return "Remote end is busy";
05130 case AST_CONTROL_TAKEOFFHOOK:
05131 return "Make it go off hook";
05132 case AST_CONTROL_OFFHOOK:
05133 return "Line is off hook";
05134 case AST_CONTROL_CONGESTION:
05135 return "Congestion (circuits busy)";
05136 case AST_CONTROL_FLASH:
05137 return "Flash hook";
05138 case AST_CONTROL_WINK:
05139 return "Wink";
05140 case AST_CONTROL_OPTION:
05141 return "Set a low-level option";
05142 case AST_CONTROL_RADIO_KEY:
05143 return "Key Radio";
05144 case AST_CONTROL_RADIO_UNKEY:
05145 return "Un-Key Radio";
05146 case AST_CONTROL_CONNECTED_LINE:
05147 return "Remote end changed";
05148 case AST_CONTROL_SRCCHANGE:
05149 return "RTP source updated";
05150 case AST_CONTROL_SRCUPDATE:
05151 return "Source of media changed";
05152 case -1:
05153 return "Stop tone";
05154 }
05155 return "UNKNOWN";
05156 }
05157
05158 static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
05159 const char *indication)
05160 {
05161 struct ast_tone_zone_sound *ts = NULL;
05162
05163 if ((ts = ast_get_indication_tone(tz, indication))) {
05164 ast_playtones_start(ast, 0, ts->data, 1);
05165 ts = ast_tone_zone_sound_unref(ts);
05166 } else {
05167 ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
05168 }
05169 }
05170
05171 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
05172 size_t datalen)
05173 {
05174 struct unistim_subchannel *sub;
05175 struct unistim_line *l;
05176 struct unistimsession *s;
05177
05178 if (unistimdebug) {
05179 ast_verb(3, "Asked to indicate '%s' (%d) condition on channel %s\n",
05180 control2str(ind), ind, ast_channel_name(ast));
05181 }
05182
05183 s = channel_to_session(ast);
05184 if (!s) {
05185 return -1;
05186 }
05187 sub = ast_channel_tech_pvt(ast);
05188 l = sub->parent;
05189
05190 switch (ind) {
05191 case AST_CONTROL_RINGING:
05192 if (ast_channel_state(ast) != AST_STATE_UP) {
05193 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Ringing...", s));
05194 in_band_indication(ast, l->parent->tz, "ring");
05195 s->device->missed_call = -1;
05196 break;
05197 }
05198 return -1;
05199 case AST_CONTROL_BUSY:
05200 if (ast_channel_state(ast) != AST_STATE_UP) {
05201 sub->alreadygone = 1;
05202 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Busy", s));
05203 in_band_indication(ast, l->parent->tz, "busy");
05204 s->device->missed_call = -1;
05205 break;
05206 }
05207 return -1;
05208 case AST_CONTROL_INCOMPLETE:
05209
05210
05211
05212 case AST_CONTROL_CONGESTION:
05213 if (ast_channel_state(ast) != AST_STATE_UP) {
05214 sub->alreadygone = 1;
05215 send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Congestion", s));
05216 in_band_indication(ast, l->parent->tz, "congestion");
05217 s->device->missed_call = -1;
05218 break;
05219 }
05220 return -1;
05221 case AST_CONTROL_HOLD:
05222 ast_moh_start(ast, data, NULL);
05223 break;
05224 case AST_CONTROL_UNHOLD:
05225 ast_moh_stop(ast);
05226 break;
05227 case AST_CONTROL_PROGRESS:
05228 case AST_CONTROL_SRCUPDATE:
05229 case AST_CONTROL_PROCEEDING:
05230 break;
05231 case -1:
05232 ast_playtones_stop(ast);
05233 s->device->missed_call = 0;
05234 break;
05235 case AST_CONTROL_CONNECTED_LINE:
05236 ast_log(LOG_NOTICE, "Connected party is now %s <%s>\n",
05237 S_COR(ast_channel_connected(ast)->id.name.valid, ast_channel_connected(ast)->id.name.str, ""),
05238 S_COR(ast_channel_connected(ast)->id.number.valid, ast_channel_connected(ast)->id.number.str, ""));
05239 if (sub->subtype == SUB_REAL) {
05240 send_callerid_screen(s, sub);
05241 }
05242 case AST_CONTROL_UPDATE_RTP_PEER:
05243 break;
05244 case AST_CONTROL_SRCCHANGE:
05245 if (sub->rtp) {
05246 ast_rtp_instance_change_source(sub->rtp);
05247 }
05248 break;
05249 default:
05250 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
05251
05252 case AST_CONTROL_PVT_CAUSE_CODE:
05253 return -1;
05254 }
05255
05256 return 0;
05257 }
05258
05259 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
05260 {
05261 struct unistim_line *l;
05262 struct unistim_device *d;
05263 struct unistim_subchannel *sub = NULL;
05264 char line[256];
05265 char *at;
05266 char *device;
05267
05268 ast_copy_string(line, dest, sizeof(line));
05269 at = strchr(line, '@');
05270 if (!at) {
05271 ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
05272 return NULL;
05273 }
05274 *at = '\0';
05275 at++;
05276 device = at;
05277 ast_mutex_lock(&devicelock);
05278 d = devices;
05279 at = strchr(device, '/');
05280 if (at) {
05281 *at = '\0';
05282 }
05283 while (d) {
05284 if (!strcasecmp(d->name, device)) {
05285 if (unistimdebug) {
05286 ast_verb(0, "Found device: %s\n", d->name);
05287 }
05288
05289 AST_LIST_LOCK(&d->lines);
05290 AST_LIST_TRAVERSE(&d->lines, l, list) {
05291
05292 if (!strcasecmp(l->name, line)) {
05293 if (unistimdebug) {
05294 ast_verb(0, "Found line: %s\n", l->name);
05295 }
05296 sub = get_sub(d, SUB_REAL);
05297 if (!sub) {
05298 sub = unistim_alloc_sub(d, SUB_REAL);
05299 }
05300 if (sub->owner) {
05301
05302 sub = unistim_alloc_sub(d, SUB_ONHOLD);
05303 }
05304 sub->ringvolume = -1;
05305 sub->ringstyle = -1;
05306 if (at) {
05307 at++;
05308 if (*at == 'r') {
05309 at++;
05310 if ((*at < '0') || (*at > '7')) {
05311 ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
05312 } else {
05313 char ring_volume = -1;
05314 char ring_style = *at - '0';
05315 at++;
05316 if ((*at >= '0') && (*at <= '3')) {
05317 ring_volume = *at - '0';
05318 }
05319 if (unistimdebug) {
05320 ast_verb(0, "Distinctive ring: style #%d volume %d\n",
05321 ring_style, ring_volume);
05322 }
05323 sub->ringvolume = ring_volume;
05324 sub->ringstyle = ring_style;
05325 }
05326 }
05327 }
05328 sub->parent = l;
05329 break;
05330 }
05331 }
05332 AST_LIST_UNLOCK(&d->lines);
05333 if (sub) {
05334 ast_mutex_unlock(&devicelock);
05335 return sub;
05336 }
05337 }
05338 d = d->next;
05339 }
05340
05341 ast_mutex_unlock(&devicelock);
05342
05343 return NULL;
05344 }
05345
05346 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
05347 {
05348 struct unistimsession *pte = channel_to_session(ast);
05349
05350 if (!pte) {
05351 return -1;
05352 }
05353 return unistim_do_senddigit(pte, digit);
05354 }
05355
05356 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
05357 {
05358 struct unistimsession *pte = channel_to_session(ast);
05359 struct ast_frame f = { 0, };
05360 struct unistim_subchannel *sub;
05361
05362 sub = get_sub(pte->device, SUB_REAL);
05363
05364 if (!sub || !sub->owner || sub->alreadygone) {
05365 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
05366 return -1;
05367 }
05368
05369 if (unistimdebug) {
05370 ast_verb(0, "Send Digit off %c\n", digit);
05371 }
05372 if (!pte) {
05373 return -1;
05374 }
05375 send_tone(pte, 0, 0);
05376 f.frametype = AST_FRAME_DTMF;
05377 f.subclass.integer = digit;
05378 f.src = "unistim";
05379 ast_queue_frame(sub->owner, &f);
05380
05381 return 0;
05382 }
05383
05384
05385
05386 static int unistim_sendtext(struct ast_channel *ast, const char *text)
05387 {
05388 struct unistimsession *pte = channel_to_session(ast);
05389 int size;
05390 char tmp[TEXT_LENGTH_MAX + 1];
05391
05392 if (unistimdebug) {
05393 ast_verb(0, "unistim_sendtext called\n");
05394 }
05395 if (!text) {
05396 ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
05397 return -1;
05398 }
05399
05400 if (!pte) {
05401 return -1;
05402 }
05403
05404 size = strlen(text);
05405 if (text[0] == '@') {
05406 int pos = 0, i = 1, tok = 0, sz = 0;
05407 char label[11];
05408 char number[16];
05409 char icon = '\0';
05410 char cur = '\0';
05411
05412 memset(label, 0, 11);
05413 memset(number, 0, 16);
05414 while (text[i]) {
05415 cur = text[i++];
05416 switch (tok) {
05417 case 0:
05418 if ((cur < '0') && (cur > '5')) {
05419 ast_log(LOG_WARNING,
05420 "sendtext failed : position must be a number beetween 0 and 5\n");
05421 return 1;
05422 }
05423 pos = cur - '0';
05424 tok = 1;
05425 continue;
05426 case 1:
05427 if (cur != '@') {
05428 ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
05429 return 1;
05430 }
05431 tok = 2;
05432 continue;
05433 case 2:
05434 if ((cur < '3') && (cur > '6')) {
05435 ast_log(LOG_WARNING,
05436 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
05437 return 1;
05438 }
05439 icon = (cur - '0') * 10;
05440 tok = 3;
05441 continue;
05442 case 3:
05443 if ((cur < '0') && (cur > '9')) {
05444 ast_log(LOG_WARNING,
05445 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
05446 return 1;
05447 }
05448 icon += (cur - '0');
05449 tok = 4;
05450 continue;
05451 case 4:
05452 if (cur != '@') {
05453 ast_log(LOG_WARNING,
05454 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
05455 return 1;
05456 }
05457 tok = 5;
05458 continue;
05459 case 5:
05460 if (cur == '@') {
05461 tok = 6;
05462 sz = 0;
05463 continue;
05464 }
05465 if (sz > 10) {
05466 continue;
05467 }
05468 label[sz] = cur;
05469 sz++;
05470 continue;
05471 case 6:
05472 if (sz > 15) {
05473 ast_log(LOG_WARNING,
05474 "sendtext failed : extension too long = %d (15 car max)\n",
05475 sz);
05476 return 1;
05477 }
05478 number[sz] = cur;
05479 sz++;
05480 continue;
05481 }
05482 }
05483 if (tok != 6) {
05484 ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
05485 return 1;
05486 }
05487 if (!pte->device) {
05488 ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
05489 return 1;
05490 }
05491 strcpy(pte->device->softkeylabel[pos], label);
05492 strcpy(pte->device->softkeynumber[pos], number);
05493 pte->device->softkeyicon[pos] = icon;
05494 send_favorite(pos, icon, pte, label);
05495 return 0;
05496 }
05497
05498 if (size <= TEXT_LENGTH_MAX * 2) {
05499 if (pte->device->height == 1) {
05500 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
05501 } else {
05502 send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Message :", pte));
05503 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
05504 }
05505 if (size <= TEXT_LENGTH_MAX) {
05506 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
05507 return 0;
05508 }
05509 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
05510 tmp[sizeof(tmp) - 1] = '\0';
05511 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
05512 return 0;
05513 }
05514 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
05515 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
05516 tmp[sizeof(tmp) - 1] = '\0';
05517 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
05518 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
05519 tmp[sizeof(tmp) - 1] = '\0';
05520 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
05521 return 0;
05522 }
05523
05524
05525 static int unistim_send_mwi_to_peer(struct unistim_line *peer, unsigned int tick)
05526 {
05527 struct ast_event *event;
05528 int new;
05529 char *mailbox, *context;
05530
05531 context = mailbox = ast_strdupa(peer->mailbox);
05532 strsep(&context, "@");
05533 if (ast_strlen_zero(context)) {
05534 context = "default";
05535 }
05536 event = ast_event_get_cached(AST_EVENT_MWI,
05537 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
05538 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
05539 AST_EVENT_IE_END);
05540
05541 if (event) {
05542 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
05543 ast_event_destroy(event);
05544 } else {
05545 new = ast_app_has_voicemail(peer->mailbox, "INBOX");
05546 }
05547 ast_debug(3, "MWI Status for mailbox %s is %d, lastmsgsent:%d\n",mailbox,new,peer->parent->lastmsgssent);
05548 peer->parent->nextmsgcheck = tick + TIMER_MWI;
05549
05550
05551 if ((peer->parent->session->state != STATE_MAINPAGE) || (new == peer->parent->lastmsgssent)) {
05552 return 0;
05553 }
05554
05555 peer->parent->lastmsgssent = new;
05556 send_led_update(peer->parent->session, (new > 0));
05557
05558 return 0;
05559 }
05560
05561
05562
05563 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
05564 {
05565 struct ast_channel *tmp;
05566 struct unistim_line *l;
05567 struct ast_format tmpfmt;
05568
05569 if (!sub) {
05570 ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
05571 return NULL;
05572 }
05573 if (!sub->parent) {
05574 ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
05575 return NULL;
05576 }
05577 l = sub->parent;
05578 tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
05579 l->parent->context, linkedid, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub);
05580 if (unistimdebug) {
05581 ast_verb(0, "unistim_new sub=%u (%p) chan=%p line=%s\n", sub->subtype, sub, tmp, l->name);
05582 }
05583 if (!tmp) {
05584 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
05585 return NULL;
05586 }
05587
05588 ast_format_cap_copy(ast_channel_nativeformats(tmp), l->cap);
05589 if (ast_format_cap_is_empty(ast_channel_nativeformats(tmp))) {
05590 ast_format_cap_copy(ast_channel_nativeformats(tmp), global_cap);
05591 }
05592 ast_best_codec(ast_channel_nativeformats(tmp), &tmpfmt);
05593
05594 if (unistimdebug) {
05595 char tmp1[256], tmp2[256], tmp3[256];
05596 ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
05597 ast_getformatname(&tmpfmt),
05598 ast_getformatname_multiple(tmp1, sizeof(tmp1), ast_channel_nativeformats(tmp)),
05599 ast_getformatname_multiple(tmp2, sizeof(tmp2), l->cap),
05600 ast_getformatname_multiple(tmp3, sizeof(tmp3), global_cap));
05601 }
05602 if ((sub->rtp) && (sub->subtype == 0)) {
05603 if (unistimdebug) {
05604 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
05605 }
05606 ast_channel_internal_fd_set(tmp, 0, ast_rtp_instance_fd(sub->rtp, 0));
05607 ast_channel_internal_fd_set(tmp, 1, ast_rtp_instance_fd(sub->rtp, 1));
05608 }
05609 if (sub->rtp) {
05610 ast_jb_configure(tmp, &global_jbconf);
05611 }
05612
05613 ast_setstate(tmp, state);
05614 if (state == AST_STATE_RING) {
05615 ast_channel_rings_set(tmp, 1);
05616 }
05617 ast_channel_adsicpe_set(tmp, AST_ADSI_UNAVAILABLE);
05618 ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
05619 ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
05620 ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
05621 ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
05622 ast_channel_tech_pvt_set(tmp, sub);
05623 ast_channel_tech_set(tmp, &unistim_tech);
05624
05625 if (!ast_strlen_zero(l->parent->language)) {
05626 ast_channel_language_set(tmp, l->parent->language);
05627 }
05628 sub->owner = tmp;
05629 ast_update_use_count();
05630 ast_channel_callgroup_set(tmp, l->callgroup);
05631 ast_channel_pickupgroup_set(tmp, l->pickupgroup);
05632 ast_channel_call_forward_set(tmp, l->parent->call_forward);
05633 if (!ast_strlen_zero(l->cid_num)) {
05634 char *name, *loc, *instr;
05635 instr = ast_strdup(l->cid_num);
05636 if (instr) {
05637 ast_callerid_parse(instr, &name, &loc);
05638 ast_channel_caller(tmp)->id.number.valid = 1;
05639 ast_free(ast_channel_caller(tmp)->id.number.str);
05640 ast_channel_caller(tmp)->id.number.str = ast_strdup(loc);
05641 ast_channel_caller(tmp)->id.name.valid = 1;
05642 ast_free(ast_channel_caller(tmp)->id.name.str);
05643 ast_channel_caller(tmp)->id.name.str = ast_strdup(name);
05644 ast_free(instr);
05645 }
05646 }
05647 ast_channel_priority_set(tmp, 1);
05648 if (state != AST_STATE_DOWN) {
05649 if (unistimdebug) {
05650 ast_verb(0, "Starting pbx in unistim_new\n");
05651 }
05652 if (ast_pbx_start(tmp)) {
05653 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmp));
05654 ast_hangup(tmp);
05655 tmp = NULL;
05656 }
05657 }
05658
05659 return tmp;
05660 }
05661
05662 static void *do_monitor(void *data)
05663 {
05664 struct unistimsession *cur = NULL;
05665 unsigned int dw_timeout = 0;
05666 unsigned int tick;
05667 int res;
05668 int reloading;
05669
05670
05671 if (unistimsock > -1) {
05672 ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
05673 }
05674
05675 for (;;) {
05676
05677
05678 tick = get_tick_count();
05679 dw_timeout = UINT_MAX;
05680 ast_mutex_lock(&sessionlock);
05681 cur = sessions;
05682 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
05683 while (cur) {
05684 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
05685 cur->timeout);
05686
05687 if (cur->timeout <= tick) {
05688 DEBUG_TIMER("Event for session %p\n", cur);
05689
05690 if (cur->last_buf_available == 0) {
05691 send_ping(cur);
05692 } else {
05693 if (send_retransmit(cur)) {
05694 DEBUG_TIMER("The chained link was modified, restarting...\n");
05695 cur = sessions;
05696 dw_timeout = UINT_MAX;
05697 continue;
05698 }
05699 }
05700 }
05701 if (dw_timeout > cur->timeout - tick) {
05702 dw_timeout = cur->timeout - tick;
05703 }
05704
05705 if (cur->device) {
05706 struct unistim_line *l;
05707 AST_LIST_LOCK(&cur->device->lines);
05708 AST_LIST_TRAVERSE(&cur->device->lines, l, list) {
05709 if ((!ast_strlen_zero(l->mailbox)) && (tick >= l->parent->nextmsgcheck)) {
05710 DEBUG_TIMER("Checking mailbox for MWI\n");
05711 unistim_send_mwi_to_peer(l, tick);
05712 break;
05713 }
05714 }
05715 AST_LIST_UNLOCK(&cur->device->lines);
05716 if (cur->device->nextdial && tick >= cur->device->nextdial) {
05717 handle_call_outgoing(cur);
05718 cur->device->nextdial = 0;
05719 }
05720 }
05721 cur = cur->next;
05722 }
05723 ast_mutex_unlock(&sessionlock);
05724 DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
05725 res = dw_timeout;
05726
05727 if ((res < 0) || (res > IDLE_WAIT)) {
05728 res = IDLE_WAIT;
05729 }
05730
05731 res = ast_io_wait(io, res);
05732
05733 ast_mutex_lock(&unistim_reload_lock);
05734 reloading = unistim_reloading;
05735 unistim_reloading = 0;
05736 ast_mutex_unlock(&unistim_reload_lock);
05737 if (reloading) {
05738 ast_verb(1, "Reloading unistim.conf...\n");
05739 reload_config();
05740 }
05741 pthread_testcancel();
05742 }
05743
05744 return NULL;
05745 }
05746
05747
05748 static int restart_monitor(void)
05749 {
05750 pthread_attr_t attr;
05751
05752 if (monitor_thread == AST_PTHREADT_STOP) {
05753 return 0;
05754 }
05755 if (ast_mutex_lock(&monlock)) {
05756 ast_log(LOG_WARNING, "Unable to lock monitor\n");
05757 return -1;
05758 }
05759 if (monitor_thread == pthread_self()) {
05760 ast_mutex_unlock(&monlock);
05761 ast_log(LOG_WARNING, "Cannot kill myself\n");
05762 return -1;
05763 }
05764 if (monitor_thread != AST_PTHREADT_NULL) {
05765
05766 pthread_kill(monitor_thread, SIGURG);
05767 } else {
05768 pthread_attr_init(&attr);
05769 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
05770
05771 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
05772 ast_mutex_unlock(&monlock);
05773 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
05774 return -1;
05775 }
05776 }
05777 ast_mutex_unlock(&monlock);
05778 return 0;
05779 }
05780
05781
05782
05783 static struct ast_channel *unistim_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *dest,
05784 int *cause)
05785 {
05786 struct unistim_subchannel *sub, *sub_ring, *sub_trans;
05787 struct unistim_device *d;
05788 struct ast_channel *tmpc = NULL;
05789 char tmp[256];
05790 char tmp2[256];
05791
05792 if (!(ast_format_cap_has_joint(cap, global_cap))) {
05793 ast_log(LOG_NOTICE,
05794 "Asked to get a channel of unsupported format %s while capability is %s\n",
05795 ast_getformatname_multiple(tmp2, sizeof(tmp2), cap), ast_getformatname_multiple(tmp, sizeof(tmp), global_cap));
05796 return NULL;
05797 }
05798
05799 ast_copy_string(tmp, dest, sizeof(tmp));
05800 if (ast_strlen_zero(tmp)) {
05801 ast_log(LOG_NOTICE, "Unistim channels require a device\n");
05802 return NULL;
05803 }
05804 sub = find_subchannel_by_name(tmp);
05805 if (!sub) {
05806 ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
05807 *cause = AST_CAUSE_CONGESTION;
05808 return NULL;
05809 }
05810 d = sub->parent->parent;
05811 sub_ring = get_sub(d, SUB_RING);
05812 sub_trans = get_sub(d, SUB_THREEWAY);
05813
05814 if (!d->session) {
05815 unistim_unalloc_sub(d, sub);
05816 *cause = AST_CAUSE_CONGESTION;
05817 return NULL;
05818 }
05819 if (sub_ring || sub_trans) {
05820 if (unistimdebug) {
05821 ast_verb(0, "Can't create channel, request already in progress: Busy!\n");
05822 }
05823 unistim_unalloc_sub(d, sub);
05824 *cause = AST_CAUSE_BUSY;
05825 return NULL;
05826 }
05827 if (d->session->state == STATE_DIALPAGE) {
05828 if (unistimdebug) {
05829 ast_verb(0, "Can't create channel, user on dialpage: Busy!\n");
05830 }
05831 unistim_unalloc_sub(d, sub);
05832 *cause = AST_CAUSE_BUSY;
05833 return NULL;
05834 }
05835
05836 if (get_avail_softkey(d->session, sub->parent->name) == -1) {
05837 if (unistimdebug) {
05838 ast_verb(0, "Can't create channel for line %s, all lines busy\n", sub->parent->name);
05839 }
05840 unistim_unalloc_sub(d, sub);
05841 *cause = AST_CAUSE_BUSY;
05842 return NULL;
05843 }
05844 sub->subtype = SUB_RING;
05845 sub->softkey = -1;
05846 ast_format_cap_copy(sub->parent->cap, cap);
05847 tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? ast_channel_linkedid(requestor) : NULL);
05848 if (!tmpc) {
05849 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
05850 }
05851 if (unistimdebug) {
05852 ast_verb(0, "unistim_request owner = %p\n", sub->owner);
05853 }
05854 restart_monitor();
05855
05856 return tmpc;
05857 }
05858
05859 static char *unistim_show_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05860 {
05861 struct unistim_device *device = devices;
05862 struct unistim_line *line;
05863 struct unistim_subchannel *sub;
05864 struct unistimsession *s;
05865 struct ast_channel *tmp;
05866
05867 switch (cmd) {
05868 case CLI_INIT:
05869 e->command = "unistim show info";
05870 e->usage =
05871 "Usage: unistim show info\n"
05872 " Dump internal structures.\n\n"
05873 " device\n"
05874 " ->line\n"
05875 " -->sub\n"
05876 " ==>key\n";
05877 return NULL;
05878
05879 case CLI_GENERATE:
05880 return NULL;
05881 }
05882
05883 if (a->argc != e->args) {
05884 return CLI_SHOWUSAGE;
05885 }
05886 ast_cli(a->fd, "Dumping internal structures:\n");
05887 ast_mutex_lock(&devicelock);
05888 while (device) {
05889 int i;
05890
05891 ast_cli(a->fd, "\nname=%s id=%s ha=%p sess=%p device=%p selected=%d height=%d\n",
05892 device->name, device->id, device->ha, device->session,
05893 device, device->selected, device->height);
05894 AST_LIST_LOCK(&device->lines);
05895 AST_LIST_TRAVERSE(&device->lines,line,list) {
05896 char tmp2[256];
05897 ast_cli(a->fd,
05898 "->name=%s fullname=%s exten=%s callid=%s cap=%s line=%p\n",
05899 line->name, line->fullname, line->exten, line->cid_num,
05900 ast_getformatname_multiple(tmp2, sizeof(tmp2), line->cap), line);
05901 }
05902 AST_LIST_UNLOCK(&device->lines);
05903
05904 AST_LIST_LOCK(&device->subs);
05905 AST_LIST_TRAVERSE(&device->subs, sub, list) {
05906 if (!sub) {
05907 continue;
05908 }
05909 if (!sub->owner) {
05910 tmp = (void *) -42;
05911 } else {
05912 tmp = ast_channel_internal_bridged_channel(sub->owner);
05913 }
05914 ast_cli(a->fd,
05915 "-->subtype=%s chan=%p rtp=%p bridge=%p line=%p alreadygone=%d softkey=%d\n",
05916 subtype_tostr(sub->subtype), sub->owner, sub->rtp, tmp, sub->parent,
05917 sub->alreadygone, sub->softkey);
05918 }
05919 AST_LIST_UNLOCK(&device->subs);
05920
05921 for (i = 0; i < FAVNUM; i++) {
05922 if (!soft_key_visible(device, i)) {
05923 continue;
05924 }
05925 ast_cli(a->fd, "==> %d. dev=%s icon=%#-4x label=%-10s number=%-5s sub=%p line=%p\n",
05926 i, device->softkeydevice[i], (unsigned)device->softkeyicon[i], device->softkeylabel[i], device->softkeynumber[i],
05927 device->ssub[i], device->sline[i]);
05928 }
05929 device = device->next;
05930 }
05931 ast_mutex_unlock(&devicelock);
05932 ast_cli(a->fd, "\nSessions:\n");
05933 ast_mutex_lock(&sessionlock);
05934 s = sessions;
05935 while (s) {
05936 ast_cli(a->fd,
05937 "sin=%s timeout=%d state=%s macaddr=%s device=%p session=%p\n",
05938 ast_inet_ntoa(s->sin.sin_addr), s->timeout, ptestate_tostr(s->state), s->macaddr,
05939 s->device, s);
05940 s = s->next;
05941 }
05942 ast_mutex_unlock(&sessionlock);
05943
05944 return CLI_SUCCESS;
05945 }
05946
05947 static char *unistim_show_devices(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05948 {
05949 struct unistim_device *device = devices;
05950
05951 switch (cmd) {
05952 case CLI_INIT:
05953 e->command = "unistim show devices";
05954 e->usage =
05955 "Usage: unistim show devices\n"
05956 " Lists all known Unistim devices.\n";
05957 return NULL;
05958 case CLI_GENERATE:
05959 return NULL;
05960 }
05961
05962 if (a->argc != e->args)
05963 return CLI_SHOWUSAGE;
05964
05965 ast_cli(a->fd, "%-20.20s %-20.20s %-15.15s %s\n", "Name/username", "MAC", "Host", "Status");
05966 ast_mutex_lock(&devicelock);
05967 while (device) {
05968 ast_cli(a->fd, "%-20.20s %-20.20s %-15.15s %s\n",
05969 device->name, device->id,
05970 (!device->session) ? "(Unspecified)" : ast_inet_ntoa(device->session->sin.sin_addr),
05971 (!device->session) ? "UNKNOWN" : "OK");
05972 device = device->next;
05973 }
05974 ast_mutex_unlock(&devicelock);
05975
05976 return CLI_SUCCESS;
05977 }
05978
05979 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05980 {
05981 BUFFSEND;
05982 struct unistim_subchannel *sub;
05983 int i, j = 0, len;
05984 unsigned char c, cc;
05985 char tmp[256];
05986
05987 switch (cmd) {
05988 case CLI_INIT:
05989 e->command = "unistim send packet";
05990 e->usage =
05991 "Usage: unistim send packet USTM/line@name hexa\n"
05992 " unistim send packet USTM/1000@hans 19040004\n";
05993 return NULL;
05994
05995 case CLI_GENERATE:
05996 return NULL;
05997 }
05998
05999 if (a->argc < 5) {
06000 return CLI_SHOWUSAGE;
06001 }
06002 if (strlen(a->argv[3]) < 9) {
06003 return CLI_SHOWUSAGE;
06004 }
06005 len = strlen(a->argv[4]);
06006 if (len % 2) {
06007 return CLI_SHOWUSAGE;
06008 }
06009 ast_copy_string(tmp, a->argv[3] + 5, sizeof(tmp));
06010 sub = find_subchannel_by_name(tmp);
06011 if (!sub) {
06012 ast_cli(a->fd, "Can't find '%s'\n", tmp);
06013 return CLI_SUCCESS;
06014 }
06015 if (!sub->parent->parent->session) {
06016 ast_cli(a->fd, "'%s' is not connected\n", tmp);
06017 return CLI_SUCCESS;
06018 }
06019 ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->parent->parent->session);
06020 for (i = 0; i < len; i++) {
06021 c = a->argv[4][i];
06022 if (c >= 'a') {
06023 c -= 'a' - 10;
06024 } else {
06025 c -= '0';
06026 }
06027 i++;
06028 cc = a->argv[4][i];
06029 if (cc >= 'a') {
06030 cc -= 'a' - 10;
06031 } else {
06032 cc -= '0';
06033 }
06034 tmp[j++] = (c << 4) | cc;
06035 }
06036 memcpy(buffsend + SIZE_HEADER, tmp, j);
06037 send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
06038 return CLI_SUCCESS;
06039 }
06040
06041 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06042 {
06043 switch (cmd) {
06044 case CLI_INIT:
06045 e->command = "unistim set debug {on|off}";
06046 e->usage =
06047 "Usage: unistim set debug\n"
06048 " Display debug messages.\n";
06049 return NULL;
06050
06051 case CLI_GENERATE:
06052 return NULL;
06053 }
06054
06055 if (a->argc != e->args) {
06056 return CLI_SHOWUSAGE;
06057 }
06058 if (!strcasecmp(a->argv[3], "on")) {
06059 unistimdebug = 1;
06060 ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
06061 } else if (!strcasecmp(a->argv[3], "off")) {
06062 unistimdebug = 0;
06063 ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
06064 } else {
06065 return CLI_SHOWUSAGE;
06066 }
06067 return CLI_SUCCESS;
06068 }
06069
06070
06071
06072
06073
06074 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06075 {
06076 switch (cmd) {
06077 case CLI_INIT:
06078 e->command = "unistim reload";
06079 e->usage =
06080 "Usage: unistim reload\n"
06081 " Reloads UNISTIM configuration from unistim.conf\n";
06082 return NULL;
06083
06084 case CLI_GENERATE:
06085 return NULL;
06086 }
06087
06088 if (e && a && a->argc != e->args) {
06089 return CLI_SHOWUSAGE;
06090 }
06091 reload();
06092
06093 return CLI_SUCCESS;
06094 }
06095
06096 static struct ast_cli_entry unistim_cli[] = {
06097 AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
06098 AST_CLI_DEFINE(unistim_show_info, "Show UNISTIM info"),
06099 AST_CLI_DEFINE(unistim_show_devices, "Show UNISTIM devices"),
06100 AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
06101 AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
06102 };
06103
06104 static void unquote(char *out, const char *src, int maxlen)
06105 {
06106 int len = strlen(src);
06107 if (!len) {
06108 return;
06109 }
06110 if ((len > 1) && src[0] == '\"') {
06111
06112 src++;
06113
06114 len--;
06115 if (maxlen > len - 1) {
06116 maxlen = len - 1;
06117 }
06118 memcpy(out, src, maxlen);
06119 ((char *) out)[maxlen] = '\0';
06120 } else {
06121 memcpy(out, src, maxlen);
06122 }
06123 return;
06124 }
06125
06126 static int parse_bookmark(const char *text, struct unistim_device *d)
06127 {
06128 char line[256];
06129 char *at;
06130 char *number;
06131 char *icon;
06132 int p;
06133 int len = strlen(text);
06134
06135 ast_copy_string(line, text, sizeof(line));
06136
06137 if ((len > 2) && (line[1] == '@')) {
06138 p = line[0];
06139 if ((p >= '0') && (p <= '5')) {
06140 p -= '0';
06141 } else {
06142 ast_log(LOG_WARNING,
06143 "Invalid position for bookmark : must be between 0 and 5\n");
06144 return 0;
06145 }
06146 if (d->softkeyicon[p] != 0) {
06147 ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used:\n", p);
06148 return 0;
06149 }
06150 memmove(line, line + 2, sizeof(line) - 2);
06151 } else {
06152
06153 for (p = 0; p <= 5; p++) {
06154 if (!d->softkeyicon[p]) {
06155 break;
06156 }
06157 }
06158 if (p > 5) {
06159 ast_log(LOG_WARNING, "No more free bookmark position\n");
06160 return 0;
06161 }
06162 }
06163 at = strchr(line, '@');
06164 if (!at) {
06165 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
06166 return 0;
06167 }
06168 *at = '\0';
06169 at++;
06170 number = at;
06171 at = strchr(at, '@');
06172 if (ast_strlen_zero(number)) {
06173 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
06174 return 0;
06175 }
06176 if (ast_strlen_zero(line)) {
06177 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
06178 return 0;
06179 }
06180
06181 at = strchr(number, '@');
06182 if (!at) {
06183 d->softkeyicon[p] = FAV_ICON_SHARP;
06184 } else {
06185 *at = '\0';
06186 at++;
06187 icon = at;
06188 if (ast_strlen_zero(icon)) {
06189 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
06190 return 0;
06191 }
06192 if (strncmp(icon, "USTM/", 5)) {
06193 d->softkeyicon[p] = atoi(icon);
06194 } else {
06195 d->softkeyicon[p] = 1;
06196 ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
06197 }
06198 }
06199 ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
06200 ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
06201 if (unistimdebug) {
06202 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%#x\n",
06203 p, d->softkeylabel[p], d->softkeynumber[p], (unsigned)d->softkeyicon[p]);
06204 }
06205 return 1;
06206 }
06207
06208
06209 static void finish_bookmark(void)
06210 {
06211 struct unistim_device *d = devices;
06212 int i;
06213 ast_mutex_lock(&devicelock);
06214 while (d) {
06215 for (i = 0; i < 6; i++) {
06216 if (d->softkeyicon[i] == 1) {
06217 struct unistim_device *d2 = devices;
06218 while (d2) {
06219 if (!strcmp(d->softkeydevice[i], d2->name)) {
06220 d->sp[i] = d2;
06221 d->softkeyicon[i] = 0;
06222 break;
06223 }
06224 d2 = d2->next;
06225 }
06226 if (d->sp[i] == NULL) {
06227 ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
06228 d->softkeydevice[i]);
06229 }
06230 }
06231 }
06232 d = d->next;
06233 }
06234 ast_mutex_unlock(&devicelock);
06235 }
06236
06237 static struct unistim_line *find_line_by_number(struct unistim_device *d, const char *val) {
06238 struct unistim_line *l, *ret = NULL;
06239
06240 AST_LIST_LOCK(&d->lines);
06241 AST_LIST_TRAVERSE(&d->lines, l, list) {
06242 if (!strcmp(l->name, val)) {
06243 ret = l;
06244 break;
06245 }
06246 }
06247 AST_LIST_UNLOCK(&d->lines);
06248 return ret;
06249 }
06250
06251 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
06252 {
06253 struct unistim_device *d;
06254 struct unistim_line *l = NULL, *lt = NULL;
06255 int create = 1;
06256 int nbsoftkey, dateformat, timeformat, callhistory, sharpdial, linecnt;
06257 char linelabel[AST_MAX_EXTENSION];
06258 char ringvolume, ringstyle, cwvolume, cwstyle;
06259
06260
06261
06262 ast_mutex_lock(&devicelock);
06263 d = devices;
06264 while (d) {
06265 if (!strcmp(d->name, cat)) {
06266
06267 if (unistimsock < 0) {
06268
06269 ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
06270 ast_mutex_unlock(&devicelock);
06271 return NULL;
06272 }
06273
06274 create = 0;
06275 break;
06276 }
06277 d = d->next;
06278 }
06279 ast_mutex_unlock(&devicelock);
06280 if (!(lt = ast_calloc(1, sizeof(*lt)))) {
06281 return NULL;
06282 }
06283 if (create) {
06284 if (!(d = ast_calloc(1, sizeof(*d)))) {
06285 return NULL;
06286 }
06287 ast_mutex_init(&d->lock);
06288 ast_copy_string(d->name, cat, sizeof(d->name));
06289 d->contrast = -1;
06290 d->output = OUTPUT_HANDSET;
06291 d->previous_output = OUTPUT_HANDSET;
06292 d->volume = VOLUME_LOW;
06293 d->mute = MUTE_OFF;
06294 d->height = DEFAULTHEIGHT;
06295 d->selected = -1;
06296 } else {
06297
06298 AST_LIST_LOCK(&d->lines);
06299 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06300 AST_LIST_REMOVE_CURRENT(list);
06301 unistim_line_destroy(l);
06302 }
06303 AST_LIST_TRAVERSE_SAFE_END
06304 AST_LIST_UNLOCK(&d->lines);
06305
06306
06307 memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
06308 memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
06309 memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
06310 memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
06311 memset(d->ssub, 0, sizeof(d->ssub));
06312 memset(d->sline, 0, sizeof(d->sline));
06313 memset(d->sp, 0, sizeof(d->sp));
06314 }
06315 ast_copy_string(d->context, DEFAULTCONTEXT, sizeof(d->context));
06316 d->selected = -1;
06317 d->interdigit_timer = DEFAULT_INTERDIGIT_TIMER;
06318 linelabel[0] = '\0';
06319 dateformat = 1;
06320 timeformat = 1;
06321 ringvolume = 2;
06322 cwvolume = 1;
06323 callhistory = 1;
06324 sharpdial = 0;
06325 ringstyle = 3;
06326 cwstyle = 2;
06327 nbsoftkey = 0;
06328 linecnt = 0;
06329 while (v) {
06330 if (!strcasecmp(v->name, "rtp_port")) {
06331 d->rtp_port = atoi(v->value);
06332 } else if (!strcasecmp(v->name, "rtp_method")) {
06333 d->rtp_method = atoi(v->value);
06334 } else if (!strcasecmp(v->name, "status_method")) {
06335 d->status_method = atoi(v->value);
06336 } else if (!strcasecmp(v->name, "device")) {
06337 ast_copy_string(d->id, v->value, sizeof(d->id));
06338 } else if (!strcasecmp(v->name, "tn")) {
06339 ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
06340 } else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny")) {
06341 d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
06342 } else if (!strcasecmp(v->name, "context")) {
06343 ast_copy_string(d->context, v->value, sizeof(d->context));
06344 } else if (!strcasecmp(v->name, "maintext0")) {
06345 unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
06346 } else if (!strcasecmp(v->name, "maintext1")) {
06347 unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
06348 } else if (!strcasecmp(v->name, "maintext2")) {
06349 unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
06350 } else if (!strcasecmp(v->name, "titledefault")) {
06351 unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
06352 } else if (!strcasecmp(v->name, "dateformat")) {
06353 dateformat = atoi(v->value);
06354 } else if (!strcasecmp(v->name, "timeformat")) {
06355 timeformat = atoi(v->value);
06356 } else if (!strcasecmp(v->name, "contrast")) {
06357 d->contrast = atoi(v->value);
06358 if ((d->contrast < 0) || (d->contrast > 15)) {
06359 ast_log(LOG_WARNING, "contrast must be beetween 0 and 15\n");
06360 d->contrast = 8;
06361 }
06362 } else if (!strcasecmp(v->name, "nat")) {
06363 d->nat = ast_true(v->value);
06364 } else if (!strcasecmp(v->name, "ringvolume")) {
06365 ringvolume = atoi(v->value);
06366 } else if (!strcasecmp(v->name, "ringstyle")) {
06367 ringstyle = atoi(v->value);
06368 } else if (!strcasecmp(v->name, "cwvolume")) {
06369 cwvolume = atoi(v->value);
06370 } else if (!strcasecmp(v->name, "cwstyle")) {
06371 cwstyle = atoi(v->value);
06372 } else if (!strcasecmp(v->name, "callhistory")) {
06373 callhistory = atoi(v->value);
06374 } else if (!strcasecmp(v->name, "sharpdial")) {
06375 sharpdial = ast_true(v->value) ? 1 : 0;
06376 } else if (!strcasecmp(v->name, "interdigit_timer")) {
06377 d->interdigit_timer = atoi(v->value);
06378 } else if (!strcasecmp(v->name, "callerid")) {
06379 if (!strcasecmp(v->value, "asreceived")) {
06380 lt->cid_num[0] = '\0';
06381 } else {
06382 ast_copy_string(lt->cid_num, v->value, sizeof(lt->cid_num));
06383 }
06384 } else if (!strcasecmp(v->name, "language")) {
06385 ast_copy_string(d->language, v->value, sizeof(d->language));
06386 } else if (!strcasecmp(v->name, "country")) {
06387 ast_copy_string(d->country, v->value, sizeof(d->country));
06388 } else if (!strcasecmp(v->name, "accountcode")) {
06389 ast_copy_string(lt->accountcode, v->value, sizeof(lt->accountcode));
06390 } else if (!strcasecmp(v->name, "amaflags")) {
06391 int y;
06392 y = ast_cdr_amaflags2int(v->value);
06393 if (y < 0) {
06394 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
06395 v->lineno);
06396 } else {
06397 lt->amaflags = y;
06398 }
06399 } else if (!strcasecmp(v->name, "musiconhold")) {
06400 ast_copy_string(lt->musicclass, v->value, sizeof(lt->musicclass));
06401 } else if (!strcasecmp(v->name, "callgroup")) {
06402 lt->callgroup = ast_get_group(v->value);
06403 } else if (!strcasecmp(v->name, "pickupgroup")) {
06404 lt->pickupgroup = ast_get_group(v->value);
06405 } else if (!strcasecmp(v->name, "mailbox")) {
06406 ast_copy_string(lt->mailbox, v->value, sizeof(lt->mailbox));
06407 } else if (!strcasecmp(v->name, "parkinglot")) {
06408 ast_copy_string(lt->parkinglot, v->value, sizeof(lt->parkinglot));
06409 } else if (!strcasecmp(v->name, "linelabel")) {
06410 unquote(linelabel, v->value, sizeof(linelabel) - 1);
06411 } else if (!strcasecmp(v->name, "extension")) {
06412 if (!strcasecmp(v->value, "none")) {
06413 d->extension = EXTENSION_NONE;
06414 } else if (!strcasecmp(v->value, "ask")) {
06415 d->extension = EXTENSION_ASK;
06416 } else if (!strcasecmp(v->value, "line")) {
06417 d->extension = EXTENSION_LINE;
06418 } else {
06419 ast_log(LOG_WARNING, "Unknown extension option.\n");
06420 }
06421 } else if (!strcasecmp(v->name, "bookmark")) {
06422 if (nbsoftkey > 5) {
06423 ast_log(LOG_WARNING,
06424 "More than 6 softkeys defined. Ignoring new entries.\n");
06425 } else {
06426 if (parse_bookmark(v->value, d)) {
06427 nbsoftkey++;
06428 }
06429 }
06430 } else if (!strcasecmp(v->name, "line")) {
06431 int len = strlen(linelabel);
06432 int create_line = 0;
06433
06434 l = find_line_by_number(d, v->value);
06435 if (!l) {
06436 if (!(l = unistim_line_alloc())) {
06437 ast_free(d);
06438 ast_free(lt);
06439 return NULL;
06440 }
06441 lt->cap = l->cap;
06442 memcpy(l, lt, sizeof(*l));
06443 ast_mutex_init(&l->lock);
06444 create_line = 1;
06445 }
06446 d->to_delete = 0;
06447
06448
06449 d->sline[nbsoftkey] = l;
06450 d->softkeyicon[nbsoftkey] = FAV_LINE_ICON;
06451 if (!len) {
06452 ast_copy_string(d->softkeylabel[nbsoftkey], v->value, sizeof(d->softkeylabel[nbsoftkey]));
06453 } else {
06454 int softkeylinepos = 0;
06455 if ((len > 2) && (linelabel[1] == '@')) {
06456 softkeylinepos = linelabel[0];
06457 if ((softkeylinepos >= '0') && (softkeylinepos <= '5')) {
06458 softkeylinepos -= '0';
06459 d->softkeyicon[nbsoftkey] = FAV_ICON_NONE;
06460 } else {
06461 ast_log(LOG_WARNING,
06462 "Invalid position for linelabel : must be between 0 and 5\n");
06463 }
06464 ast_copy_string(d->softkeylabel[softkeylinepos], linelabel + 2,
06465 sizeof(d->softkeylabel[softkeylinepos]));
06466 d->softkeyicon[softkeylinepos] = FAV_LINE_ICON;
06467 } else {
06468 ast_copy_string(d->softkeylabel[nbsoftkey], linelabel,
06469 sizeof(d->softkeylabel[nbsoftkey]));
06470 }
06471 }
06472 nbsoftkey++;
06473
06474 if (create_line) {
06475 ast_copy_string(l->name, v->value, sizeof(l->name));
06476 snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
06477 if (!ast_strlen_zero(l->mailbox)) {
06478 if (unistimdebug) {
06479 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
06480 }
06481 }
06482 ast_format_cap_copy(l->cap, global_cap);
06483 l->parent = d;
06484 linecnt++;
06485 AST_LIST_LOCK(&d->lines);
06486 AST_LIST_INSERT_TAIL(&d->lines, l, list);
06487 AST_LIST_UNLOCK(&d->lines);
06488 }
06489 } else if (!strcasecmp(v->name, "height")) {
06490
06491
06492 d->height = atoi(v->value);
06493 } else
06494 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
06495 v->lineno);
06496 v = v->next;
06497 }
06498 ast_free(lt);
06499 if (linecnt == 0) {
06500 ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
06501 ast_free(d);
06502 return NULL;
06503 }
06504 d->ringvolume = ringvolume;
06505 d->ringstyle = ringstyle;
06506 d->cwvolume = cwvolume;
06507 d->cwstyle = cwstyle;
06508 d->callhistory = callhistory;
06509 d->sharp_dial = sharpdial;
06510 d->tz = ast_get_indication_zone(d->country);
06511 if ((d->tz == NULL) && !ast_strlen_zero(d->country)) {
06512 ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
06513 d->country);
06514 }
06515 d->datetimeformat = 56 + (dateformat * 4);
06516 d->datetimeformat += timeformat;
06517 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
06518 (!ast_strlen_zero(d->extension_number))) {
06519 d->extension = EXTENSION_TN;
06520 if (!ast_strlen_zero(d->id)) {
06521 ast_log(LOG_WARNING,
06522 "tn= and device= can't be used together. Ignoring device= entry\n");
06523 }
06524 d->id[0] = 'T';
06525 ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
06526 d->extension_number[0] = '\0';
06527 } else if (ast_strlen_zero(d->id)) {
06528 if (strcmp(d->name, "template")) {
06529 ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
06530 if (d->tz) {
06531 d->tz = ast_tone_zone_unref(d->tz);
06532 }
06533 ast_free(d);
06534 return NULL;
06535 } else {
06536 strcpy(d->id, "000000000000");
06537 }
06538 }
06539 if (!d->rtp_port) {
06540 d->rtp_port = 10000;
06541 }
06542 if (d->contrast == -1) {
06543 d->contrast = 8;
06544 }
06545 if (ast_strlen_zero(d->maintext1)) {
06546 strcpy(d->maintext1, d->name);
06547 }
06548 if (ast_strlen_zero(d->titledefault)) {
06549 struct ast_tm tm = { 0, };
06550 struct timeval cur_time = ast_tvnow();
06551
06552 if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
06553 ast_log(LOG_WARNING, "Error in ast_localtime()\n");
06554 ast_copy_string(d->titledefault, "UNISTIM for*", 12);
06555 } else {
06556 if (strlen(tm.tm_zone) < 4) {
06557 strcpy(d->titledefault, "TimeZone ");
06558 strcat(d->titledefault, tm.tm_zone);
06559 } else if (strlen(tm.tm_zone) < 9) {
06560 strcpy(d->titledefault, "TZ ");
06561 strcat(d->titledefault, tm.tm_zone);
06562 } else {
06563 ast_copy_string(d->titledefault, tm.tm_zone, 12);
06564 }
06565 }
06566 }
06567
06568 if (create) {
06569 ast_mutex_lock(&devicelock);
06570 d->next = devices;
06571 devices = d;
06572 ast_mutex_unlock(&devicelock);
06573 ast_verb(3, "Added device '%s'\n", d->name);
06574 } else {
06575 ast_verb(3, "Device '%s' reloaded\n", d->name);
06576 }
06577 return d;
06578 }
06579
06580
06581 static int reload_config(void)
06582 {
06583 struct ast_config *cfg;
06584 struct ast_variable *v;
06585 struct ast_hostent ahp;
06586 struct hostent *hp;
06587 struct sockaddr_in bindaddr = { 0, };
06588 char *config = "unistim.conf";
06589 char *cat;
06590 struct unistim_device *d;
06591 const int reuseFlag = 1;
06592 struct unistimsession *s;
06593 struct ast_flags config_flags = { 0, };
06594
06595 cfg = ast_config_load(config, config_flags);
06596
06597 if (!cfg) {
06598 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
06599 return -1;
06600 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
06601 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
06602 return -1;
06603 }
06604
06605
06606 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
06607
06608 unistim_keepalive = 120;
06609 unistim_port = 0;
06610 v = ast_variable_browse(cfg, "general");
06611 while (v) {
06612
06613 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value)) {
06614 continue;
06615 }
06616 if (!strcasecmp(v->name, "keepalive")) {
06617 unistim_keepalive = atoi(v->value);
06618 } else if (!strcasecmp(v->name, "port")) {
06619 unistim_port = atoi(v->value);
06620 } else if (!strcasecmp(v->name, "tos")) {
06621 if (ast_str2tos(v->value, &qos.tos)) {
06622 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
06623 }
06624 } else if (!strcasecmp(v->name, "tos_audio")) {
06625 if (ast_str2tos(v->value, &qos.tos_audio)) {
06626 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06627 }
06628 } else if (!strcasecmp(v->name, "cos")) {
06629 if (ast_str2cos(v->value, &qos.cos)) {
06630 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
06631 }
06632 } else if (!strcasecmp(v->name, "cos_audio")) {
06633 if (ast_str2cos(v->value, &qos.cos_audio)) {
06634 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
06635 }
06636 } else if (!strcasecmp(v->name, "debug")) {
06637 if (!strcasecmp(v->value, "no")) {
06638 unistimdebug = 0;
06639 } else if (!strcasecmp(v->value, "yes")) {
06640 unistimdebug = 1;
06641 }
06642 } else if (!strcasecmp(v->name, "autoprovisioning")) {
06643 if (!strcasecmp(v->value, "no")) {
06644 autoprovisioning = AUTOPROVISIONING_NO;
06645 } else if (!strcasecmp(v->value, "yes")) {
06646 autoprovisioning = AUTOPROVISIONING_YES;
06647 } else if (!strcasecmp(v->value, "tn")) {
06648 autoprovisioning = AUTOPROVISIONING_TN;
06649 } else {
06650 ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
06651 }
06652 } else if (!strcasecmp(v->name, "public_ip")) {
06653 if (!ast_strlen_zero(v->value)) {
06654 if (!(hp = ast_gethostbyname(v->value, &ahp))) {
06655 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
06656 } else {
06657 memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
06658 public_ip.sin_family = AF_INET;
06659 }
06660 }
06661 }
06662 v = v->next;
06663 }
06664 if ((unistim_keepalive < 10) ||
06665 (unistim_keepalive >
06666 255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
06667 ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
06668 ast_config_destroy(cfg);
06669 return -1;
06670 }
06671 packet_send_ping[4] =
06672 unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
06673 if ((unistim_port < 1) || (unistim_port > 65535)) {
06674 ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
06675 ast_config_destroy(cfg);
06676 return -1;
06677 }
06678 unistim_keepalive *= 1000;
06679
06680 ast_mutex_lock(&devicelock);
06681 d = devices;
06682 while (d) {
06683 if (d->to_delete >= 0) {
06684 d->to_delete = 1;
06685 }
06686 d = d->next;
06687 }
06688 ast_mutex_unlock(&devicelock);
06689
06690 cat = ast_category_browse(cfg, NULL);
06691 while (cat) {
06692 if (strcasecmp(cat, "general")) {
06693 d = build_device(cat, ast_variable_browse(cfg, cat));
06694 }
06695 cat = ast_category_browse(cfg, cat);
06696 }
06697 ast_mutex_lock(&devicelock);
06698 d = devices;
06699 while (d) {
06700 if (d->to_delete) {
06701 struct unistim_line *l;
06702 struct unistim_subchannel *sub;
06703
06704 if (unistimdebug) {
06705 ast_verb(0, "Removing device '%s'\n", d->name);
06706 }
06707 AST_LIST_LOCK(&d->subs);
06708 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, sub, list){
06709 if (sub->subtype == SUB_REAL) {
06710 if (!sub) {
06711 ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
06712 d->name);
06713 ast_config_destroy(cfg);
06714 return 0;
06715 }
06716 if (sub->owner) {
06717 ast_log(LOG_WARNING,
06718 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
06719 d->name);
06720 d = d->next;
06721 continue;
06722 }
06723 }
06724 if (sub->subtype == SUB_THREEWAY) {
06725 ast_log(LOG_WARNING,
06726 "Device '%s' with threeway call subchannels allocated, aborting.\n",
06727 d->name);
06728 break;
06729 }
06730 AST_LIST_REMOVE_CURRENT(list);
06731 ast_mutex_destroy(&sub->lock);
06732 ast_free(sub);
06733 }
06734 AST_LIST_TRAVERSE_SAFE_END
06735 AST_LIST_UNLOCK(&d->subs);
06736
06737
06738 AST_LIST_LOCK(&d->lines);
06739 AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
06740 AST_LIST_REMOVE_CURRENT(list);
06741 ast_mutex_destroy(&l->lock);
06742 unistim_line_destroy(l);
06743 }
06744 AST_LIST_TRAVERSE_SAFE_END
06745 AST_LIST_UNLOCK(&d->lines);
06746
06747 if (d->session) {
06748 if (sessions == d->session) {
06749 sessions = d->session->next;
06750 } else {
06751 s = sessions;
06752 while (s) {
06753 if (s->next == d->session) {
06754 s->next = d->session->next;
06755 break;
06756 }
06757 s = s->next;
06758 }
06759 }
06760 ast_mutex_destroy(&d->session->lock);
06761 ast_free(d->session);
06762 }
06763 if (devices == d) {
06764 devices = d->next;
06765 } else {
06766 struct unistim_device *d2 = devices;
06767 while (d2) {
06768 if (d2->next == d) {
06769 d2->next = d->next;
06770 break;
06771 }
06772 d2 = d2->next;
06773 }
06774 }
06775 if (d->tz) {
06776 d->tz = ast_tone_zone_unref(d->tz);
06777 }
06778 ast_mutex_destroy(&d->lock);
06779 ast_free(d);
06780 d = devices;
06781 continue;
06782 }
06783 d = d->next;
06784 }
06785 finish_bookmark();
06786 ast_mutex_unlock(&devicelock);
06787 ast_config_destroy(cfg);
06788 ast_mutex_lock(&sessionlock);
06789 s = sessions;
06790 while (s) {
06791 if (s->device) {
06792 refresh_all_favorite(s);
06793 if (ast_strlen_zero(s->device->language)) {
06794 struct unistim_languages lang;
06795 lang = options_languages[find_language(s->device->language)];
06796 send_charset_update(s, lang.encoding);
06797 }
06798 }
06799 s = s->next;
06800 }
06801 ast_mutex_unlock(&sessionlock);
06802
06803 if (unistimsock > -1) {
06804 return 0;
06805 }
06806 bindaddr.sin_addr.s_addr = INADDR_ANY;
06807 bindaddr.sin_port = htons(unistim_port);
06808 bindaddr.sin_family = AF_INET;
06809 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
06810 if (unistimsock < 0) {
06811 ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
06812 return -1;
06813 }
06814 #ifdef HAVE_PKTINFO
06815 {
06816 const int pktinfoFlag = 1;
06817 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
06818 sizeof(pktinfoFlag));
06819 }
06820 #else
06821 if (public_ip.sin_family == 0) {
06822 ast_log(LOG_WARNING,
06823 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
06824 unistimsock = -1;
06825 return -1;
06826 }
06827 #endif
06828 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
06829 sizeof(reuseFlag));
06830 if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
06831 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
06832 ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
06833 strerror(errno));
06834 close(unistimsock);
06835 unistimsock = -1;
06836 } else {
06837 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
06838 ast_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
06839 }
06840 return 0;
06841 }
06842
06843 static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
06844 {
06845 struct unistim_subchannel *sub = ast_channel_tech_pvt(chan);
06846
06847 if (!sub) {
06848 return AST_RTP_GLUE_RESULT_FORBID;
06849 }
06850 if (!sub->rtp) {
06851 return AST_RTP_GLUE_RESULT_FORBID;
06852 }
06853
06854 ao2_ref(sub->rtp, +1);
06855 *instance = sub->rtp;
06856
06857 return AST_RTP_GLUE_RESULT_LOCAL;
06858 }
06859
06860 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)
06861 {
06862 struct unistim_subchannel *sub;
06863 struct sockaddr_in them = { 0, };
06864 struct sockaddr_in us = { 0, };
06865
06866 if (!rtp) {
06867 return 0;
06868 }
06869
06870 sub = ast_channel_tech_pvt(chan);
06871 if (!sub) {
06872 ast_log(LOG_ERROR, "No Private Structure, this is bad\n");
06873 return -1;
06874 }
06875 {
06876 struct ast_sockaddr tmp;
06877 ast_rtp_instance_get_remote_address(rtp, &tmp);
06878 ast_sockaddr_to_sin(&tmp, &them);
06879 ast_rtp_instance_get_local_address(rtp, &tmp);
06880 ast_sockaddr_to_sin(&tmp, &us);
06881 }
06882
06883
06884
06885 return 0;
06886 }
06887
06888 static struct ast_rtp_glue unistim_rtp_glue = {
06889 .type = channel_type,
06890 .get_rtp_info = unistim_get_rtp_peer,
06891 .update_peer = unistim_set_rtp_peer,
06892 };
06893
06894
06895 int load_module(void)
06896 {
06897 int res;
06898 struct ast_format tmpfmt;
06899 if (!(global_cap = ast_format_cap_alloc())) {
06900 goto buff_failed;
06901 }
06902 if (!(unistim_tech.capabilities = ast_format_cap_alloc())) {
06903 goto buff_failed;
06904 }
06905
06906 ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ULAW, 0));
06907 ast_format_cap_add(global_cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
06908 ast_format_cap_copy(unistim_tech.capabilities, global_cap);
06909 if (!(buff = ast_malloc(SIZE_PAGE))) {
06910 goto buff_failed;
06911 }
06912
06913 io = io_context_create();
06914 if (!io) {
06915 ast_log(LOG_ERROR, "Failed to allocate IO context\n");
06916 goto io_failed;
06917 }
06918
06919 sched = ast_sched_context_create();
06920 if (!sched) {
06921 ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
06922 goto sched_failed;
06923 }
06924
06925 res = reload_config();
06926 if (res) {
06927 return AST_MODULE_LOAD_DECLINE;
06928 }
06929
06930 if (ast_channel_register(&unistim_tech)) {
06931 ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
06932 goto chanreg_failed;
06933 }
06934
06935 ast_rtp_glue_register(&unistim_rtp_glue);
06936
06937 ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
06938
06939 restart_monitor();
06940
06941 return AST_MODULE_LOAD_SUCCESS;
06942
06943 chanreg_failed:
06944
06945 ast_sched_context_destroy(sched);
06946 sched = NULL;
06947 sched_failed:
06948 io_context_destroy(io);
06949 io = NULL;
06950 io_failed:
06951 ast_free(buff);
06952 buff = NULL;
06953 global_cap = ast_format_cap_destroy(global_cap);
06954 unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
06955 buff_failed:
06956 return AST_MODULE_LOAD_FAILURE;
06957 }
06958
06959 static int unload_module(void)
06960 {
06961
06962 if (sched) {
06963 ast_sched_context_destroy(sched);
06964 }
06965
06966 ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
06967
06968 ast_channel_unregister(&unistim_tech);
06969 ast_rtp_glue_unregister(&unistim_rtp_glue);
06970
06971 ast_mutex_lock(&monlock);
06972 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
06973 pthread_cancel(monitor_thread);
06974 pthread_kill(monitor_thread, SIGURG);
06975 pthread_join(monitor_thread, NULL);
06976 }
06977 monitor_thread = AST_PTHREADT_STOP;
06978 ast_mutex_unlock(&monlock);
06979
06980 if (buff) {
06981 ast_free(buff);
06982 }
06983 if (unistimsock > -1) {
06984 close(unistimsock);
06985 }
06986 global_cap = ast_format_cap_destroy(global_cap);
06987 unistim_tech.capabilities = ast_format_cap_destroy(unistim_tech.capabilities);
06988
06989 return 0;
06990 }
06991
06992
06993 int reload(void)
06994 {
06995 if (unistimdebug) {
06996 ast_verb(0, "reload unistim\n");
06997 }
06998 ast_mutex_lock(&unistim_reload_lock);
06999 if (!unistim_reloading) {
07000 unistim_reloading = 1;
07001 }
07002 ast_mutex_unlock(&unistim_reload_lock);
07003
07004 restart_monitor();
07005
07006 return 0;
07007 }
07008
07009 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
07010 .load = load_module,
07011 .unload = unload_module,
07012 .reload = reload,
07013 );