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: 382409 $")
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/netsock.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
00077
00078 #define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW
00079
00080 #define DEFAULTCONTEXT "default"
00081 #define DEFAULTCALLERID "Unknown"
00082 #define DEFAULTCALLERNAME " "
00083 #define DEFAULTHEIGHT 3
00084 #define USTM_LOG_DIR "unistimHistory"
00085
00086
00087 #define MAX_BUF_SIZE 64
00088
00089 #define MAX_BUF_NUMBER 50
00090
00091 #define NB_MAX_RETRANSMIT 8
00092
00093 #define IDLE_WAIT 1000
00094
00095 #define RETRANSMIT_TIMER 2000
00096
00097 #define TIMER_MWI 10000
00098
00099 #define DEFAULT_CODEC 0x00
00100 #define SIZE_PAGE 4096
00101 #define DEVICE_NAME_LEN 16
00102 #define AST_CONFIG_MAX_PATH 255
00103 #define MAX_ENTRY_LOG 30
00104
00105 #define SUB_REAL 0
00106 #define SUB_THREEWAY 1
00107 #define MAX_SUBS 2
00108
00109 enum autoprovision {
00110 AUTOPROVISIONING_NO = 0,
00111 AUTOPROVISIONING_YES,
00112 AUTOPROVISIONING_DB,
00113 AUTOPROVISIONING_TN
00114 };
00115
00116 enum autoprov_extn {
00117
00118 EXTENSION_NONE = 0,
00119
00120 EXTENSION_ASK,
00121
00122 EXTENSION_LINE,
00123
00124 EXTENSION_TN
00125 };
00126 #define OUTPUT_HANDSET 0xC0
00127 #define OUTPUT_HEADPHONE 0xC1
00128 #define OUTPUT_SPEAKER 0xC2
00129
00130 #define VOLUME_LOW 0x01
00131 #define VOLUME_LOW_SPEAKER 0x03
00132 #define VOLUME_NORMAL 0x02
00133 #define VOLUME_INSANELY_LOUD 0x07
00134
00135 #define MUTE_OFF 0x00
00136 #define MUTE_ON 0xFF
00137 #define MUTE_ON_DISCRET 0xCE
00138
00139 #define SIZE_HEADER 6
00140 #define SIZE_MAC_ADDR 17
00141 #define TEXT_LENGTH_MAX 24
00142 #define TEXT_LINE0 0x00
00143 #define TEXT_LINE1 0x20
00144 #define TEXT_LINE2 0x40
00145 #define TEXT_NORMAL 0x05
00146 #define TEXT_INVERSE 0x25
00147 #define STATUS_LENGTH_MAX 28
00148
00149 #define FAV_ICON_NONE 0x00
00150 #define FAV_ICON_ONHOOK_BLACK 0x20
00151 #define FAV_ICON_ONHOOK_WHITE 0x21
00152 #define FAV_ICON_SPEAKER_ONHOOK_BLACK 0x22
00153 #define FAV_ICON_SPEAKER_ONHOOK_WHITE 0x23
00154 #define FAV_ICON_OFFHOOK_BLACK 0x24
00155 #define FAV_ICON_OFFHOOK_WHITE 0x25
00156 #define FAV_ICON_ONHOLD_BLACK 0x26
00157 #define FAV_ICON_ONHOLD_WHITE 0x27
00158 #define FAV_ICON_SPEAKER_OFFHOOK_BLACK 0x28
00159 #define FAV_ICON_SPEAKER_OFFHOOK_WHITE 0x29
00160 #define FAV_ICON_PHONE_BLACK 0x2A
00161 #define FAV_ICON_PHONE_WHITE 0x2B
00162 #define FAV_ICON_SPEAKER_ONHOLD_BLACK 0x2C
00163 #define FAV_ICON_SPEAKER_ONHOLD_WHITE 0x2D
00164 #define FAV_ICON_HEADPHONES 0x2E
00165 #define FAV_ICON_HEADPHONES_ONHOLD 0x2F
00166 #define FAV_ICON_HOME 0x30
00167 #define FAV_ICON_CITY 0x31
00168 #define FAV_ICON_SHARP 0x32
00169 #define FAV_ICON_PAGER 0x33
00170 #define FAV_ICON_CALL_CENTER 0x34
00171 #define FAV_ICON_FAX 0x35
00172 #define FAV_ICON_MAILBOX 0x36
00173 #define FAV_ICON_REFLECT 0x37
00174 #define FAV_ICON_COMPUTER 0x38
00175 #define FAV_ICON_FORWARD 0x39
00176 #define FAV_ICON_LOCKED 0x3A
00177 #define FAV_ICON_TRASH 0x3B
00178 #define FAV_ICON_INBOX 0x3C
00179 #define FAV_ICON_OUTBOX 0x3D
00180 #define FAV_ICON_MEETING 0x3E
00181 #define FAV_ICON_BOX 0x3F
00182
00183 #define FAV_BLINK_FAST 0x20
00184 #define FAV_BLINK_SLOW 0x40
00185
00186 #define FAV_MAX_LENGTH 0x0A
00187
00188 static void dummy(char *unused, ...)
00189 {
00190 return;
00191 }
00192
00193
00194
00195 static struct ast_jb_conf default_jbconf =
00196 {
00197 .flags = 0,
00198 .max_size = 200,
00199 .resync_threshold = 1000,
00200 .impl = "fixed",
00201 .target_extra = 40,
00202 };
00203 static struct ast_jb_conf global_jbconf;
00204
00205
00206
00207
00208
00209 #define DEBUG_TIMER dummy
00210
00211 static int unistimdebug = 0;
00212 static int unistim_port;
00213 static enum autoprovision autoprovisioning = AUTOPROVISIONING_NO;
00214 static int unistim_keepalive;
00215 static int unistimsock = -1;
00216
00217 static struct {
00218 unsigned int tos;
00219 unsigned int tos_audio;
00220 unsigned int cos;
00221 unsigned int cos_audio;
00222 } qos = { 0, 0, 0, 0 };
00223
00224 static struct io_context *io;
00225 static struct sched_context *sched;
00226 static struct sockaddr_in public_ip = { 0, };
00227
00228 static struct sockaddr_in address_from;
00229
00230 static unsigned int size_addr_from = sizeof(address_from);
00231
00232 static unsigned char *buff;
00233 static int unistim_reloading = 0;
00234 AST_MUTEX_DEFINE_STATIC(unistim_reload_lock);
00235 AST_MUTEX_DEFINE_STATIC(usecnt_lock);
00236 static int usecnt = 0;
00237
00238
00239
00240
00241 static pthread_t monitor_thread = AST_PTHREADT_NULL;
00242
00243
00244
00245 AST_MUTEX_DEFINE_STATIC(monlock);
00246
00247 AST_MUTEX_DEFINE_STATIC(sessionlock);
00248
00249 AST_MUTEX_DEFINE_STATIC(devicelock);
00250
00251 enum phone_state {
00252 STATE_INIT,
00253 STATE_AUTHDENY,
00254 STATE_MAINPAGE,
00255 STATE_EXTENSION,
00256 STATE_DIALPAGE,
00257 STATE_RINGING,
00258 STATE_CALL,
00259 STATE_SELECTCODEC,
00260 STATE_CLEANING,
00261 STATE_HISTORY
00262 };
00263
00264 enum handset_state {
00265 STATE_ONHOOK,
00266 STATE_OFFHOOK,
00267 };
00268
00269 enum phone_key {
00270 KEY_0 = 0x40,
00271 KEY_1 = 0x41,
00272 KEY_2 = 0x42,
00273 KEY_3 = 0x43,
00274 KEY_4 = 0x44,
00275 KEY_5 = 0x45,
00276 KEY_6 = 0x46,
00277 KEY_7 = 0x47,
00278 KEY_8 = 0x48,
00279 KEY_9 = 0x49,
00280 KEY_STAR = 0x4a,
00281 KEY_SHARP = 0x4b,
00282 KEY_UP = 0x4c,
00283 KEY_DOWN = 0x4d,
00284 KEY_RIGHT = 0x4e,
00285 KEY_LEFT = 0x4f,
00286 KEY_QUIT = 0x50,
00287 KEY_COPY = 0x51,
00288 KEY_FUNC1 = 0x54,
00289 KEY_FUNC2 = 0x55,
00290 KEY_FUNC3 = 0x56,
00291 KEY_FUNC4 = 0x57,
00292 KEY_ONHOLD = 0x5b,
00293 KEY_HANGUP = 0x5c,
00294 KEY_MUTE = 0x5d,
00295 KEY_HEADPHN = 0x5e,
00296 KEY_LOUDSPK = 0x5f,
00297 KEY_FAV0 = 0x60,
00298 KEY_FAV1 = 0x61,
00299 KEY_FAV2 = 0x62,
00300 KEY_FAV3 = 0x63,
00301 KEY_FAV4 = 0x64,
00302 KEY_FAV5 = 0x65,
00303 KEY_COMPUTR = 0x7b,
00304 KEY_CONF = 0x7c,
00305 KEY_SNDHIST = 0x7d,
00306 KEY_RCVHIST = 0x7e,
00307 KEY_INDEX = 0x7f
00308 };
00309
00310 struct tone_zone_unistim {
00311 char country[3];
00312 int freq1;
00313 int freq2;
00314 };
00315
00316 static const struct tone_zone_unistim frequency[] = {
00317 {"us", 350, 440},
00318 {"fr", 440, 0},
00319 {"au", 413, 438},
00320 {"nl", 425, 0},
00321 {"uk", 350, 440},
00322 {"fi", 425, 0},
00323 {"es", 425, 0},
00324 {"jp", 400, 0},
00325 {"no", 425, 0},
00326 {"at", 420, 0},
00327 {"nz", 400, 0},
00328 {"tw", 350, 440},
00329 {"cl", 400, 0},
00330 {"se", 425, 0},
00331 {"be", 425, 0},
00332 {"sg", 425, 0},
00333 {"il", 414, 0},
00334 {"br", 425, 0},
00335 {"hu", 425, 0},
00336 {"lt", 425, 0},
00337 {"pl", 425, 0},
00338 {"za", 400, 0},
00339 {"pt", 425, 0},
00340 {"ee", 425, 0},
00341 {"mx", 425, 0},
00342 {"in", 400, 0},
00343 {"de", 425, 0},
00344 {"ch", 425, 0},
00345 {"dk", 425, 0},
00346 {"cn", 450, 0},
00347 {"--", 0, 0}
00348 };
00349
00350 struct wsabuf {
00351 u_long len;
00352 unsigned char *buf;
00353 };
00354
00355 struct systemtime {
00356 unsigned short w_year;
00357 unsigned short w_month;
00358 unsigned short w_day_of_week;
00359 unsigned short w_day;
00360 unsigned short w_hour;
00361 unsigned short w_minute;
00362 unsigned short w_second;
00363 unsigned short w_milliseconds;
00364 };
00365
00366 struct unistim_subchannel {
00367 ast_mutex_t lock;
00368
00369 unsigned int subtype;
00370
00371 struct ast_channel *owner;
00372
00373 struct unistim_line *parent;
00374
00375 struct ast_rtp_instance *rtp;
00376 int alreadygone;
00377 char ringvolume;
00378 char ringstyle;
00379 };
00380
00381
00382
00383
00384 struct unistim_line {
00385 ast_mutex_t lock;
00386
00387 char name[80];
00388
00389 char fullname[80];
00390
00391 struct unistim_subchannel *subs[MAX_SUBS];
00392
00393 char exten[AST_MAX_EXTENSION];
00394
00395 char context[AST_MAX_EXTENSION];
00396
00397 char language[MAX_LANGUAGE];
00398
00399 char cid_num[AST_MAX_EXTENSION];
00400
00401 char mailbox[AST_MAX_EXTENSION];
00402
00403 int lastmsgssent;
00404
00405 time_t nextmsgcheck;
00406
00407 char musicclass[MAX_MUSICCLASS];
00408
00409 unsigned int callgroup;
00410
00411 unsigned int pickupgroup;
00412
00413 char accountcode[80];
00414
00415 int amaflags;
00416
00417 format_t capability;
00418
00419 char parkinglot[AST_MAX_CONTEXT];
00420 struct unistim_line *next;
00421 struct unistim_device *parent;
00422 };
00423
00424
00425
00426
00427 static struct unistim_device {
00428 int receiver_state;
00429 int size_phone_number;
00430 char phone_number[16];
00431 char redial_number[16];
00432 int phone_current;
00433 int pos_fav;
00434 char id[18];
00435 char name[DEVICE_NAME_LEN];
00436 int softkeylinepos;
00437 char softkeylabel[6][11];
00438 char softkeynumber[6][16];
00439 char softkeyicon[6];
00440 char softkeydevice[6][16];
00441 struct unistim_device *sp[6];
00442 int height;
00443 char maintext0[25];
00444 char maintext1[25];
00445 char maintext2[25];
00446 char titledefault[13];
00447 char datetimeformat;
00448 char contrast;
00449 char country[3];
00450 struct ast_tone_zone *tz;
00451 char ringvolume;
00452 char ringstyle;
00453 int rtp_port;
00454 int rtp_method;
00455 int status_method;
00456 char codec_number;
00457 int missed_call;
00458 int callhistory;
00459 char lst_cid[TEXT_LENGTH_MAX];
00460 char lst_cnm[TEXT_LENGTH_MAX];
00461 char call_forward[AST_MAX_EXTENSION];
00462 int output;
00463 int previous_output;
00464 int volume;
00465 int mute;
00466 int moh;
00467 int nat;
00468 enum autoprov_extn extension;
00469 char extension_number[11];
00470 char to_delete;
00471 time_t start_call_timestamp;
00472 struct ast_silence_generator *silence_generator;
00473 struct unistim_line *lines;
00474 struct ast_ha *ha;
00475 struct unistimsession *session;
00476 struct unistim_device *next;
00477 } *devices = NULL;
00478
00479 static struct unistimsession {
00480 ast_mutex_t lock;
00481 struct sockaddr_in sin;
00482 struct sockaddr_in sout;
00483 int timeout;
00484 unsigned short seq_phone;
00485 unsigned short seq_server;
00486 unsigned short last_seq_ack;
00487 unsigned long tick_next_ping;
00488 int last_buf_available;
00489 int nb_retransmit;
00490 int state;
00491 int size_buff_entry;
00492 char buff_entry[16];
00493 char macaddr[18];
00494 struct wsabuf wsabufsend[MAX_BUF_NUMBER];
00495 unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE];
00496 struct unistim_device *device;
00497 struct unistimsession *next;
00498 } *sessions = NULL;
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511 static const unsigned char packet_rcv_discovery[] =
00512 { 0xff, 0xff, 0xff, 0xff, 0x02, 0x02, 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
00513 static const unsigned char packet_send_discovery_ack[] =
00514 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 };
00515
00516 static const unsigned char packet_recv_firm_version[] =
00517 { 0x00, 0x00, 0x00, 0x13, 0x9a, 0x0a, 0x02 };
00518 static const unsigned char packet_recv_pressed_key[] =
00519 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x04, 0x00 };
00520 static const unsigned char packet_recv_pick_up[] =
00521 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x04 };
00522 static const unsigned char packet_recv_hangup[] =
00523 { 0x00, 0x00, 0x00, 0x13, 0x99, 0x03, 0x03 };
00524 static const unsigned char packet_recv_r2[] = { 0x00, 0x00, 0x00, 0x13, 0x96, 0x03, 0x03 };
00525
00526
00527 static const unsigned char packet_recv_resume_connection_with_server[] =
00528 { 0xff, 0xff, 0xff, 0xff, 0x9e, 0x03, 0x08 };
00529 static const unsigned char packet_recv_mac_addr[] =
00530 { 0xff, 0xff, 0xff, 0xff, 0x9a, 0x0d, 0x07 };
00531
00532 static const unsigned char packet_send_date_time3[] =
00533 { 0x11, 0x09, 0x02, 0x02, 0x05, 0x06, 0x07,
00534 0x08, 0x32
00535 };
00536 static const unsigned char packet_send_date_time[] =
00537 { 0x11, 0x09, 0x02, 0x0a, 0x05, 0x06, 0x07,
00538 0x08, 0x32, 0x17, 0x04, 0x24, 0x07, 0x19,
00539 0x04, 0x07, 0x00, 0x19, 0x05, 0x09, 0x3e, 0x0f, 0x16, 0x05, 0x00, 0x80, 0x00, 0x1e,
00540 0x05, 0x12, 0x00, 0x78
00541 };
00542
00543 static const unsigned char packet_send_no_ring[] =
00544 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00 };
00545 static const unsigned char packet_send_s4[] =
00546 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff,
00547 0x16, 0x05, 0x1c, 0x00, 0x00, 0x17, 0x05,
00548 0x0b, 0x00, 0x00, 0x19, 0x04, 0x00, 0x00, 0x19, 0x04, 0x00, 0x08, 0x19, 0x04, 0x00,
00549 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
00550 0x31, 0x00, 0x00, 0x16, 0x05, 0x04, 0x00, 0x00
00551 };
00552 static const unsigned char packet_send_call[] =
00553 { 0x16, 0x04, 0x1a, 0x00, 0x16, 0x04, 0x11, 0x00, 0x16, 0x06, 0x32, 0xdf,
00554 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16, 0x0a, 0x38, 0x00, 0x12, 0xca, 0x03,
00555 0xc0, 0xc3, 0xc5, 0x16, 0x16, 0x30, 0x00,
00556 0x00, 0x12, 0x12, 0x01, 0x5c, 0x00,
00557 0x0f, 0xa0, 0x9c, 0x41,
00558 0x0f, 0xa0, 0x9c, 0x41, 0x0a, 0x01,
00559 0x16, 0x66
00560 };
00561 static const unsigned char packet_send_stream_based_tone_off[] =
00562 { 0x16, 0x05, 0x1c, 0x00, 0x00 };
00563
00564
00565
00566
00567 static const unsigned char packet_send_stream_based_tone_on[] =
00568 { 0x16, 0x06, 0x1b, 0x00, 0x00, 0x05 };
00569 static const unsigned char packet_send_stream_based_tone_single_freq[] =
00570 { 0x16, 0x06, 0x1d, 0x00, 0x01, 0xb8 };
00571 static const unsigned char packet_send_stream_based_tone_dial_freq[] =
00572 { 0x16, 0x08, 0x1d, 0x00, 0x01, 0xb8, 0x01, 0x5e };
00573 static const unsigned char packet_send_select_output[] =
00574 { 0x16, 0x06, 0x32, 0xc0, 0x01, 0x00 };
00575 static const unsigned char packet_send_ring[] =
00576 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x1c, 0x00, 0x00, 0x16,
00577 0x04, 0x1a, 0x01, 0x16, 0x05, 0x12, 0x13 , 0x18, 0x16, 0x04, 0x18,
00578 0x20, 0x16, 0x04, 0x10, 0x00
00579 };
00580 static const unsigned char packet_send_end_call[] =
00581 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x16, 0x05, 0x31, 0x00, 0x00, 0x19, 0x04, 0x00,
00582 0x10, 0x19, 0x04, 0x00, 0x18, 0x16, 0x05,
00583 0x04, 0x00, 0x00, 0x16, 0x04, 0x37, 0x10
00584 };
00585 static const unsigned char packet_send_s9[] =
00586 { 0x16, 0x06, 0x32, 0xdf, 0x00, 0xff, 0x19, 0x04, 0x00, 0x10, 0x16, 0x05, 0x1c, 0x00,
00587 0x00 };
00588 static const unsigned char packet_send_rtp_packet_size[] =
00589 { 0x16, 0x08, 0x38, 0x00, 0x00, 0xe0, 0x00, 0xa0 };
00590 static const unsigned char packet_send_jitter_buffer_conf[] =
00591 { 0x16, 0x0e, 0x3a, 0x00, 0x02, 0x04, 0x00, 0x00,
00592 0x3e, 0x80,
00593 0x00, 0x00, 0x3e, 0x80
00594 };
00595
00596
00597
00598
00599 static const unsigned char packet_send_open_audio_stream_rx[] =
00600 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
00601 0x0e, 0x01, 0x14, 0x50, 0x00,
00602 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
00603 };
00604 static const unsigned char packet_send_open_audio_stream_tx[] =
00605 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0xb8, 0xb8, 0x0e,
00606 0x0e, 0x01, 0x14, 0x50,
00607 0x00, 0x00, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93, 0x69, 0x05
00608 };
00609
00610 static const unsigned char packet_send_open_audio_stream_rx3[] =
00611 { 0x16, 0x1a, 0x30, 0x00, 0xff, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
00612 0x06, 0x81, 0x14, 0x50,
00613 0x14,
00614 0x51, 0x14, 0x50, 0x00, 0x00, 0x0a, 0x93,
00615 0x69, 0x05
00616 };
00617 static const unsigned char packet_send_open_audio_stream_tx3[] =
00618 { 0x16, 0x1a, 0x30, 0xff, 0x00, 0x00, 0x00, 0x02, 0x01, 0xb8, 0xb8, 0x06,
00619 0x06, 0x81, 0x14, 0x50,
00620 0x00, 0x00, 0x14, 0x50, 0x00, 0x00,
00621 0x0a, 0x93, 0x69, 0x05
00622 };
00623
00624 static const unsigned char packet_send_arrow[] = { 0x17, 0x04, 0x04, 0x00 };
00625 static const unsigned char packet_send_blink_cursor[] = { 0x17, 0x04, 0x10, 0x86 };
00626 static const unsigned char packet_send_date_time2[] = { 0x17, 0x04, 0x17, 0x3d, 0x11, 0x09, 0x02, 0x0a, 0x05,
00627 0x06, 0x07, 0x08, 0x32
00628 };
00629 static const unsigned char packet_send_Contrast[] =
00630 { 0x17, 0x04, 0x24, 0x08 };
00631 static const unsigned char packet_send_StartTimer[] =
00632 { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, 0x44, 0x75, 0x72, 0xe9,
00633 0x65 };
00634 static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
00635 static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, 0x00, 0x25 };
00636 static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
00637 static const unsigned char packet_send_set_pos_cursor[] =
00638 { 0x17, 0x06, 0x10, 0x81, 0x04, 0x20 };
00639
00640
00641
00642 static const unsigned char packet_send_favorite[] =
00643 { 0x17, 0x0f, 0x19, 0x10, 0x01, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00644 0x20, 0x20, 0x20, 0x20, 0x19,
00645 0x05, 0x0f, 0x01, 0x00
00646 };
00647 static const unsigned char packet_send_title[] =
00648 { 0x17, 0x10, 0x19, 0x02, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00649 0x20, 0x20, 0x20, 0x20 };
00650 static const unsigned char packet_send_text[] =
00651 { 0x17, 0x1e, 0x1b, 0x04, 0x00, 0x25, 0x20, 0x20,
00652 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00653 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00654 0x17, 0x04, 0x10, 0x87
00655 };
00656 static const unsigned char packet_send_status[] =
00657 { 0x17, 0x20, 0x19, 0x08, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00658 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
00659 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
00660 };
00661 static const unsigned char packet_send_status2[] =
00662 { 0x17, 0x0b, 0x19, 0x00, 0x20, 0x20, 0x20, 0x20,
00663 0x20, 0x20, 0x20 };
00664
00665 static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
00666
00667 static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
00668 static const unsigned char packet_send_query_mac_address[] = { 0x1a, 0x04, 0x01, 0x08 };
00669 static const unsigned char packet_send_query_basic_manager_10[] = { 0x1a, 0x04, 0x01, 0x10 };
00670 static const unsigned char packet_send_S1[] = { 0x1a, 0x07, 0x07, 0x00, 0x00, 0x00, 0x13 };
00671
00672 static unsigned char packet_send_ping[] =
00673 { 0x1e, 0x05, 0x12, 0x00, 0x78 };
00674
00675 #define BUFFSEND unsigned char buffsend[64] = { 0x00, 0x00, 0xaa, 0xbb, 0x02, 0x01 }
00676
00677 static const char tdesc[] = "UNISTIM Channel Driver";
00678 static const char channel_type[] = "USTM";
00679
00680
00681 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid);
00682 static int load_module(void);
00683 static int reload(void);
00684 static int unload_module(void);
00685 static int reload_config(void);
00686 static void show_main_page(struct unistimsession *pte);
00687 static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor,
00688 void *data, int *cause);
00689 static int unistim_call(struct ast_channel *ast, char *dest, int timeout);
00690 static int unistim_hangup(struct ast_channel *ast);
00691 static int unistim_answer(struct ast_channel *ast);
00692 static struct ast_frame *unistim_read(struct ast_channel *ast);
00693 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame);
00694 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
00695 size_t datalen);
00696 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan);
00697 static int unistim_senddigit_begin(struct ast_channel *ast, char digit);
00698 static int unistim_senddigit_end(struct ast_channel *ast, char digit,
00699 unsigned int duration);
00700 static int unistim_sendtext(struct ast_channel *ast, const char *text);
00701
00702 static int write_entry_history(struct unistimsession *pte, FILE * f, char c,
00703 char *line1);
00704 static void change_callerid(struct unistimsession *pte, int type, char *callerid);
00705
00706 static const struct ast_channel_tech unistim_tech = {
00707 .type = channel_type,
00708 .description = tdesc,
00709 .capabilities = CAPABILITY,
00710 .properties = AST_CHAN_TP_WANTSJITTER | AST_CHAN_TP_CREATESJITTER,
00711 .requester = unistim_request,
00712 .call = unistim_call,
00713 .hangup = unistim_hangup,
00714 .answer = unistim_answer,
00715 .read = unistim_read,
00716 .write = unistim_write,
00717 .indicate = unistim_indicate,
00718 .fixup = unistim_fixup,
00719 .send_digit_begin = unistim_senddigit_begin,
00720 .send_digit_end = unistim_senddigit_end,
00721 .send_text = unistim_sendtext,
00722 .bridge = ast_rtp_instance_bridge,
00723 };
00724
00725 static void display_last_error(const char *sz_msg)
00726 {
00727 time_t cur_time;
00728
00729 time(&cur_time);
00730
00731
00732 ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
00733 strerror(errno));
00734 }
00735
00736 static unsigned int get_tick_count(void)
00737 {
00738 struct timeval now = ast_tvnow();
00739
00740 return (now.tv_sec * 1000) + (now.tv_usec / 1000);
00741 }
00742
00743
00744 static void send_raw_client(int size, const unsigned char *data, struct sockaddr_in *addr_to,
00745 const struct sockaddr_in *addr_ourip)
00746 {
00747 #ifdef HAVE_PKTINFO
00748 struct iovec msg_iov;
00749 struct msghdr msg;
00750 char buffer[CMSG_SPACE(sizeof(struct in_pktinfo))];
00751 struct cmsghdr *ip_msg = (struct cmsghdr *) buffer;
00752 struct in_pktinfo *pki = (struct in_pktinfo *) CMSG_DATA(ip_msg);
00753
00754
00755
00756
00757
00758
00759 msg_iov.iov_base = (char *) data;
00760 msg_iov.iov_len = size;
00761
00762 msg.msg_name = addr_to;
00763 msg.msg_namelen = sizeof(struct sockaddr_in);
00764 msg.msg_iov = &msg_iov;
00765 msg.msg_iovlen = 1;
00766 msg.msg_control = ip_msg;
00767 msg.msg_controllen = sizeof(buffer);
00768 msg.msg_flags = 0;
00769
00770 ip_msg->cmsg_len = CMSG_LEN(sizeof(*pki));
00771 ip_msg->cmsg_level = IPPROTO_IP;
00772 ip_msg->cmsg_type = IP_PKTINFO;
00773 pki->ipi_ifindex = 0;
00774 pki->ipi_spec_dst.s_addr = addr_ourip->sin_addr.s_addr;
00775
00776
00777 #ifdef DUMP_PACKET
00778 if (unistimdebug) {
00779 int tmp;
00780 char iabuf[INET_ADDRSTRLEN];
00781 char iabuf2[INET_ADDRSTRLEN];
00782 ast_verb(0, "\n**> From %s sending %d bytes to %s ***\n",
00783 ast_inet_ntoa(addr_ourip->sin_addr), (int) size,
00784 ast_inet_ntoa(addr_to->sin_addr));
00785 for (tmp = 0; tmp < size; tmp++)
00786 ast_verb(0, "%.2x ", (unsigned char) data[tmp]);
00787 ast_verb(0, "\n******************************************\n");
00788
00789 }
00790 #endif
00791
00792 if (sendmsg(unistimsock, &msg, 0) == -1)
00793 display_last_error("Error sending datas");
00794 #else
00795 if (sendto(unistimsock, data, size, 0, (struct sockaddr *) addr_to, sizeof(*addr_to))
00796 == -1)
00797 display_last_error("Error sending datas");
00798 #endif
00799 }
00800
00801 static void send_client(int size, const unsigned char *data, struct unistimsession *pte)
00802 {
00803 unsigned int tick;
00804 int buf_pos;
00805 unsigned short seq = ntohs(++pte->seq_server);
00806
00807 ast_mutex_lock(&pte->lock);
00808 buf_pos = pte->last_buf_available;
00809
00810 if (buf_pos >= MAX_BUF_NUMBER) {
00811 ast_log(LOG_WARNING, "Error : send queue overflow\n");
00812 ast_mutex_unlock(&pte->lock);
00813 return;
00814 }
00815 memcpy((void *)data + sizeof(unsigned short), (void *)&seq, sizeof(unsigned short));
00816 pte->wsabufsend[buf_pos].len = size;
00817 memcpy(pte->wsabufsend[buf_pos].buf, data, size);
00818
00819 tick = get_tick_count();
00820 pte->timeout = tick + RETRANSMIT_TIMER;
00821
00822
00823 if (unistimdebug)
00824 ast_verb(6, "Sending datas with seq #0x%.4x Using slot #%d :\n", pte->seq_server, buf_pos);
00825
00826 send_raw_client(pte->wsabufsend[buf_pos].len, pte->wsabufsend[buf_pos].buf, &(pte->sin),
00827 &(pte->sout));
00828 pte->last_buf_available++;
00829 ast_mutex_unlock(&pte->lock);
00830 }
00831
00832 static void send_ping(struct unistimsession *pte)
00833 {
00834 BUFFSEND;
00835 if (unistimdebug)
00836 ast_verb(6, "Sending ping\n");
00837 pte->tick_next_ping = get_tick_count() + unistim_keepalive;
00838 memcpy(buffsend + SIZE_HEADER, packet_send_ping, sizeof(packet_send_ping));
00839 send_client(SIZE_HEADER + sizeof(packet_send_ping), buffsend, pte);
00840 }
00841
00842 static int get_to_address(int fd, struct sockaddr_in *toAddr)
00843 {
00844 #ifdef HAVE_PKTINFO
00845 int err;
00846 struct msghdr msg;
00847 struct {
00848 struct cmsghdr cm;
00849 int len;
00850 struct in_addr address;
00851 } ip_msg;
00852
00853
00854
00855 memset(&msg, 0, sizeof(msg));
00856 memset(&ip_msg, 0, sizeof(ip_msg));
00857
00858
00859 msg.msg_control = &ip_msg;
00860 msg.msg_controllen = sizeof(ip_msg);
00861
00862 err = recvmsg(fd, &msg, MSG_PEEK);
00863 if (err == -1)
00864 ast_log(LOG_WARNING, "recvmsg returned an error: %s\n", strerror(errno));
00865 memcpy(&toAddr->sin_addr, &ip_msg.address, sizeof(struct in_addr));
00866 return err;
00867 #else
00868 memcpy(&toAddr, &public_ip, sizeof(&toAddr));
00869 return 0;
00870 #endif
00871 }
00872
00873
00874
00875 static struct unistimsession *create_client(const struct sockaddr_in *addr_from)
00876 {
00877 int tmp;
00878 struct unistimsession *s;
00879
00880 if (!(s = ast_calloc(1, sizeof(*s))))
00881 return NULL;
00882
00883 memcpy(&s->sin, addr_from, sizeof(struct sockaddr_in));
00884 get_to_address(unistimsock, &s->sout);
00885 s->sout.sin_family = AF_INET;
00886 if (unistimdebug) {
00887 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
00888 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
00889 }
00890 ast_mutex_init(&s->lock);
00891 ast_mutex_lock(&sessionlock);
00892 s->next = sessions;
00893 sessions = s;
00894
00895 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
00896 s->seq_phone = (short) 0x0000;
00897 s->seq_server = (short) 0x0000;
00898 s->last_seq_ack = (short) 0x000;
00899 s->last_buf_available = 0;
00900 s->nb_retransmit = 0;
00901 s->state = STATE_INIT;
00902 s->tick_next_ping = get_tick_count() + unistim_keepalive;
00903
00904 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
00905 s->wsabufsend[tmp].buf = s->buf[tmp];
00906 }
00907 ast_mutex_unlock(&sessionlock);
00908 return s;
00909 }
00910
00911 static void send_end_call(struct unistimsession *pte)
00912 {
00913 BUFFSEND;
00914 if (unistimdebug)
00915 ast_verb(0, "Sending end call\n");
00916 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
00917 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
00918 }
00919
00920 static void set_ping_timer(struct unistimsession *pte)
00921 {
00922 unsigned int tick = 0;
00923
00924 pte->timeout = pte->tick_next_ping;
00925 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
00926 return;
00927 }
00928
00929
00930
00931 static void check_send_queue(struct unistimsession *pte)
00932 {
00933
00934 if (pte->last_buf_available == 1) {
00935 if (unistimdebug)
00936 ast_verb(6, "Our single packet was ACKed.\n");
00937 pte->last_buf_available--;
00938 set_ping_timer(pte);
00939 return;
00940 }
00941
00942 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
00943 if (unistimdebug)
00944 ast_verb(6, "Our send queue is completely ACKed.\n");
00945 pte->last_buf_available = 0;
00946 set_ping_timer(pte);
00947 return;
00948 }
00949 if (unistimdebug)
00950 ast_verb(6, "We still have packets in our send queue\n");
00951 return;
00952 }
00953
00954 static void send_start_timer(struct unistimsession *pte)
00955 {
00956 BUFFSEND;
00957 if (unistimdebug)
00958 ast_verb(0, "Sending start timer\n");
00959 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
00960 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
00961 }
00962
00963 static void send_stop_timer(struct unistimsession *pte)
00964 {
00965 BUFFSEND;
00966 if (unistimdebug)
00967 ast_verb(0, "Sending stop timer\n");
00968 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
00969 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
00970 }
00971
00972 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
00973 {
00974 BUFFSEND;
00975 if (unistimdebug)
00976 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
00977 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
00978 buffsend[9] = pos;
00979 buffsend[10] = status;
00980 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
00981 }
00982
00983 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
00984 {
00985 BUFFSEND;
00986 if (!tone1) {
00987 if (unistimdebug)
00988 ast_verb(0, "Sending Stream Based Tone Off\n");
00989 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
00990 sizeof(packet_send_stream_based_tone_off));
00991 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
00992 return;
00993 }
00994
00995
00996
00997
00998
00999 if (unistimdebug)
01000 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
01001 tone1 *= 8;
01002 if (!tone2) {
01003 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
01004 sizeof(packet_send_stream_based_tone_single_freq));
01005 buffsend[10] = (tone1 & 0xff00) >> 8;
01006 buffsend[11] = (tone1 & 0x00ff);
01007 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
01008 pte);
01009 } else {
01010 tone2 *= 8;
01011 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
01012 sizeof(packet_send_stream_based_tone_dial_freq));
01013 buffsend[10] = (tone1 & 0xff00) >> 8;
01014 buffsend[11] = (tone1 & 0x00ff);
01015 buffsend[12] = (tone2 & 0xff00) >> 8;
01016 buffsend[13] = (tone2 & 0x00ff);
01017 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
01018 pte);
01019 }
01020
01021 if (unistimdebug)
01022 ast_verb(0, "Sending Stream Based Tone On\n");
01023 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
01024 sizeof(packet_send_stream_based_tone_on));
01025 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
01026 }
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036 static void
01037 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
01038 const char *text)
01039 {
01040 BUFFSEND;
01041 int i;
01042
01043 if (unistimdebug)
01044 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
01045 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
01046 buffsend[10] = pos;
01047 buffsend[24] = pos;
01048 buffsend[25] = status;
01049 i = strlen(text);
01050 if (i > FAV_MAX_LENGTH)
01051 i = FAV_MAX_LENGTH;
01052 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
01053 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
01054 }
01055
01056 static void refresh_all_favorite(struct unistimsession *pte)
01057 {
01058 int i = 0;
01059
01060 if (unistimdebug)
01061 ast_verb(0, "Refreshing all favorite\n");
01062 for (i = 0; i < 6; i++) {
01063 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
01064 (pte->device->softkeylinepos != i))
01065 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
01066 pte->device->softkeylabel[i]);
01067 else
01068 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
01069 pte->device->softkeylabel[i]);
01070
01071 }
01072 }
01073
01074
01075
01076 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
01077 {
01078 struct unistim_device *d = devices;
01079 int i;
01080
01081 if (pte->state != STATE_CLEANING)
01082 send_favorite(pte->device->softkeylinepos, status, pte,
01083 pte->device->softkeylabel[pte->device->softkeylinepos]);
01084
01085 while (d) {
01086 for (i = 0; i < 6; i++) {
01087 if (d->sp[i] == pte->device) {
01088 if (d->softkeyicon[i] != status) {
01089 d->softkeyicon[i] = status;
01090 if (d->session)
01091 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
01092 }
01093 }
01094 }
01095 d = d->next;
01096 }
01097 }
01098
01099 static int RegisterExtension(const struct unistimsession *pte)
01100 {
01101 if (unistimdebug)
01102 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
01103 pte->device->extension_number, pte->device->lines->context,
01104 pte->device->lines->fullname);
01105 return ast_add_extension(pte->device->lines->context, 0,
01106 pte->device->extension_number, 1, NULL, NULL, "Dial",
01107 pte->device->lines->fullname, 0, "Unistim");
01108 }
01109
01110 static int UnregisterExtension(const struct unistimsession *pte)
01111 {
01112 if (unistimdebug)
01113 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
01114 pte->device->extension_number, pte->device->lines->context);
01115 return ast_context_remove_extension(pte->device->lines->context,
01116 pte->device->extension_number, 1, "Unistim");
01117 }
01118
01119
01120 static void close_client(struct unistimsession *s)
01121 {
01122 struct unistim_subchannel *sub;
01123 struct unistimsession *cur, *prev = NULL;
01124 ast_mutex_lock(&sessionlock);
01125 cur = sessions;
01126
01127 while (cur) {
01128 if (cur == s)
01129 break;
01130 prev = cur;
01131 cur = cur->next;
01132 }
01133 if (cur) {
01134 if (cur->device) {
01135 s->state = STATE_CLEANING;
01136 if (unistimdebug)
01137 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
01138 s, s->device, s->device->lines,
01139 s->device->lines->subs[SUB_REAL]);
01140 change_favorite_icon(s, FAV_ICON_NONE);
01141 sub = s->device->lines->subs[SUB_REAL];
01142 if (sub) {
01143 if (sub->owner) {
01144 if (unistimdebug)
01145 ast_verb(0, "Aborting call\n");
01146 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
01147 }
01148 } else
01149 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
01150 if (!ast_strlen_zero(s->device->extension_number))
01151 UnregisterExtension(s);
01152 cur->device->session = NULL;
01153 } else {
01154 if (unistimdebug)
01155 ast_verb(0, "Freeing an unregistered client\n");
01156 }
01157 if (prev)
01158 prev->next = cur->next;
01159 else
01160 sessions = cur->next;
01161 ast_mutex_destroy(&s->lock);
01162 ast_free(s);
01163 } else
01164 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
01165 ast_mutex_unlock(&sessionlock);
01166 return;
01167 }
01168
01169
01170 static int send_retransmit(struct unistimsession *pte)
01171 {
01172 int i;
01173
01174 ast_mutex_lock(&pte->lock);
01175 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
01176 if (unistimdebug)
01177 ast_verb(0, "Too many retransmit - freeing client\n");
01178 ast_mutex_unlock(&pte->lock);
01179 close_client(pte);
01180 return 1;
01181 }
01182 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
01183
01184 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
01185 i < pte->last_buf_available; i++) {
01186 if (i < 0) {
01187 ast_log(LOG_WARNING,
01188 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
01189 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
01190 continue;
01191 }
01192
01193 if (unistimdebug) {
01194 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
01195 unsigned short seq;
01196
01197 seq = ntohs(sbuf[1]);
01198 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
01199 seq, pte->last_seq_ack);
01200 }
01201 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
01202 &pte->sout);
01203 }
01204 ast_mutex_unlock(&pte->lock);
01205 return 0;
01206 }
01207
01208
01209 static void
01210 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
01211 const char *text)
01212 {
01213 int i;
01214 BUFFSEND;
01215 if (unistimdebug)
01216 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
01217 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
01218 buffsend[10] = pos;
01219 buffsend[11] = inverse;
01220 i = strlen(text);
01221 if (i > TEXT_LENGTH_MAX)
01222 i = TEXT_LENGTH_MAX;
01223 memcpy(buffsend + 12, text, i);
01224 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
01225 }
01226
01227 static void send_text_status(struct unistimsession *pte, const char *text)
01228 {
01229 BUFFSEND;
01230 int i;
01231 if (unistimdebug)
01232 ast_verb(0, "Sending status text\n");
01233 if (pte->device) {
01234 if (pte->device->status_method == 1) {
01235 int n = strlen(text);
01236
01237 int j;
01238 for (i = 0, j = 0; i < 4; i++, j += 7) {
01239 int pos = 0x08 + (i * 0x20);
01240 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
01241 sizeof(packet_send_status2));
01242
01243 buffsend[9] = pos;
01244 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
01245 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
01246 }
01247 return;
01248 }
01249 }
01250
01251
01252 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
01253 i = strlen(text);
01254 if (i > STATUS_LENGTH_MAX)
01255 i = STATUS_LENGTH_MAX;
01256 memcpy(buffsend + 10, text, i);
01257 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
01258
01259 }
01260
01261
01262
01263
01264
01265 static void send_led_update(struct unistimsession *pte, unsigned char led)
01266 {
01267 BUFFSEND;
01268 if (unistimdebug)
01269 ast_verb(0, "Sending led_update (%x)\n", led);
01270 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
01271 buffsend[9] = led;
01272 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
01273 }
01274
01275
01276
01277
01278 static void
01279 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
01280 unsigned char mute)
01281 {
01282 BUFFSEND;
01283 if (unistimdebug)
01284 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
01285 volume, mute);
01286 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
01287 sizeof(packet_send_select_output));
01288 buffsend[9] = output;
01289 if (output == OUTPUT_SPEAKER)
01290 volume = VOLUME_LOW_SPEAKER;
01291 else
01292 volume = VOLUME_LOW;
01293 buffsend[10] = volume;
01294 if (mute == MUTE_ON_DISCRET)
01295 buffsend[11] = MUTE_ON;
01296 else
01297 buffsend[11] = mute;
01298 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
01299 if (mute == MUTE_OFF)
01300 send_led_update(pte, 0x18);
01301 else if (mute == MUTE_ON)
01302 send_led_update(pte, 0x19);
01303 pte->device->mute = mute;
01304 if (output == OUTPUT_HANDSET) {
01305 if (mute == MUTE_ON)
01306 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
01307 else
01308 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
01309 send_led_update(pte, 0x08);
01310 send_led_update(pte, 0x10);
01311 } else if (output == OUTPUT_HEADPHONE) {
01312 if (mute == MUTE_ON)
01313 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
01314 else
01315 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
01316 send_led_update(pte, 0x08);
01317 send_led_update(pte, 0x11);
01318 } else if (output == OUTPUT_SPEAKER) {
01319 send_led_update(pte, 0x10);
01320 send_led_update(pte, 0x09);
01321 if (pte->device->receiver_state == STATE_OFFHOOK) {
01322 if (mute == MUTE_ON)
01323 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01324 else
01325 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
01326 } else {
01327 if (mute == MUTE_ON)
01328 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01329 else
01330 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
01331 }
01332 } else
01333 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
01334 if (output != pte->device->output)
01335 pte->device->previous_output = pte->device->output;
01336 pte->device->output = output;
01337 }
01338
01339 static void send_ring(struct unistimsession *pte, char volume, char style)
01340 {
01341 BUFFSEND;
01342 if (unistimdebug)
01343 ast_verb(0, "Sending ring packet\n");
01344 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
01345 buffsend[24] = style + 0x10;
01346 buffsend[29] = volume * 0x10;
01347 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
01348 }
01349
01350 static void send_no_ring(struct unistimsession *pte)
01351 {
01352 BUFFSEND;
01353 if (unistimdebug)
01354 ast_verb(0, "Sending no ring packet\n");
01355 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
01356 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
01357 }
01358
01359 static void send_texttitle(struct unistimsession *pte, const char *text)
01360 {
01361 BUFFSEND;
01362 int i;
01363 if (unistimdebug)
01364 ast_verb(0, "Sending title text\n");
01365 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
01366 i = strlen(text);
01367 if (i > 12)
01368 i = 12;
01369 memcpy(buffsend + 10, text, i);
01370 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
01371
01372 }
01373
01374 static void send_date_time(struct unistimsession *pte)
01375 {
01376 BUFFSEND;
01377 struct timeval now = ast_tvnow();
01378 struct ast_tm atm = { 0, };
01379
01380 if (unistimdebug)
01381 ast_verb(0, "Sending Time & Date\n");
01382 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
01383 ast_localtime(&now, &atm, NULL);
01384 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01385 buffsend[11] = (unsigned char) atm.tm_mday;
01386 buffsend[12] = (unsigned char) atm.tm_hour;
01387 buffsend[13] = (unsigned char) atm.tm_min;
01388 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
01389 }
01390
01391 static void send_date_time2(struct unistimsession *pte)
01392 {
01393 BUFFSEND;
01394 struct timeval now = ast_tvnow();
01395 struct ast_tm atm = { 0, };
01396
01397 if (unistimdebug)
01398 ast_verb(0, "Sending Time & Date #2\n");
01399 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
01400 ast_localtime(&now, &atm, NULL);
01401 if (pte->device)
01402 buffsend[9] = pte->device->datetimeformat;
01403 else
01404 buffsend[9] = 61;
01405 buffsend[14] = (unsigned char) atm.tm_mon + 1;
01406 buffsend[15] = (unsigned char) atm.tm_mday;
01407 buffsend[16] = (unsigned char) atm.tm_hour;
01408 buffsend[17] = (unsigned char) atm.tm_min;
01409 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
01410 }
01411
01412 static void send_date_time3(struct unistimsession *pte)
01413 {
01414 BUFFSEND;
01415 struct timeval now = ast_tvnow();
01416 struct ast_tm atm = { 0, };
01417
01418 if (unistimdebug)
01419 ast_verb(0, "Sending Time & Date #3\n");
01420 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
01421 ast_localtime(&now, &atm, NULL);
01422 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01423 buffsend[11] = (unsigned char) atm.tm_mday;
01424 buffsend[12] = (unsigned char) atm.tm_hour;
01425 buffsend[13] = (unsigned char) atm.tm_min;
01426 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
01427 }
01428
01429 static void send_blink_cursor(struct unistimsession *pte)
01430 {
01431 BUFFSEND;
01432 if (unistimdebug)
01433 ast_verb(0, "Sending set blink\n");
01434 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
01435 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
01436 return;
01437 }
01438
01439
01440 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
01441 {
01442 BUFFSEND;
01443 if (unistimdebug)
01444 ast_verb(0, "Sending set cursor position\n");
01445 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
01446 sizeof(packet_send_set_pos_cursor));
01447 buffsend[11] = pos;
01448 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
01449 return;
01450 }
01451
01452 static void rcv_resume_connection_with_server(struct unistimsession *pte)
01453 {
01454 BUFFSEND;
01455 if (unistimdebug) {
01456 ast_verb(0, "ResumeConnectionWithServer received\n");
01457 ast_verb(0, "Sending packet_send_query_mac_address\n");
01458 }
01459 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
01460 sizeof(packet_send_query_mac_address));
01461 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
01462 return;
01463 }
01464
01465 static int unistim_register(struct unistimsession *s)
01466 {
01467 struct unistim_device *d;
01468
01469 ast_mutex_lock(&devicelock);
01470 d = devices;
01471 while (d) {
01472 if (!strcasecmp(s->macaddr, d->id)) {
01473
01474 s->device = d;
01475 d->session = s;
01476 d->codec_number = DEFAULT_CODEC;
01477 d->pos_fav = 0;
01478 d->missed_call = 0;
01479 d->receiver_state = STATE_ONHOOK;
01480 break;
01481 }
01482 d = d->next;
01483 }
01484 ast_mutex_unlock(&devicelock);
01485
01486 if (!d)
01487 return 0;
01488
01489 return 1;
01490 }
01491
01492 static int alloc_sub(struct unistim_line *l, int x)
01493 {
01494 struct unistim_subchannel *sub;
01495 if (!(sub = ast_calloc(1, sizeof(*sub))))
01496 return 0;
01497
01498 if (unistimdebug)
01499 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
01500 sub->parent = l;
01501 sub->subtype = x;
01502 l->subs[x] = sub;
01503 ast_mutex_init(&sub->lock);
01504 return 1;
01505 }
01506
01507 static int unalloc_sub(struct unistim_line *p, int x)
01508 {
01509 if (!x) {
01510 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
01511 p->parent->name);
01512 return -1;
01513 }
01514 if (unistimdebug)
01515 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
01516 p->parent->name);
01517 ast_mutex_destroy(&p->lock);
01518 ast_free(p->subs[x]);
01519 p->subs[x] = 0;
01520 return 0;
01521 }
01522
01523 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
01524 {
01525 BUFFSEND;
01526 int tmp, i = 0;
01527 char addrmac[19];
01528 int res = 0;
01529 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
01530 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
01531 i += 2;
01532 }
01533 if (unistimdebug) {
01534 ast_verb(0, "Mac Address received : %s\n", addrmac);
01535 }
01536 strcpy(pte->macaddr, addrmac);
01537 res = unistim_register(pte);
01538 if (!res) {
01539 switch (autoprovisioning) {
01540 case AUTOPROVISIONING_NO:
01541 ast_log(LOG_WARNING, "No entry found for this phone : %s\n", addrmac);
01542 pte->state = STATE_AUTHDENY;
01543 break;
01544 case AUTOPROVISIONING_YES:
01545 {
01546 struct unistim_device *d, *newd;
01547 struct unistim_line *newl;
01548 if (unistimdebug)
01549 ast_verb(0, "New phone, autoprovisioning on\n");
01550
01551 ast_mutex_lock(&devicelock);
01552 d = devices;
01553 while (d) {
01554 if (!strcasecmp(d->name, "template")) {
01555
01556 if (!(newd = ast_malloc(sizeof(*newd)))) {
01557 ast_mutex_unlock(&devicelock);
01558 return;
01559 }
01560
01561 memcpy(newd, d, sizeof(*newd));
01562 if (!(newl = ast_malloc(sizeof(*newl)))) {
01563 ast_free(newd);
01564 ast_mutex_unlock(&devicelock);
01565 return;
01566 }
01567
01568 memcpy(newl, d->lines, sizeof(*newl));
01569 if (!alloc_sub(newl, SUB_REAL)) {
01570 ast_free(newd);
01571 ast_free(newl);
01572 ast_mutex_unlock(&devicelock);
01573 return;
01574 }
01575
01576 ast_copy_string(newd->id, addrmac, sizeof(newd->id));
01577 ast_copy_string(newd->name, addrmac, sizeof(newd->name));
01578 if (newd->extension == EXTENSION_NONE)
01579 newd->extension = EXTENSION_ASK;
01580 newd->lines = newl;
01581 newd->receiver_state = STATE_ONHOOK;
01582 newd->session = pte;
01583 newd->to_delete = -1;
01584 pte->device = newd;
01585 newd->next = NULL;
01586 newl->parent = newd;
01587 strcpy(newl->name, d->lines->name);
01588 snprintf(d->lines->name, sizeof(d->lines->name), "%d",
01589 atoi(d->lines->name) + 1);
01590 snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
01591 newl->name, newd->name);
01592
01593 while (d->next) {
01594 d = d->next;
01595 }
01596 d->next = newd;
01597 d = newd;
01598 break;
01599 }
01600 d = d->next;
01601 }
01602 ast_mutex_unlock(&devicelock);
01603 if (!d) {
01604 ast_log(LOG_WARNING, "No entry [template] found in unistim.conf\n");
01605 pte->state = STATE_AUTHDENY;
01606 }
01607 }
01608 break;
01609 case AUTOPROVISIONING_TN:
01610 pte->state = STATE_AUTHDENY;
01611 break;
01612 case AUTOPROVISIONING_DB:
01613 ast_log(LOG_WARNING,
01614 "Autoprovisioning with database is not yet functional\n");
01615 break;
01616 default:
01617 ast_log(LOG_WARNING, "Internal error : unknown autoprovisioning value = %d\n",
01618 autoprovisioning);
01619 }
01620 }
01621 if (pte->state != STATE_AUTHDENY) {
01622 ast_verb(3, "Device '%s' successfuly registered\n", pte->device->name);
01623 switch (pte->device->extension) {
01624 case EXTENSION_NONE:
01625 pte->state = STATE_MAINPAGE;
01626 break;
01627 case EXTENSION_ASK:
01628
01629 if (ast_strlen_zero(pte->device->extension_number))
01630 pte->state = STATE_EXTENSION;
01631 else {
01632
01633 if (RegisterExtension(pte))
01634 pte->state = STATE_EXTENSION;
01635 else
01636 pte->state = STATE_MAINPAGE;
01637 }
01638 break;
01639 case EXTENSION_LINE:
01640 ast_copy_string(pte->device->extension_number, pte->device->lines->name,
01641 sizeof(pte->device->extension_number));
01642 if (RegisterExtension(pte))
01643 pte->state = STATE_EXTENSION;
01644 else
01645 pte->state = STATE_MAINPAGE;
01646 break;
01647 case EXTENSION_TN:
01648
01649 pte->state = STATE_MAINPAGE;
01650 break;
01651 default:
01652 ast_log(LOG_WARNING, "Internal error, extension value unknown : %d\n",
01653 pte->device->extension);
01654 pte->state = STATE_AUTHDENY;
01655 break;
01656 }
01657 }
01658 if (pte->state == STATE_EXTENSION) {
01659 if (pte->device->extension != EXTENSION_TN)
01660 pte->device->extension = EXTENSION_ASK;
01661 pte->device->extension_number[0] = '\0';
01662 }
01663 if (unistimdebug)
01664 ast_verb(0, "\nSending S1\n");
01665 memcpy(buffsend + SIZE_HEADER, packet_send_S1, sizeof(packet_send_S1));
01666 send_client(SIZE_HEADER + sizeof(packet_send_S1), buffsend, pte);
01667
01668 if (unistimdebug)
01669 ast_verb(0, "Sending query_basic_manager_04\n");
01670 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_04,
01671 sizeof(packet_send_query_basic_manager_04));
01672 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_04), buffsend, pte);
01673
01674 if (unistimdebug)
01675 ast_verb(0, "Sending query_basic_manager_10\n");
01676 memcpy(buffsend + SIZE_HEADER, packet_send_query_basic_manager_10,
01677 sizeof(packet_send_query_basic_manager_10));
01678 send_client(SIZE_HEADER + sizeof(packet_send_query_basic_manager_10), buffsend, pte);
01679
01680 send_date_time(pte);
01681 return;
01682 }
01683
01684 static int write_entry_history(struct unistimsession *pte, FILE * f, char c, char *line1)
01685 {
01686 if (fwrite(&c, 1, 1, f) != 1) {
01687 display_last_error("Unable to write history log header.");
01688 return -1;
01689 }
01690 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
01691 display_last_error("Unable to write history entry - date.");
01692 return -1;
01693 }
01694 if (fwrite(pte->device->lst_cid, TEXT_LENGTH_MAX, 1, f) != 1) {
01695 display_last_error("Unable to write history entry - callerid.");
01696 return -1;
01697 }
01698 if (fwrite(pte->device->lst_cnm, TEXT_LENGTH_MAX, 1, f) != 1) {
01699 display_last_error("Unable to write history entry - callername.");
01700 return -1;
01701 }
01702 return 0;
01703 }
01704
01705 static int write_history(struct unistimsession *pte, char way, char ismissed)
01706 {
01707 char tmp[AST_CONFIG_MAX_PATH], tmp2[AST_CONFIG_MAX_PATH];
01708 char line1[TEXT_LENGTH_MAX + 1];
01709 char count = 0, *histbuf;
01710 int size;
01711 FILE *f, *f2;
01712 struct timeval now = ast_tvnow();
01713 struct ast_tm atm = { 0, };
01714
01715 if (!pte->device)
01716 return -1;
01717 if (!pte->device->callhistory)
01718 return 0;
01719 if (strchr(pte->device->name, '/') || (pte->device->name[0] == '.')) {
01720 ast_log(LOG_WARNING, "Account code '%s' insecure for writing file\n",
01721 pte->device->name);
01722 return -1;
01723 }
01724
01725 snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
01726 if (ast_mkdir(tmp, 0770)) {
01727 if (errno != EEXIST) {
01728 display_last_error("Unable to create directory for history");
01729 return -1;
01730 }
01731 }
01732
01733 ast_localtime(&now, &atm, NULL);
01734 if (ismissed) {
01735 if (way == 'i')
01736 strcpy(tmp2, "Miss");
01737 else
01738 strcpy(tmp2, "Fail");
01739 } else
01740 strcpy(tmp2, "Answ");
01741 snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
01742 atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
01743 atm.tm_min, atm.tm_sec, tmp2);
01744
01745 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
01746 USTM_LOG_DIR, pte->device->name, way);
01747 if ((f = fopen(tmp, "r"))) {
01748 struct stat bufstat;
01749
01750 if (stat(tmp, &bufstat)) {
01751 display_last_error("Unable to stat history log.");
01752 fclose(f);
01753 return -1;
01754 }
01755 size = 1 + (MAX_ENTRY_LOG * TEXT_LENGTH_MAX * 3);
01756 if (bufstat.st_size != size) {
01757 ast_log(LOG_WARNING,
01758 "History file %s has an incorrect size (%d instead of %d). It will be replaced by a new one.",
01759 tmp, (int) bufstat.st_size, size);
01760 fclose(f);
01761 f = NULL;
01762 count = 1;
01763 }
01764 }
01765
01766
01767 if (!f) {
01768 char c = 1;
01769 int i;
01770
01771 if ((errno != ENOENT) && (count == 0)) {
01772 display_last_error("Unable to open history log.");
01773 return -1;
01774 }
01775 f = fopen(tmp, "w");
01776 if (!f) {
01777 display_last_error("Unable to create history log.");
01778 return -1;
01779 }
01780 if (write_entry_history(pte, f, c, line1)) {
01781 fclose(f);
01782 return -1;
01783 }
01784 memset(line1, ' ', TEXT_LENGTH_MAX);
01785 for (i = 3; i < MAX_ENTRY_LOG * 3; i++) {
01786 if (fwrite(line1, TEXT_LENGTH_MAX, 1, f) != 1) {
01787 display_last_error("Unable to write history entry - stuffing.");
01788 fclose(f);
01789 return -1;
01790 }
01791 }
01792 if (fclose(f))
01793 display_last_error("Unable to close history - creation.");
01794 return 0;
01795 }
01796
01797 if (fread(&count, 1, 1, f) != 1) {
01798 display_last_error("Unable to read history header.");
01799 fclose(f);
01800 return -1;
01801 }
01802 if (count > MAX_ENTRY_LOG) {
01803 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
01804 count, MAX_ENTRY_LOG);
01805 fclose(f);
01806 return -1;
01807 }
01808 snprintf(tmp2, sizeof(tmp2), "%s/%s/%s-%c.csv.tmp", ast_config_AST_LOG_DIR,
01809 USTM_LOG_DIR, pte->device->name, way);
01810 if (!(f2 = fopen(tmp2, "w"))) {
01811 display_last_error("Unable to create temporary history log.");
01812 fclose(f);
01813 return -1;
01814 }
01815
01816 if (++count > MAX_ENTRY_LOG)
01817 count = MAX_ENTRY_LOG;
01818
01819 if (write_entry_history(pte, f2, count, line1)) {
01820 fclose(f);
01821 fclose(f2);
01822 return -1;
01823 }
01824
01825 size = (MAX_ENTRY_LOG - 1) * TEXT_LENGTH_MAX * 3;
01826 if (!(histbuf = ast_malloc(size))) {
01827 fclose(f);
01828 fclose(f2);
01829 return -1;
01830 }
01831
01832 if (fread(histbuf, size, 1, f) != 1) {
01833 ast_free(histbuf);
01834 fclose(f);
01835 fclose(f2);
01836 display_last_error("Unable to read previous history entries.");
01837 return -1;
01838 }
01839 if (fwrite(histbuf, size, 1, f2) != 1) {
01840 ast_free(histbuf);
01841 fclose(f);
01842 fclose(f2);
01843 display_last_error("Unable to write previous history entries.");
01844 return -1;
01845 }
01846 ast_free(histbuf);
01847 if (fclose(f))
01848 display_last_error("Unable to close history log.");
01849 if (fclose(f2))
01850 display_last_error("Unable to close temporary history log.");
01851 if (unlink(tmp))
01852 display_last_error("Unable to remove old history log.");
01853 if (rename(tmp2, tmp))
01854 display_last_error("Unable to rename new history log.");
01855 return 0;
01856 }
01857
01858 static void cancel_dial(struct unistimsession *pte)
01859 {
01860 send_no_ring(pte);
01861 pte->device->missed_call++;
01862 write_history(pte, 'i', 1);
01863 show_main_page(pte);
01864 return;
01865 }
01866
01867 static void swap_subs(struct unistim_line *p, int a, int b)
01868 {
01869
01870 struct ast_rtp_instance *rtp;
01871 int fds;
01872
01873 if (unistimdebug)
01874 ast_verb(0, "Swapping %d and %d\n", a, b);
01875
01876 if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
01877 ast_log(LOG_WARNING,
01878 "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
01879 a, p->subs[a]->owner, b, p->subs[b]->owner);
01880 return;
01881 }
01882 rtp = p->subs[a]->rtp;
01883 p->subs[a]->rtp = p->subs[b]->rtp;
01884 p->subs[b]->rtp = rtp;
01885
01886 fds = p->subs[a]->owner->fds[0];
01887 p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
01888 p->subs[b]->owner->fds[0] = fds;
01889
01890 fds = p->subs[a]->owner->fds[1];
01891 p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
01892 p->subs[b]->owner->fds[1] = fds;
01893 }
01894
01895 static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
01896 {
01897 int res = 0;
01898 struct ast_channel
01899 *chana = NULL, *chanb = NULL, *bridgea = NULL, *bridgeb = NULL, *peera =
01900 NULL, *peerb = NULL, *peerc = NULL;
01901
01902 if (!p1->owner || !p2->owner) {
01903 ast_log(LOG_WARNING, "Transfer attempted without dual ownership?\n");
01904 return -1;
01905 }
01906 chana = p1->owner;
01907 chanb = p2->owner;
01908 bridgea = ast_bridged_channel(chana);
01909 bridgeb = ast_bridged_channel(chanb);
01910
01911 if (bridgea) {
01912 peera = chana;
01913 peerb = chanb;
01914 peerc = bridgea;
01915 } else if (bridgeb) {
01916 peera = chanb;
01917 peerb = chana;
01918 peerc = bridgeb;
01919 }
01920
01921 if (peera && peerb && peerc && (peerb != peerc)) {
01922
01923
01924
01925
01926
01927 if (ast_channel_masquerade(peerb, peerc)) {
01928 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
01929 peerc->name);
01930 res = -1;
01931 }
01932 return res;
01933 } else {
01934 ast_log(LOG_NOTICE,
01935 "Transfer attempted with no appropriate bridged calls to transfer\n");
01936 if (chana)
01937 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
01938 if (chanb)
01939 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
01940 return -1;
01941 }
01942 return 0;
01943 }
01944
01945 void change_callerid(struct unistimsession *pte, int type, char *callerid)
01946 {
01947 char *data;
01948 int size;
01949
01950 if (type)
01951 data = pte->device->lst_cnm;
01952 else
01953 data = pte->device->lst_cid;
01954
01955
01956
01957 memset(data, ' ', TEXT_LENGTH_MAX);
01958 size = strlen(callerid);
01959 if (size > TEXT_LENGTH_MAX)
01960 size = TEXT_LENGTH_MAX;
01961 memcpy(data, callerid, size);
01962 }
01963
01964 static void close_call(struct unistimsession *pte)
01965 {
01966 struct unistim_subchannel *sub;
01967 struct unistim_line *l = pte->device->lines;
01968
01969 sub = pte->device->lines->subs[SUB_REAL];
01970 send_stop_timer(pte);
01971 if (sub->owner) {
01972 sub->alreadygone = 1;
01973 if (l->subs[SUB_THREEWAY]) {
01974 l->subs[SUB_THREEWAY]->alreadygone = 1;
01975 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
01976 ast_verb(0, "attempt_transfer failed.\n");
01977 } else
01978 ast_queue_hangup(sub->owner);
01979 } else {
01980 if (l->subs[SUB_THREEWAY]) {
01981 if (l->subs[SUB_THREEWAY]->owner)
01982 ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
01983 else
01984 ast_log(LOG_WARNING, "threeway sub without owner\n");
01985 } else
01986 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
01987 sub->parent->parent->name, sub->subtype);
01988 }
01989 change_callerid(pte, 0, pte->device->redial_number);
01990 change_callerid(pte, 1, "");
01991 write_history(pte, 'o', pte->device->missed_call);
01992 pte->device->missed_call = 0;
01993 show_main_page(pte);
01994 return;
01995 }
01996
01997 static void IgnoreCall(struct unistimsession *pte)
01998 {
01999 send_no_ring(pte);
02000 return;
02001 }
02002
02003 static void *unistim_ss(void *data)
02004 {
02005 struct ast_channel *chan = data;
02006 struct unistim_subchannel *sub = chan->tech_pvt;
02007 struct unistim_line *l = sub->parent;
02008 struct unistimsession *s = l->parent->session;
02009 int res;
02010
02011 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
02012 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
02013 ast_copy_string(s->device->redial_number, s->device->phone_number,
02014 sizeof(s->device->redial_number));
02015 ast_setstate(chan, AST_STATE_RING);
02016 res = ast_pbx_run(chan);
02017 if (res) {
02018 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02019 send_tone(s, 1000, 0);;
02020 }
02021 return NULL;
02022 }
02023
02024 static void start_rtp(struct unistim_subchannel *sub)
02025 {
02026 BUFFSEND;
02027 struct sockaddr_in us = { 0, };
02028 struct sockaddr_in public = { 0, };
02029 struct sockaddr_in sin = { 0, };
02030 format_t codec;
02031 struct sockaddr_in sout = { 0, };
02032 struct ast_sockaddr us_tmp;
02033 struct ast_sockaddr sin_tmp;
02034 struct ast_sockaddr sout_tmp;
02035
02036
02037 if (!sub) {
02038 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
02039 return;
02040 }
02041 if (!sub->parent) {
02042 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
02043 return;
02044 }
02045 if (!sub->parent->parent) {
02046 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
02047 return;
02048 }
02049 if (!sub->parent->parent->session) {
02050 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
02051 return;
02052 }
02053 sout = sub->parent->parent->session->sout;
02054
02055 ast_mutex_lock(&sub->lock);
02056
02057 if (unistimdebug)
02058 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
02059 ast_sockaddr_from_sin(&sout_tmp, &sout);
02060 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
02061 if (!sub->rtp) {
02062 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
02063 strerror(errno), ast_inet_ntoa(sout.sin_addr));
02064 ast_mutex_unlock(&sub->lock);
02065 return;
02066 }
02067 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
02068 if (sub->owner) {
02069 sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
02070 sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
02071 }
02072 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
02073 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
02074
02075
02076 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
02077 ast_sockaddr_to_sin(&us_tmp, &us);
02078 sin.sin_family = AF_INET;
02079
02080 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
02081 sizeof(sin.sin_addr));
02082 sin.sin_port = htons(sub->parent->parent->rtp_port);
02083 ast_sockaddr_from_sin(&sin_tmp, &sin);
02084 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
02085 if (!(sub->owner->nativeformats & sub->owner->readformat)) {
02086 format_t fmt;
02087 char tmp[256];
02088 fmt = ast_best_codec(sub->owner->nativeformats);
02089 ast_log(LOG_WARNING,
02090 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
02091 ast_getformatname(sub->owner->readformat),
02092 ast_getformatname(fmt),
02093 ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
02094 sub->owner->readformat = fmt;
02095 sub->owner->writeformat = fmt;
02096 }
02097 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
02098
02099 if (public_ip.sin_family == 0)
02100 memcpy(&public, &us, sizeof(public));
02101 else
02102 memcpy(&public, &public_ip, sizeof(public));
02103 if (unistimdebug) {
02104 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
02105 ast_inet_ntoa(us.sin_addr),
02106 htons(us.sin_port), ast_getformatname(sub->owner->readformat));
02107 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
02108 ast_inet_ntoa(public.sin_addr));
02109 }
02110 if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
02111 (sub->owner->readformat == AST_FORMAT_ALAW)) {
02112 if (unistimdebug)
02113 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %s\n", ast_getformatname(codec));
02114 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
02115 sizeof(packet_send_rtp_packet_size));
02116 buffsend[10] = (int) codec & 0xffffffffLL;
02117 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
02118 sub->parent->parent->session);
02119 }
02120 if (unistimdebug)
02121 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
02122 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
02123 sizeof(packet_send_jitter_buffer_conf));
02124 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
02125 sub->parent->parent->session);
02126 if (sub->parent->parent->rtp_method != 0) {
02127 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02128
02129 if (unistimdebug)
02130 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
02131 sub->parent->parent->rtp_method);
02132 if (sub->parent->parent->rtp_method == 3)
02133 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
02134 sizeof(packet_send_open_audio_stream_tx3));
02135 else
02136 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
02137 sizeof(packet_send_open_audio_stream_tx));
02138 if (sub->parent->parent->rtp_method != 2) {
02139 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02140 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02141 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02142 buffsend[23] = (rtcpsin_port & 0x00ff);
02143 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02144 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02145 buffsend[24] = (us.sin_port & 0x00ff);
02146 buffsend[27] = (rtcpsin_port & 0x00ff);
02147 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02148 } else {
02149 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02150 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02151 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02152 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02153 buffsend[19] = (us.sin_port & 0x00ff);
02154 }
02155 buffsend[11] = codec;
02156 buffsend[12] = codec;
02157 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
02158 sub->parent->parent->session);
02159
02160 if (unistimdebug)
02161 ast_verb(0, "Sending OpenAudioStreamRX\n");
02162 if (sub->parent->parent->rtp_method == 3)
02163 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
02164 sizeof(packet_send_open_audio_stream_rx3));
02165 else
02166 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
02167 sizeof(packet_send_open_audio_stream_rx));
02168 if (sub->parent->parent->rtp_method != 2) {
02169 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02170 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02171 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02172 buffsend[23] = (rtcpsin_port & 0x00ff);
02173 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02174 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02175 buffsend[24] = (us.sin_port & 0x00ff);
02176 buffsend[27] = (rtcpsin_port & 0x00ff);
02177 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02178 } else {
02179 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02180 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02181 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02182 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02183 buffsend[19] = (us.sin_port & 0x00ff);
02184 }
02185 buffsend[11] = codec;
02186 buffsend[12] = codec;
02187 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
02188 sub->parent->parent->session);
02189 } else {
02190 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02191
02192 if (unistimdebug)
02193 ast_verb(0, "Sending packet_send_call default method\n");
02194
02195 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
02196 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
02197
02198 buffsend[49] = (us.sin_port & 0x00ff);
02199 buffsend[50] = (us.sin_port & 0xff00) >> 8;
02200
02201 buffsend[52] = (rtcpsin_port & 0x00ff);
02202 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
02203
02204 buffsend[40] = codec;
02205 buffsend[41] = codec;
02206 if (sub->owner->readformat == AST_FORMAT_ULAW)
02207 buffsend[42] = 1;
02208 else if (sub->owner->readformat == AST_FORMAT_ALAW)
02209 buffsend[42] = 1;
02210 else if (sub->owner->readformat == AST_FORMAT_G723_1)
02211 buffsend[42] = 2;
02212 else if (sub->owner->readformat == AST_FORMAT_G729A)
02213 buffsend[42] = 2;
02214 else
02215 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
02216 ast_getformatname(sub->owner->readformat));
02217
02218 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
02219 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
02220 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
02221 buffsend[48] = (rtcpsin_port & 0x00ff);
02222 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
02223 sub->parent->parent->session);
02224 }
02225 ast_mutex_unlock(&sub->lock);
02226 }
02227
02228 static void SendDialTone(struct unistimsession *pte)
02229 {
02230 int i;
02231
02232 if (ast_strlen_zero(pte->device->country)) {
02233 if (unistimdebug)
02234 ast_verb(0, "No country defined, using US tone\n");
02235 send_tone(pte, 350, 440);
02236 return;
02237 }
02238 if (strlen(pte->device->country) != 2) {
02239 if (unistimdebug)
02240 ast_verb(0, "Country code != 2 char, using US tone\n");
02241 send_tone(pte, 350, 440);
02242 return;
02243 }
02244 i = 0;
02245 while (frequency[i].freq1) {
02246 if ((frequency[i].country[0] == pte->device->country[0]) &&
02247 (frequency[i].country[1] == pte->device->country[1])) {
02248 if (unistimdebug)
02249 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
02250 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
02251 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
02252 }
02253 i++;
02254 }
02255 }
02256
02257 static void handle_dial_page(struct unistimsession *pte)
02258 {
02259 pte->state = STATE_DIALPAGE;
02260 if (pte->device->call_forward[0] == -1) {
02261 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
02262 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
02263 send_text_status(pte, "ForwardCancel BackSpcErase");
02264 if (pte->device->call_forward[1] != 0) {
02265 char tmp[TEXT_LENGTH_MAX + 1];
02266
02267 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
02268 sizeof(pte->device->phone_number));
02269 pte->device->size_phone_number = strlen(pte->device->phone_number);
02270 if (pte->device->size_phone_number > 15)
02271 pte->device->size_phone_number = 15;
02272 strcpy(tmp, "Number : ...............");
02273 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
02274
02275 if (pte->device->height == 1) {
02276 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
02277 send_blink_cursor(pte);
02278 send_cursor_pos(pte,
02279 (unsigned char) (TEXT_LINE0 + 0x09 +
02280 pte->device->size_phone_number));
02281 } else {
02282 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
02283 send_blink_cursor(pte);
02284 send_cursor_pos(pte,
02285 (unsigned char) (TEXT_LINE2 + 0x09 +
02286 pte->device->size_phone_number));
02287 }
02288
02289 send_led_update(pte, 0);
02290 return;
02291 }
02292 } else {
02293 if ((pte->device->output == OUTPUT_HANDSET) &&
02294 (pte->device->receiver_state == STATE_ONHOOK))
02295 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02296 else
02297 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02298 SendDialTone(pte);
02299
02300 if (pte->device->height > 1) {
02301 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
02302 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
02303 }
02304 send_text_status(pte, "Call Redial BackSpcErase");
02305 }
02306
02307 if (pte->device->height == 1) {
02308 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
02309 send_blink_cursor(pte);
02310 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
02311 } else {
02312 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
02313 send_blink_cursor(pte);
02314 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
02315 }
02316 pte->device->size_phone_number = 0;
02317 pte->device->phone_number[0] = 0;
02318 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
02319 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
02320 pte->device->missed_call = 0;
02321 send_led_update(pte, 0);
02322 return;
02323 }
02324
02325
02326 static void TransferCallStep1(struct unistimsession *pte)
02327 {
02328 struct unistim_subchannel *sub;
02329 struct unistim_line *p = pte->device->lines;
02330
02331 sub = p->subs[SUB_REAL];
02332
02333 if (!sub->owner) {
02334 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02335 return;
02336 }
02337 if (p->subs[SUB_THREEWAY]) {
02338 if (unistimdebug)
02339 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
02340 if (p->subs[SUB_THREEWAY]->owner)
02341 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
02342 else
02343 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
02344 return;
02345 }
02346
02347 if (pte->device->moh)
02348 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
02349 else {
02350 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
02351 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
02352 pte->device->lines->musicclass, NULL);
02353 pte->device->moh = 1;
02354 } else {
02355 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
02356 return;
02357 }
02358 }
02359
02360 if (!pte->device->silence_generator) {
02361 pte->device->silence_generator =
02362 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
02363 if (pte->device->silence_generator == NULL)
02364 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
02365 else if (unistimdebug)
02366 ast_verb(0, "Starting silence generator\n");
02367 }
02368 handle_dial_page(pte);
02369 }
02370
02371
02372 static void HandleCallOutgoing(struct unistimsession *s)
02373 {
02374 struct ast_channel *c;
02375 struct unistim_subchannel *sub;
02376 pthread_t t;
02377 s->state = STATE_CALL;
02378 sub = s->device->lines->subs[SUB_REAL];
02379 if (!sub) {
02380 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
02381 return;
02382 }
02383 if (!sub->owner) {
02384 c = unistim_new(sub, AST_STATE_DOWN, NULL);
02385 if (c) {
02386
02387 if (!sub->rtp)
02388 start_rtp(sub);
02389 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02390
02391 if (s->device->height == 1) {
02392 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
02393 } else {
02394 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
02395 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
02396 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
02397 }
02398 send_text_status(s, "Hangup");
02399
02400
02401 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
02402 display_last_error("Unable to create switch thread");
02403 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
02404 }
02405 } else
02406 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
02407 sub->parent->name, s->device->name);
02408 } else {
02409
02410 if (s->device->moh) {
02411 struct unistim_subchannel *subchannel;
02412 struct unistim_line *p = s->device->lines;
02413 subchannel = p->subs[SUB_REAL];
02414
02415 if (!subchannel->owner) {
02416 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02417 return;
02418 }
02419 if (p->subs[SUB_THREEWAY]) {
02420 ast_log(LOG_WARNING,
02421 "Can't transfer while an another transfer is taking place\n");
02422 return;
02423 }
02424 if (!alloc_sub(p, SUB_THREEWAY)) {
02425 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
02426 return;
02427 }
02428
02429 if (s->device->silence_generator) {
02430 if (unistimdebug)
02431 ast_verb(0, "Stopping silence generator\n");
02432 ast_channel_stop_silence_generator(subchannel->owner,
02433 s->device->silence_generator);
02434 s->device->silence_generator = NULL;
02435 }
02436 send_tone(s, 0, 0);
02437
02438 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
02439 if (!c) {
02440 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
02441 return;
02442 }
02443
02444 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02445 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02446
02447 if (s->device->height == 1) {
02448 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
02449 } else {
02450 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
02451 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
02452 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
02453 }
02454 send_text_status(s, "TransfrCancel");
02455
02456 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
02457 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
02458 ast_hangup(c);
02459 return;
02460 }
02461 if (unistimdebug)
02462 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
02463 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
02464 p->subs[SUB_THREEWAY]->subtype);
02465 } else
02466 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
02467 }
02468 return;
02469 }
02470
02471
02472 static void HandleCallIncoming(struct unistimsession *s)
02473 {
02474 struct unistim_subchannel *sub;
02475 s->state = STATE_CALL;
02476 s->device->missed_call = 0;
02477 send_no_ring(s);
02478 sub = s->device->lines->subs[SUB_REAL];
02479 if (!sub) {
02480 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
02481 return;
02482 } else if (unistimdebug)
02483 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
02484 s->device->name);
02485 start_rtp(sub);
02486 if (!sub->rtp)
02487 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
02488 s->device->name);
02489 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
02490 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
02491 send_text_status(s, "Hangup Transf");
02492 send_start_timer(s);
02493
02494 if ((s->device->output == OUTPUT_HANDSET) &&
02495 (s->device->receiver_state == STATE_ONHOOK))
02496 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
02497 else
02498 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02499 s->device->start_call_timestamp = time(0);
02500 write_history(s, 'i', 0);
02501 return;
02502 }
02503
02504 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
02505 {
02506 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
02507 struct unistim_subchannel *sub;
02508 sub = pte->device->lines->subs[SUB_REAL];
02509 if (!sub->owner || sub->alreadygone) {
02510 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
02511 return -1;
02512 }
02513
02514
02515 ast_queue_frame(sub->owner, &f);
02516
02517 if (unistimdebug)
02518 ast_verb(0, "Send Digit %c\n", digit);
02519 switch (digit) {
02520 case '0':
02521 send_tone(pte, 941, 1336);
02522 break;
02523 case '1':
02524 send_tone(pte, 697, 1209);
02525 break;
02526 case '2':
02527 send_tone(pte, 697, 1336);
02528 break;
02529 case '3':
02530 send_tone(pte, 697, 1477);
02531 break;
02532 case '4':
02533 send_tone(pte, 770, 1209);
02534 break;
02535 case '5':
02536 send_tone(pte, 770, 1336);
02537 break;
02538 case '6':
02539 send_tone(pte, 770, 1477);
02540 break;
02541 case '7':
02542 send_tone(pte, 852, 1209);
02543 break;
02544 case '8':
02545 send_tone(pte, 852, 1336);
02546 break;
02547 case '9':
02548 send_tone(pte, 852, 1477);
02549 break;
02550 case 'A':
02551 send_tone(pte, 697, 1633);
02552 break;
02553 case 'B':
02554 send_tone(pte, 770, 1633);
02555 break;
02556 case 'C':
02557 send_tone(pte, 852, 1633);
02558 break;
02559 case 'D':
02560 send_tone(pte, 941, 1633);
02561 break;
02562 case '*':
02563 send_tone(pte, 941, 1209);
02564 break;
02565 case '#':
02566 send_tone(pte, 941, 1477);
02567 break;
02568 default:
02569 send_tone(pte, 500, 2000);
02570 }
02571 usleep(150000);
02572 send_tone(pte, 0, 0);
02573 return 0;
02574 }
02575
02576 static void key_call(struct unistimsession *pte, char keycode)
02577 {
02578 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02579 if (keycode == KEY_SHARP)
02580 keycode = '#';
02581 else if (keycode == KEY_STAR)
02582 keycode = '*';
02583 else
02584 keycode -= 0x10;
02585 unistim_do_senddigit(pte, keycode);
02586 return;
02587 }
02588 switch (keycode) {
02589 case KEY_HANGUP:
02590 case KEY_FUNC1:
02591 close_call(pte);
02592 break;
02593 case KEY_FUNC2:
02594 TransferCallStep1(pte);
02595 break;
02596 case KEY_HEADPHN:
02597 if (pte->device->output == OUTPUT_HEADPHONE)
02598 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02599 else
02600 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02601 break;
02602 case KEY_LOUDSPK:
02603 if (pte->device->output != OUTPUT_SPEAKER)
02604 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02605 else
02606 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02607 MUTE_OFF);
02608 break;
02609 case KEY_MUTE:
02610 if (!pte->device->moh) {
02611 if (pte->device->mute == MUTE_ON)
02612 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02613 else
02614 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
02615 break;
02616 }
02617 case KEY_ONHOLD:
02618 {
02619 struct unistim_subchannel *sub;
02620 struct ast_channel *bridgepeer = NULL;
02621 sub = pte->device->lines->subs[SUB_REAL];
02622 if (!sub->owner) {
02623 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02624 return;
02625 }
02626 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
02627 if (pte->device->moh) {
02628 ast_moh_stop(bridgepeer);
02629 pte->device->moh = 0;
02630 send_select_output(pte, pte->device->output, pte->device->volume,
02631 MUTE_OFF);
02632 } else {
02633 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
02634 pte->device->moh = 1;
02635 send_select_output(pte, pte->device->output, pte->device->volume,
02636 MUTE_ON);
02637 }
02638 } else
02639 ast_log(LOG_WARNING,
02640 "Unable to find peer subchannel for music on hold\n");
02641 break;
02642 }
02643 }
02644 return;
02645 }
02646
02647 static void key_ringing(struct unistimsession *pte, char keycode)
02648 {
02649 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
02650 HandleCallIncoming(pte);
02651 return;
02652 }
02653 switch (keycode) {
02654 case KEY_HANGUP:
02655 case KEY_FUNC4:
02656 IgnoreCall(pte);
02657 break;
02658 case KEY_FUNC1:
02659 HandleCallIncoming(pte);
02660 break;
02661 }
02662 return;
02663 }
02664
02665 static void Keyfavorite(struct unistimsession *pte, char keycode)
02666 {
02667 int fav;
02668
02669 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
02670 ast_log(LOG_WARNING, "It's not a favorite key\n");
02671 return;
02672 }
02673 if (keycode == KEY_FAV0)
02674 return;
02675 fav = keycode - KEY_FAV0;
02676 if (pte->device->softkeyicon[fav] == 0)
02677 return;
02678 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
02679 sizeof(pte->device->phone_number));
02680 HandleCallOutgoing(pte);
02681 return;
02682 }
02683
02684 static void key_dial_page(struct unistimsession *pte, char keycode)
02685 {
02686 if (keycode == KEY_FUNC3) {
02687 if (pte->device->size_phone_number <= 1)
02688 keycode = KEY_FUNC4;
02689 else {
02690 pte->device->size_phone_number -= 2;
02691 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
02692 }
02693 }
02694 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02695 char tmpbuf[] = "Number : ...............";
02696 int i = 0;
02697
02698 if (pte->device->size_phone_number >= 15)
02699 return;
02700 if (pte->device->size_phone_number == 0)
02701 send_tone(pte, 0, 0);
02702 while (i < pte->device->size_phone_number) {
02703 tmpbuf[i + 9] = pte->device->phone_number[i];
02704 i++;
02705 }
02706 if (keycode == KEY_SHARP)
02707 keycode = '#';
02708 else if (keycode == KEY_STAR)
02709 keycode = '*';
02710 else
02711 keycode -= 0x10;
02712 tmpbuf[i + 9] = keycode;
02713 pte->device->phone_number[i] = keycode;
02714 pte->device->size_phone_number++;
02715 pte->device->phone_number[i + 1] = 0;
02716 if (pte->device->height == 1) {
02717 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
02718 } else {
02719 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02720 }
02721 send_blink_cursor(pte);
02722 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
02723 return;
02724 }
02725 if (keycode == KEY_FUNC4) {
02726
02727 pte->device->size_phone_number = 0;
02728 if (pte->device->height == 1) {
02729 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
02730 send_blink_cursor(pte);
02731 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
02732 } else {
02733 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
02734 send_blink_cursor(pte);
02735 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
02736 }
02737 return;
02738 }
02739
02740 if (pte->device->call_forward[0] == -1) {
02741 if (keycode == KEY_FUNC1) {
02742 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
02743 sizeof(pte->device->call_forward));
02744 show_main_page(pte);
02745 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
02746 pte->device->call_forward[0] = '\0';
02747 show_main_page(pte);
02748 }
02749 return;
02750 }
02751 switch (keycode) {
02752 case KEY_FUNC2:
02753 if (ast_strlen_zero(pte->device->redial_number))
02754 break;
02755 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
02756 sizeof(pte->device->phone_number));
02757 case KEY_FUNC1:
02758 HandleCallOutgoing(pte);
02759 break;
02760 case KEY_HANGUP:
02761 if (pte->device->lines->subs[SUB_REAL]->owner) {
02762
02763 if (pte->device->silence_generator) {
02764 if (unistimdebug)
02765 ast_verb(0, "Stopping silence generator\n");
02766 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
02767 owner, pte->device->silence_generator);
02768 pte->device->silence_generator = NULL;
02769 }
02770 send_tone(pte, 0, 0);
02771 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
02772 pte->device->moh = 0;
02773 pte->state = STATE_CALL;
02774
02775 if (pte->device->height == 1) {
02776 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
02777 } else {
02778 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
02779 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
02780 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
02781 }
02782 send_text_status(pte, "Hangup Transf");
02783 } else
02784 show_main_page(pte);
02785 break;
02786 case KEY_FAV1:
02787 case KEY_FAV2:
02788 case KEY_FAV3:
02789 case KEY_FAV4:
02790 case KEY_FAV5:
02791 Keyfavorite(pte, keycode);
02792 break;
02793 case KEY_LOUDSPK:
02794 if (pte->device->output == OUTPUT_SPEAKER) {
02795 if (pte->device->receiver_state == STATE_OFFHOOK)
02796 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02797 MUTE_OFF);
02798 else
02799 show_main_page(pte);
02800 } else
02801 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02802 break;
02803 case KEY_HEADPHN:
02804 if (pte->device->output == OUTPUT_HEADPHONE) {
02805 if (pte->device->receiver_state == STATE_OFFHOOK)
02806 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02807 else
02808 show_main_page(pte);
02809 } else
02810 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02811 break;
02812 }
02813 return;
02814 }
02815
02816 #define SELECTCODEC_START_ENTRY_POS 15
02817 #define SELECTCODEC_MAX_LENGTH 2
02818 #define SELECTCODEC_MSG "Codec number : .."
02819 static void HandleSelectCodec(struct unistimsession *pte)
02820 {
02821 char buf[30], buf2[5];
02822
02823 pte->state = STATE_SELECTCODEC;
02824 strcpy(buf, "Using codec ");
02825 sprintf(buf2, "%d", pte->device->codec_number);
02826 strcat(buf, buf2);
02827 strcat(buf, " (G711u=0,");
02828
02829 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
02830 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
02831 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02832 send_blink_cursor(pte);
02833 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02834 pte->size_buff_entry = 0;
02835 send_text_status(pte, "Select BackSpcErase Cancel");
02836 return;
02837 }
02838
02839 static void key_select_codec(struct unistimsession *pte, char keycode)
02840 {
02841 if (keycode == KEY_FUNC2) {
02842 if (pte->size_buff_entry <= 1)
02843 keycode = KEY_FUNC3;
02844 else {
02845 pte->size_buff_entry -= 2;
02846 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02847 }
02848 }
02849 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02850 char tmpbuf[] = SELECTCODEC_MSG;
02851 int i = 0;
02852
02853 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
02854 return;
02855
02856 while (i < pte->size_buff_entry) {
02857 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
02858 i++;
02859 }
02860 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
02861 pte->buff_entry[i] = keycode - 0x10;
02862 pte->size_buff_entry++;
02863 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
02864 send_blink_cursor(pte);
02865 send_cursor_pos(pte,
02866 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
02867 return;
02868 }
02869
02870 switch (keycode) {
02871 case KEY_FUNC1:
02872 if (pte->size_buff_entry == 1)
02873 pte->device->codec_number = pte->buff_entry[0] - 48;
02874 else if (pte->size_buff_entry == 2)
02875 pte->device->codec_number =
02876 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
02877 show_main_page(pte);
02878 break;
02879 case KEY_FUNC3:
02880 pte->size_buff_entry = 0;
02881 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02882 send_blink_cursor(pte);
02883 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02884 break;
02885 case KEY_HANGUP:
02886 case KEY_FUNC4:
02887 show_main_page(pte);
02888 break;
02889 }
02890 return;
02891 }
02892
02893 #define SELECTEXTENSION_START_ENTRY_POS 0
02894 #define SELECTEXTENSION_MAX_LENGTH 10
02895 #define SELECTEXTENSION_MSG ".........."
02896 static void ShowExtensionPage(struct unistimsession *pte)
02897 {
02898 pte->state = STATE_EXTENSION;
02899
02900 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
02901 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
02902 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
02903 send_blink_cursor(pte);
02904 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
02905 send_text_status(pte, "Enter BackSpcErase");
02906 pte->size_buff_entry = 0;
02907 return;
02908 }
02909
02910 static void key_select_extension(struct unistimsession *pte, char keycode)
02911 {
02912 if (keycode == KEY_FUNC2) {
02913 if (pte->size_buff_entry <= 1)
02914 keycode = KEY_FUNC3;
02915 else {
02916 pte->size_buff_entry -= 2;
02917 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02918 }
02919 }
02920 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02921 char tmpbuf[] = SELECTEXTENSION_MSG;
02922 int i = 0;
02923
02924 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
02925 return;
02926
02927 while (i < pte->size_buff_entry) {
02928 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
02929 i++;
02930 }
02931 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
02932 pte->buff_entry[i] = keycode - 0x10;
02933 pte->size_buff_entry++;
02934 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02935 send_blink_cursor(pte);
02936 send_cursor_pos(pte,
02937 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
02938 i));
02939 return;
02940 }
02941
02942 switch (keycode) {
02943 case KEY_FUNC1:
02944 if (pte->size_buff_entry < 1)
02945 return;
02946 if (autoprovisioning == AUTOPROVISIONING_TN) {
02947 struct unistim_device *d;
02948
02949
02950 ast_mutex_lock(&devicelock);
02951 d = devices;
02952 pte->buff_entry[pte->size_buff_entry] = '\0';
02953 while (d) {
02954 if (d->id[0] == 'T') {
02955
02956 if (!strcmp((d->id) + 1, pte->buff_entry)) {
02957 pte->device = d;
02958 d->session = pte;
02959 d->codec_number = DEFAULT_CODEC;
02960 d->pos_fav = 0;
02961 d->missed_call = 0;
02962 d->receiver_state = STATE_ONHOOK;
02963 strcpy(d->id, pte->macaddr);
02964 pte->device->extension_number[0] = 'T';
02965 pte->device->extension = EXTENSION_TN;
02966 ast_copy_string((pte->device->extension_number) + 1,
02967 pte->buff_entry, pte->size_buff_entry + 1);
02968 ast_mutex_unlock(&devicelock);
02969 show_main_page(pte);
02970 refresh_all_favorite(pte);
02971 return;
02972 }
02973 }
02974 d = d->next;
02975 }
02976 ast_mutex_unlock(&devicelock);
02977 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
02978 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
02979 send_cursor_pos(pte,
02980 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
02981 pte->size_buff_entry));
02982 send_blink_cursor(pte);
02983 } else {
02984 ast_copy_string(pte->device->extension_number, pte->buff_entry,
02985 pte->size_buff_entry + 1);
02986 if (RegisterExtension(pte)) {
02987 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
02988 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
02989 send_cursor_pos(pte,
02990 (unsigned char) (TEXT_LINE2 +
02991 SELECTEXTENSION_START_ENTRY_POS +
02992 pte->size_buff_entry));
02993 send_blink_cursor(pte);
02994 } else
02995 show_main_page(pte);
02996 }
02997 break;
02998 case KEY_FUNC3:
02999 pte->size_buff_entry = 0;
03000 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03001 send_blink_cursor(pte);
03002 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03003 break;
03004 }
03005 return;
03006 }
03007
03008 static int ReformatNumber(char *number)
03009 {
03010 int pos = 0, i = 0, size = strlen(number);
03011
03012 for (; i < size; i++) {
03013 if ((number[i] >= '0') && (number[i] <= '9')) {
03014 if (i == pos) {
03015 pos++;
03016 continue;
03017 }
03018 number[pos] = number[i];
03019 pos++;
03020 }
03021 }
03022 number[pos] = 0;
03023 return pos;
03024 }
03025
03026 static void show_entry_history(struct unistimsession *pte, FILE ** f)
03027 {
03028 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
03029 func3[10];
03030
03031 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03032 display_last_error("Can't read history date entry");
03033 fclose(*f);
03034 return;
03035 }
03036 line[sizeof(line) - 1] = '\0';
03037 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03038 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03039 display_last_error("Can't read callerid entry");
03040 fclose(*f);
03041 return;
03042 }
03043 line[sizeof(line) - 1] = '\0';
03044 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
03045 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
03046 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03047 display_last_error("Can't read callername entry");
03048 fclose(*f);
03049 return;
03050 }
03051 line[sizeof(line) - 1] = '\0';
03052 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
03053 fclose(*f);
03054
03055 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
03056 pte->buff_entry[1]);
03057 send_texttitle(pte, line);
03058
03059 if (pte->buff_entry[2] == 1)
03060 strcpy(func1, " ");
03061 else
03062 strcpy(func1, "Prvious");
03063 if (pte->buff_entry[2] >= pte->buff_entry[1])
03064 strcpy(func2, " ");
03065 else
03066 strcpy(func2, "Next ");
03067 if (ReformatNumber(pte->device->lst_cid))
03068 strcpy(func3, "Redial ");
03069 else
03070 strcpy(func3, " ");
03071 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
03072 send_text_status(pte, status);
03073 }
03074
03075 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
03076 {
03077 char tmp[AST_CONFIG_MAX_PATH];
03078 char count;
03079
03080 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
03081 USTM_LOG_DIR, pte->device->name, way);
03082 *f = fopen(tmp, "r");
03083 if (!*f) {
03084 display_last_error("Unable to open history file");
03085 return 0;
03086 }
03087 if (fread(&count, 1, 1, *f) != 1) {
03088 display_last_error("Unable to read history header - display.");
03089 fclose(*f);
03090 return 0;
03091 }
03092 if (count > MAX_ENTRY_LOG) {
03093 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
03094 count, MAX_ENTRY_LOG);
03095 fclose(*f);
03096 return 0;
03097 }
03098 return count;
03099 }
03100
03101 static void show_history(struct unistimsession *pte, char way)
03102 {
03103 FILE *f;
03104 char count;
03105
03106 if (!pte->device)
03107 return;
03108 if (!pte->device->callhistory)
03109 return;
03110 count = OpenHistory(pte, way, &f);
03111 if (!count)
03112 return;
03113 pte->buff_entry[0] = way;
03114 pte->buff_entry[1] = count;
03115 pte->buff_entry[2] = 1;
03116 show_entry_history(pte, &f);
03117 pte->state = STATE_HISTORY;
03118 }
03119
03120 static void show_main_page(struct unistimsession *pte)
03121 {
03122 char tmpbuf[TEXT_LENGTH_MAX + 1];
03123
03124
03125 if ((pte->device->extension == EXTENSION_ASK) &&
03126 (ast_strlen_zero(pte->device->extension_number))) {
03127 ShowExtensionPage(pte);
03128 return;
03129 }
03130
03131 pte->state = STATE_MAINPAGE;
03132
03133 send_tone(pte, 0, 0);
03134 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
03135 pte->device->lines->lastmsgssent = 0;
03136 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
03137 pte->device->softkeylabel[pte->device->softkeylinepos]);
03138 if (!ast_strlen_zero(pte->device->call_forward)) {
03139 if (pte->device->height == 1) {
03140 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Forwarding ON");
03141 } else {
03142 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
03143 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
03144 }
03145 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
03146 send_text_status(pte, "Dial Redial NoForwd");
03147 } else {
03148 if ((pte->device->extension == EXTENSION_ASK) ||
03149 (pte->device->extension == EXTENSION_TN))
03150 send_text_status(pte, "Dial Redial ForwardUnregis");
03151 else
03152 send_text_status(pte, "Dial Redial Forward");
03153
03154 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
03155 if (pte->device->missed_call == 0)
03156 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
03157 else {
03158 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
03159 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
03160 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
03161 }
03162 }
03163 if (ast_strlen_zero(pte->device->maintext2)) {
03164 strcpy(tmpbuf, "IP : ");
03165 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03166 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03167 } else
03168 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
03169 send_texttitle(pte, pte->device->titledefault);
03170 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
03171 }
03172
03173 static void key_main_page(struct unistimsession *pte, char keycode)
03174 {
03175 if (pte->device->missed_call) {
03176 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03177 pte->device->missed_call = 0;
03178 }
03179 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03180 handle_dial_page(pte);
03181 key_dial_page(pte, keycode);
03182 return;
03183 }
03184 switch (keycode) {
03185 case KEY_FUNC1:
03186 handle_dial_page(pte);
03187 break;
03188 case KEY_FUNC2:
03189 if (ast_strlen_zero(pte->device->redial_number))
03190 break;
03191 if ((pte->device->output == OUTPUT_HANDSET) &&
03192 (pte->device->receiver_state == STATE_ONHOOK))
03193 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03194 else
03195 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03196
03197 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03198 sizeof(pte->device->phone_number));
03199 HandleCallOutgoing(pte);
03200 break;
03201 case KEY_FUNC3:
03202 if (!ast_strlen_zero(pte->device->call_forward)) {
03203
03204 memmove(pte->device->call_forward + 1, pte->device->call_forward,
03205 sizeof(pte->device->call_forward) - 1);
03206 pte->device->call_forward[0] = '\0';
03207 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03208 pte->device->output = OUTPUT_HANDSET;
03209 show_main_page(pte);
03210 break;
03211 }
03212 pte->device->call_forward[0] = -1;
03213 handle_dial_page(pte);
03214 break;
03215 case KEY_FUNC4:
03216 if (pte->device->extension == EXTENSION_ASK) {
03217 UnregisterExtension(pte);
03218 pte->device->extension_number[0] = '\0';
03219 ShowExtensionPage(pte);
03220 } else if (pte->device->extension == EXTENSION_TN) {
03221 ast_mutex_lock(&devicelock);
03222 strcpy(pte->device->id, pte->device->extension_number);
03223 pte->buff_entry[0] = '\0';
03224 pte->size_buff_entry = 0;
03225 pte->device->session = NULL;
03226 pte->device = NULL;
03227 ast_mutex_unlock(&devicelock);
03228 ShowExtensionPage(pte);
03229 }
03230 break;
03231 case KEY_FAV0:
03232 handle_dial_page(pte);
03233 break;
03234 case KEY_FAV1:
03235 case KEY_FAV2:
03236 case KEY_FAV3:
03237 case KEY_FAV4:
03238 case KEY_FAV5:
03239 if ((pte->device->output == OUTPUT_HANDSET) &&
03240 (pte->device->receiver_state == STATE_ONHOOK))
03241 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03242 else
03243 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03244 Keyfavorite(pte, keycode);
03245 break;
03246 case KEY_CONF:
03247 HandleSelectCodec(pte);
03248 break;
03249 case KEY_LOUDSPK:
03250 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03251 handle_dial_page(pte);
03252 break;
03253 case KEY_HEADPHN:
03254 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03255 handle_dial_page(pte);
03256 break;
03257 case KEY_SNDHIST:
03258 show_history(pte, 'o');
03259 break;
03260 case KEY_RCVHIST:
03261 show_history(pte, 'i');
03262 break;
03263 }
03264 return;
03265 }
03266
03267 static void key_history(struct unistimsession *pte, char keycode)
03268 {
03269 FILE *f;
03270 char count;
03271 long offset;
03272
03273 switch (keycode) {
03274 case KEY_UP:
03275 case KEY_LEFT:
03276 case KEY_FUNC1:
03277 if (pte->buff_entry[2] <= 1)
03278 return;
03279 pte->buff_entry[2]--;
03280 count = OpenHistory(pte, pte->buff_entry[0], &f);
03281 if (!count)
03282 return;
03283 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03284 if (fseek(f, offset, SEEK_CUR)) {
03285 display_last_error("Unable to seek history entry.");
03286 fclose(f);
03287 return;
03288 }
03289 show_entry_history(pte, &f);
03290 break;
03291 case KEY_DOWN:
03292 case KEY_RIGHT:
03293 case KEY_FUNC2:
03294 if (pte->buff_entry[2] >= pte->buff_entry[1])
03295 return;
03296 pte->buff_entry[2]++;
03297 count = OpenHistory(pte, pte->buff_entry[0], &f);
03298 if (!count)
03299 return;
03300 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03301 if (fseek(f, offset, SEEK_CUR)) {
03302 display_last_error("Unable to seek history entry.");
03303 fclose(f);
03304 return;
03305 }
03306 show_entry_history(pte, &f);
03307 break;
03308 case KEY_FUNC3:
03309 if (!ReformatNumber(pte->device->lst_cid))
03310 break;
03311 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
03312 sizeof(pte->device->redial_number));
03313 key_main_page(pte, KEY_FUNC2);
03314 break;
03315 case KEY_FUNC4:
03316 case KEY_HANGUP:
03317 show_main_page(pte);
03318 break;
03319 case KEY_SNDHIST:
03320 if (pte->buff_entry[0] == 'i')
03321 show_history(pte, 'o');
03322 else
03323 show_main_page(pte);
03324 break;
03325 case KEY_RCVHIST:
03326 if (pte->buff_entry[0] == 'i')
03327 show_main_page(pte);
03328 else
03329 show_history(pte, 'i');
03330 break;
03331 }
03332 return;
03333 }
03334
03335 static void init_phone_step2(struct unistimsession *pte)
03336 {
03337 BUFFSEND;
03338 if (unistimdebug)
03339 ast_verb(0, "Sending S4\n");
03340 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
03341 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
03342 send_date_time2(pte);
03343 send_date_time3(pte);
03344 if (unistimdebug)
03345 ast_verb(0, "Sending S7\n");
03346 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03347 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03348 if (unistimdebug)
03349 ast_verb(0, "Sending Contrast\n");
03350 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
03351 if (pte->device != NULL)
03352 buffsend[9] = pte->device->contrast;
03353 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
03354
03355 if (unistimdebug)
03356 ast_verb(0, "Sending S9\n");
03357 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
03358 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
03359 send_no_ring(pte);
03360
03361 if (unistimdebug)
03362 ast_verb(0, "Sending S7\n");
03363 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03364 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03365 send_led_update(pte, 0);
03366 send_ping(pte);
03367 if (pte->state < STATE_MAINPAGE) {
03368 if (autoprovisioning == AUTOPROVISIONING_TN) {
03369 ShowExtensionPage(pte);
03370 return;
03371 } else {
03372 int i;
03373 char tmp[30];
03374
03375 for (i = 1; i < 6; i++)
03376 send_favorite(i, 0, pte, "");
03377 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
03378 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
03379 strcpy(tmp, "MAC = ");
03380 strcat(tmp, pte->macaddr);
03381 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
03382 send_text_status(pte, "");
03383 send_texttitle(pte, "UNISTIM for*");
03384 return;
03385 }
03386 }
03387 show_main_page(pte);
03388 refresh_all_favorite(pte);
03389 if (unistimdebug)
03390 ast_verb(0, "Sending arrow\n");
03391 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
03392 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
03393 return;
03394 }
03395
03396 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
03397 {
03398 char tmpbuf[255];
03399 if (memcmp
03400 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
03401 sizeof(packet_recv_resume_connection_with_server)) == 0) {
03402 rcv_resume_connection_with_server(pte);
03403 return;
03404 }
03405 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
03406 0) {
03407 buf[size] = 0;
03408 if (unistimdebug)
03409 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
03410 init_phone_step2(pte);
03411 return;
03412 }
03413 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
03414 rcv_mac_addr(pte, buf);
03415 return;
03416 }
03417 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
03418 if (unistimdebug)
03419 ast_verb(0, "R2 received\n");
03420 return;
03421 }
03422
03423 if (pte->state < STATE_MAINPAGE) {
03424 if (unistimdebug)
03425 ast_verb(0, "Request not authorized in this state\n");
03426 return;
03427 }
03428 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
03429 char keycode = buf[13];
03430
03431 if (unistimdebug)
03432 ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
03433 pte->state);
03434
03435 switch (pte->state) {
03436 case STATE_INIT:
03437 if (unistimdebug)
03438 ast_verb(0, "No keys allowed in the init state\n");
03439 break;
03440 case STATE_AUTHDENY:
03441 if (unistimdebug)
03442 ast_verb(0, "No keys allowed in authdeny state\n");
03443 break;
03444 case STATE_MAINPAGE:
03445 key_main_page(pte, keycode);
03446 break;
03447 case STATE_DIALPAGE:
03448 key_dial_page(pte, keycode);
03449 break;
03450 case STATE_RINGING:
03451 key_ringing(pte, keycode);
03452 break;
03453 case STATE_CALL:
03454 key_call(pte, keycode);
03455 break;
03456 case STATE_EXTENSION:
03457 key_select_extension(pte, keycode);
03458 break;
03459 case STATE_SELECTCODEC:
03460 key_select_codec(pte, keycode);
03461 break;
03462 case STATE_HISTORY:
03463 key_history(pte, keycode);
03464 break;
03465 default:
03466 ast_log(LOG_WARNING, "Key : Unknown state\n");
03467 }
03468 return;
03469 }
03470 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
03471 if (unistimdebug)
03472 ast_verb(0, "Handset off hook\n");
03473 if (!pte->device)
03474 return;
03475 pte->device->receiver_state = STATE_OFFHOOK;
03476 if (pte->device->output == OUTPUT_HEADPHONE)
03477 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03478 else
03479 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03480 if (pte->state == STATE_RINGING)
03481 HandleCallIncoming(pte);
03482 else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
03483 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03484 else if (pte->state == STATE_EXTENSION)
03485 return;
03486 else {
03487 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03488 handle_dial_page(pte);
03489 }
03490 return;
03491 }
03492 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
03493 if (unistimdebug)
03494 ast_verb(0, "Handset on hook\n");
03495 if (!pte->device)
03496 return;
03497 pte->device->receiver_state = STATE_ONHOOK;
03498 if (pte->state == STATE_CALL)
03499 close_call(pte);
03500 else if (pte->device->lines->subs[SUB_REAL]->owner)
03501 close_call(pte);
03502 else if (pte->state == STATE_EXTENSION)
03503 return;
03504 else
03505 show_main_page(pte);
03506 return;
03507 }
03508 strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03509 strcat(tmpbuf, " Unknown request packet\n");
03510 if (unistimdebug)
03511 ast_debug(1, "%s", tmpbuf);
03512 return;
03513 }
03514
03515 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
03516 struct sockaddr_in *addr_from)
03517 {
03518 unsigned short *sbuf = (unsigned short *) buf;
03519 unsigned short seq;
03520 char tmpbuf[255];
03521
03522 strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
03523
03524 if (size < 10) {
03525 if (size == 0) {
03526 ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
03527 } else {
03528 ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
03529 }
03530 return;
03531 }
03532 if (sbuf[0] == 0xffff) {
03533 if (size != sizeof(packet_rcv_discovery)) {
03534 ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
03535 } else {
03536 if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
03537 if (unistimdebug)
03538 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
03539 if (pte) {
03540 if (pte->state == STATE_INIT) {
03541 if (unistimdebug)
03542 ast_verb(1, "Duplicated Discovery packet\n");
03543 send_raw_client(sizeof(packet_send_discovery_ack),
03544 packet_send_discovery_ack, addr_from, &pte->sout);
03545 pte->seq_phone = (short) 0x0000;
03546 } else {
03547 close_client(pte);
03548 if (create_client(addr_from))
03549 send_raw_client(sizeof(packet_send_discovery_ack),
03550 packet_send_discovery_ack, addr_from, &pte->sout);
03551 }
03552 } else {
03553
03554 if ((pte = create_client(addr_from)))
03555 send_raw_client(sizeof(packet_send_discovery_ack),
03556 packet_send_discovery_ack, addr_from, &pte->sout);
03557 }
03558 return;
03559 }
03560 ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
03561 }
03562 return;
03563 }
03564 if (!pte) {
03565 if (unistimdebug)
03566 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n",
03567 tmpbuf);
03568 return;
03569 }
03570
03571 if (sbuf[0] != 0) {
03572 ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
03573 return;
03574 }
03575 if (buf[5] != 2) {
03576 ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
03577 buf[5]);
03578 return;
03579 }
03580 seq = ntohs(sbuf[1]);
03581 if (buf[4] == 1) {
03582 ast_mutex_lock(&pte->lock);
03583 if (unistimdebug)
03584 ast_verb(6, "ACK received for packet #0x%.4x\n", seq);
03585 pte->nb_retransmit = 0;
03586
03587 if ((pte->last_seq_ack) + 1 == seq) {
03588 pte->last_seq_ack++;
03589 check_send_queue(pte);
03590 ast_mutex_unlock(&pte->lock);
03591 return;
03592 }
03593 if (pte->last_seq_ack > seq) {
03594 if (pte->last_seq_ack == 0xffff) {
03595 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
03596 pte->last_seq_ack = 0;
03597 } else
03598 ast_log(LOG_NOTICE,
03599 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
03600 tmpbuf, seq, pte->last_seq_ack);
03601 ast_mutex_unlock(&pte->lock);
03602 return;
03603 }
03604 if (pte->seq_server < seq) {
03605 ast_log(LOG_NOTICE,
03606 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
03607 tmpbuf, pte->seq_server);
03608 ast_mutex_unlock(&pte->lock);
03609 return;
03610 }
03611 if (unistimdebug)
03612 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
03613 tmpbuf, seq, pte->last_seq_ack);
03614 pte->last_seq_ack = seq;
03615 check_send_queue(pte);
03616 ast_mutex_unlock(&pte->lock);
03617 return;
03618 }
03619 if (buf[4] == 2) {
03620 if (unistimdebug)
03621 ast_verb(0, "Request received\n");
03622 if (pte->seq_phone == seq) {
03623
03624 buf[4] = 1;
03625 buf[5] = 1;
03626 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03627 pte->seq_phone++;
03628
03629 process_request(size, buf, pte);
03630 return;
03631 }
03632 if (pte->seq_phone > seq) {
03633 ast_log(LOG_NOTICE,
03634 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
03635 tmpbuf, seq, pte->seq_phone);
03636
03637
03638 buf[4] = 1;
03639 buf[5] = 1;
03640 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03641 return;
03642 }
03643 ast_log(LOG_NOTICE,
03644 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
03645 tmpbuf, seq, pte->seq_phone);
03646 return;
03647 }
03648 if (buf[4] == 0) {
03649 ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, seq);
03650 if (pte->last_seq_ack > seq) {
03651 ast_log(LOG_NOTICE,
03652 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
03653 tmpbuf, pte->last_seq_ack);
03654 return;
03655 }
03656 if (pte->seq_server < seq) {
03657 ast_log(LOG_NOTICE,
03658 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
03659 tmpbuf, pte->seq_server);
03660 return;
03661 }
03662 send_retransmit(pte);
03663 return;
03664 }
03665 ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
03666 tmpbuf, buf[4]);
03667 return;
03668 }
03669
03670 static struct unistimsession *channel_to_session(struct ast_channel *ast)
03671 {
03672 struct unistim_subchannel *sub;
03673 if (!ast) {
03674 ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
03675 return NULL;
03676 }
03677 if (!ast->tech_pvt) {
03678 ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
03679 return NULL;
03680 }
03681 sub = ast->tech_pvt;
03682
03683 if (!sub->parent) {
03684 ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
03685 return NULL;
03686 }
03687 if (!sub->parent->parent) {
03688 ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
03689 return NULL;
03690 }
03691 if (!sub->parent->parent->session) {
03692 ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
03693 return NULL;
03694 }
03695 return sub->parent->parent->session;
03696 }
03697
03698
03699
03700 static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
03701 {
03702 int res = 0;
03703 struct unistim_subchannel *sub;
03704 struct unistimsession *session;
03705
03706 session = channel_to_session(ast);
03707 if (!session) {
03708 ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03709 return -1;
03710 }
03711
03712 sub = ast->tech_pvt;
03713 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03714 ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
03715 ast->name);
03716 return -1;
03717 }
03718
03719 if (unistimdebug)
03720 ast_verb(3, "unistim_call(%s)\n", ast->name);
03721
03722 session->state = STATE_RINGING;
03723 Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
03724
03725 if (sub->owner) {
03726 if (sub->owner->connected.id.number.valid
03727 && sub->owner->connected.id.number.str) {
03728 if (session->device->height == 1) {
03729 send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
03730 } else {
03731 send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
03732 }
03733 change_callerid(session, 0, sub->owner->connected.id.number.str);
03734 } else {
03735 if (session->device->height == 1) {
03736 send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERID);
03737 } else {
03738 send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
03739 }
03740 change_callerid(session, 0, DEFAULTCALLERID);
03741 }
03742 if (sub->owner->connected.id.name.valid
03743 && sub->owner->connected.id.name.str) {
03744 send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name.str);
03745 change_callerid(session, 1, sub->owner->connected.id.name.str);
03746 } else {
03747 send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
03748 change_callerid(session, 1, DEFAULTCALLERNAME);
03749 }
03750 }
03751 send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
03752 send_text_status(session, "Accept Ignore");
03753
03754 if (sub->ringstyle == -1)
03755 send_ring(session, session->device->ringvolume, session->device->ringstyle);
03756 else {
03757 if (sub->ringvolume == -1)
03758 send_ring(session, session->device->ringvolume, sub->ringstyle);
03759 else
03760 send_ring(session, sub->ringvolume, sub->ringstyle);
03761 }
03762 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
03763
03764 ast_setstate(ast, AST_STATE_RINGING);
03765 ast_queue_control(ast, AST_CONTROL_RINGING);
03766 return res;
03767 }
03768
03769
03770 static int unistim_hangup(struct ast_channel *ast)
03771 {
03772 struct unistim_subchannel *sub;
03773 struct unistim_line *l;
03774 struct unistimsession *s;
03775
03776 s = channel_to_session(ast);
03777 sub = ast->tech_pvt;
03778 if (!s) {
03779 ast_debug(1, "Asked to hangup channel not connected\n");
03780 ast_mutex_lock(&sub->lock);
03781 sub->owner = NULL;
03782 ast->tech_pvt = NULL;
03783 sub->alreadygone = 0;
03784 ast_mutex_unlock(&sub->lock);
03785 if (sub->rtp) {
03786 if (unistimdebug)
03787 ast_verb(0, "Destroying RTP session\n");
03788 ast_rtp_instance_destroy(sub->rtp);
03789 sub->rtp = NULL;
03790 }
03791 return 0;
03792 }
03793 l = sub->parent;
03794 if (unistimdebug)
03795 ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
03796
03797 if ((l->subs[SUB_THREEWAY]) && (sub->subtype == SUB_REAL)) {
03798 if (unistimdebug)
03799 ast_verb(0, "Real call disconnected while talking to threeway\n");
03800 sub->owner = NULL;
03801 ast->tech_pvt = NULL;
03802 return 0;
03803 }
03804 if ((l->subs[SUB_REAL]->owner) && (sub->subtype == SUB_THREEWAY) &&
03805 (sub->alreadygone == 0)) {
03806 if (unistimdebug)
03807 ast_verb(0, "threeway call disconnected, switching to real call\n");
03808 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Three way call canceled,");
03809 send_text(TEXT_LINE1, TEXT_NORMAL, s, "switching back to");
03810 send_text(TEXT_LINE2, TEXT_NORMAL, s, "previous call.");
03811 send_text_status(s, "Hangup Transf");
03812 ast_moh_stop(ast_bridged_channel(l->subs[SUB_REAL]->owner));
03813 swap_subs(l, SUB_THREEWAY, SUB_REAL);
03814 l->parent->moh = 0;
03815 ast_mutex_lock(&sub->lock);
03816 sub->owner = NULL;
03817 ast->tech_pvt = NULL;
03818 ast_mutex_unlock(&sub->lock);
03819 unalloc_sub(l, SUB_THREEWAY);
03820 return 0;
03821 }
03822 ast_mutex_lock(&sub->lock);
03823 sub->owner = NULL;
03824 ast->tech_pvt = NULL;
03825 sub->alreadygone = 0;
03826 ast_mutex_unlock(&sub->lock);
03827 if (!s) {
03828 if (unistimdebug)
03829 ast_verb(0, "Asked to hangup channel not connected (no session)\n");
03830 if (sub->rtp) {
03831 if (unistimdebug)
03832 ast_verb(0, "Destroying RTP session\n");
03833 ast_rtp_instance_destroy(sub->rtp);
03834 sub->rtp = NULL;
03835 }
03836 return 0;
03837 }
03838 if (sub->subtype == SUB_REAL) {
03839
03840 if (s->device->silence_generator) {
03841 if (unistimdebug)
03842 ast_verb(0, "Stopping silence generator\n");
03843 if (sub->owner)
03844 ast_channel_stop_silence_generator(sub->owner,
03845 s->device->silence_generator);
03846 else
03847 ast_log(LOG_WARNING,
03848 "Trying to stop silence generator on a null channel !\n");
03849 s->device->silence_generator = NULL;
03850 }
03851 }
03852 l->parent->moh = 0;
03853 send_no_ring(s);
03854 send_end_call(s);
03855 if (sub->rtp) {
03856 if (unistimdebug)
03857 ast_verb(0, "Destroying RTP session\n");
03858 ast_rtp_instance_destroy(sub->rtp);
03859 sub->rtp = NULL;
03860 } else if (unistimdebug)
03861 ast_verb(0, "No RTP session to destroy\n");
03862 if (l->subs[SUB_THREEWAY]) {
03863 if (unistimdebug)
03864 ast_verb(0, "Cleaning other subchannels\n");
03865 unalloc_sub(l, SUB_THREEWAY);
03866 }
03867 if (s->state == STATE_RINGING)
03868 cancel_dial(s);
03869 else if (s->state == STATE_CALL)
03870 close_call(s);
03871
03872 return 0;
03873 }
03874
03875
03876 static int unistim_answer(struct ast_channel *ast)
03877 {
03878 int res = 0;
03879 struct unistim_subchannel *sub;
03880 struct unistim_line *l;
03881 struct unistimsession *s;
03882
03883 s = channel_to_session(ast);
03884 if (!s) {
03885 ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
03886 return -1;
03887 }
03888 sub = ast->tech_pvt;
03889 l = sub->parent;
03890
03891 if ((!sub->rtp) && (!l->subs[SUB_THREEWAY]))
03892 start_rtp(sub);
03893 if (unistimdebug)
03894 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast->name, l->name,
03895 l->parent->name, sub->subtype);
03896 send_text(TEXT_LINE2, TEXT_NORMAL, l->parent->session, "is now on-line");
03897 if (l->subs[SUB_THREEWAY])
03898 send_text_status(l->parent->session, "Transf Cancel");
03899 else
03900 send_text_status(l->parent->session, "Hangup Transf");
03901 send_start_timer(l->parent->session);
03902 if (ast->_state != AST_STATE_UP)
03903 ast_setstate(ast, AST_STATE_UP);
03904 return res;
03905 }
03906
03907
03908
03909 static int unistimsock_read(int *id, int fd, short events, void *ignore)
03910 {
03911 struct sockaddr_in addr_from = { 0, };
03912 struct unistimsession *cur = NULL;
03913 int found = 0;
03914 int tmp = 0;
03915 int dw_num_bytes_rcvd;
03916 #ifdef DUMP_PACKET
03917 int dw_num_bytes_rcvdd;
03918 char iabuf[INET_ADDRSTRLEN];
03919 #endif
03920
03921 dw_num_bytes_rcvd =
03922 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
03923 &size_addr_from);
03924 if (dw_num_bytes_rcvd == -1) {
03925 if (errno == EAGAIN)
03926 ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
03927 else if (errno != ECONNREFUSED)
03928 ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
03929 return 1;
03930 }
03931
03932
03933 ast_mutex_lock(&sessionlock);
03934 cur = sessions;
03935 while (cur) {
03936 if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
03937 found = 1;
03938 break;
03939 }
03940 tmp++;
03941 cur = cur->next;
03942 }
03943 ast_mutex_unlock(&sessionlock);
03944
03945 #ifdef DUMP_PACKET
03946 if (unistimdebug)
03947 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
03948 dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
03949 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
03950 dw_num_bytes_rcvdd++)
03951 ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
03952 ast_verb(0, "\n******************************************\n");
03953 #endif
03954
03955 if (!found) {
03956 if (unistimdebug)
03957 ast_verb(0, "Received a packet from an unknown source\n");
03958 parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
03959
03960 } else
03961 parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
03962
03963 return 1;
03964 }
03965
03966 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
03967 const struct unistim_subchannel *sub)
03968 {
03969
03970 struct ast_frame *f;
03971
03972 if (!ast) {
03973 ast_log(LOG_WARNING, "Channel NULL while reading\n");
03974 return &ast_null_frame;
03975 }
03976
03977 if (!sub->rtp) {
03978 ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %d\n",
03979 sub->subtype);
03980 return &ast_null_frame;
03981 }
03982
03983 switch (ast->fdno) {
03984 case 0:
03985 f = ast_rtp_instance_read(sub->rtp, 0);
03986 break;
03987 case 1:
03988 f = ast_rtp_instance_read(sub->rtp, 1);
03989 break;
03990 default:
03991 f = &ast_null_frame;
03992 }
03993
03994 if (sub->owner) {
03995
03996 if (f->frametype == AST_FRAME_VOICE) {
03997 if (f->subclass.codec != sub->owner->nativeformats) {
03998 ast_debug(1,
03999 "Oooh, format changed from %s to %s\n",
04000 ast_getformatname(sub->owner->nativeformats),
04001 ast_getformatname(f->subclass.codec));
04002
04003 sub->owner->nativeformats = f->subclass.codec;
04004 ast_set_read_format(sub->owner, sub->owner->readformat);
04005 ast_set_write_format(sub->owner, sub->owner->writeformat);
04006 }
04007 }
04008 }
04009
04010 return f;
04011 }
04012
04013 static struct ast_frame *unistim_read(struct ast_channel *ast)
04014 {
04015 struct ast_frame *fr;
04016 struct unistim_subchannel *sub = ast->tech_pvt;
04017
04018 ast_mutex_lock(&sub->lock);
04019 fr = unistim_rtp_read(ast, sub);
04020 ast_mutex_unlock(&sub->lock);
04021
04022 return fr;
04023 }
04024
04025 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
04026 {
04027 struct unistim_subchannel *sub = ast->tech_pvt;
04028 int res = 0;
04029
04030 if (frame->frametype != AST_FRAME_VOICE) {
04031 if (frame->frametype == AST_FRAME_IMAGE)
04032 return 0;
04033 else {
04034 ast_log(LOG_WARNING, "Can't send %d type frames with unistim_write\n",
04035 frame->frametype);
04036 return 0;
04037 }
04038 } else {
04039 if (!(frame->subclass.codec & ast->nativeformats)) {
04040 char tmp[256];
04041 ast_log(LOG_WARNING,
04042 "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
04043 ast_getformatname(frame->subclass.codec),
04044 ast_getformatname_multiple(tmp, sizeof(tmp), ast->nativeformats),
04045 ast_getformatname(ast->readformat),
04046 ast_getformatname(ast->writeformat));
04047 return -1;
04048 }
04049 }
04050
04051 if (sub) {
04052 ast_mutex_lock(&sub->lock);
04053 if (sub->rtp) {
04054 res = ast_rtp_instance_write(sub->rtp, frame);
04055 }
04056 ast_mutex_unlock(&sub->lock);
04057 }
04058
04059 return res;
04060 }
04061
04062 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04063 {
04064 struct unistim_subchannel *p = newchan->tech_pvt;
04065 struct unistim_line *l = p->parent;
04066
04067 ast_mutex_lock(&p->lock);
04068
04069 ast_debug(1, "New owner for channel USTM/%s@%s-%d is %s\n", l->name,
04070 l->parent->name, p->subtype, newchan->name);
04071
04072 if (p->owner != oldchan) {
04073 ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
04074 oldchan->name, oldchan, p->owner->name, p->owner);
04075 ast_mutex_unlock(&p->lock);
04076 return -1;
04077 }
04078
04079 p->owner = newchan;
04080
04081 ast_mutex_unlock(&p->lock);
04082
04083 return 0;
04084
04085 }
04086
04087 static char *control2str(int ind)
04088 {
04089 switch (ind) {
04090 case AST_CONTROL_HANGUP:
04091 return "Other end has hungup";
04092 case AST_CONTROL_RING:
04093 return "Local ring";
04094 case AST_CONTROL_RINGING:
04095 return "Remote end is ringing";
04096 case AST_CONTROL_ANSWER:
04097 return "Remote end has answered";
04098 case AST_CONTROL_BUSY:
04099 return "Remote end is busy";
04100 case AST_CONTROL_TAKEOFFHOOK:
04101 return "Make it go off hook";
04102 case AST_CONTROL_OFFHOOK:
04103 return "Line is off hook";
04104 case AST_CONTROL_CONGESTION:
04105 return "Congestion (circuits busy)";
04106 case AST_CONTROL_FLASH:
04107 return "Flash hook";
04108 case AST_CONTROL_WINK:
04109 return "Wink";
04110 case AST_CONTROL_OPTION:
04111 return "Set a low-level option";
04112 case AST_CONTROL_RADIO_KEY:
04113 return "Key Radio";
04114 case AST_CONTROL_RADIO_UNKEY:
04115 return "Un-Key Radio";
04116 case -1:
04117 return "Stop tone";
04118 }
04119 return "UNKNOWN";
04120 }
04121
04122 static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
04123 const char *indication)
04124 {
04125 struct ast_tone_zone_sound *ts = NULL;
04126
04127 if ((ts = ast_get_indication_tone(tz, indication))) {
04128 ast_playtones_start(ast, 0, ts->data, 1);
04129 ts = ast_tone_zone_sound_unref(ts);
04130 } else {
04131 ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
04132 }
04133 }
04134
04135 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
04136 size_t datalen)
04137 {
04138 struct unistim_subchannel *sub;
04139 struct unistim_line *l;
04140 struct unistimsession *s;
04141
04142 if (unistimdebug) {
04143 ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
04144 control2str(ind), ast->name);
04145 }
04146
04147 s = channel_to_session(ast);
04148 if (!s)
04149 return -1;
04150
04151 sub = ast->tech_pvt;
04152 l = sub->parent;
04153
04154 switch (ind) {
04155 case AST_CONTROL_RINGING:
04156 if (ast->_state != AST_STATE_UP) {
04157 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Ringing...");
04158 in_band_indication(ast, l->parent->tz, "ring");
04159 s->device->missed_call = -1;
04160 break;
04161 }
04162 return -1;
04163 case AST_CONTROL_BUSY:
04164 if (ast->_state != AST_STATE_UP) {
04165 sub->alreadygone = 1;
04166 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Busy");
04167 in_band_indication(ast, l->parent->tz, "busy");
04168 s->device->missed_call = -1;
04169 break;
04170 }
04171 return -1;
04172 case AST_CONTROL_INCOMPLETE:
04173
04174
04175
04176 case AST_CONTROL_CONGESTION:
04177 if (ast->_state != AST_STATE_UP) {
04178 sub->alreadygone = 1;
04179 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Congestion");
04180 in_band_indication(ast, l->parent->tz, "congestion");
04181 s->device->missed_call = -1;
04182 break;
04183 }
04184 return -1;
04185 case AST_CONTROL_HOLD:
04186 ast_moh_start(ast, data, NULL);
04187 break;
04188 case AST_CONTROL_UNHOLD:
04189 ast_moh_stop(ast);
04190 break;
04191 case AST_CONTROL_PROGRESS:
04192 case AST_CONTROL_SRCUPDATE:
04193 break;
04194 case -1:
04195 ast_playtones_stop(ast);
04196 s->device->missed_call = 0;
04197 break;
04198 case AST_CONTROL_PROCEEDING:
04199 break;
04200 default:
04201 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
04202 return -1;
04203 }
04204
04205 return 0;
04206 }
04207
04208 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
04209 {
04210 struct unistim_line *l;
04211 struct unistim_device *d;
04212 char line[256];
04213 char *at;
04214 char *device;
04215
04216 ast_copy_string(line, dest, sizeof(line));
04217 at = strchr(line, '@');
04218 if (!at) {
04219 ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
04220 return NULL;
04221 }
04222 *at = '\0';
04223 at++;
04224 device = at;
04225 ast_mutex_lock(&devicelock);
04226 d = devices;
04227 at = strchr(device, '/');
04228 if (at)
04229 *at = '\0';
04230 while (d) {
04231 if (!strcasecmp(d->name, device)) {
04232 if (unistimdebug)
04233 ast_verb(0, "Found device: %s\n", d->name);
04234
04235 l = d->lines;
04236 while (l) {
04237
04238 if (!strcasecmp(l->name, line)) {
04239 l->subs[SUB_REAL]->ringvolume = -1;
04240 l->subs[SUB_REAL]->ringstyle = -1;
04241 if (at) {
04242 at++;
04243 if (*at == 'r') {
04244 at++;
04245 if ((*at < '0') || (*at > '7'))
04246 ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
04247 else {
04248 char ring_volume = -1;
04249 char ring_style = *at - '0';
04250 at++;
04251 if ((*at >= '0') && (*at <= '3'))
04252 ring_volume = *at - '0';
04253 if (unistimdebug)
04254 ast_verb(0, "Distinctive ring : style #%d volume %d\n",
04255 ring_style, ring_volume);
04256 l->subs[SUB_REAL]->ringvolume = ring_volume;
04257 l->subs[SUB_REAL]->ringstyle = ring_style;
04258 }
04259 }
04260 }
04261 ast_mutex_unlock(&devicelock);
04262 return l->subs[SUB_REAL];
04263 }
04264 l = l->next;
04265 }
04266 }
04267 d = d->next;
04268 }
04269
04270 ast_mutex_unlock(&devicelock);
04271
04272 return NULL;
04273 }
04274
04275 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
04276 {
04277 struct unistimsession *pte = channel_to_session(ast);
04278
04279 if (!pte)
04280 return -1;
04281
04282 return unistim_do_senddigit(pte, digit);
04283 }
04284
04285 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
04286 {
04287 struct unistimsession *pte = channel_to_session(ast);
04288 struct ast_frame f = { 0, };
04289 struct unistim_subchannel *sub;
04290
04291 sub = pte->device->lines->subs[SUB_REAL];
04292
04293 if (!sub->owner || sub->alreadygone) {
04294 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
04295 return -1;
04296 }
04297
04298 if (unistimdebug)
04299 ast_verb(0, "Send Digit off %c\n", digit);
04300
04301 if (!pte)
04302 return -1;
04303
04304 send_tone(pte, 0, 0);
04305 f.frametype = AST_FRAME_DTMF;
04306 f.subclass.integer = digit;
04307 f.src = "unistim";
04308 ast_queue_frame(sub->owner, &f);
04309
04310 return 0;
04311 }
04312
04313
04314
04315 static int unistim_sendtext(struct ast_channel *ast, const char *text)
04316 {
04317 struct unistimsession *pte = channel_to_session(ast);
04318 int size;
04319 char tmp[TEXT_LENGTH_MAX + 1];
04320
04321 if (unistimdebug)
04322 ast_verb(0, "unistim_sendtext called\n");
04323
04324 if (!text) {
04325 ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
04326 return 1;
04327 }
04328
04329 size = strlen(text);
04330 if (text[0] == '@') {
04331 int pos = 0, i = 1, tok = 0, sz = 0;
04332 char label[11];
04333 char number[16];
04334 char icon = '\0';
04335 char cur = '\0';
04336
04337 memset(label, 0, 11);
04338 memset(number, 0, 16);
04339 while (text[i]) {
04340 cur = text[i++];
04341 switch (tok) {
04342 case 0:
04343 if ((cur < '0') && (cur > '5')) {
04344 ast_log(LOG_WARNING,
04345 "sendtext failed : position must be a number beetween 0 and 5\n");
04346 return 1;
04347 }
04348 pos = cur - '0';
04349 tok = 1;
04350 continue;
04351 case 1:
04352 if (cur != '@') {
04353 ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
04354 return 1;
04355 }
04356 tok = 2;
04357 continue;
04358 case 2:
04359 if ((cur < '3') && (cur > '6')) {
04360 ast_log(LOG_WARNING,
04361 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
04362 return 1;
04363 }
04364 icon = (cur - '0') * 10;
04365 tok = 3;
04366 continue;
04367 case 3:
04368 if ((cur < '0') && (cur > '9')) {
04369 ast_log(LOG_WARNING,
04370 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
04371 return 1;
04372 }
04373 icon += (cur - '0');
04374 tok = 4;
04375 continue;
04376 case 4:
04377 if (cur != '@') {
04378 ast_log(LOG_WARNING,
04379 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
04380 return 1;
04381 }
04382 tok = 5;
04383 continue;
04384 case 5:
04385 if (cur == '@') {
04386 tok = 6;
04387 sz = 0;
04388 continue;
04389 }
04390 if (sz > 10)
04391 continue;
04392 label[sz] = cur;
04393 sz++;
04394 continue;
04395 case 6:
04396 if (sz > 15) {
04397 ast_log(LOG_WARNING,
04398 "sendtext failed : extension too long = %d (15 car max)\n",
04399 sz);
04400 return 1;
04401 }
04402 number[sz] = cur;
04403 sz++;
04404 continue;
04405 }
04406 }
04407 if (tok != 6) {
04408 ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
04409 return 1;
04410 }
04411 if (!pte->device) {
04412 ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
04413 return 1;
04414 }
04415 strcpy(pte->device->softkeylabel[pos], label);
04416 strcpy(pte->device->softkeynumber[pos], number);
04417 pte->device->softkeyicon[pos] = icon;
04418 send_favorite(pos, icon, pte, label);
04419 return 0;
04420 }
04421
04422 if (size <= TEXT_LENGTH_MAX * 2) {
04423 if (pte->device->height == 1) {
04424 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
04425 } else {
04426 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Message :");
04427 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
04428 }
04429 if (size <= TEXT_LENGTH_MAX) {
04430 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
04431 return 0;
04432 }
04433 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04434 tmp[sizeof(tmp) - 1] = '\0';
04435 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04436 return 0;
04437 }
04438 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
04439 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04440 tmp[sizeof(tmp) - 1] = '\0';
04441 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
04442 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
04443 tmp[sizeof(tmp) - 1] = '\0';
04444 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04445 return 0;
04446 }
04447
04448
04449 static int unistim_send_mwi_to_peer(struct unistimsession *s, unsigned int tick)
04450 {
04451 struct ast_event *event;
04452 int new;
04453 char *mailbox, *context;
04454 struct unistim_line *peer = s->device->lines;
04455
04456 context = mailbox = ast_strdupa(peer->mailbox);
04457 strsep(&context, "@");
04458 if (ast_strlen_zero(context))
04459 context = "default";
04460
04461 event = ast_event_get_cached(AST_EVENT_MWI,
04462 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
04463 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
04464 AST_EVENT_IE_END);
04465
04466 if (event) {
04467 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
04468 ast_event_destroy(event);
04469 } else {
04470 new = ast_app_has_voicemail(peer->mailbox, "INBOX");
04471 }
04472
04473 peer->nextmsgcheck = tick + TIMER_MWI;
04474
04475
04476 if (new == peer->lastmsgssent) {
04477 return 0;
04478 }
04479
04480 peer->lastmsgssent = new;
04481 if (new == 0) {
04482 send_led_update(s, 0);
04483 } else {
04484 send_led_update(s, 1);
04485 }
04486
04487 return 0;
04488 }
04489
04490
04491
04492 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
04493 {
04494 struct ast_channel *tmp;
04495 struct unistim_line *l;
04496 int fmt;
04497
04498 if (!sub) {
04499 ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
04500 return NULL;
04501 }
04502 if (!sub->parent) {
04503 ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
04504 return NULL;
04505 }
04506 l = sub->parent;
04507 tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
04508 l->context, linkedid, l->amaflags, "%s@%s-%d", l->name, l->parent->name, sub->subtype);
04509 if (unistimdebug)
04510 ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub->subtype, sub, tmp);
04511 if (!tmp) {
04512 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
04513 return NULL;
04514 }
04515
04516 tmp->nativeformats = l->capability;
04517 if (!tmp->nativeformats)
04518 tmp->nativeformats = CAPABILITY;
04519 fmt = ast_best_codec(tmp->nativeformats);
04520 if (unistimdebug) {
04521 char tmp1[256], tmp2[256], tmp3[256];
04522 ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
04523 ast_getformatname(fmt),
04524 ast_getformatname_multiple(tmp1, sizeof(tmp1), tmp->nativeformats),
04525 ast_getformatname_multiple(tmp2, sizeof(tmp2), l->capability),
04526 ast_getformatname_multiple(tmp3, sizeof(tmp3), CAPABILITY));
04527 }
04528 if ((sub->rtp) && (sub->subtype == 0)) {
04529 if (unistimdebug)
04530 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
04531 tmp->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
04532 tmp->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
04533 }
04534 if (sub->rtp)
04535 ast_jb_configure(tmp, &global_jbconf);
04536
04537
04538 ast_setstate(tmp, state);
04539 if (state == AST_STATE_RING)
04540 tmp->rings = 1;
04541 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04542 tmp->writeformat = fmt;
04543 tmp->rawwriteformat = fmt;
04544 tmp->readformat = fmt;
04545 tmp->rawreadformat = fmt;
04546 tmp->tech_pvt = sub;
04547 tmp->tech = &unistim_tech;
04548 if (!ast_strlen_zero(l->language))
04549 ast_string_field_set(tmp, language, l->language);
04550 sub->owner = tmp;
04551 ast_mutex_lock(&usecnt_lock);
04552 usecnt++;
04553 ast_mutex_unlock(&usecnt_lock);
04554 ast_update_use_count();
04555 tmp->callgroup = l->callgroup;
04556 tmp->pickupgroup = l->pickupgroup;
04557 ast_string_field_set(tmp, call_forward, l->parent->call_forward);
04558 if (!ast_strlen_zero(l->cid_num)) {
04559 char *name, *loc, *instr;
04560 instr = ast_strdup(l->cid_num);
04561 if (instr) {
04562 ast_callerid_parse(instr, &name, &loc);
04563 tmp->caller.id.number.valid = 1;
04564 ast_free(tmp->caller.id.number.str);
04565 tmp->caller.id.number.str = ast_strdup(loc);
04566 tmp->caller.id.name.valid = 1;
04567 ast_free(tmp->caller.id.name.str);
04568 tmp->caller.id.name.str = ast_strdup(name);
04569 ast_free(instr);
04570 }
04571 }
04572 tmp->priority = 1;
04573 if (state != AST_STATE_DOWN) {
04574 if (unistimdebug)
04575 ast_verb(0, "Starting pbx in unistim_new\n");
04576 if (ast_pbx_start(tmp)) {
04577 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04578 ast_hangup(tmp);
04579 tmp = NULL;
04580 }
04581 }
04582
04583 return tmp;
04584 }
04585
04586 static void *do_monitor(void *data)
04587 {
04588 struct unistimsession *cur = NULL;
04589 unsigned int dw_timeout = 0;
04590 unsigned int tick;
04591 int res;
04592 int reloading;
04593
04594
04595 if (unistimsock > -1)
04596 ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
04597
04598
04599 for (;;) {
04600
04601
04602 tick = get_tick_count();
04603 dw_timeout = UINT_MAX;
04604 ast_mutex_lock(&sessionlock);
04605 cur = sessions;
04606 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
04607 while (cur) {
04608 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
04609 cur->timeout);
04610
04611 if (cur->timeout <= tick) {
04612 DEBUG_TIMER("Event for session %p\n", cur);
04613
04614 if (cur->last_buf_available == 0)
04615 send_ping(cur);
04616 else {
04617 if (send_retransmit(cur)) {
04618 DEBUG_TIMER("The chained link was modified, restarting...\n");
04619 cur = sessions;
04620 dw_timeout = UINT_MAX;
04621 continue;
04622 }
04623 }
04624 }
04625 if (dw_timeout > cur->timeout - tick)
04626 dw_timeout = cur->timeout - tick;
04627
04628 if (cur->device) {
04629 if ((!ast_strlen_zero(cur->device->lines->mailbox)) &&
04630 ((tick >= cur->device->lines->nextmsgcheck))) {
04631 DEBUG_TIMER("Checking mailbox for MWI\n");
04632 unistim_send_mwi_to_peer(cur, tick);
04633 break;
04634 }
04635 }
04636 cur = cur->next;
04637 }
04638 ast_mutex_unlock(&sessionlock);
04639 DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
04640 res = dw_timeout;
04641
04642 if ((res < 0) || (res > IDLE_WAIT))
04643 res = IDLE_WAIT;
04644
04645 res = ast_io_wait(io, res);
04646
04647 ast_mutex_lock(&unistim_reload_lock);
04648 reloading = unistim_reloading;
04649 unistim_reloading = 0;
04650 ast_mutex_unlock(&unistim_reload_lock);
04651 if (reloading) {
04652 ast_verb(1, "Reloading unistim.conf...\n");
04653 reload_config();
04654 }
04655 pthread_testcancel();
04656 }
04657
04658 return NULL;
04659 }
04660
04661
04662 static int restart_monitor(void)
04663 {
04664 pthread_attr_t attr;
04665
04666 if (monitor_thread == AST_PTHREADT_STOP)
04667 return 0;
04668 if (ast_mutex_lock(&monlock)) {
04669 ast_log(LOG_WARNING, "Unable to lock monitor\n");
04670 return -1;
04671 }
04672 if (monitor_thread == pthread_self()) {
04673 ast_mutex_unlock(&monlock);
04674 ast_log(LOG_WARNING, "Cannot kill myself\n");
04675 return -1;
04676 }
04677 if (monitor_thread != AST_PTHREADT_NULL) {
04678
04679 pthread_kill(monitor_thread, SIGURG);
04680 } else {
04681 pthread_attr_init(&attr);
04682 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
04683
04684 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
04685 ast_mutex_unlock(&monlock);
04686 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04687 return -1;
04688 }
04689 }
04690 ast_mutex_unlock(&monlock);
04691 return 0;
04692 }
04693
04694
04695
04696 static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor, void *data,
04697 int *cause)
04698 {
04699 format_t oldformat;
04700 struct unistim_subchannel *sub;
04701 struct ast_channel *tmpc = NULL;
04702 char tmp[256];
04703 char *dest = data;
04704
04705 oldformat = format;
04706 format &= CAPABILITY;
04707 ast_log(LOG_NOTICE,
04708 "Asked to get a channel of format %s while capability is %s result : %s\n",
04709 ast_getformatname(oldformat),
04710 ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY),
04711 ast_getformatname(format));
04712 if (!format) {
04713 ast_log(LOG_NOTICE,
04714 "Asked to get a channel of unsupported format %s while capability is %s\n",
04715 ast_getformatname(oldformat), ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY));
04716 return NULL;
04717 }
04718
04719 ast_copy_string(tmp, dest, sizeof(tmp));
04720 if (ast_strlen_zero(tmp)) {
04721 ast_log(LOG_NOTICE, "Unistim channels require a device\n");
04722 return NULL;
04723 }
04724
04725 sub = find_subchannel_by_name(tmp);
04726 if (!sub) {
04727 ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
04728 *cause = AST_CAUSE_CONGESTION;
04729 return NULL;
04730 }
04731
04732 ast_verb(3, "unistim_request(%s)\n", tmp);
04733
04734 if (sub->owner) {
04735 if (unistimdebug)
04736 ast_verb(0, "Can't create channel : Busy !\n");
04737 *cause = AST_CAUSE_BUSY;
04738 return NULL;
04739 }
04740 sub->parent->capability = format;
04741 tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
04742 if (!tmpc)
04743 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
04744 if (unistimdebug)
04745 ast_verb(0, "unistim_request owner = %p\n", sub->owner);
04746 restart_monitor();
04747
04748
04749 return tmpc;
04750 }
04751
04752 static char *unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04753 {
04754 struct unistim_device *device = devices;
04755 struct unistim_line *line;
04756 struct unistim_subchannel *sub;
04757 struct unistimsession *s;
04758 int i;
04759 struct ast_channel *tmp;
04760
04761 switch (cmd) {
04762 case CLI_INIT:
04763 e->command = "unistim show info";
04764 e->usage =
04765 "Usage: unistim show info\n"
04766 " Dump internal structures.\n";
04767 return NULL;
04768
04769 case CLI_GENERATE:
04770 return NULL;
04771 }
04772
04773 if (a->argc != e->args)
04774 return CLI_SHOWUSAGE;
04775
04776 ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
04777 while (device) {
04778 ast_cli(a->fd, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
04779 device->name, device->id, device->lines, device->ha, device->session,
04780 device);
04781 line = device->lines;
04782 while (line) {
04783 ast_cli(a->fd,
04784 "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " device=%p line=%p\n",
04785 line->name, line->fullname, line->exten, line->cid_num,
04786 line->capability, line->parent, line);
04787 for (i = 0; i < MAX_SUBS; i++) {
04788 sub = line->subs[i];
04789 if (!sub)
04790 continue;
04791 if (!sub->owner)
04792 tmp = (void *) -42;
04793 else
04794 tmp = sub->owner->_bridge;
04795 if (sub->subtype != i)
04796 ast_cli(a->fd, "Warning ! subchannel->subs[%d] have a subtype=%d\n", i,
04797 sub->subtype);
04798 ast_cli(a->fd,
04799 "-->subtype=%d chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
04800 sub->subtype, sub->owner, sub->rtp, tmp, sub->parent,
04801 sub->alreadygone);
04802 }
04803 line = line->next;
04804 }
04805 device = device->next;
04806 }
04807 ast_cli(a->fd, "\nSessions:\n");
04808 ast_mutex_lock(&sessionlock);
04809 s = sessions;
04810 while (s) {
04811 ast_cli(a->fd,
04812 "sin=%s timeout=%u state=%d macaddr=%s device=%p session=%p\n",
04813 ast_inet_ntoa(s->sin.sin_addr), s->timeout, s->state, s->macaddr,
04814 s->device, s);
04815 s = s->next;
04816 }
04817 ast_mutex_unlock(&sessionlock);
04818
04819 return CLI_SUCCESS;
04820 }
04821
04822 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04823 {
04824 BUFFSEND;
04825 struct unistim_subchannel *sub;
04826 int i, j = 0, len;
04827 unsigned char c, cc;
04828 char tmp[256];
04829
04830 switch (cmd) {
04831 case CLI_INIT:
04832 e->command = "unistim send packet";
04833 e->usage =
04834 "Usage: unistim send packet USTM/line@name hexa\n"
04835 " unistim send packet USTM/1000@hans 19040004\n";
04836 return NULL;
04837
04838 case CLI_GENERATE:
04839 return NULL;
04840 }
04841
04842 if (a->argc < 5)
04843 return CLI_SHOWUSAGE;
04844
04845 if (strlen(a->argv[3]) < 9)
04846 return CLI_SHOWUSAGE;
04847
04848 len = strlen(a->argv[4]);
04849 if (len % 2)
04850 return CLI_SHOWUSAGE;
04851
04852 ast_copy_string(tmp, a->argv[3] + 5, sizeof(tmp));
04853 sub = find_subchannel_by_name(tmp);
04854 if (!sub) {
04855 ast_cli(a->fd, "Can't find '%s'\n", tmp);
04856 return CLI_SUCCESS;
04857 }
04858 if (!sub->parent->parent->session) {
04859 ast_cli(a->fd, "'%s' is not connected\n", tmp);
04860 return CLI_SUCCESS;
04861 }
04862 ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->parent->parent->session);
04863 for (i = 0; i < len; i++) {
04864 c = a->argv[4][i];
04865 if (c >= 'a')
04866 c -= 'a' - 10;
04867 else
04868 c -= '0';
04869 i++;
04870 cc = a->argv[4][i];
04871 if (cc >= 'a')
04872 cc -= 'a' - 10;
04873 else
04874 cc -= '0';
04875 tmp[j++] = (c << 4) | cc;
04876 }
04877 memcpy(buffsend + SIZE_HEADER, tmp, j);
04878 send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
04879 return CLI_SUCCESS;
04880 }
04881
04882 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04883 {
04884 switch (cmd) {
04885 case CLI_INIT:
04886 e->command = "unistim set debug {on|off}";
04887 e->usage =
04888 "Usage: unistim set debug\n"
04889 " Display debug messages.\n";
04890 return NULL;
04891
04892 case CLI_GENERATE:
04893 return NULL;
04894 }
04895
04896 if (a->argc != e->args)
04897 return CLI_SHOWUSAGE;
04898
04899 if (!strcasecmp(a->argv[3], "on")) {
04900 unistimdebug = 1;
04901 ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
04902 } else if (!strcasecmp(a->argv[3], "off")) {
04903 unistimdebug = 0;
04904 ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
04905 } else
04906 return CLI_SHOWUSAGE;
04907
04908 return CLI_SUCCESS;
04909 }
04910
04911
04912
04913
04914
04915 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04916 {
04917 switch (cmd) {
04918 case CLI_INIT:
04919 e->command = "unistim reload";
04920 e->usage =
04921 "Usage: unistim reload\n"
04922 " Reloads UNISTIM configuration from unistim.conf\n";
04923 return NULL;
04924
04925 case CLI_GENERATE:
04926 return NULL;
04927 }
04928
04929 if (e && a && a->argc != e->args)
04930 return CLI_SHOWUSAGE;
04931
04932 if (unistimdebug)
04933 ast_verb(0, "reload unistim\n");
04934
04935 ast_mutex_lock(&unistim_reload_lock);
04936 if (!unistim_reloading)
04937 unistim_reloading = 1;
04938 ast_mutex_unlock(&unistim_reload_lock);
04939
04940 restart_monitor();
04941
04942 return CLI_SUCCESS;
04943 }
04944
04945 static struct ast_cli_entry unistim_cli[] = {
04946 AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
04947 AST_CLI_DEFINE(unistim_info, "Show UNISTIM info"),
04948 AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
04949 AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
04950 };
04951
04952 static void unquote(char *out, const char *src, int maxlen)
04953 {
04954 int len = strlen(src);
04955 if (!len)
04956 return;
04957 if ((len > 1) && src[0] == '\"') {
04958
04959 src++;
04960
04961 len--;
04962 if (maxlen > len - 1)
04963 maxlen = len - 1;
04964 memcpy(out, src, maxlen);
04965 ((char *) out)[maxlen] = '\0';
04966 } else
04967 memcpy(out, src, maxlen);
04968 return;
04969 }
04970
04971 static int ParseBookmark(const char *text, struct unistim_device *d)
04972 {
04973 char line[256];
04974 char *at;
04975 char *number;
04976 char *icon;
04977 int p;
04978 int len = strlen(text);
04979
04980 ast_copy_string(line, text, sizeof(line));
04981
04982 if ((len > 2) && (line[1] == '@')) {
04983 p = line[0];
04984 if ((p >= '0') && (p <= '5'))
04985 p -= '0';
04986 else {
04987 ast_log(LOG_WARNING,
04988 "Invalid position for bookmark : must be between 0 and 5\n");
04989 return 0;
04990 }
04991 if (d->softkeyicon[p] != 0) {
04992 ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used\n:", p);
04993 return 0;
04994 }
04995 memmove(line, line + 2, sizeof(line) - 2);
04996 } else {
04997
04998 for (p = 0; p <= 5; p++) {
04999 if (!d->softkeyicon[p])
05000 break;
05001 }
05002 if (p > 5) {
05003 ast_log(LOG_WARNING, "No more free bookmark position\n");
05004 return 0;
05005 }
05006 }
05007 at = strchr(line, '@');
05008 if (!at) {
05009 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
05010 return 0;
05011 }
05012 *at = '\0';
05013 at++;
05014 number = at;
05015 at = strchr(at, '@');
05016 if (ast_strlen_zero(number)) {
05017 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
05018 return 0;
05019 }
05020 if (ast_strlen_zero(line)) {
05021 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
05022 return 0;
05023 }
05024
05025 at = strchr(number, '@');
05026 if (!at)
05027 d->softkeyicon[p] = FAV_ICON_SHARP;
05028 else {
05029 *at = '\0';
05030 at++;
05031 icon = at;
05032 if (ast_strlen_zero(icon)) {
05033 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
05034 return 0;
05035 }
05036 if (strncmp(icon, "USTM/", 5))
05037 d->softkeyicon[p] = atoi(icon);
05038 else {
05039 d->softkeyicon[p] = 1;
05040 ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
05041 }
05042 }
05043 ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
05044 ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
05045 if (unistimdebug)
05046 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
05047 p, d->softkeylabel[p], d->softkeynumber[p], d->softkeyicon[p]);
05048 return 1;
05049 }
05050
05051
05052 static void finish_bookmark(void)
05053 {
05054 struct unistim_device *d = devices;
05055 int i;
05056 while (d) {
05057 for (i = 0; i < 6; i++) {
05058 if (d->softkeyicon[i] == 1) {
05059 struct unistim_device *d2 = devices;
05060 while (d2) {
05061 if (!strcmp(d->softkeydevice[i], d2->name)) {
05062 d->sp[i] = d2;
05063 d->softkeyicon[i] = 0;
05064 break;
05065 }
05066 d2 = d2->next;
05067 }
05068 if (d->sp[i] == NULL)
05069 ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
05070 d->softkeydevice[i]);
05071 }
05072 }
05073 d = d->next;
05074 }
05075 }
05076
05077 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
05078 {
05079 struct unistim_device *d;
05080 struct unistim_line *l = NULL;
05081 int create = 1;
05082 int nbsoftkey, dateformat, timeformat, callhistory;
05083 char linelabel[AST_MAX_EXTENSION];
05084 char context[AST_MAX_EXTENSION];
05085 char ringvolume, ringstyle;
05086
05087
05088
05089 ast_mutex_lock(&devicelock);
05090 d = devices;
05091 while (d) {
05092 if (!strcmp(d->name, cat)) {
05093
05094 if (unistimsock < 0) {
05095
05096 ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
05097 ast_mutex_unlock(&devicelock);
05098 return NULL;
05099 }
05100
05101 create = 0;
05102 l = d->lines;
05103 break;
05104 }
05105 d = d->next;
05106 }
05107 ast_mutex_unlock(&devicelock);
05108 if (create) {
05109 if (!(d = ast_calloc(1, sizeof(*d))))
05110 return NULL;
05111
05112 if (!(l = ast_calloc(1, sizeof(*l)))) {
05113 ast_free(d);
05114 return NULL;
05115 }
05116 ast_copy_string(d->name, cat, sizeof(d->name));
05117 }
05118 ast_copy_string(context, DEFAULTCONTEXT, sizeof(context));
05119 d->contrast = -1;
05120 d->output = OUTPUT_HANDSET;
05121 d->previous_output = OUTPUT_HANDSET;
05122 d->volume = VOLUME_LOW;
05123 d->mute = MUTE_OFF;
05124 d->height = DEFAULTHEIGHT;
05125 linelabel[0] = '\0';
05126 dateformat = 1;
05127 timeformat = 1;
05128 ringvolume = 2;
05129 callhistory = 1;
05130 ringstyle = 3;
05131 nbsoftkey = 0;
05132 while (v) {
05133 if (!strcasecmp(v->name, "rtp_port"))
05134 d->rtp_port = atoi(v->value);
05135 else if (!strcasecmp(v->name, "rtp_method"))
05136 d->rtp_method = atoi(v->value);
05137 else if (!strcasecmp(v->name, "status_method"))
05138 d->status_method = atoi(v->value);
05139 else if (!strcasecmp(v->name, "device"))
05140 ast_copy_string(d->id, v->value, sizeof(d->id));
05141 else if (!strcasecmp(v->name, "tn"))
05142 ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
05143 else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny"))
05144 d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
05145 else if (!strcasecmp(v->name, "context"))
05146 ast_copy_string(context, v->value, sizeof(context));
05147 else if (!strcasecmp(v->name, "maintext0"))
05148 unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
05149 else if (!strcasecmp(v->name, "maintext1"))
05150 unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
05151 else if (!strcasecmp(v->name, "maintext2"))
05152 unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
05153 else if (!strcasecmp(v->name, "titledefault"))
05154 unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
05155 else if (!strcasecmp(v->name, "dateformat"))
05156 dateformat = atoi(v->value);
05157 else if (!strcasecmp(v->name, "timeformat"))
05158 timeformat = atoi(v->value);
05159 else if (!strcasecmp(v->name, "contrast")) {
05160 d->contrast = atoi(v->value);
05161 if ((d->contrast < 0) || (d->contrast > 15)) {
05162 ast_log(LOG_WARNING, "contrast must be beetween 0 and 15\n");
05163 d->contrast = 8;
05164 }
05165 } else if (!strcasecmp(v->name, "nat"))
05166 d->nat = ast_true(v->value);
05167 else if (!strcasecmp(v->name, "ringvolume"))
05168 ringvolume = atoi(v->value);
05169 else if (!strcasecmp(v->name, "ringstyle"))
05170 ringstyle = atoi(v->value);
05171 else if (!strcasecmp(v->name, "callhistory"))
05172 callhistory = atoi(v->value);
05173 else if (!strcasecmp(v->name, "callerid")) {
05174 if (!strcasecmp(v->value, "asreceived"))
05175 l->cid_num[0] = '\0';
05176 else
05177 ast_copy_string(l->cid_num, v->value, sizeof(l->cid_num));
05178 } else if (!strcasecmp(v->name, "language"))
05179 ast_copy_string(l->language, v->value, sizeof(l->language));
05180 else if (!strcasecmp(v->name, "country"))
05181 ast_copy_string(d->country, v->value, sizeof(d->country));
05182 else if (!strcasecmp(v->name, "accountcode"))
05183 ast_copy_string(l->accountcode, v->value, sizeof(l->accountcode));
05184 else if (!strcasecmp(v->name, "amaflags")) {
05185 int y;
05186 y = ast_cdr_amaflags2int(v->value);
05187 if (y < 0)
05188 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
05189 v->lineno);
05190 else
05191 l->amaflags = y;
05192 } else if (!strcasecmp(v->name, "musiconhold"))
05193 ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass));
05194 else if (!strcasecmp(v->name, "callgroup"))
05195 l->callgroup = ast_get_group(v->value);
05196 else if (!strcasecmp(v->name, "pickupgroup"))
05197 l->pickupgroup = ast_get_group(v->value);
05198 else if (!strcasecmp(v->name, "mailbox"))
05199 ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
05200 else if (!strcasecmp(v->name, "parkinglot"))
05201 ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
05202 else if (!strcasecmp(v->name, "linelabel"))
05203 unquote(linelabel, v->value, sizeof(linelabel) - 1);
05204 else if (!strcasecmp(v->name, "extension")) {
05205 if (!strcasecmp(v->value, "none"))
05206 d->extension = EXTENSION_NONE;
05207 else if (!strcasecmp(v->value, "ask"))
05208 d->extension = EXTENSION_ASK;
05209 else if (!strcasecmp(v->value, "line"))
05210 d->extension = EXTENSION_LINE;
05211 else
05212 ast_log(LOG_WARNING, "Unknown extension option.\n");
05213 } else if (!strcasecmp(v->name, "bookmark")) {
05214 if (nbsoftkey > 5)
05215 ast_log(LOG_WARNING,
05216 "More than 6 softkeys defined. Ignoring new entries.\n");
05217 else {
05218 if (ParseBookmark(v->value, d))
05219 nbsoftkey++;
05220 }
05221 } else if (!strcasecmp(v->name, "line")) {
05222 int len = strlen(linelabel);
05223
05224 if (nbsoftkey) {
05225 ast_log(LOG_WARNING,
05226 "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
05227 if (create) {
05228 ast_free(d);
05229 ast_free(l);
05230 }
05231 return NULL;
05232 }
05233 if (create) {
05234 ast_mutex_init(&l->lock);
05235 } else {
05236 d->to_delete = 0;
05237
05238 memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
05239 memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
05240 memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
05241 memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
05242 memset(d->sp, 0, sizeof(d->sp));
05243 }
05244 ast_copy_string(l->name, v->value, sizeof(l->name));
05245 snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
05246 d->softkeyicon[0] = FAV_ICON_ONHOOK_BLACK;
05247 if (!len)
05248 ast_copy_string(d->softkeylabel[0], v->value, sizeof(d->softkeylabel[0]));
05249 else {
05250 if ((len > 2) && (linelabel[1] == '@')) {
05251 d->softkeylinepos = linelabel[0];
05252 if ((d->softkeylinepos >= '0') && (d->softkeylinepos <= '5')) {
05253 d->softkeylinepos -= '0';
05254 d->softkeyicon[0] = 0;
05255 } else {
05256 ast_log(LOG_WARNING,
05257 "Invalid position for linelabel : must be between 0 and 5\n");
05258 d->softkeylinepos = 0;
05259 }
05260 ast_copy_string(d->softkeylabel[d->softkeylinepos], linelabel + 2,
05261 sizeof(d->softkeylabel[d->softkeylinepos]));
05262 d->softkeyicon[d->softkeylinepos] = FAV_ICON_ONHOOK_BLACK;
05263 } else
05264 ast_copy_string(d->softkeylabel[0], linelabel,
05265 sizeof(d->softkeylabel[0]));
05266 }
05267 nbsoftkey++;
05268 ast_copy_string(l->context, context, sizeof(l->context));
05269 if (!ast_strlen_zero(l->mailbox)) {
05270 if (unistimdebug)
05271 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
05272 }
05273
05274 l->capability = CAPABILITY;
05275 l->parent = d;
05276
05277 if (create) {
05278 if (!alloc_sub(l, SUB_REAL)) {
05279 ast_mutex_destroy(&l->lock);
05280 ast_free(l);
05281 ast_free(d);
05282 return NULL;
05283 }
05284 l->next = d->lines;
05285 d->lines = l;
05286 }
05287 } else if (!strcasecmp(v->name, "height")) {
05288
05289
05290 d->height = atoi(v->value);
05291 } else
05292 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
05293 v->lineno);
05294 v = v->next;
05295 }
05296 d->ringvolume = ringvolume;
05297 d->ringstyle = ringstyle;
05298 d->callhistory = callhistory;
05299 d->tz = ast_get_indication_zone(d->country);
05300 if ((d->tz == NULL) && !ast_strlen_zero(d->country))
05301 ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
05302 d->country);
05303 d->datetimeformat = 56 + (dateformat * 4);
05304 d->datetimeformat += timeformat;
05305 if (!d->lines) {
05306 ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
05307 ast_mutex_destroy(&l->lock);
05308 ast_free(l);
05309 if (d->tz) {
05310 d->tz = ast_tone_zone_unref(d->tz);
05311 }
05312 ast_free(d);
05313 return NULL;
05314 }
05315 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
05316 (!ast_strlen_zero(d->extension_number))) {
05317 d->extension = EXTENSION_TN;
05318 if (!ast_strlen_zero(d->id))
05319 ast_log(LOG_WARNING,
05320 "tn= and device= can't be used together. Ignoring device= entry\n");
05321 d->id[0] = 'T';
05322 ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
05323 d->extension_number[0] = '\0';
05324 } else if (ast_strlen_zero(d->id)) {
05325 if (strcmp(d->name, "template")) {
05326 ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
05327 ast_mutex_destroy(&l->lock);
05328 ast_free(l);
05329 if (d->tz) {
05330 d->tz = ast_tone_zone_unref(d->tz);
05331 }
05332 ast_free(d);
05333 return NULL;
05334 } else
05335 strcpy(d->id, "000000000000");
05336 }
05337 if (!d->rtp_port)
05338 d->rtp_port = 10000;
05339 if (d->contrast == -1)
05340 d->contrast = 8;
05341 if (ast_strlen_zero(d->maintext0))
05342 strcpy(d->maintext0, "Welcome");
05343 if (ast_strlen_zero(d->maintext1))
05344 strcpy(d->maintext1, d->name);
05345 if (ast_strlen_zero(d->titledefault)) {
05346 struct ast_tm tm = { 0, };
05347 struct timeval cur_time = ast_tvnow();
05348
05349 if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
05350 display_last_error("Error in ast_localtime()");
05351 ast_copy_string(d->titledefault, "UNISTIM for*", 12);
05352 } else {
05353 if (strlen(tm.tm_zone) < 4) {
05354 strcpy(d->titledefault, "TimeZone ");
05355 strcat(d->titledefault, tm.tm_zone);
05356 } else if (strlen(tm.tm_zone) < 9) {
05357 strcpy(d->titledefault, "TZ ");
05358 strcat(d->titledefault, tm.tm_zone);
05359 } else
05360 ast_copy_string(d->titledefault, tm.tm_zone, 12);
05361 }
05362 }
05363
05364 if (create) {
05365 ast_mutex_lock(&devicelock);
05366 d->next = devices;
05367 devices = d;
05368 ast_mutex_unlock(&devicelock);
05369 ast_verb(3, "Added device '%s'\n", d->name);
05370 } else {
05371 ast_verb(3, "Device '%s' reloaded\n", d->name);
05372 }
05373 return d;
05374 }
05375
05376
05377 static int reload_config(void)
05378 {
05379 struct ast_config *cfg;
05380 struct ast_variable *v;
05381 struct ast_hostent ahp;
05382 struct hostent *hp;
05383 struct sockaddr_in bindaddr = { 0, };
05384 char *config = "unistim.conf";
05385 char *cat;
05386 struct unistim_device *d;
05387 const int reuseFlag = 1;
05388 struct unistimsession *s;
05389 struct ast_flags config_flags = { 0, };
05390
05391 cfg = ast_config_load(config, config_flags);
05392
05393 if (!cfg) {
05394 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
05395 return -1;
05396 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
05397 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
05398 return -1;
05399 }
05400
05401
05402 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
05403
05404 unistim_keepalive = 120;
05405 unistim_port = 0;
05406 v = ast_variable_browse(cfg, "general");
05407 while (v) {
05408
05409 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
05410 continue;
05411
05412 if (!strcasecmp(v->name, "keepalive"))
05413 unistim_keepalive = atoi(v->value);
05414 else if (!strcasecmp(v->name, "port"))
05415 unistim_port = atoi(v->value);
05416 else if (!strcasecmp(v->name, "tos")) {
05417 if (ast_str2tos(v->value, &qos.tos))
05418 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
05419 } else if (!strcasecmp(v->name, "tos_audio")) {
05420 if (ast_str2tos(v->value, &qos.tos_audio))
05421 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05422 } else if (!strcasecmp(v->name, "cos")) {
05423 if (ast_str2cos(v->value, &qos.cos))
05424 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
05425 } else if (!strcasecmp(v->name, "cos_audio")) {
05426 if (ast_str2cos(v->value, &qos.cos_audio))
05427 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05428 } else if (!strcasecmp(v->name, "autoprovisioning")) {
05429 if (!strcasecmp(v->value, "no"))
05430 autoprovisioning = AUTOPROVISIONING_NO;
05431 else if (!strcasecmp(v->value, "yes"))
05432 autoprovisioning = AUTOPROVISIONING_YES;
05433 else if (!strcasecmp(v->value, "db"))
05434 autoprovisioning = AUTOPROVISIONING_DB;
05435 else if (!strcasecmp(v->value, "tn"))
05436 autoprovisioning = AUTOPROVISIONING_TN;
05437 else
05438 ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
05439 } else if (!strcasecmp(v->name, "public_ip")) {
05440 if (!ast_strlen_zero(v->value)) {
05441 if (!(hp = ast_gethostbyname(v->value, &ahp)))
05442 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
05443 else {
05444 memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
05445 public_ip.sin_family = AF_INET;
05446 }
05447 }
05448 }
05449 v = v->next;
05450 }
05451 if ((unistim_keepalive < 10) ||
05452 (unistim_keepalive >
05453 255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
05454 ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
05455 ast_config_destroy(cfg);
05456 return -1;
05457 }
05458 packet_send_ping[4] =
05459 unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
05460 if ((unistim_port < 1) || (unistim_port > 65535)) {
05461 ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
05462 ast_config_destroy(cfg);
05463 return -1;
05464 }
05465 unistim_keepalive *= 1000;
05466
05467 ast_mutex_lock(&devicelock);
05468 d = devices;
05469 while (d) {
05470 if (d->to_delete >= 0)
05471 d->to_delete = 1;
05472 d = d->next;
05473 }
05474 ast_mutex_unlock(&devicelock);
05475
05476 cat = ast_category_browse(cfg, NULL);
05477 while (cat) {
05478 if (strcasecmp(cat, "general")) {
05479 d = build_device(cat, ast_variable_browse(cfg, cat));
05480 }
05481 cat = ast_category_browse(cfg, cat);
05482 }
05483 ast_mutex_lock(&devicelock);
05484 d = devices;
05485 while (d) {
05486 if (d->to_delete) {
05487 int i;
05488
05489 if (unistimdebug)
05490 ast_verb(0, "Removing device '%s'\n", d->name);
05491 if (!d->lines) {
05492 ast_log(LOG_ERROR, "Device '%s' without a line !, aborting\n", d->name);
05493 ast_config_destroy(cfg);
05494 return 0;
05495 }
05496 if (!d->lines->subs[0]) {
05497 ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
05498 d->name);
05499 ast_config_destroy(cfg);
05500 return 0;
05501 }
05502 if (d->lines->subs[0]->owner) {
05503 ast_log(LOG_WARNING,
05504 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
05505 d->name);
05506 d = d->next;
05507 continue;
05508 }
05509 ast_mutex_destroy(&d->lines->subs[0]->lock);
05510 ast_free(d->lines->subs[0]);
05511 for (i = 1; i < MAX_SUBS; i++) {
05512 if (d->lines->subs[i]) {
05513 ast_log(LOG_WARNING,
05514 "Device '%s' with threeway call subchannels allocated, aborting.\n",
05515 d->name);
05516 break;
05517 }
05518 }
05519 if (i < MAX_SUBS) {
05520 d = d->next;
05521 continue;
05522 }
05523 ast_mutex_destroy(&d->lines->lock);
05524 ast_free(d->lines);
05525 if (d->session) {
05526 if (sessions == d->session)
05527 sessions = d->session->next;
05528 else {
05529 s = sessions;
05530 while (s) {
05531 if (s->next == d->session) {
05532 s->next = d->session->next;
05533 break;
05534 }
05535 s = s->next;
05536 }
05537 }
05538 ast_mutex_destroy(&d->session->lock);
05539 ast_free(d->session);
05540 }
05541 if (devices == d)
05542 devices = d->next;
05543 else {
05544 struct unistim_device *d2 = devices;
05545 while (d2) {
05546 if (d2->next == d) {
05547 d2->next = d->next;
05548 break;
05549 }
05550 d2 = d2->next;
05551 }
05552 }
05553 if (d->tz) {
05554 d->tz = ast_tone_zone_unref(d->tz);
05555 }
05556 ast_free(d);
05557 d = devices;
05558 continue;
05559 }
05560 d = d->next;
05561 }
05562 finish_bookmark();
05563 ast_mutex_unlock(&devicelock);
05564 ast_config_destroy(cfg);
05565 ast_mutex_lock(&sessionlock);
05566 s = sessions;
05567 while (s) {
05568 if (s->device)
05569 refresh_all_favorite(s);
05570 s = s->next;
05571 }
05572 ast_mutex_unlock(&sessionlock);
05573
05574 if (unistimsock > -1)
05575 return 0;
05576 bindaddr.sin_addr.s_addr = INADDR_ANY;
05577 bindaddr.sin_port = htons(unistim_port);
05578 bindaddr.sin_family = AF_INET;
05579 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
05580 if (unistimsock < 0) {
05581 ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
05582 return -1;
05583 }
05584 #ifdef HAVE_PKTINFO
05585 {
05586 const int pktinfoFlag = 1;
05587 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
05588 sizeof(pktinfoFlag));
05589 }
05590 #else
05591 if (public_ip.sin_family == 0) {
05592 ast_log(LOG_WARNING,
05593 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
05594 unistimsock = -1;
05595 return -1;
05596 }
05597 #endif
05598 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
05599 sizeof(reuseFlag));
05600 if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
05601 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
05602 ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
05603 strerror(errno));
05604 close(unistimsock);
05605 unistimsock = -1;
05606 } else {
05607 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
05608 ast_netsock_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
05609 }
05610 return 0;
05611 }
05612
05613 static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
05614 {
05615 struct unistim_subchannel *sub = chan->tech_pvt;
05616
05617 ao2_ref(sub->rtp, +1);
05618 *instance = sub->rtp;
05619
05620 return AST_RTP_GLUE_RESULT_LOCAL;
05621 }
05622
05623 static struct ast_rtp_glue unistim_rtp_glue = {
05624 .type = channel_type,
05625 .get_rtp_info = unistim_get_rtp_peer,
05626 };
05627
05628
05629 int load_module(void)
05630 {
05631 int res;
05632
05633 if (!(buff = ast_malloc(SIZE_PAGE)))
05634 goto buff_failed;
05635
05636 io = io_context_create();
05637 if (!io) {
05638 ast_log(LOG_ERROR, "Failed to allocate IO context\n");
05639 goto io_failed;
05640 }
05641
05642 sched = sched_context_create();
05643 if (!sched) {
05644 ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
05645 goto sched_failed;
05646 }
05647
05648 res = reload_config();
05649 if (res)
05650 return AST_MODULE_LOAD_DECLINE;
05651
05652
05653 if (ast_channel_register(&unistim_tech)) {
05654 ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
05655 goto chanreg_failed;
05656 }
05657
05658 ast_rtp_glue_register(&unistim_rtp_glue);
05659
05660 ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05661
05662 restart_monitor();
05663
05664 return AST_MODULE_LOAD_SUCCESS;
05665
05666 chanreg_failed:
05667
05668 sched_context_destroy(sched);
05669 sched = NULL;
05670 sched_failed:
05671 io_context_destroy(io);
05672 io = NULL;
05673 io_failed:
05674 ast_free(buff);
05675 buff = NULL;
05676 buff_failed:
05677 return AST_MODULE_LOAD_FAILURE;
05678 }
05679
05680 static int unload_module(void)
05681 {
05682
05683 if (sched)
05684 sched_context_destroy(sched);
05685
05686 ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05687
05688 ast_channel_unregister(&unistim_tech);
05689 ast_rtp_glue_unregister(&unistim_rtp_glue);
05690
05691 ast_mutex_lock(&monlock);
05692 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
05693 pthread_cancel(monitor_thread);
05694 pthread_kill(monitor_thread, SIGURG);
05695 pthread_join(monitor_thread, NULL);
05696 }
05697 monitor_thread = AST_PTHREADT_STOP;
05698 ast_mutex_unlock(&monlock);
05699
05700 if (buff)
05701 ast_free(buff);
05702 if (unistimsock > -1)
05703 close(unistimsock);
05704
05705 return 0;
05706 }
05707
05708
05709 int reload(void)
05710 {
05711 unistim_reload(NULL, 0, NULL);
05712 return 0;
05713 }
05714
05715 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
05716 .load = load_module,
05717 .unload = unload_module,
05718 .reload = reload,
05719 );