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: 328209 $")
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 *sdata = (unsigned short *) data;
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 sdata[1] = ntohs(++(pte->seq_server));
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 if (unistimdebug) {
00886 ast_verb(0, "Creating a new entry for the phone from %s received via server ip %s\n",
00887 ast_inet_ntoa(addr_from->sin_addr), ast_inet_ntoa(s->sout.sin_addr));
00888 }
00889 ast_mutex_init(&s->lock);
00890 ast_mutex_lock(&sessionlock);
00891 s->next = sessions;
00892 sessions = s;
00893
00894 s->timeout = get_tick_count() + RETRANSMIT_TIMER;
00895 s->seq_phone = (short) 0x0000;
00896 s->seq_server = (short) 0x0000;
00897 s->last_seq_ack = (short) 0x000;
00898 s->last_buf_available = 0;
00899 s->nb_retransmit = 0;
00900 s->state = STATE_INIT;
00901 s->tick_next_ping = get_tick_count() + unistim_keepalive;
00902
00903 for (tmp = 0; tmp < MAX_BUF_NUMBER; tmp++) {
00904 s->wsabufsend[tmp].buf = s->buf[tmp];
00905 }
00906 ast_mutex_unlock(&sessionlock);
00907 return s;
00908 }
00909
00910 static void send_end_call(struct unistimsession *pte)
00911 {
00912 BUFFSEND;
00913 if (unistimdebug)
00914 ast_verb(0, "Sending end call\n");
00915 memcpy(buffsend + SIZE_HEADER, packet_send_end_call, sizeof(packet_send_end_call));
00916 send_client(SIZE_HEADER + sizeof(packet_send_end_call), buffsend, pte);
00917 }
00918
00919 static void set_ping_timer(struct unistimsession *pte)
00920 {
00921 unsigned int tick = 0;
00922
00923 pte->timeout = pte->tick_next_ping;
00924 DEBUG_TIMER("tick = %u next ping at %u tick\n", tick, pte->timeout);
00925 return;
00926 }
00927
00928
00929
00930 static void check_send_queue(struct unistimsession *pte)
00931 {
00932
00933 if (pte->last_buf_available == 1) {
00934 if (unistimdebug)
00935 ast_verb(6, "Our single packet was ACKed.\n");
00936 pte->last_buf_available--;
00937 set_ping_timer(pte);
00938 return;
00939 }
00940
00941 else if (pte->last_seq_ack + 1 == pte->seq_server + 1) {
00942 if (unistimdebug)
00943 ast_verb(6, "Our send queue is completely ACKed.\n");
00944 pte->last_buf_available = 0;
00945 set_ping_timer(pte);
00946 return;
00947 }
00948 if (unistimdebug)
00949 ast_verb(6, "We still have packets in our send queue\n");
00950 return;
00951 }
00952
00953 static void send_start_timer(struct unistimsession *pte)
00954 {
00955 BUFFSEND;
00956 if (unistimdebug)
00957 ast_verb(0, "Sending start timer\n");
00958 memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
00959 send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
00960 }
00961
00962 static void send_stop_timer(struct unistimsession *pte)
00963 {
00964 BUFFSEND;
00965 if (unistimdebug)
00966 ast_verb(0, "Sending stop timer\n");
00967 memcpy(buffsend + SIZE_HEADER, packet_send_stop_timer, sizeof(packet_send_stop_timer));
00968 send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
00969 }
00970
00971 static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
00972 {
00973 BUFFSEND;
00974 if (unistimdebug)
00975 ast_verb(0, "Sending icon pos %d with status 0x%.2x\n", pos, status);
00976 memcpy(buffsend + SIZE_HEADER, packet_send_icon, sizeof(packet_send_icon));
00977 buffsend[9] = pos;
00978 buffsend[10] = status;
00979 send_client(SIZE_HEADER + sizeof(packet_send_icon), buffsend, pte);
00980 }
00981
00982 static void send_tone(struct unistimsession *pte, uint16_t tone1, uint16_t tone2)
00983 {
00984 BUFFSEND;
00985 if (!tone1) {
00986 if (unistimdebug)
00987 ast_verb(0, "Sending Stream Based Tone Off\n");
00988 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_off,
00989 sizeof(packet_send_stream_based_tone_off));
00990 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_off), buffsend, pte);
00991 return;
00992 }
00993
00994
00995
00996
00997
00998 if (unistimdebug)
00999 ast_verb(0, "Sending Stream Based Tone Frequency Component List Download %d %d\n", tone1, tone2);
01000 tone1 *= 8;
01001 if (!tone2) {
01002 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_single_freq,
01003 sizeof(packet_send_stream_based_tone_single_freq));
01004 buffsend[10] = (tone1 & 0xff00) >> 8;
01005 buffsend[11] = (tone1 & 0x00ff);
01006 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_single_freq), buffsend,
01007 pte);
01008 } else {
01009 tone2 *= 8;
01010 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_dial_freq,
01011 sizeof(packet_send_stream_based_tone_dial_freq));
01012 buffsend[10] = (tone1 & 0xff00) >> 8;
01013 buffsend[11] = (tone1 & 0x00ff);
01014 buffsend[12] = (tone2 & 0xff00) >> 8;
01015 buffsend[13] = (tone2 & 0x00ff);
01016 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_dial_freq), buffsend,
01017 pte);
01018 }
01019
01020 if (unistimdebug)
01021 ast_verb(0, "Sending Stream Based Tone On\n");
01022 memcpy(buffsend + SIZE_HEADER, packet_send_stream_based_tone_on,
01023 sizeof(packet_send_stream_based_tone_on));
01024 send_client(SIZE_HEADER + sizeof(packet_send_stream_based_tone_on), buffsend, pte);
01025 }
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 static void
01036 send_favorite(unsigned char pos, unsigned char status, struct unistimsession *pte,
01037 const char *text)
01038 {
01039 BUFFSEND;
01040 int i;
01041
01042 if (unistimdebug)
01043 ast_verb(0, "Sending favorite pos %d with status 0x%.2x\n", pos, status);
01044 memcpy(buffsend + SIZE_HEADER, packet_send_favorite, sizeof(packet_send_favorite));
01045 buffsend[10] = pos;
01046 buffsend[24] = pos;
01047 buffsend[25] = status;
01048 i = strlen(text);
01049 if (i > FAV_MAX_LENGTH)
01050 i = FAV_MAX_LENGTH;
01051 memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
01052 send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
01053 }
01054
01055 static void refresh_all_favorite(struct unistimsession *pte)
01056 {
01057 int i = 0;
01058
01059 if (unistimdebug)
01060 ast_verb(0, "Refreshing all favorite\n");
01061 for (i = 0; i < 6; i++) {
01062 if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
01063 (pte->device->softkeylinepos != i))
01064 send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
01065 pte->device->softkeylabel[i]);
01066 else
01067 send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
01068 pte->device->softkeylabel[i]);
01069
01070 }
01071 }
01072
01073
01074
01075 static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
01076 {
01077 struct unistim_device *d = devices;
01078 int i;
01079
01080 if (pte->state != STATE_CLEANING)
01081 send_favorite(pte->device->softkeylinepos, status, pte,
01082 pte->device->softkeylabel[pte->device->softkeylinepos]);
01083
01084 while (d) {
01085 for (i = 0; i < 6; i++) {
01086 if (d->sp[i] == pte->device) {
01087 if (d->softkeyicon[i] != status) {
01088 d->softkeyicon[i] = status;
01089 if (d->session)
01090 send_favorite(i, status + 1, d->session, d->softkeylabel[i]);
01091 }
01092 }
01093 }
01094 d = d->next;
01095 }
01096 }
01097
01098 static int RegisterExtension(const struct unistimsession *pte)
01099 {
01100 if (unistimdebug)
01101 ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
01102 pte->device->extension_number, pte->device->lines->context,
01103 pte->device->lines->fullname);
01104 return ast_add_extension(pte->device->lines->context, 0,
01105 pte->device->extension_number, 1, NULL, NULL, "Dial",
01106 pte->device->lines->fullname, 0, "Unistim");
01107 }
01108
01109 static int UnregisterExtension(const struct unistimsession *pte)
01110 {
01111 if (unistimdebug)
01112 ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
01113 pte->device->extension_number, pte->device->lines->context);
01114 return ast_context_remove_extension(pte->device->lines->context,
01115 pte->device->extension_number, 1, "Unistim");
01116 }
01117
01118
01119 static void close_client(struct unistimsession *s)
01120 {
01121 struct unistim_subchannel *sub;
01122 struct unistimsession *cur, *prev = NULL;
01123 ast_mutex_lock(&sessionlock);
01124 cur = sessions;
01125
01126 while (cur) {
01127 if (cur == s)
01128 break;
01129 prev = cur;
01130 cur = cur->next;
01131 }
01132 if (cur) {
01133 if (cur->device) {
01134 s->state = STATE_CLEANING;
01135 if (unistimdebug)
01136 ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
01137 s, s->device, s->device->lines,
01138 s->device->lines->subs[SUB_REAL]);
01139 change_favorite_icon(s, FAV_ICON_NONE);
01140 sub = s->device->lines->subs[SUB_REAL];
01141 if (sub) {
01142 if (sub->owner) {
01143 if (unistimdebug)
01144 ast_verb(0, "Aborting call\n");
01145 ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NETWORK_OUT_OF_ORDER);
01146 }
01147 } else
01148 ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
01149 if (!ast_strlen_zero(s->device->extension_number))
01150 UnregisterExtension(s);
01151 cur->device->session = NULL;
01152 } else {
01153 if (unistimdebug)
01154 ast_verb(0, "Freeing an unregistered client\n");
01155 }
01156 if (prev)
01157 prev->next = cur->next;
01158 else
01159 sessions = cur->next;
01160 ast_mutex_destroy(&s->lock);
01161 ast_free(s);
01162 } else
01163 ast_log(LOG_WARNING, "Trying to delete non-existent session %p?\n", s);
01164 ast_mutex_unlock(&sessionlock);
01165 return;
01166 }
01167
01168
01169 static int send_retransmit(struct unistimsession *pte)
01170 {
01171 int i;
01172
01173 ast_mutex_lock(&pte->lock);
01174 if (++pte->nb_retransmit >= NB_MAX_RETRANSMIT) {
01175 if (unistimdebug)
01176 ast_verb(0, "Too many retransmit - freeing client\n");
01177 ast_mutex_unlock(&pte->lock);
01178 close_client(pte);
01179 return 1;
01180 }
01181 pte->timeout = get_tick_count() + RETRANSMIT_TIMER;
01182
01183 for (i = pte->last_buf_available - (pte->seq_server - pte->last_seq_ack);
01184 i < pte->last_buf_available; i++) {
01185 if (i < 0) {
01186 ast_log(LOG_WARNING,
01187 "Asked to retransmit an ACKed slot ! last_buf_available=%d, seq_server = #0x%.4x last_seq_ack = #0x%.4x\n",
01188 pte->last_buf_available, pte->seq_server, pte->last_seq_ack);
01189 continue;
01190 }
01191
01192 if (unistimdebug) {
01193 unsigned short *sbuf = (unsigned short *) pte->wsabufsend[i].buf;
01194 unsigned short seq;
01195
01196 seq = ntohs(sbuf[1]);
01197 ast_verb(0, "Retransmit slot #%d (seq=#0x%.4x), last ack was #0x%.4x\n", i,
01198 seq, pte->last_seq_ack);
01199 }
01200 send_raw_client(pte->wsabufsend[i].len, pte->wsabufsend[i].buf, &pte->sin,
01201 &pte->sout);
01202 }
01203 ast_mutex_unlock(&pte->lock);
01204 return 0;
01205 }
01206
01207
01208 static void
01209 send_text(unsigned char pos, unsigned char inverse, struct unistimsession *pte,
01210 const char *text)
01211 {
01212 int i;
01213 BUFFSEND;
01214 if (unistimdebug)
01215 ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
01216 memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
01217 buffsend[10] = pos;
01218 buffsend[11] = inverse;
01219 i = strlen(text);
01220 if (i > TEXT_LENGTH_MAX)
01221 i = TEXT_LENGTH_MAX;
01222 memcpy(buffsend + 12, text, i);
01223 send_client(SIZE_HEADER + sizeof(packet_send_text), buffsend, pte);
01224 }
01225
01226 static void send_text_status(struct unistimsession *pte, const char *text)
01227 {
01228 BUFFSEND;
01229 int i;
01230 if (unistimdebug)
01231 ast_verb(0, "Sending status text\n");
01232 if (pte->device) {
01233 if (pte->device->status_method == 1) {
01234 int n = strlen(text);
01235
01236 int j;
01237 for (i = 0, j = 0; i < 4; i++, j += 7) {
01238 int pos = 0x08 + (i * 0x20);
01239 memcpy(buffsend + SIZE_HEADER, packet_send_status2,
01240 sizeof(packet_send_status2));
01241
01242 buffsend[9] = pos;
01243 memcpy(buffsend + 10, (j < n) ? (text + j) : " ", 7);
01244 send_client(SIZE_HEADER + sizeof(packet_send_status2), buffsend, pte);
01245 }
01246 return;
01247 }
01248 }
01249
01250
01251 memcpy(buffsend + SIZE_HEADER, packet_send_status, sizeof(packet_send_status));
01252 i = strlen(text);
01253 if (i > STATUS_LENGTH_MAX)
01254 i = STATUS_LENGTH_MAX;
01255 memcpy(buffsend + 10, text, i);
01256 send_client(SIZE_HEADER + sizeof(packet_send_status), buffsend, pte);
01257
01258 }
01259
01260
01261
01262
01263
01264 static void send_led_update(struct unistimsession *pte, unsigned char led)
01265 {
01266 BUFFSEND;
01267 if (unistimdebug)
01268 ast_verb(0, "Sending led_update (%x)\n", led);
01269 memcpy(buffsend + SIZE_HEADER, packet_send_led_update, sizeof(packet_send_led_update));
01270 buffsend[9] = led;
01271 send_client(SIZE_HEADER + sizeof(packet_send_led_update), buffsend, pte);
01272 }
01273
01274
01275
01276
01277 static void
01278 send_select_output(struct unistimsession *pte, unsigned char output, unsigned char volume,
01279 unsigned char mute)
01280 {
01281 BUFFSEND;
01282 if (unistimdebug)
01283 ast_verb(0, "Sending select output packet output=%x volume=%x mute=%x\n", output,
01284 volume, mute);
01285 memcpy(buffsend + SIZE_HEADER, packet_send_select_output,
01286 sizeof(packet_send_select_output));
01287 buffsend[9] = output;
01288 if (output == OUTPUT_SPEAKER)
01289 volume = VOLUME_LOW_SPEAKER;
01290 else
01291 volume = VOLUME_LOW;
01292 buffsend[10] = volume;
01293 if (mute == MUTE_ON_DISCRET)
01294 buffsend[11] = MUTE_ON;
01295 else
01296 buffsend[11] = mute;
01297 send_client(SIZE_HEADER + sizeof(packet_send_select_output), buffsend, pte);
01298 if (mute == MUTE_OFF)
01299 send_led_update(pte, 0x18);
01300 else if (mute == MUTE_ON)
01301 send_led_update(pte, 0x19);
01302 pte->device->mute = mute;
01303 if (output == OUTPUT_HANDSET) {
01304 if (mute == MUTE_ON)
01305 change_favorite_icon(pte, FAV_ICON_ONHOLD_BLACK);
01306 else
01307 change_favorite_icon(pte, FAV_ICON_OFFHOOK_BLACK);
01308 send_led_update(pte, 0x08);
01309 send_led_update(pte, 0x10);
01310 } else if (output == OUTPUT_HEADPHONE) {
01311 if (mute == MUTE_ON)
01312 change_favorite_icon(pte, FAV_ICON_HEADPHONES_ONHOLD);
01313 else
01314 change_favorite_icon(pte, FAV_ICON_HEADPHONES);
01315 send_led_update(pte, 0x08);
01316 send_led_update(pte, 0x11);
01317 } else if (output == OUTPUT_SPEAKER) {
01318 send_led_update(pte, 0x10);
01319 send_led_update(pte, 0x09);
01320 if (pte->device->receiver_state == STATE_OFFHOOK) {
01321 if (mute == MUTE_ON)
01322 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01323 else
01324 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOOK_BLACK);
01325 } else {
01326 if (mute == MUTE_ON)
01327 change_favorite_icon(pte, FAV_ICON_SPEAKER_ONHOLD_BLACK);
01328 else
01329 change_favorite_icon(pte, FAV_ICON_SPEAKER_OFFHOOK_BLACK);
01330 }
01331 } else
01332 ast_log(LOG_WARNING, "Invalid output (%d)\n", output);
01333 if (output != pte->device->output)
01334 pte->device->previous_output = pte->device->output;
01335 pte->device->output = output;
01336 }
01337
01338 static void send_ring(struct unistimsession *pte, char volume, char style)
01339 {
01340 BUFFSEND;
01341 if (unistimdebug)
01342 ast_verb(0, "Sending ring packet\n");
01343 memcpy(buffsend + SIZE_HEADER, packet_send_ring, sizeof(packet_send_ring));
01344 buffsend[24] = style + 0x10;
01345 buffsend[29] = volume * 0x10;
01346 send_client(SIZE_HEADER + sizeof(packet_send_ring), buffsend, pte);
01347 }
01348
01349 static void send_no_ring(struct unistimsession *pte)
01350 {
01351 BUFFSEND;
01352 if (unistimdebug)
01353 ast_verb(0, "Sending no ring packet\n");
01354 memcpy(buffsend + SIZE_HEADER, packet_send_no_ring, sizeof(packet_send_no_ring));
01355 send_client(SIZE_HEADER + sizeof(packet_send_no_ring), buffsend, pte);
01356 }
01357
01358 static void send_texttitle(struct unistimsession *pte, const char *text)
01359 {
01360 BUFFSEND;
01361 int i;
01362 if (unistimdebug)
01363 ast_verb(0, "Sending title text\n");
01364 memcpy(buffsend + SIZE_HEADER, packet_send_title, sizeof(packet_send_title));
01365 i = strlen(text);
01366 if (i > 12)
01367 i = 12;
01368 memcpy(buffsend + 10, text, i);
01369 send_client(SIZE_HEADER + sizeof(packet_send_title), buffsend, pte);
01370
01371 }
01372
01373 static void send_date_time(struct unistimsession *pte)
01374 {
01375 BUFFSEND;
01376 struct timeval now = ast_tvnow();
01377 struct ast_tm atm = { 0, };
01378
01379 if (unistimdebug)
01380 ast_verb(0, "Sending Time & Date\n");
01381 memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
01382 ast_localtime(&now, &atm, NULL);
01383 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01384 buffsend[11] = (unsigned char) atm.tm_mday;
01385 buffsend[12] = (unsigned char) atm.tm_hour;
01386 buffsend[13] = (unsigned char) atm.tm_min;
01387 send_client(SIZE_HEADER + sizeof(packet_send_date_time), buffsend, pte);
01388 }
01389
01390 static void send_date_time2(struct unistimsession *pte)
01391 {
01392 BUFFSEND;
01393 struct timeval now = ast_tvnow();
01394 struct ast_tm atm = { 0, };
01395
01396 if (unistimdebug)
01397 ast_verb(0, "Sending Time & Date #2\n");
01398 memcpy(buffsend + SIZE_HEADER, packet_send_date_time2, sizeof(packet_send_date_time2));
01399 ast_localtime(&now, &atm, NULL);
01400 if (pte->device)
01401 buffsend[9] = pte->device->datetimeformat;
01402 else
01403 buffsend[9] = 61;
01404 buffsend[14] = (unsigned char) atm.tm_mon + 1;
01405 buffsend[15] = (unsigned char) atm.tm_mday;
01406 buffsend[16] = (unsigned char) atm.tm_hour;
01407 buffsend[17] = (unsigned char) atm.tm_min;
01408 send_client(SIZE_HEADER + sizeof(packet_send_date_time2), buffsend, pte);
01409 }
01410
01411 static void send_date_time3(struct unistimsession *pte)
01412 {
01413 BUFFSEND;
01414 struct timeval now = ast_tvnow();
01415 struct ast_tm atm = { 0, };
01416
01417 if (unistimdebug)
01418 ast_verb(0, "Sending Time & Date #3\n");
01419 memcpy(buffsend + SIZE_HEADER, packet_send_date_time3, sizeof(packet_send_date_time3));
01420 ast_localtime(&now, &atm, NULL);
01421 buffsend[10] = (unsigned char) atm.tm_mon + 1;
01422 buffsend[11] = (unsigned char) atm.tm_mday;
01423 buffsend[12] = (unsigned char) atm.tm_hour;
01424 buffsend[13] = (unsigned char) atm.tm_min;
01425 send_client(SIZE_HEADER + sizeof(packet_send_date_time3), buffsend, pte);
01426 }
01427
01428 static void send_blink_cursor(struct unistimsession *pte)
01429 {
01430 BUFFSEND;
01431 if (unistimdebug)
01432 ast_verb(0, "Sending set blink\n");
01433 memcpy(buffsend + SIZE_HEADER, packet_send_blink_cursor, sizeof(packet_send_blink_cursor));
01434 send_client(SIZE_HEADER + sizeof(packet_send_blink_cursor), buffsend, pte);
01435 return;
01436 }
01437
01438
01439 static void send_cursor_pos(struct unistimsession *pte, unsigned char pos)
01440 {
01441 BUFFSEND;
01442 if (unistimdebug)
01443 ast_verb(0, "Sending set cursor position\n");
01444 memcpy(buffsend + SIZE_HEADER, packet_send_set_pos_cursor,
01445 sizeof(packet_send_set_pos_cursor));
01446 buffsend[11] = pos;
01447 send_client(SIZE_HEADER + sizeof(packet_send_set_pos_cursor), buffsend, pte);
01448 return;
01449 }
01450
01451 static void rcv_resume_connection_with_server(struct unistimsession *pte)
01452 {
01453 BUFFSEND;
01454 if (unistimdebug) {
01455 ast_verb(0, "ResumeConnectionWithServer received\n");
01456 ast_verb(0, "Sending packet_send_query_mac_address\n");
01457 }
01458 memcpy(buffsend + SIZE_HEADER, packet_send_query_mac_address,
01459 sizeof(packet_send_query_mac_address));
01460 send_client(SIZE_HEADER + sizeof(packet_send_query_mac_address), buffsend, pte);
01461 return;
01462 }
01463
01464 static int unistim_register(struct unistimsession *s)
01465 {
01466 struct unistim_device *d;
01467
01468 ast_mutex_lock(&devicelock);
01469 d = devices;
01470 while (d) {
01471 if (!strcasecmp(s->macaddr, d->id)) {
01472
01473 s->device = d;
01474 d->session = s;
01475 d->codec_number = DEFAULT_CODEC;
01476 d->pos_fav = 0;
01477 d->missed_call = 0;
01478 d->receiver_state = STATE_ONHOOK;
01479 break;
01480 }
01481 d = d->next;
01482 }
01483 ast_mutex_unlock(&devicelock);
01484
01485 if (!d)
01486 return 0;
01487
01488 return 1;
01489 }
01490
01491 static int alloc_sub(struct unistim_line *l, int x)
01492 {
01493 struct unistim_subchannel *sub;
01494 if (!(sub = ast_calloc(1, sizeof(*sub))))
01495 return 0;
01496
01497 if (unistimdebug)
01498 ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
01499 sub->parent = l;
01500 sub->subtype = x;
01501 l->subs[x] = sub;
01502 ast_mutex_init(&sub->lock);
01503 return 1;
01504 }
01505
01506 static int unalloc_sub(struct unistim_line *p, int x)
01507 {
01508 if (!x) {
01509 ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
01510 p->parent->name);
01511 return -1;
01512 }
01513 if (unistimdebug)
01514 ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
01515 p->parent->name);
01516 ast_mutex_destroy(&p->lock);
01517 ast_free(p->subs[x]);
01518 p->subs[x] = 0;
01519 return 0;
01520 }
01521
01522 static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
01523 {
01524 BUFFSEND;
01525 int tmp, i = 0;
01526 char addrmac[19];
01527 int res = 0;
01528 if (unistimdebug)
01529 ast_verb(0, "Mac Address received : ");
01530 for (tmp = 15; tmp < 15 + SIZE_HEADER; tmp++) {
01531 sprintf(&addrmac[i], "%.2x", (unsigned char) buf[tmp]);
01532 i += 2;
01533 }
01534 if (unistimdebug)
01535 ast_verb(0, "%s\n", addrmac);
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 (peera->cdr && peerb->cdr) {
01928 peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
01929 } else if (peera->cdr) {
01930 peerb->cdr = peera->cdr;
01931 }
01932 peera->cdr = NULL;
01933
01934 if (peerb->cdr && peerc->cdr) {
01935 peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
01936 } else if (peerc->cdr) {
01937 peerb->cdr = peerc->cdr;
01938 }
01939 peerc->cdr = NULL;
01940
01941 if (ast_channel_masquerade(peerb, peerc)) {
01942 ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
01943 peerc->name);
01944 res = -1;
01945 }
01946 return res;
01947 } else {
01948 ast_log(LOG_NOTICE,
01949 "Transfer attempted with no appropriate bridged calls to transfer\n");
01950 if (chana)
01951 ast_softhangup_nolock(chana, AST_SOFTHANGUP_DEV);
01952 if (chanb)
01953 ast_softhangup_nolock(chanb, AST_SOFTHANGUP_DEV);
01954 return -1;
01955 }
01956 return 0;
01957 }
01958
01959 void change_callerid(struct unistimsession *pte, int type, char *callerid)
01960 {
01961 char *data;
01962 int size;
01963
01964 if (type)
01965 data = pte->device->lst_cnm;
01966 else
01967 data = pte->device->lst_cid;
01968
01969
01970
01971 memset(data, ' ', TEXT_LENGTH_MAX);
01972 size = strlen(callerid);
01973 if (size > TEXT_LENGTH_MAX)
01974 size = TEXT_LENGTH_MAX;
01975 memcpy(data, callerid, size);
01976 }
01977
01978 static void close_call(struct unistimsession *pte)
01979 {
01980 struct unistim_subchannel *sub;
01981 struct unistim_line *l = pte->device->lines;
01982
01983 sub = pte->device->lines->subs[SUB_REAL];
01984 send_stop_timer(pte);
01985 if (sub->owner) {
01986 sub->alreadygone = 1;
01987 if (l->subs[SUB_THREEWAY]) {
01988 l->subs[SUB_THREEWAY]->alreadygone = 1;
01989 if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
01990 ast_verb(0, "attempt_transfer failed.\n");
01991 } else
01992 ast_queue_hangup(sub->owner);
01993 } else {
01994 if (l->subs[SUB_THREEWAY]) {
01995 if (l->subs[SUB_THREEWAY]->owner)
01996 ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
01997 else
01998 ast_log(LOG_WARNING, "threeway sub without owner\n");
01999 } else
02000 ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
02001 sub->parent->parent->name, sub->subtype);
02002 }
02003 change_callerid(pte, 0, pte->device->redial_number);
02004 change_callerid(pte, 1, "");
02005 write_history(pte, 'o', pte->device->missed_call);
02006 pte->device->missed_call = 0;
02007 show_main_page(pte);
02008 return;
02009 }
02010
02011 static void IgnoreCall(struct unistimsession *pte)
02012 {
02013 send_no_ring(pte);
02014 return;
02015 }
02016
02017 static void *unistim_ss(void *data)
02018 {
02019 struct ast_channel *chan = data;
02020 struct unistim_subchannel *sub = chan->tech_pvt;
02021 struct unistim_line *l = sub->parent;
02022 struct unistimsession *s = l->parent->session;
02023 int res;
02024
02025 ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
02026 ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
02027 ast_copy_string(s->device->redial_number, s->device->phone_number,
02028 sizeof(s->device->redial_number));
02029 ast_setstate(chan, AST_STATE_RING);
02030 res = ast_pbx_run(chan);
02031 if (res) {
02032 ast_log(LOG_WARNING, "PBX exited non-zero\n");
02033 send_tone(s, 1000, 0);;
02034 }
02035 return NULL;
02036 }
02037
02038 static void start_rtp(struct unistim_subchannel *sub)
02039 {
02040 BUFFSEND;
02041 struct sockaddr_in us = { 0, };
02042 struct sockaddr_in public = { 0, };
02043 struct sockaddr_in sin = { 0, };
02044 format_t codec;
02045 struct sockaddr_in sout = { 0, };
02046 struct ast_sockaddr us_tmp;
02047 struct ast_sockaddr sin_tmp;
02048 struct ast_sockaddr sout_tmp;
02049
02050
02051 if (!sub) {
02052 ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
02053 return;
02054 }
02055 if (!sub->parent) {
02056 ast_log(LOG_WARNING, "start_rtp with a null line !\n");
02057 return;
02058 }
02059 if (!sub->parent->parent) {
02060 ast_log(LOG_WARNING, "start_rtp with a null device !\n");
02061 return;
02062 }
02063 if (!sub->parent->parent->session) {
02064 ast_log(LOG_WARNING, "start_rtp with a null session !\n");
02065 return;
02066 }
02067 sout = sub->parent->parent->session->sout;
02068
02069 ast_mutex_lock(&sub->lock);
02070
02071 if (unistimdebug)
02072 ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
02073 ast_sockaddr_from_sin(&sout_tmp, &sout);
02074 sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
02075 if (!sub->rtp) {
02076 ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
02077 strerror(errno), ast_inet_ntoa(sout.sin_addr));
02078 ast_mutex_unlock(&sub->lock);
02079 return;
02080 }
02081 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
02082 if (sub->owner) {
02083 sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
02084 sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
02085 }
02086 ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
02087 ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
02088
02089
02090 ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
02091 ast_sockaddr_to_sin(&us_tmp, &us);
02092 sin.sin_family = AF_INET;
02093
02094 memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
02095 sizeof(sin.sin_addr));
02096 sin.sin_port = htons(sub->parent->parent->rtp_port);
02097 ast_sockaddr_from_sin(&sin_tmp, &sin);
02098 ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
02099 if (!(sub->owner->nativeformats & sub->owner->readformat)) {
02100 format_t fmt;
02101 char tmp[256];
02102 fmt = ast_best_codec(sub->owner->nativeformats);
02103 ast_log(LOG_WARNING,
02104 "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
02105 ast_getformatname(sub->owner->readformat),
02106 ast_getformatname(fmt),
02107 ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
02108 sub->owner->readformat = fmt;
02109 sub->owner->writeformat = fmt;
02110 }
02111 codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
02112
02113 if (public_ip.sin_family == 0)
02114 memcpy(&public, &us, sizeof(public));
02115 else
02116 memcpy(&public, &public_ip, sizeof(public));
02117 if (unistimdebug) {
02118 ast_verb(0, "RTP started : Our IP/port is : %s:%hd with codec %s\n",
02119 ast_inet_ntoa(us.sin_addr),
02120 htons(us.sin_port), ast_getformatname(sub->owner->readformat));
02121 ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
02122 ast_inet_ntoa(public.sin_addr));
02123 }
02124 if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
02125 (sub->owner->readformat == AST_FORMAT_ALAW)) {
02126 if (unistimdebug)
02127 ast_verb(0, "Sending packet_send_rtp_packet_size for codec %s\n", ast_getformatname(codec));
02128 memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
02129 sizeof(packet_send_rtp_packet_size));
02130 buffsend[10] = (int) codec & 0xffffffffLL;
02131 send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
02132 sub->parent->parent->session);
02133 }
02134 if (unistimdebug)
02135 ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
02136 memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
02137 sizeof(packet_send_jitter_buffer_conf));
02138 send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
02139 sub->parent->parent->session);
02140 if (sub->parent->parent->rtp_method != 0) {
02141 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02142
02143 if (unistimdebug)
02144 ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
02145 sub->parent->parent->rtp_method);
02146 if (sub->parent->parent->rtp_method == 3)
02147 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
02148 sizeof(packet_send_open_audio_stream_tx3));
02149 else
02150 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
02151 sizeof(packet_send_open_audio_stream_tx));
02152 if (sub->parent->parent->rtp_method != 2) {
02153 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02154 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02155 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02156 buffsend[23] = (rtcpsin_port & 0x00ff);
02157 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02158 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02159 buffsend[24] = (us.sin_port & 0x00ff);
02160 buffsend[27] = (rtcpsin_port & 0x00ff);
02161 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02162 } else {
02163 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02164 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02165 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02166 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02167 buffsend[19] = (us.sin_port & 0x00ff);
02168 buffsend[11] = codec;
02169 }
02170 buffsend[12] = codec;
02171 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
02172 sub->parent->parent->session);
02173
02174 if (unistimdebug)
02175 ast_verb(0, "Sending OpenAudioStreamRX\n");
02176 if (sub->parent->parent->rtp_method == 3)
02177 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
02178 sizeof(packet_send_open_audio_stream_rx3));
02179 else
02180 memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
02181 sizeof(packet_send_open_audio_stream_rx));
02182 if (sub->parent->parent->rtp_method != 2) {
02183 memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
02184 buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
02185 buffsend[21] = (htons(sin.sin_port) & 0x00ff);
02186 buffsend[23] = (rtcpsin_port & 0x00ff);
02187 buffsend[22] = (rtcpsin_port & 0xff00) >> 8;
02188 buffsend[25] = (us.sin_port & 0xff00) >> 8;
02189 buffsend[24] = (us.sin_port & 0x00ff);
02190 buffsend[27] = (rtcpsin_port & 0x00ff);
02191 buffsend[26] = (rtcpsin_port & 0xff00) >> 8;
02192 } else {
02193 memcpy(buffsend + 23, &public.sin_addr, sizeof(public.sin_addr));
02194 buffsend[15] = (htons(sin.sin_port) & 0xff00) >> 8;
02195 buffsend[16] = (htons(sin.sin_port) & 0x00ff);
02196 buffsend[20] = (us.sin_port & 0xff00) >> 8;
02197 buffsend[19] = (us.sin_port & 0x00ff);
02198 buffsend[12] = codec;
02199 }
02200 buffsend[11] = codec;
02201 send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
02202 sub->parent->parent->session);
02203 } else {
02204 uint16_t rtcpsin_port = htons(us.sin_port) + 1;
02205
02206 if (unistimdebug)
02207 ast_verb(0, "Sending packet_send_call default method\n");
02208
02209 memcpy(buffsend + SIZE_HEADER, packet_send_call, sizeof(packet_send_call));
02210 memcpy(buffsend + 53, &public.sin_addr, sizeof(public.sin_addr));
02211
02212 buffsend[49] = (us.sin_port & 0x00ff);
02213 buffsend[50] = (us.sin_port & 0xff00) >> 8;
02214
02215 buffsend[52] = (rtcpsin_port & 0x00ff);
02216 buffsend[51] = (rtcpsin_port & 0xff00) >> 8;
02217
02218 buffsend[40] = codec;
02219 buffsend[41] = codec;
02220 if (sub->owner->readformat == AST_FORMAT_ULAW)
02221 buffsend[42] = 1;
02222 else if (sub->owner->readformat == AST_FORMAT_ALAW)
02223 buffsend[42] = 1;
02224 else if (sub->owner->readformat == AST_FORMAT_G723_1)
02225 buffsend[42] = 2;
02226 else if (sub->owner->readformat == AST_FORMAT_G729A)
02227 buffsend[42] = 2;
02228 else
02229 ast_log(LOG_WARNING, "Unsupported codec %s!\n",
02230 ast_getformatname(sub->owner->readformat));
02231
02232 buffsend[45] = (htons(sin.sin_port) & 0xff00) >> 8;
02233 buffsend[46] = (htons(sin.sin_port) & 0x00ff);
02234 buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
02235 buffsend[48] = (rtcpsin_port & 0x00ff);
02236 send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
02237 sub->parent->parent->session);
02238 }
02239 ast_mutex_unlock(&sub->lock);
02240 }
02241
02242 static void SendDialTone(struct unistimsession *pte)
02243 {
02244 int i;
02245
02246 if (ast_strlen_zero(pte->device->country)) {
02247 if (unistimdebug)
02248 ast_verb(0, "No country defined, using US tone\n");
02249 send_tone(pte, 350, 440);
02250 return;
02251 }
02252 if (strlen(pte->device->country) != 2) {
02253 if (unistimdebug)
02254 ast_verb(0, "Country code != 2 char, using US tone\n");
02255 send_tone(pte, 350, 440);
02256 return;
02257 }
02258 i = 0;
02259 while (frequency[i].freq1) {
02260 if ((frequency[i].country[0] == pte->device->country[0]) &&
02261 (frequency[i].country[1] == pte->device->country[1])) {
02262 if (unistimdebug)
02263 ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
02264 frequency[i].country, frequency[i].freq1, frequency[i].freq2);
02265 send_tone(pte, frequency[i].freq1, frequency[i].freq2);
02266 }
02267 i++;
02268 }
02269 }
02270
02271 static void handle_dial_page(struct unistimsession *pte)
02272 {
02273 pte->state = STATE_DIALPAGE;
02274 if (pte->device->call_forward[0] == -1) {
02275 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
02276 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
02277 send_text_status(pte, "ForwardCancel BackSpcErase");
02278 if (pte->device->call_forward[1] != 0) {
02279 char tmp[TEXT_LENGTH_MAX + 1];
02280
02281 ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
02282 sizeof(pte->device->phone_number));
02283 pte->device->size_phone_number = strlen(pte->device->phone_number);
02284 if (pte->device->size_phone_number > 15)
02285 pte->device->size_phone_number = 15;
02286 strcpy(tmp, "Number : ...............");
02287 memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
02288
02289 if (pte->device->height == 1) {
02290 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
02291 send_blink_cursor(pte);
02292 send_cursor_pos(pte,
02293 (unsigned char) (TEXT_LINE0 + 0x09 +
02294 pte->device->size_phone_number));
02295 } else {
02296 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
02297 send_blink_cursor(pte);
02298 send_cursor_pos(pte,
02299 (unsigned char) (TEXT_LINE2 + 0x09 +
02300 pte->device->size_phone_number));
02301 }
02302
02303 send_led_update(pte, 0);
02304 return;
02305 }
02306 } else {
02307 if ((pte->device->output == OUTPUT_HANDSET) &&
02308 (pte->device->receiver_state == STATE_ONHOOK))
02309 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02310 else
02311 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02312 SendDialTone(pte);
02313
02314 if (pte->device->height > 1) {
02315 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
02316 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
02317 }
02318 send_text_status(pte, "Call Redial BackSpcErase");
02319 }
02320
02321 if (pte->device->height == 1) {
02322 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
02323 send_blink_cursor(pte);
02324 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
02325 } else {
02326 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
02327 send_blink_cursor(pte);
02328 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
02329 }
02330 pte->device->size_phone_number = 0;
02331 pte->device->phone_number[0] = 0;
02332 change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
02333 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
02334 pte->device->missed_call = 0;
02335 send_led_update(pte, 0);
02336 return;
02337 }
02338
02339
02340 static void TransferCallStep1(struct unistimsession *pte)
02341 {
02342 struct unistim_subchannel *sub;
02343 struct unistim_line *p = pte->device->lines;
02344
02345 sub = p->subs[SUB_REAL];
02346
02347 if (!sub->owner) {
02348 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02349 return;
02350 }
02351 if (p->subs[SUB_THREEWAY]) {
02352 if (unistimdebug)
02353 ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
02354 if (p->subs[SUB_THREEWAY]->owner)
02355 ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
02356 else
02357 ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
02358 return;
02359 }
02360
02361 if (pte->device->moh)
02362 ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
02363 else {
02364 if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
02365 ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
02366 pte->device->lines->musicclass, NULL);
02367 pte->device->moh = 1;
02368 } else {
02369 ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
02370 return;
02371 }
02372 }
02373
02374 if (!pte->device->silence_generator) {
02375 pte->device->silence_generator =
02376 ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
02377 if (pte->device->silence_generator == NULL)
02378 ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
02379 else if (unistimdebug)
02380 ast_verb(0, "Starting silence generator\n");
02381 }
02382 handle_dial_page(pte);
02383 }
02384
02385
02386 static void HandleCallOutgoing(struct unistimsession *s)
02387 {
02388 struct ast_channel *c;
02389 struct unistim_subchannel *sub;
02390 pthread_t t;
02391 s->state = STATE_CALL;
02392 sub = s->device->lines->subs[SUB_REAL];
02393 if (!sub) {
02394 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
02395 return;
02396 }
02397 if (!sub->owner) {
02398 c = unistim_new(sub, AST_STATE_DOWN, NULL);
02399 if (c) {
02400
02401 if (!sub->rtp)
02402 start_rtp(sub);
02403 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02404
02405 if (s->device->height == 1) {
02406 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
02407 } else {
02408 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
02409 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
02410 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
02411 }
02412 send_text_status(s, "Hangup");
02413
02414
02415 if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
02416 display_last_error("Unable to create switch thread");
02417 ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
02418 }
02419 } else
02420 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
02421 sub->parent->name, s->device->name);
02422 } else {
02423
02424 if (s->device->moh) {
02425 struct unistim_subchannel *subchannel;
02426 struct unistim_line *p = s->device->lines;
02427 subchannel = p->subs[SUB_REAL];
02428
02429 if (!subchannel->owner) {
02430 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02431 return;
02432 }
02433 if (p->subs[SUB_THREEWAY]) {
02434 ast_log(LOG_WARNING,
02435 "Can't transfer while an another transfer is taking place\n");
02436 return;
02437 }
02438 if (!alloc_sub(p, SUB_THREEWAY)) {
02439 ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
02440 return;
02441 }
02442
02443 if (s->device->silence_generator) {
02444 if (unistimdebug)
02445 ast_verb(0, "Stopping silence generator\n");
02446 ast_channel_stop_silence_generator(subchannel->owner,
02447 s->device->silence_generator);
02448 s->device->silence_generator = NULL;
02449 }
02450 send_tone(s, 0, 0);
02451
02452 c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
02453 if (!c) {
02454 ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
02455 return;
02456 }
02457
02458 swap_subs(p, SUB_THREEWAY, SUB_REAL);
02459 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02460
02461 if (s->device->height == 1) {
02462 send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
02463 } else {
02464 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
02465 send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
02466 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
02467 }
02468 send_text_status(s, "TransfrCancel");
02469
02470 if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
02471 ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
02472 ast_hangup(c);
02473 return;
02474 }
02475 if (unistimdebug)
02476 ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
02477 p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
02478 p->subs[SUB_THREEWAY]->subtype);
02479 } else
02480 ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
02481 }
02482 return;
02483 }
02484
02485
02486 static void HandleCallIncoming(struct unistimsession *s)
02487 {
02488 struct unistim_subchannel *sub;
02489 s->state = STATE_CALL;
02490 s->device->missed_call = 0;
02491 send_no_ring(s);
02492 sub = s->device->lines->subs[SUB_REAL];
02493 if (!sub) {
02494 ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
02495 return;
02496 } else if (unistimdebug)
02497 ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
02498 s->device->name);
02499 start_rtp(sub);
02500 if (!sub->rtp)
02501 ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
02502 s->device->name);
02503 ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
02504 send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
02505 send_text_status(s, "Hangup Transf");
02506 send_start_timer(s);
02507
02508 if ((s->device->output == OUTPUT_HANDSET) &&
02509 (s->device->receiver_state == STATE_ONHOOK))
02510 send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
02511 else
02512 send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
02513 s->device->start_call_timestamp = time(0);
02514 write_history(s, 'i', 0);
02515 return;
02516 }
02517
02518 static int unistim_do_senddigit(struct unistimsession *pte, char digit)
02519 {
02520 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
02521 struct unistim_subchannel *sub;
02522 sub = pte->device->lines->subs[SUB_REAL];
02523 if (!sub->owner || sub->alreadygone) {
02524 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
02525 return -1;
02526 }
02527
02528
02529 ast_queue_frame(sub->owner, &f);
02530
02531 if (unistimdebug)
02532 ast_verb(0, "Send Digit %c\n", digit);
02533 switch (digit) {
02534 case '0':
02535 send_tone(pte, 941, 1336);
02536 break;
02537 case '1':
02538 send_tone(pte, 697, 1209);
02539 break;
02540 case '2':
02541 send_tone(pte, 697, 1336);
02542 break;
02543 case '3':
02544 send_tone(pte, 697, 1477);
02545 break;
02546 case '4':
02547 send_tone(pte, 770, 1209);
02548 break;
02549 case '5':
02550 send_tone(pte, 770, 1336);
02551 break;
02552 case '6':
02553 send_tone(pte, 770, 1477);
02554 break;
02555 case '7':
02556 send_tone(pte, 852, 1209);
02557 break;
02558 case '8':
02559 send_tone(pte, 852, 1336);
02560 break;
02561 case '9':
02562 send_tone(pte, 852, 1477);
02563 break;
02564 case 'A':
02565 send_tone(pte, 697, 1633);
02566 break;
02567 case 'B':
02568 send_tone(pte, 770, 1633);
02569 break;
02570 case 'C':
02571 send_tone(pte, 852, 1633);
02572 break;
02573 case 'D':
02574 send_tone(pte, 941, 1633);
02575 break;
02576 case '*':
02577 send_tone(pte, 941, 1209);
02578 break;
02579 case '#':
02580 send_tone(pte, 941, 1477);
02581 break;
02582 default:
02583 send_tone(pte, 500, 2000);
02584 }
02585 usleep(150000);
02586 send_tone(pte, 0, 0);
02587 return 0;
02588 }
02589
02590 static void key_call(struct unistimsession *pte, char keycode)
02591 {
02592 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02593 if (keycode == KEY_SHARP)
02594 keycode = '#';
02595 else if (keycode == KEY_STAR)
02596 keycode = '*';
02597 else
02598 keycode -= 0x10;
02599 unistim_do_senddigit(pte, keycode);
02600 return;
02601 }
02602 switch (keycode) {
02603 case KEY_HANGUP:
02604 case KEY_FUNC1:
02605 close_call(pte);
02606 break;
02607 case KEY_FUNC2:
02608 TransferCallStep1(pte);
02609 break;
02610 case KEY_HEADPHN:
02611 if (pte->device->output == OUTPUT_HEADPHONE)
02612 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02613 else
02614 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02615 break;
02616 case KEY_LOUDSPK:
02617 if (pte->device->output != OUTPUT_SPEAKER)
02618 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02619 else
02620 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02621 MUTE_OFF);
02622 break;
02623 case KEY_MUTE:
02624 if (!pte->device->moh) {
02625 if (pte->device->mute == MUTE_ON)
02626 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02627 else
02628 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
02629 break;
02630 }
02631 case KEY_ONHOLD:
02632 {
02633 struct unistim_subchannel *sub;
02634 struct ast_channel *bridgepeer = NULL;
02635 sub = pte->device->lines->subs[SUB_REAL];
02636 if (!sub->owner) {
02637 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02638 return;
02639 }
02640 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
02641 if (pte->device->moh) {
02642 ast_moh_stop(bridgepeer);
02643 pte->device->moh = 0;
02644 send_select_output(pte, pte->device->output, pte->device->volume,
02645 MUTE_OFF);
02646 } else {
02647 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
02648 pte->device->moh = 1;
02649 send_select_output(pte, pte->device->output, pte->device->volume,
02650 MUTE_ON);
02651 }
02652 } else
02653 ast_log(LOG_WARNING,
02654 "Unable to find peer subchannel for music on hold\n");
02655 break;
02656 }
02657 }
02658 return;
02659 }
02660
02661 static void key_ringing(struct unistimsession *pte, char keycode)
02662 {
02663 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
02664 HandleCallIncoming(pte);
02665 return;
02666 }
02667 switch (keycode) {
02668 case KEY_HANGUP:
02669 case KEY_FUNC4:
02670 IgnoreCall(pte);
02671 break;
02672 case KEY_FUNC1:
02673 HandleCallIncoming(pte);
02674 break;
02675 }
02676 return;
02677 }
02678
02679 static void Keyfavorite(struct unistimsession *pte, char keycode)
02680 {
02681 int fav;
02682
02683 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
02684 ast_log(LOG_WARNING, "It's not a favorite key\n");
02685 return;
02686 }
02687 if (keycode == KEY_FAV0)
02688 return;
02689 fav = keycode - KEY_FAV0;
02690 if (pte->device->softkeyicon[fav] == 0)
02691 return;
02692 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
02693 sizeof(pte->device->phone_number));
02694 HandleCallOutgoing(pte);
02695 return;
02696 }
02697
02698 static void key_dial_page(struct unistimsession *pte, char keycode)
02699 {
02700 if (keycode == KEY_FUNC3) {
02701 if (pte->device->size_phone_number <= 1)
02702 keycode = KEY_FUNC4;
02703 else {
02704 pte->device->size_phone_number -= 2;
02705 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
02706 }
02707 }
02708 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02709 char tmpbuf[] = "Number : ...............";
02710 int i = 0;
02711
02712 if (pte->device->size_phone_number >= 15)
02713 return;
02714 if (pte->device->size_phone_number == 0)
02715 send_tone(pte, 0, 0);
02716 while (i < pte->device->size_phone_number) {
02717 tmpbuf[i + 9] = pte->device->phone_number[i];
02718 i++;
02719 }
02720 if (keycode == KEY_SHARP)
02721 keycode = '#';
02722 else if (keycode == KEY_STAR)
02723 keycode = '*';
02724 else
02725 keycode -= 0x10;
02726 tmpbuf[i + 9] = keycode;
02727 pte->device->phone_number[i] = keycode;
02728 pte->device->size_phone_number++;
02729 pte->device->phone_number[i + 1] = 0;
02730 if (pte->device->height == 1) {
02731 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
02732 } else {
02733 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02734 }
02735 send_blink_cursor(pte);
02736 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
02737 return;
02738 }
02739 if (keycode == KEY_FUNC4) {
02740
02741 pte->device->size_phone_number = 0;
02742 if (pte->device->height == 1) {
02743 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
02744 send_blink_cursor(pte);
02745 send_cursor_pos(pte, TEXT_LINE0 + 0x09);
02746 } else {
02747 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
02748 send_blink_cursor(pte);
02749 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
02750 }
02751 return;
02752 }
02753
02754 if (pte->device->call_forward[0] == -1) {
02755 if (keycode == KEY_FUNC1) {
02756 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
02757 sizeof(pte->device->call_forward));
02758 show_main_page(pte);
02759 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
02760 pte->device->call_forward[0] = '\0';
02761 show_main_page(pte);
02762 }
02763 return;
02764 }
02765 switch (keycode) {
02766 case KEY_FUNC2:
02767 if (ast_strlen_zero(pte->device->redial_number))
02768 break;
02769 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
02770 sizeof(pte->device->phone_number));
02771 case KEY_FUNC1:
02772 HandleCallOutgoing(pte);
02773 break;
02774 case KEY_HANGUP:
02775 if (pte->device->lines->subs[SUB_REAL]->owner) {
02776
02777 if (pte->device->silence_generator) {
02778 if (unistimdebug)
02779 ast_verb(0, "Stopping silence generator\n");
02780 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
02781 owner, pte->device->silence_generator);
02782 pte->device->silence_generator = NULL;
02783 }
02784 send_tone(pte, 0, 0);
02785 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
02786 pte->device->moh = 0;
02787 pte->state = STATE_CALL;
02788
02789 if (pte->device->height == 1) {
02790 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
02791 } else {
02792 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
02793 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
02794 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
02795 }
02796 send_text_status(pte, "Hangup Transf");
02797 } else
02798 show_main_page(pte);
02799 break;
02800 case KEY_FAV1:
02801 case KEY_FAV2:
02802 case KEY_FAV3:
02803 case KEY_FAV4:
02804 case KEY_FAV5:
02805 Keyfavorite(pte, keycode);
02806 break;
02807 case KEY_LOUDSPK:
02808 if (pte->device->output == OUTPUT_SPEAKER) {
02809 if (pte->device->receiver_state == STATE_OFFHOOK)
02810 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02811 MUTE_OFF);
02812 else
02813 show_main_page(pte);
02814 } else
02815 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02816 break;
02817 case KEY_HEADPHN:
02818 if (pte->device->output == OUTPUT_HEADPHONE) {
02819 if (pte->device->receiver_state == STATE_OFFHOOK)
02820 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02821 else
02822 show_main_page(pte);
02823 } else
02824 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02825 break;
02826 }
02827 return;
02828 }
02829
02830 #define SELECTCODEC_START_ENTRY_POS 15
02831 #define SELECTCODEC_MAX_LENGTH 2
02832 #define SELECTCODEC_MSG "Codec number : .."
02833 static void HandleSelectCodec(struct unistimsession *pte)
02834 {
02835 char buf[30], buf2[5];
02836
02837 pte->state = STATE_SELECTCODEC;
02838 strcpy(buf, "Using codec ");
02839 sprintf(buf2, "%d", pte->device->codec_number);
02840 strcat(buf, buf2);
02841 strcat(buf, " (G711u=0,");
02842
02843 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
02844 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
02845 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02846 send_blink_cursor(pte);
02847 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02848 pte->size_buff_entry = 0;
02849 send_text_status(pte, "Select BackSpcErase Cancel");
02850 return;
02851 }
02852
02853 static void key_select_codec(struct unistimsession *pte, char keycode)
02854 {
02855 if (keycode == KEY_FUNC2) {
02856 if (pte->size_buff_entry <= 1)
02857 keycode = KEY_FUNC3;
02858 else {
02859 pte->size_buff_entry -= 2;
02860 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02861 }
02862 }
02863 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02864 char tmpbuf[] = SELECTCODEC_MSG;
02865 int i = 0;
02866
02867 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
02868 return;
02869
02870 while (i < pte->size_buff_entry) {
02871 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
02872 i++;
02873 }
02874 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
02875 pte->buff_entry[i] = keycode - 0x10;
02876 pte->size_buff_entry++;
02877 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
02878 send_blink_cursor(pte);
02879 send_cursor_pos(pte,
02880 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
02881 return;
02882 }
02883
02884 switch (keycode) {
02885 case KEY_FUNC1:
02886 if (pte->size_buff_entry == 1)
02887 pte->device->codec_number = pte->buff_entry[0] - 48;
02888 else if (pte->size_buff_entry == 2)
02889 pte->device->codec_number =
02890 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
02891 show_main_page(pte);
02892 break;
02893 case KEY_FUNC3:
02894 pte->size_buff_entry = 0;
02895 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02896 send_blink_cursor(pte);
02897 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02898 break;
02899 case KEY_HANGUP:
02900 case KEY_FUNC4:
02901 show_main_page(pte);
02902 break;
02903 }
02904 return;
02905 }
02906
02907 #define SELECTEXTENSION_START_ENTRY_POS 0
02908 #define SELECTEXTENSION_MAX_LENGTH 10
02909 #define SELECTEXTENSION_MSG ".........."
02910 static void ShowExtensionPage(struct unistimsession *pte)
02911 {
02912 pte->state = STATE_EXTENSION;
02913
02914 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
02915 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
02916 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
02917 send_blink_cursor(pte);
02918 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
02919 send_text_status(pte, "Enter BackSpcErase");
02920 pte->size_buff_entry = 0;
02921 return;
02922 }
02923
02924 static void key_select_extension(struct unistimsession *pte, char keycode)
02925 {
02926 if (keycode == KEY_FUNC2) {
02927 if (pte->size_buff_entry <= 1)
02928 keycode = KEY_FUNC3;
02929 else {
02930 pte->size_buff_entry -= 2;
02931 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02932 }
02933 }
02934 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02935 char tmpbuf[] = SELECTEXTENSION_MSG;
02936 int i = 0;
02937
02938 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
02939 return;
02940
02941 while (i < pte->size_buff_entry) {
02942 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
02943 i++;
02944 }
02945 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
02946 pte->buff_entry[i] = keycode - 0x10;
02947 pte->size_buff_entry++;
02948 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02949 send_blink_cursor(pte);
02950 send_cursor_pos(pte,
02951 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
02952 i));
02953 return;
02954 }
02955
02956 switch (keycode) {
02957 case KEY_FUNC1:
02958 if (pte->size_buff_entry < 1)
02959 return;
02960 if (autoprovisioning == AUTOPROVISIONING_TN) {
02961 struct unistim_device *d;
02962
02963
02964 ast_mutex_lock(&devicelock);
02965 d = devices;
02966 pte->buff_entry[pte->size_buff_entry] = '\0';
02967 while (d) {
02968 if (d->id[0] == 'T') {
02969
02970 if (!strcmp((d->id) + 1, pte->buff_entry)) {
02971 pte->device = d;
02972 d->session = pte;
02973 d->codec_number = DEFAULT_CODEC;
02974 d->pos_fav = 0;
02975 d->missed_call = 0;
02976 d->receiver_state = STATE_ONHOOK;
02977 strcpy(d->id, pte->macaddr);
02978 pte->device->extension_number[0] = 'T';
02979 pte->device->extension = EXTENSION_TN;
02980 ast_copy_string((pte->device->extension_number) + 1,
02981 pte->buff_entry, pte->size_buff_entry + 1);
02982 ast_mutex_unlock(&devicelock);
02983 show_main_page(pte);
02984 refresh_all_favorite(pte);
02985 return;
02986 }
02987 }
02988 d = d->next;
02989 }
02990 ast_mutex_unlock(&devicelock);
02991 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
02992 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
02993 send_cursor_pos(pte,
02994 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
02995 pte->size_buff_entry));
02996 send_blink_cursor(pte);
02997 } else {
02998 ast_copy_string(pte->device->extension_number, pte->buff_entry,
02999 pte->size_buff_entry + 1);
03000 if (RegisterExtension(pte)) {
03001 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
03002 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
03003 send_cursor_pos(pte,
03004 (unsigned char) (TEXT_LINE2 +
03005 SELECTEXTENSION_START_ENTRY_POS +
03006 pte->size_buff_entry));
03007 send_blink_cursor(pte);
03008 } else
03009 show_main_page(pte);
03010 }
03011 break;
03012 case KEY_FUNC3:
03013 pte->size_buff_entry = 0;
03014 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
03015 send_blink_cursor(pte);
03016 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
03017 break;
03018 }
03019 return;
03020 }
03021
03022 static int ReformatNumber(char *number)
03023 {
03024 int pos = 0, i = 0, size = strlen(number);
03025
03026 for (; i < size; i++) {
03027 if ((number[i] >= '0') && (number[i] <= '9')) {
03028 if (i == pos) {
03029 pos++;
03030 continue;
03031 }
03032 number[pos] = number[i];
03033 pos++;
03034 }
03035 }
03036 number[pos] = 0;
03037 return pos;
03038 }
03039
03040 static void show_entry_history(struct unistimsession *pte, FILE ** f)
03041 {
03042 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
03043 func3[10];
03044
03045 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03046 display_last_error("Can't read history date entry");
03047 fclose(*f);
03048 return;
03049 }
03050 line[sizeof(line) - 1] = '\0';
03051 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
03052 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03053 display_last_error("Can't read callerid entry");
03054 fclose(*f);
03055 return;
03056 }
03057 line[sizeof(line) - 1] = '\0';
03058 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
03059 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
03060 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
03061 display_last_error("Can't read callername entry");
03062 fclose(*f);
03063 return;
03064 }
03065 line[sizeof(line) - 1] = '\0';
03066 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
03067 fclose(*f);
03068
03069 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
03070 pte->buff_entry[1]);
03071 send_texttitle(pte, line);
03072
03073 if (pte->buff_entry[2] == 1)
03074 strcpy(func1, " ");
03075 else
03076 strcpy(func1, "Prvious");
03077 if (pte->buff_entry[2] >= pte->buff_entry[1])
03078 strcpy(func2, " ");
03079 else
03080 strcpy(func2, "Next ");
03081 if (ReformatNumber(pte->device->lst_cid))
03082 strcpy(func3, "Redial ");
03083 else
03084 strcpy(func3, " ");
03085 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
03086 send_text_status(pte, status);
03087 }
03088
03089 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
03090 {
03091 char tmp[AST_CONFIG_MAX_PATH];
03092 char count;
03093
03094 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
03095 USTM_LOG_DIR, pte->device->name, way);
03096 *f = fopen(tmp, "r");
03097 if (!*f) {
03098 display_last_error("Unable to open history file");
03099 return 0;
03100 }
03101 if (fread(&count, 1, 1, *f) != 1) {
03102 display_last_error("Unable to read history header - display.");
03103 fclose(*f);
03104 return 0;
03105 }
03106 if (count > MAX_ENTRY_LOG) {
03107 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
03108 count, MAX_ENTRY_LOG);
03109 fclose(*f);
03110 return 0;
03111 }
03112 return count;
03113 }
03114
03115 static void show_history(struct unistimsession *pte, char way)
03116 {
03117 FILE *f;
03118 char count;
03119
03120 if (!pte->device)
03121 return;
03122 if (!pte->device->callhistory)
03123 return;
03124 count = OpenHistory(pte, way, &f);
03125 if (!count)
03126 return;
03127 pte->buff_entry[0] = way;
03128 pte->buff_entry[1] = count;
03129 pte->buff_entry[2] = 1;
03130 show_entry_history(pte, &f);
03131 pte->state = STATE_HISTORY;
03132 }
03133
03134 static void show_main_page(struct unistimsession *pte)
03135 {
03136 char tmpbuf[TEXT_LENGTH_MAX + 1];
03137
03138
03139 if ((pte->device->extension == EXTENSION_ASK) &&
03140 (ast_strlen_zero(pte->device->extension_number))) {
03141 ShowExtensionPage(pte);
03142 return;
03143 }
03144
03145 pte->state = STATE_MAINPAGE;
03146
03147 send_tone(pte, 0, 0);
03148 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
03149 pte->device->lines->lastmsgssent = 0;
03150 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
03151 pte->device->softkeylabel[pte->device->softkeylinepos]);
03152 if (!ast_strlen_zero(pte->device->call_forward)) {
03153 if (pte->device->height == 1) {
03154 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Forwarding ON");
03155 } else {
03156 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
03157 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
03158 }
03159 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
03160 send_text_status(pte, "Dial Redial NoForwd");
03161 } else {
03162 if ((pte->device->extension == EXTENSION_ASK) ||
03163 (pte->device->extension == EXTENSION_TN))
03164 send_text_status(pte, "Dial Redial ForwardUnregis");
03165 else
03166 send_text_status(pte, "Dial Redial Forward");
03167
03168 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
03169 if (pte->device->missed_call == 0)
03170 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
03171 else {
03172 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
03173 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
03174 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
03175 }
03176 }
03177 if (ast_strlen_zero(pte->device->maintext2)) {
03178 strcpy(tmpbuf, "IP : ");
03179 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03180 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03181 } else
03182 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
03183 send_texttitle(pte, pte->device->titledefault);
03184 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
03185 }
03186
03187 static void key_main_page(struct unistimsession *pte, char keycode)
03188 {
03189 if (pte->device->missed_call) {
03190 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03191 pte->device->missed_call = 0;
03192 }
03193 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03194 handle_dial_page(pte);
03195 key_dial_page(pte, keycode);
03196 return;
03197 }
03198 switch (keycode) {
03199 case KEY_FUNC1:
03200 handle_dial_page(pte);
03201 break;
03202 case KEY_FUNC2:
03203 if (ast_strlen_zero(pte->device->redial_number))
03204 break;
03205 if ((pte->device->output == OUTPUT_HANDSET) &&
03206 (pte->device->receiver_state == STATE_ONHOOK))
03207 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03208 else
03209 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03210
03211 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03212 sizeof(pte->device->phone_number));
03213 HandleCallOutgoing(pte);
03214 break;
03215 case KEY_FUNC3:
03216 if (!ast_strlen_zero(pte->device->call_forward)) {
03217
03218 memmove(pte->device->call_forward + 1, pte->device->call_forward,
03219 sizeof(pte->device->call_forward));
03220 pte->device->call_forward[0] = '\0';
03221 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03222 pte->device->output = OUTPUT_HANDSET;
03223 show_main_page(pte);
03224 break;
03225 }
03226 pte->device->call_forward[0] = -1;
03227 handle_dial_page(pte);
03228 break;
03229 case KEY_FUNC4:
03230 if (pte->device->extension == EXTENSION_ASK) {
03231 UnregisterExtension(pte);
03232 pte->device->extension_number[0] = '\0';
03233 ShowExtensionPage(pte);
03234 } else if (pte->device->extension == EXTENSION_TN) {
03235 ast_mutex_lock(&devicelock);
03236 strcpy(pte->device->id, pte->device->extension_number);
03237 pte->buff_entry[0] = '\0';
03238 pte->size_buff_entry = 0;
03239 pte->device->session = NULL;
03240 pte->device = NULL;
03241 ast_mutex_unlock(&devicelock);
03242 ShowExtensionPage(pte);
03243 }
03244 break;
03245 case KEY_FAV0:
03246 handle_dial_page(pte);
03247 break;
03248 case KEY_FAV1:
03249 case KEY_FAV2:
03250 case KEY_FAV3:
03251 case KEY_FAV4:
03252 case KEY_FAV5:
03253 if ((pte->device->output == OUTPUT_HANDSET) &&
03254 (pte->device->receiver_state == STATE_ONHOOK))
03255 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03256 else
03257 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03258 Keyfavorite(pte, keycode);
03259 break;
03260 case KEY_CONF:
03261 HandleSelectCodec(pte);
03262 break;
03263 case KEY_LOUDSPK:
03264 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03265 handle_dial_page(pte);
03266 break;
03267 case KEY_HEADPHN:
03268 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03269 handle_dial_page(pte);
03270 break;
03271 case KEY_SNDHIST:
03272 show_history(pte, 'o');
03273 break;
03274 case KEY_RCVHIST:
03275 show_history(pte, 'i');
03276 break;
03277 }
03278 return;
03279 }
03280
03281 static void key_history(struct unistimsession *pte, char keycode)
03282 {
03283 FILE *f;
03284 char count;
03285 long offset;
03286
03287 switch (keycode) {
03288 case KEY_UP:
03289 case KEY_LEFT:
03290 case KEY_FUNC1:
03291 if (pte->buff_entry[2] <= 1)
03292 return;
03293 pte->buff_entry[2]--;
03294 count = OpenHistory(pte, pte->buff_entry[0], &f);
03295 if (!count)
03296 return;
03297 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03298 if (fseek(f, offset, SEEK_CUR)) {
03299 display_last_error("Unable to seek history entry.");
03300 fclose(f);
03301 return;
03302 }
03303 show_entry_history(pte, &f);
03304 break;
03305 case KEY_DOWN:
03306 case KEY_RIGHT:
03307 case KEY_FUNC2:
03308 if (pte->buff_entry[2] >= pte->buff_entry[1])
03309 return;
03310 pte->buff_entry[2]++;
03311 count = OpenHistory(pte, pte->buff_entry[0], &f);
03312 if (!count)
03313 return;
03314 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03315 if (fseek(f, offset, SEEK_CUR)) {
03316 display_last_error("Unable to seek history entry.");
03317 fclose(f);
03318 return;
03319 }
03320 show_entry_history(pte, &f);
03321 break;
03322 case KEY_FUNC3:
03323 if (!ReformatNumber(pte->device->lst_cid))
03324 break;
03325 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
03326 sizeof(pte->device->redial_number));
03327 key_main_page(pte, KEY_FUNC2);
03328 break;
03329 case KEY_FUNC4:
03330 case KEY_HANGUP:
03331 show_main_page(pte);
03332 break;
03333 case KEY_SNDHIST:
03334 if (pte->buff_entry[0] == 'i')
03335 show_history(pte, 'o');
03336 else
03337 show_main_page(pte);
03338 break;
03339 case KEY_RCVHIST:
03340 if (pte->buff_entry[0] == 'i')
03341 show_main_page(pte);
03342 else
03343 show_history(pte, 'i');
03344 break;
03345 }
03346 return;
03347 }
03348
03349 static void init_phone_step2(struct unistimsession *pte)
03350 {
03351 BUFFSEND;
03352 if (unistimdebug)
03353 ast_verb(0, "Sending S4\n");
03354 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
03355 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
03356 send_date_time2(pte);
03357 send_date_time3(pte);
03358 if (unistimdebug)
03359 ast_verb(0, "Sending S7\n");
03360 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03361 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03362 if (unistimdebug)
03363 ast_verb(0, "Sending Contrast\n");
03364 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
03365 if (pte->device != NULL)
03366 buffsend[9] = pte->device->contrast;
03367 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
03368
03369 if (unistimdebug)
03370 ast_verb(0, "Sending S9\n");
03371 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
03372 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
03373 send_no_ring(pte);
03374
03375 if (unistimdebug)
03376 ast_verb(0, "Sending S7\n");
03377 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03378 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03379 send_led_update(pte, 0);
03380 send_ping(pte);
03381 if (pte->state < STATE_MAINPAGE) {
03382 if (autoprovisioning == AUTOPROVISIONING_TN) {
03383 ShowExtensionPage(pte);
03384 return;
03385 } else {
03386 int i;
03387 char tmp[30];
03388
03389 for (i = 1; i < 6; i++)
03390 send_favorite(i, 0, pte, "");
03391 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
03392 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
03393 strcpy(tmp, "MAC = ");
03394 strcat(tmp, pte->macaddr);
03395 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
03396 send_text_status(pte, "");
03397 send_texttitle(pte, "UNISTIM for*");
03398 return;
03399 }
03400 }
03401 show_main_page(pte);
03402 refresh_all_favorite(pte);
03403 if (unistimdebug)
03404 ast_verb(0, "Sending arrow\n");
03405 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
03406 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
03407 return;
03408 }
03409
03410 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
03411 {
03412 char tmpbuf[255];
03413 if (memcmp
03414 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
03415 sizeof(packet_recv_resume_connection_with_server)) == 0) {
03416 rcv_resume_connection_with_server(pte);
03417 return;
03418 }
03419 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
03420 0) {
03421 buf[size] = 0;
03422 if (unistimdebug)
03423 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
03424 init_phone_step2(pte);
03425 return;
03426 }
03427 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
03428 rcv_mac_addr(pte, buf);
03429 return;
03430 }
03431 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
03432 if (unistimdebug)
03433 ast_verb(0, "R2 received\n");
03434 return;
03435 }
03436
03437 if (pte->state < STATE_MAINPAGE) {
03438 if (unistimdebug)
03439 ast_verb(0, "Request not authorized in this state\n");
03440 return;
03441 }
03442 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
03443 char keycode = buf[13];
03444
03445 if (unistimdebug)
03446 ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
03447 pte->state);
03448
03449 switch (pte->state) {
03450 case STATE_INIT:
03451 if (unistimdebug)
03452 ast_verb(0, "No keys allowed in the init state\n");
03453 break;
03454 case STATE_AUTHDENY:
03455 if (unistimdebug)
03456 ast_verb(0, "No keys allowed in authdeny state\n");
03457 break;
03458 case STATE_MAINPAGE:
03459 key_main_page(pte, keycode);
03460 break;
03461 case STATE_DIALPAGE:
03462 key_dial_page(pte, keycode);
03463 break;
03464 case STATE_RINGING:
03465 key_ringing(pte, keycode);
03466 break;
03467 case STATE_CALL:
03468 key_call(pte, keycode);
03469 break;
03470 case STATE_EXTENSION:
03471 key_select_extension(pte, keycode);
03472 break;
03473 case STATE_SELECTCODEC:
03474 key_select_codec(pte, keycode);
03475 break;
03476 case STATE_HISTORY:
03477 key_history(pte, keycode);
03478 break;
03479 default:
03480 ast_log(LOG_WARNING, "Key : Unknown state\n");
03481 }
03482 return;
03483 }
03484 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
03485 if (unistimdebug)
03486 ast_verb(0, "Handset off hook\n");
03487 if (!pte->device)
03488 return;
03489 pte->device->receiver_state = STATE_OFFHOOK;
03490 if (pte->device->output == OUTPUT_HEADPHONE)
03491 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03492 else
03493 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03494 if (pte->state == STATE_RINGING)
03495 HandleCallIncoming(pte);
03496 else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
03497 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03498 else if (pte->state == STATE_EXTENSION)
03499 return;
03500 else {
03501 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03502 handle_dial_page(pte);
03503 }
03504 return;
03505 }
03506 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
03507 if (unistimdebug)
03508 ast_verb(0, "Handset on hook\n");
03509 if (!pte->device)
03510 return;
03511 pte->device->receiver_state = STATE_ONHOOK;
03512 if (pte->state == STATE_CALL)
03513 close_call(pte);
03514 else if (pte->device->lines->subs[SUB_REAL]->owner)
03515 close_call(pte);
03516 else if (pte->state == STATE_EXTENSION)
03517 return;
03518 else
03519 show_main_page(pte);
03520 return;
03521 }
03522 strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03523 strcat(tmpbuf, " Unknown request packet\n");
03524 if (unistimdebug)
03525 ast_debug(1, "%s", tmpbuf);
03526 return;
03527 }
03528
03529 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
03530 struct sockaddr_in *addr_from)
03531 {
03532 unsigned short *sbuf = (unsigned short *) buf;
03533 unsigned short seq;
03534 char tmpbuf[255];
03535
03536 strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
03537
03538 if (size < 10) {
03539 if (size == 0) {
03540 ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
03541 } else {
03542 ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
03543 }
03544 return;
03545 }
03546 if (sbuf[0] == 0xffff) {
03547 if (size != sizeof(packet_rcv_discovery)) {
03548 ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
03549 } else {
03550 if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
03551 if (unistimdebug)
03552 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
03553 if (pte) {
03554 if (pte->state == STATE_INIT) {
03555 if (unistimdebug)
03556 ast_verb(1, "Duplicated Discovery packet\n");
03557 send_raw_client(sizeof(packet_send_discovery_ack),
03558 packet_send_discovery_ack, addr_from, &pte->sout);
03559 pte->seq_phone = (short) 0x0000;
03560 } else {
03561 close_client(pte);
03562 if (create_client(addr_from))
03563 send_raw_client(sizeof(packet_send_discovery_ack),
03564 packet_send_discovery_ack, addr_from, &pte->sout);
03565 }
03566 } else {
03567
03568 if ((pte = create_client(addr_from)))
03569 send_raw_client(sizeof(packet_send_discovery_ack),
03570 packet_send_discovery_ack, addr_from, &pte->sout);
03571 }
03572 return;
03573 }
03574 ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
03575 }
03576 return;
03577 }
03578 if (!pte) {
03579 if (unistimdebug)
03580 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n",
03581 tmpbuf);
03582 return;
03583 }
03584
03585 if (sbuf[0] != 0) {
03586 ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
03587 return;
03588 }
03589 if (buf[5] != 2) {
03590 ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
03591 buf[5]);
03592 return;
03593 }
03594 seq = ntohs(sbuf[1]);
03595 if (buf[4] == 1) {
03596 ast_mutex_lock(&pte->lock);
03597 if (unistimdebug)
03598 ast_verb(6, "ACK received for packet #0x%.4x\n", seq);
03599 pte->nb_retransmit = 0;
03600
03601 if ((pte->last_seq_ack) + 1 == seq) {
03602 pte->last_seq_ack++;
03603 check_send_queue(pte);
03604 ast_mutex_unlock(&pte->lock);
03605 return;
03606 }
03607 if (pte->last_seq_ack > seq) {
03608 if (pte->last_seq_ack == 0xffff) {
03609 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
03610 pte->last_seq_ack = 0;
03611 } else
03612 ast_log(LOG_NOTICE,
03613 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
03614 tmpbuf, seq, pte->last_seq_ack);
03615 ast_mutex_unlock(&pte->lock);
03616 return;
03617 }
03618 if (pte->seq_server < seq) {
03619 ast_log(LOG_NOTICE,
03620 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
03621 tmpbuf, pte->seq_server);
03622 ast_mutex_unlock(&pte->lock);
03623 return;
03624 }
03625 if (unistimdebug)
03626 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
03627 tmpbuf, seq, pte->last_seq_ack);
03628 pte->last_seq_ack = seq;
03629 check_send_queue(pte);
03630 ast_mutex_unlock(&pte->lock);
03631 return;
03632 }
03633 if (buf[4] == 2) {
03634 if (unistimdebug)
03635 ast_verb(0, "Request received\n");
03636 if (pte->seq_phone == seq) {
03637
03638 buf[4] = 1;
03639 buf[5] = 1;
03640 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03641 pte->seq_phone++;
03642
03643 process_request(size, buf, pte);
03644 return;
03645 }
03646 if (pte->seq_phone > seq) {
03647 ast_log(LOG_NOTICE,
03648 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
03649 tmpbuf, seq, pte->seq_phone);
03650
03651
03652 buf[4] = 1;
03653 buf[5] = 1;
03654 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03655 return;
03656 }
03657 ast_log(LOG_NOTICE,
03658 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
03659 tmpbuf, seq, pte->seq_phone);
03660 return;
03661 }
03662 if (buf[4] == 0) {
03663 ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, seq);
03664 if (pte->last_seq_ack > seq) {
03665 ast_log(LOG_NOTICE,
03666 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
03667 tmpbuf, pte->last_seq_ack);
03668 return;
03669 }
03670 if (pte->seq_server < seq) {
03671 ast_log(LOG_NOTICE,
03672 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
03673 tmpbuf, pte->seq_server);
03674 return;
03675 }
03676 send_retransmit(pte);
03677 return;
03678 }
03679 ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
03680 tmpbuf, buf[4]);
03681 return;
03682 }
03683
03684 static struct unistimsession *channel_to_session(struct ast_channel *ast)
03685 {
03686 struct unistim_subchannel *sub;
03687 if (!ast) {
03688 ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
03689 return NULL;
03690 }
03691 if (!ast->tech_pvt) {
03692 ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
03693 return NULL;
03694 }
03695 sub = ast->tech_pvt;
03696
03697 if (!sub->parent) {
03698 ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
03699 return NULL;
03700 }
03701 if (!sub->parent->parent) {
03702 ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
03703 return NULL;
03704 }
03705 if (!sub->parent->parent->session) {
03706 ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
03707 return NULL;
03708 }
03709 return sub->parent->parent->session;
03710 }
03711
03712
03713
03714 static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
03715 {
03716 int res = 0;
03717 struct unistim_subchannel *sub;
03718 struct unistimsession *session;
03719
03720 session = channel_to_session(ast);
03721 if (!session) {
03722 ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03723 return -1;
03724 }
03725
03726 sub = ast->tech_pvt;
03727 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03728 ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
03729 ast->name);
03730 return -1;
03731 }
03732
03733 if (unistimdebug)
03734 ast_verb(3, "unistim_call(%s)\n", ast->name);
03735
03736 session->state = STATE_RINGING;
03737 Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
03738
03739 if (sub->owner) {
03740 if (sub->owner->connected.id.number.valid
03741 && sub->owner->connected.id.number.str) {
03742 if (session->device->height == 1) {
03743 send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
03744 } else {
03745 send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
03746 }
03747 change_callerid(session, 0, sub->owner->connected.id.number.str);
03748 } else {
03749 if (session->device->height == 1) {
03750 send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERID);
03751 } else {
03752 send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
03753 }
03754 change_callerid(session, 0, DEFAULTCALLERID);
03755 }
03756 if (sub->owner->connected.id.name.valid
03757 && sub->owner->connected.id.name.str) {
03758 send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name.str);
03759 change_callerid(session, 1, sub->owner->connected.id.name.str);
03760 } else {
03761 send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
03762 change_callerid(session, 1, DEFAULTCALLERNAME);
03763 }
03764 }
03765 send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
03766 send_text_status(session, "Accept Ignore");
03767
03768 if (sub->ringstyle == -1)
03769 send_ring(session, session->device->ringvolume, session->device->ringstyle);
03770 else {
03771 if (sub->ringvolume == -1)
03772 send_ring(session, session->device->ringvolume, sub->ringstyle);
03773 else
03774 send_ring(session, sub->ringvolume, sub->ringstyle);
03775 }
03776 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
03777
03778 ast_setstate(ast, AST_STATE_RINGING);
03779 ast_queue_control(ast, AST_CONTROL_RINGING);
03780 return res;
03781 }
03782
03783
03784 static int unistim_hangup(struct ast_channel *ast)
03785 {
03786 struct unistim_subchannel *sub;
03787 struct unistim_line *l;
03788 struct unistimsession *s;
03789
03790 s = channel_to_session(ast);
03791 sub = ast->tech_pvt;
03792 if (!s) {
03793 ast_debug(1, "Asked to hangup channel not connected\n");
03794 ast_mutex_lock(&sub->lock);
03795 sub->owner = NULL;
03796 ast->tech_pvt = NULL;
03797 sub->alreadygone = 0;
03798 ast_mutex_unlock(&sub->lock);
03799 if (sub->rtp) {
03800 if (unistimdebug)
03801 ast_verb(0, "Destroying RTP session\n");
03802 ast_rtp_instance_destroy(sub->rtp);
03803 sub->rtp = NULL;
03804 }
03805 return 0;
03806 }
03807 l = sub->parent;
03808 if (unistimdebug)
03809 ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
03810
03811 if ((l->subs[SUB_THREEWAY]) && (sub->subtype == SUB_REAL)) {
03812 if (unistimdebug)
03813 ast_verb(0, "Real call disconnected while talking to threeway\n");
03814 sub->owner = NULL;
03815 ast->tech_pvt = NULL;
03816 return 0;
03817 }
03818 if ((l->subs[SUB_REAL]->owner) && (sub->subtype == SUB_THREEWAY) &&
03819 (sub->alreadygone == 0)) {
03820 if (unistimdebug)
03821 ast_verb(0, "threeway call disconnected, switching to real call\n");
03822 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Three way call canceled,");
03823 send_text(TEXT_LINE1, TEXT_NORMAL, s, "switching back to");
03824 send_text(TEXT_LINE2, TEXT_NORMAL, s, "previous call.");
03825 send_text_status(s, "Hangup Transf");
03826 ast_moh_stop(ast_bridged_channel(l->subs[SUB_REAL]->owner));
03827 swap_subs(l, SUB_THREEWAY, SUB_REAL);
03828 l->parent->moh = 0;
03829 ast_mutex_lock(&sub->lock);
03830 sub->owner = NULL;
03831 ast->tech_pvt = NULL;
03832 ast_mutex_unlock(&sub->lock);
03833 unalloc_sub(l, SUB_THREEWAY);
03834 return 0;
03835 }
03836 ast_mutex_lock(&sub->lock);
03837 sub->owner = NULL;
03838 ast->tech_pvt = NULL;
03839 sub->alreadygone = 0;
03840 ast_mutex_unlock(&sub->lock);
03841 if (!s) {
03842 if (unistimdebug)
03843 ast_verb(0, "Asked to hangup channel not connected (no session)\n");
03844 if (sub->rtp) {
03845 if (unistimdebug)
03846 ast_verb(0, "Destroying RTP session\n");
03847 ast_rtp_instance_destroy(sub->rtp);
03848 sub->rtp = NULL;
03849 }
03850 return 0;
03851 }
03852 if (sub->subtype == SUB_REAL) {
03853
03854 if (s->device->silence_generator) {
03855 if (unistimdebug)
03856 ast_verb(0, "Stopping silence generator\n");
03857 if (sub->owner)
03858 ast_channel_stop_silence_generator(sub->owner,
03859 s->device->silence_generator);
03860 else
03861 ast_log(LOG_WARNING,
03862 "Trying to stop silence generator on a null channel !\n");
03863 s->device->silence_generator = NULL;
03864 }
03865 }
03866 l->parent->moh = 0;
03867 send_no_ring(s);
03868 send_end_call(s);
03869 if (sub->rtp) {
03870 if (unistimdebug)
03871 ast_verb(0, "Destroying RTP session\n");
03872 ast_rtp_instance_destroy(sub->rtp);
03873 sub->rtp = NULL;
03874 } else if (unistimdebug)
03875 ast_verb(0, "No RTP session to destroy\n");
03876 if (l->subs[SUB_THREEWAY]) {
03877 if (unistimdebug)
03878 ast_verb(0, "Cleaning other subchannels\n");
03879 unalloc_sub(l, SUB_THREEWAY);
03880 }
03881 if (s->state == STATE_RINGING)
03882 cancel_dial(s);
03883 else if (s->state == STATE_CALL)
03884 close_call(s);
03885
03886 return 0;
03887 }
03888
03889
03890 static int unistim_answer(struct ast_channel *ast)
03891 {
03892 int res = 0;
03893 struct unistim_subchannel *sub;
03894 struct unistim_line *l;
03895 struct unistimsession *s;
03896
03897 s = channel_to_session(ast);
03898 if (!s) {
03899 ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
03900 return -1;
03901 }
03902 sub = ast->tech_pvt;
03903 l = sub->parent;
03904
03905 if ((!sub->rtp) && (!l->subs[SUB_THREEWAY]))
03906 start_rtp(sub);
03907 if (unistimdebug)
03908 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast->name, l->name,
03909 l->parent->name, sub->subtype);
03910 send_text(TEXT_LINE2, TEXT_NORMAL, l->parent->session, "is now on-line");
03911 if (l->subs[SUB_THREEWAY])
03912 send_text_status(l->parent->session, "Transf Cancel");
03913 else
03914 send_text_status(l->parent->session, "Hangup Transf");
03915 send_start_timer(l->parent->session);
03916 if (ast->_state != AST_STATE_UP)
03917 ast_setstate(ast, AST_STATE_UP);
03918 return res;
03919 }
03920
03921
03922
03923 static int unistimsock_read(int *id, int fd, short events, void *ignore)
03924 {
03925 struct sockaddr_in addr_from = { 0, };
03926 struct unistimsession *cur = NULL;
03927 int found = 0;
03928 int tmp = 0;
03929 int dw_num_bytes_rcvd;
03930 #ifdef DUMP_PACKET
03931 int dw_num_bytes_rcvdd;
03932 char iabuf[INET_ADDRSTRLEN];
03933 #endif
03934
03935 dw_num_bytes_rcvd =
03936 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
03937 &size_addr_from);
03938 if (dw_num_bytes_rcvd == -1) {
03939 if (errno == EAGAIN)
03940 ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
03941 else if (errno != ECONNREFUSED)
03942 ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
03943 return 1;
03944 }
03945
03946
03947 ast_mutex_lock(&sessionlock);
03948 cur = sessions;
03949 while (cur) {
03950 if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
03951 found = 1;
03952 break;
03953 }
03954 tmp++;
03955 cur = cur->next;
03956 }
03957 ast_mutex_unlock(&sessionlock);
03958
03959 #ifdef DUMP_PACKET
03960 if (unistimdebug)
03961 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
03962 dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
03963 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
03964 dw_num_bytes_rcvdd++)
03965 ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
03966 ast_verb(0, "\n******************************************\n");
03967 #endif
03968
03969 if (!found) {
03970 if (unistimdebug)
03971 ast_verb(0, "Received a packet from an unknown source\n");
03972 parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
03973
03974 } else
03975 parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
03976
03977 return 1;
03978 }
03979
03980 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
03981 const struct unistim_subchannel *sub)
03982 {
03983
03984 struct ast_frame *f;
03985
03986 if (!ast) {
03987 ast_log(LOG_WARNING, "Channel NULL while reading\n");
03988 return &ast_null_frame;
03989 }
03990
03991 if (!sub->rtp) {
03992 ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %d\n",
03993 sub->subtype);
03994 return &ast_null_frame;
03995 }
03996
03997 switch (ast->fdno) {
03998 case 0:
03999 f = ast_rtp_instance_read(sub->rtp, 0);
04000 break;
04001 case 1:
04002 f = ast_rtp_instance_read(sub->rtp, 1);
04003 break;
04004 default:
04005 f = &ast_null_frame;
04006 }
04007
04008 if (sub->owner) {
04009
04010 if (f->frametype == AST_FRAME_VOICE) {
04011 if (f->subclass.codec != sub->owner->nativeformats) {
04012 ast_debug(1,
04013 "Oooh, format changed from %s to %s\n",
04014 ast_getformatname(sub->owner->nativeformats),
04015 ast_getformatname(f->subclass.codec));
04016
04017 sub->owner->nativeformats = f->subclass.codec;
04018 ast_set_read_format(sub->owner, sub->owner->readformat);
04019 ast_set_write_format(sub->owner, sub->owner->writeformat);
04020 }
04021 }
04022 }
04023
04024 return f;
04025 }
04026
04027 static struct ast_frame *unistim_read(struct ast_channel *ast)
04028 {
04029 struct ast_frame *fr;
04030 struct unistim_subchannel *sub = ast->tech_pvt;
04031
04032 ast_mutex_lock(&sub->lock);
04033 fr = unistim_rtp_read(ast, sub);
04034 ast_mutex_unlock(&sub->lock);
04035
04036 return fr;
04037 }
04038
04039 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
04040 {
04041 struct unistim_subchannel *sub = ast->tech_pvt;
04042 int res = 0;
04043
04044 if (frame->frametype != AST_FRAME_VOICE) {
04045 if (frame->frametype == AST_FRAME_IMAGE)
04046 return 0;
04047 else {
04048 ast_log(LOG_WARNING, "Can't send %d type frames with unistim_write\n",
04049 frame->frametype);
04050 return 0;
04051 }
04052 } else {
04053 if (!(frame->subclass.codec & ast->nativeformats)) {
04054 char tmp[256];
04055 ast_log(LOG_WARNING,
04056 "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
04057 ast_getformatname(frame->subclass.codec),
04058 ast_getformatname_multiple(tmp, sizeof(tmp), ast->nativeformats),
04059 ast_getformatname(ast->readformat),
04060 ast_getformatname(ast->writeformat));
04061 return -1;
04062 }
04063 }
04064
04065 if (sub) {
04066 ast_mutex_lock(&sub->lock);
04067 if (sub->rtp) {
04068 res = ast_rtp_instance_write(sub->rtp, frame);
04069 }
04070 ast_mutex_unlock(&sub->lock);
04071 }
04072
04073 return res;
04074 }
04075
04076 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04077 {
04078 struct unistim_subchannel *p = newchan->tech_pvt;
04079 struct unistim_line *l = p->parent;
04080
04081 ast_mutex_lock(&p->lock);
04082
04083 ast_debug(1, "New owner for channel USTM/%s@%s-%d is %s\n", l->name,
04084 l->parent->name, p->subtype, newchan->name);
04085
04086 if (p->owner != oldchan) {
04087 ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
04088 oldchan->name, oldchan, p->owner->name, p->owner);
04089 return -1;
04090 }
04091
04092 p->owner = newchan;
04093
04094 ast_mutex_unlock(&p->lock);
04095
04096 return 0;
04097
04098 }
04099
04100 static char *control2str(int ind)
04101 {
04102 switch (ind) {
04103 case AST_CONTROL_HANGUP:
04104 return "Other end has hungup";
04105 case AST_CONTROL_RING:
04106 return "Local ring";
04107 case AST_CONTROL_RINGING:
04108 return "Remote end is ringing";
04109 case AST_CONTROL_ANSWER:
04110 return "Remote end has answered";
04111 case AST_CONTROL_BUSY:
04112 return "Remote end is busy";
04113 case AST_CONTROL_TAKEOFFHOOK:
04114 return "Make it go off hook";
04115 case AST_CONTROL_OFFHOOK:
04116 return "Line is off hook";
04117 case AST_CONTROL_CONGESTION:
04118 return "Congestion (circuits busy)";
04119 case AST_CONTROL_FLASH:
04120 return "Flash hook";
04121 case AST_CONTROL_WINK:
04122 return "Wink";
04123 case AST_CONTROL_OPTION:
04124 return "Set a low-level option";
04125 case AST_CONTROL_RADIO_KEY:
04126 return "Key Radio";
04127 case AST_CONTROL_RADIO_UNKEY:
04128 return "Un-Key Radio";
04129 case -1:
04130 return "Stop tone";
04131 }
04132 return "UNKNOWN";
04133 }
04134
04135 static void in_band_indication(struct ast_channel *ast, const struct ast_tone_zone *tz,
04136 const char *indication)
04137 {
04138 struct ast_tone_zone_sound *ts = NULL;
04139
04140 if ((ts = ast_get_indication_tone(tz, indication))) {
04141 ast_playtones_start(ast, 0, ts->data, 1);
04142 ts = ast_tone_zone_sound_unref(ts);
04143 } else {
04144 ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
04145 }
04146 }
04147
04148 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
04149 size_t datalen)
04150 {
04151 struct unistim_subchannel *sub;
04152 struct unistim_line *l;
04153 struct unistimsession *s;
04154
04155 if (unistimdebug) {
04156 ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
04157 control2str(ind), ast->name);
04158 }
04159
04160 s = channel_to_session(ast);
04161 if (!s)
04162 return -1;
04163
04164 sub = ast->tech_pvt;
04165 l = sub->parent;
04166
04167 switch (ind) {
04168 case AST_CONTROL_RINGING:
04169 if (ast->_state != AST_STATE_UP) {
04170 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Ringing...");
04171 in_band_indication(ast, l->parent->tz, "ring");
04172 s->device->missed_call = -1;
04173 break;
04174 }
04175 return -1;
04176 case AST_CONTROL_BUSY:
04177 if (ast->_state != AST_STATE_UP) {
04178 sub->alreadygone = 1;
04179 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Busy");
04180 in_band_indication(ast, l->parent->tz, "busy");
04181 s->device->missed_call = -1;
04182 break;
04183 }
04184 return -1;
04185 case AST_CONTROL_CONGESTION:
04186 if (ast->_state != AST_STATE_UP) {
04187 sub->alreadygone = 1;
04188 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Congestion");
04189 in_band_indication(ast, l->parent->tz, "congestion");
04190 s->device->missed_call = -1;
04191 break;
04192 }
04193 return -1;
04194 case AST_CONTROL_HOLD:
04195 ast_moh_start(ast, data, NULL);
04196 break;
04197 case AST_CONTROL_UNHOLD:
04198 ast_moh_stop(ast);
04199 break;
04200 case AST_CONTROL_PROGRESS:
04201 case AST_CONTROL_SRCUPDATE:
04202 break;
04203 case -1:
04204 ast_playtones_stop(ast);
04205 s->device->missed_call = 0;
04206 break;
04207 case AST_CONTROL_PROCEEDING:
04208 break;
04209 default:
04210 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
04211 return -1;
04212 }
04213
04214 return 0;
04215 }
04216
04217 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
04218 {
04219 struct unistim_line *l;
04220 struct unistim_device *d;
04221 char line[256];
04222 char *at;
04223 char *device;
04224
04225 ast_copy_string(line, dest, sizeof(line));
04226 at = strchr(line, '@');
04227 if (!at) {
04228 ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
04229 return NULL;
04230 }
04231 *at = '\0';
04232 at++;
04233 device = at;
04234 ast_mutex_lock(&devicelock);
04235 d = devices;
04236 at = strchr(device, '/');
04237 if (at)
04238 *at = '\0';
04239 while (d) {
04240 if (!strcasecmp(d->name, device)) {
04241 if (unistimdebug)
04242 ast_verb(0, "Found device: %s\n", d->name);
04243
04244 l = d->lines;
04245 while (l) {
04246
04247 if (!strcasecmp(l->name, line)) {
04248 l->subs[SUB_REAL]->ringvolume = -1;
04249 l->subs[SUB_REAL]->ringstyle = -1;
04250 if (at) {
04251 at++;
04252 if (*at == 'r') {
04253 at++;
04254 if ((*at < '0') || (*at > '7'))
04255 ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
04256 else {
04257 char ring_volume = -1;
04258 char ring_style = *at - '0';
04259 at++;
04260 if ((*at >= '0') && (*at <= '3'))
04261 ring_volume = *at - '0';
04262 if (unistimdebug)
04263 ast_verb(0, "Distinctive ring : style #%d volume %d\n",
04264 ring_style, ring_volume);
04265 l->subs[SUB_REAL]->ringvolume = ring_volume;
04266 l->subs[SUB_REAL]->ringstyle = ring_style;
04267 }
04268 }
04269 }
04270 ast_mutex_unlock(&devicelock);
04271 return l->subs[SUB_REAL];
04272 }
04273 l = l->next;
04274 }
04275 }
04276 d = d->next;
04277 }
04278
04279 ast_mutex_unlock(&devicelock);
04280
04281 return NULL;
04282 }
04283
04284 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
04285 {
04286 struct unistimsession *pte = channel_to_session(ast);
04287
04288 if (!pte)
04289 return -1;
04290
04291 return unistim_do_senddigit(pte, digit);
04292 }
04293
04294 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
04295 {
04296 struct unistimsession *pte = channel_to_session(ast);
04297 struct ast_frame f = { 0, };
04298 struct unistim_subchannel *sub;
04299
04300 sub = pte->device->lines->subs[SUB_REAL];
04301
04302 if (!sub->owner || sub->alreadygone) {
04303 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
04304 return -1;
04305 }
04306
04307 if (unistimdebug)
04308 ast_verb(0, "Send Digit off %c\n", digit);
04309
04310 if (!pte)
04311 return -1;
04312
04313 send_tone(pte, 0, 0);
04314 f.frametype = AST_FRAME_DTMF;
04315 f.subclass.integer = digit;
04316 f.src = "unistim";
04317 ast_queue_frame(sub->owner, &f);
04318
04319 return 0;
04320 }
04321
04322
04323
04324 static int unistim_sendtext(struct ast_channel *ast, const char *text)
04325 {
04326 struct unistimsession *pte = channel_to_session(ast);
04327 int size;
04328 char tmp[TEXT_LENGTH_MAX + 1];
04329
04330 if (unistimdebug)
04331 ast_verb(0, "unistim_sendtext called\n");
04332
04333 if (!text) {
04334 ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
04335 return 1;
04336 }
04337
04338 size = strlen(text);
04339 if (text[0] == '@') {
04340 int pos = 0, i = 1, tok = 0, sz = 0;
04341 char label[11];
04342 char number[16];
04343 char icon = '\0';
04344 char cur = '\0';
04345
04346 memset(label, 0, 11);
04347 memset(number, 0, 16);
04348 while (text[i]) {
04349 cur = text[i++];
04350 switch (tok) {
04351 case 0:
04352 if ((cur < '0') && (cur > '5')) {
04353 ast_log(LOG_WARNING,
04354 "sendtext failed : position must be a number beetween 0 and 5\n");
04355 return 1;
04356 }
04357 pos = cur - '0';
04358 tok = 1;
04359 continue;
04360 case 1:
04361 if (cur != '@') {
04362 ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
04363 return 1;
04364 }
04365 tok = 2;
04366 continue;
04367 case 2:
04368 if ((cur < '3') && (cur > '6')) {
04369 ast_log(LOG_WARNING,
04370 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
04371 return 1;
04372 }
04373 icon = (cur - '0') * 10;
04374 tok = 3;
04375 continue;
04376 case 3:
04377 if ((cur < '0') && (cur > '9')) {
04378 ast_log(LOG_WARNING,
04379 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
04380 return 1;
04381 }
04382 icon += (cur - '0');
04383 tok = 4;
04384 continue;
04385 case 4:
04386 if (cur != '@') {
04387 ast_log(LOG_WARNING,
04388 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
04389 return 1;
04390 }
04391 tok = 5;
04392 continue;
04393 case 5:
04394 if (cur == '@') {
04395 tok = 6;
04396 sz = 0;
04397 continue;
04398 }
04399 if (sz > 10)
04400 continue;
04401 label[sz] = cur;
04402 sz++;
04403 continue;
04404 case 6:
04405 if (sz > 15) {
04406 ast_log(LOG_WARNING,
04407 "sendtext failed : extension too long = %d (15 car max)\n",
04408 sz);
04409 return 1;
04410 }
04411 number[sz] = cur;
04412 sz++;
04413 continue;
04414 }
04415 }
04416 if (tok != 6) {
04417 ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
04418 return 1;
04419 }
04420 if (!pte->device) {
04421 ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
04422 return 1;
04423 }
04424 strcpy(pte->device->softkeylabel[pos], label);
04425 strcpy(pte->device->softkeynumber[pos], number);
04426 pte->device->softkeyicon[pos] = icon;
04427 send_favorite(pos, icon, pte, label);
04428 return 0;
04429 }
04430
04431 if (size <= TEXT_LENGTH_MAX * 2) {
04432 if (pte->device->height == 1) {
04433 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
04434 } else {
04435 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Message :");
04436 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
04437 }
04438 if (size <= TEXT_LENGTH_MAX) {
04439 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
04440 return 0;
04441 }
04442 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04443 tmp[sizeof(tmp) - 1] = '\0';
04444 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04445 return 0;
04446 }
04447 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
04448 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04449 tmp[sizeof(tmp) - 1] = '\0';
04450 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
04451 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
04452 tmp[sizeof(tmp) - 1] = '\0';
04453 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04454 return 0;
04455 }
04456
04457
04458 static int unistim_send_mwi_to_peer(struct unistimsession *s, unsigned int tick)
04459 {
04460 struct ast_event *event;
04461 int new;
04462 char *mailbox, *context;
04463 struct unistim_line *peer = s->device->lines;
04464
04465 context = mailbox = ast_strdupa(peer->mailbox);
04466 strsep(&context, "@");
04467 if (ast_strlen_zero(context))
04468 context = "default";
04469
04470 event = ast_event_get_cached(AST_EVENT_MWI,
04471 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
04472 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
04473 AST_EVENT_IE_END);
04474
04475 if (event) {
04476 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
04477 ast_event_destroy(event);
04478 } else {
04479 new = ast_app_has_voicemail(peer->mailbox, "INBOX");
04480 }
04481
04482 peer->nextmsgcheck = tick + TIMER_MWI;
04483
04484
04485 if (new == peer->lastmsgssent) {
04486 return 0;
04487 }
04488
04489 peer->lastmsgssent = new;
04490 if (new == 0) {
04491 send_led_update(s, 0);
04492 } else {
04493 send_led_update(s, 1);
04494 }
04495
04496 return 0;
04497 }
04498
04499
04500
04501 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state, const char *linkedid)
04502 {
04503 struct ast_channel *tmp;
04504 struct unistim_line *l;
04505 int fmt;
04506
04507 if (!sub) {
04508 ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
04509 return NULL;
04510 }
04511 if (!sub->parent) {
04512 ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
04513 return NULL;
04514 }
04515 l = sub->parent;
04516 tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
04517 l->context, linkedid, l->amaflags, "%s@%s-%d", l->name, l->parent->name, sub->subtype);
04518 if (unistimdebug)
04519 ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub->subtype, sub, tmp);
04520 if (!tmp) {
04521 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
04522 return NULL;
04523 }
04524
04525 tmp->nativeformats = l->capability;
04526 if (!tmp->nativeformats)
04527 tmp->nativeformats = CAPABILITY;
04528 fmt = ast_best_codec(tmp->nativeformats);
04529 if (unistimdebug) {
04530 char tmp1[256], tmp2[256], tmp3[256];
04531 ast_verb(0, "Best codec = %s from nativeformats %s (line cap=%s global=%s)\n",
04532 ast_getformatname(fmt),
04533 ast_getformatname_multiple(tmp1, sizeof(tmp1), tmp->nativeformats),
04534 ast_getformatname_multiple(tmp2, sizeof(tmp2), l->capability),
04535 ast_getformatname_multiple(tmp3, sizeof(tmp3), CAPABILITY));
04536 }
04537 if ((sub->rtp) && (sub->subtype == 0)) {
04538 if (unistimdebug)
04539 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
04540 tmp->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
04541 tmp->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
04542 }
04543 if (sub->rtp)
04544 ast_jb_configure(tmp, &global_jbconf);
04545
04546
04547 ast_setstate(tmp, state);
04548 if (state == AST_STATE_RING)
04549 tmp->rings = 1;
04550 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04551 tmp->writeformat = fmt;
04552 tmp->rawwriteformat = fmt;
04553 tmp->readformat = fmt;
04554 tmp->rawreadformat = fmt;
04555 tmp->tech_pvt = sub;
04556 tmp->tech = &unistim_tech;
04557 if (!ast_strlen_zero(l->language))
04558 ast_string_field_set(tmp, language, l->language);
04559 sub->owner = tmp;
04560 ast_mutex_lock(&usecnt_lock);
04561 usecnt++;
04562 ast_mutex_unlock(&usecnt_lock);
04563 ast_update_use_count();
04564 tmp->callgroup = l->callgroup;
04565 tmp->pickupgroup = l->pickupgroup;
04566 ast_string_field_set(tmp, call_forward, l->parent->call_forward);
04567 if (!ast_strlen_zero(l->cid_num)) {
04568 char *name, *loc, *instr;
04569 instr = ast_strdup(l->cid_num);
04570 if (instr) {
04571 ast_callerid_parse(instr, &name, &loc);
04572 tmp->caller.id.number.valid = 1;
04573 ast_free(tmp->caller.id.number.str);
04574 tmp->caller.id.number.str = ast_strdup(loc);
04575 tmp->caller.id.name.valid = 1;
04576 ast_free(tmp->caller.id.name.str);
04577 tmp->caller.id.name.str = ast_strdup(name);
04578 ast_free(instr);
04579 }
04580 }
04581 tmp->priority = 1;
04582 if (state != AST_STATE_DOWN) {
04583 if (unistimdebug)
04584 ast_verb(0, "Starting pbx in unistim_new\n");
04585 if (ast_pbx_start(tmp)) {
04586 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04587 ast_hangup(tmp);
04588 tmp = NULL;
04589 }
04590 }
04591
04592 return tmp;
04593 }
04594
04595 static void *do_monitor(void *data)
04596 {
04597 struct unistimsession *cur = NULL;
04598 unsigned int dw_timeout = 0;
04599 unsigned int tick;
04600 int res;
04601 int reloading;
04602
04603
04604 if (unistimsock > -1)
04605 ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
04606
04607
04608 for (;;) {
04609
04610
04611 tick = get_tick_count();
04612 dw_timeout = UINT_MAX;
04613 ast_mutex_lock(&sessionlock);
04614 cur = sessions;
04615 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
04616 while (cur) {
04617 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
04618 cur->timeout);
04619
04620 if (cur->timeout <= tick) {
04621 DEBUG_TIMER("Event for session %p\n", cur);
04622
04623 if (cur->last_buf_available == 0)
04624 send_ping(cur);
04625 else {
04626 if (send_retransmit(cur)) {
04627 DEBUG_TIMER("The chained link was modified, restarting...\n");
04628 cur = sessions;
04629 dw_timeout = UINT_MAX;
04630 continue;
04631 }
04632 }
04633 }
04634 if (dw_timeout > cur->timeout - tick)
04635 dw_timeout = cur->timeout - tick;
04636
04637 if (cur->device) {
04638 if ((!ast_strlen_zero(cur->device->lines->mailbox)) &&
04639 ((tick >= cur->device->lines->nextmsgcheck))) {
04640 DEBUG_TIMER("Checking mailbox for MWI\n");
04641 unistim_send_mwi_to_peer(cur, tick);
04642 break;
04643 }
04644 }
04645 cur = cur->next;
04646 }
04647 ast_mutex_unlock(&sessionlock);
04648 DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
04649 res = dw_timeout;
04650
04651 if ((res < 0) || (res > IDLE_WAIT))
04652 res = IDLE_WAIT;
04653
04654 res = ast_io_wait(io, res);
04655
04656 ast_mutex_lock(&unistim_reload_lock);
04657 reloading = unistim_reloading;
04658 unistim_reloading = 0;
04659 ast_mutex_unlock(&unistim_reload_lock);
04660 if (reloading) {
04661 ast_verb(1, "Reloading unistim.conf...\n");
04662 reload_config();
04663 }
04664 pthread_testcancel();
04665 }
04666
04667 return NULL;
04668 }
04669
04670
04671 static int restart_monitor(void)
04672 {
04673 pthread_attr_t attr;
04674
04675 if (monitor_thread == AST_PTHREADT_STOP)
04676 return 0;
04677 if (ast_mutex_lock(&monlock)) {
04678 ast_log(LOG_WARNING, "Unable to lock monitor\n");
04679 return -1;
04680 }
04681 if (monitor_thread == pthread_self()) {
04682 ast_mutex_unlock(&monlock);
04683 ast_log(LOG_WARNING, "Cannot kill myself\n");
04684 return -1;
04685 }
04686 if (monitor_thread != AST_PTHREADT_NULL) {
04687
04688 pthread_kill(monitor_thread, SIGURG);
04689 } else {
04690 pthread_attr_init(&attr);
04691 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
04692
04693 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
04694 ast_mutex_unlock(&monlock);
04695 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04696 return -1;
04697 }
04698 }
04699 ast_mutex_unlock(&monlock);
04700 return 0;
04701 }
04702
04703
04704
04705 static struct ast_channel *unistim_request(const char *type, format_t format, const struct ast_channel *requestor, void *data,
04706 int *cause)
04707 {
04708 format_t oldformat;
04709 struct unistim_subchannel *sub;
04710 struct ast_channel *tmpc = NULL;
04711 char tmp[256];
04712 char *dest = data;
04713
04714 oldformat = format;
04715 format &= CAPABILITY;
04716 ast_log(LOG_NOTICE,
04717 "Asked to get a channel of format %s while capability is %s result : %s\n",
04718 ast_getformatname(oldformat),
04719 ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY),
04720 ast_getformatname(format));
04721 if (!format) {
04722 ast_log(LOG_NOTICE,
04723 "Asked to get a channel of unsupported format %s while capability is %s\n",
04724 ast_getformatname(oldformat), ast_getformatname_multiple(tmp, sizeof(tmp), CAPABILITY));
04725 return NULL;
04726 }
04727
04728 ast_copy_string(tmp, dest, sizeof(tmp));
04729 if (ast_strlen_zero(tmp)) {
04730 ast_log(LOG_NOTICE, "Unistim channels require a device\n");
04731 return NULL;
04732 }
04733
04734 sub = find_subchannel_by_name(tmp);
04735 if (!sub) {
04736 ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
04737 *cause = AST_CAUSE_CONGESTION;
04738 return NULL;
04739 }
04740
04741 ast_verb(3, "unistim_request(%s)\n", tmp);
04742
04743 if (sub->owner) {
04744 if (unistimdebug)
04745 ast_verb(0, "Can't create channel : Busy !\n");
04746 *cause = AST_CAUSE_BUSY;
04747 return NULL;
04748 }
04749 sub->parent->capability = format;
04750 tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
04751 if (!tmpc)
04752 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
04753 if (unistimdebug)
04754 ast_verb(0, "unistim_request owner = %p\n", sub->owner);
04755 restart_monitor();
04756
04757
04758 return tmpc;
04759 }
04760
04761 static char *unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04762 {
04763 struct unistim_device *device = devices;
04764 struct unistim_line *line;
04765 struct unistim_subchannel *sub;
04766 struct unistimsession *s;
04767 int i;
04768 struct ast_channel *tmp;
04769
04770 switch (cmd) {
04771 case CLI_INIT:
04772 e->command = "unistim show info";
04773 e->usage =
04774 "Usage: unistim show info\n"
04775 " Dump internal structures.\n";
04776 return NULL;
04777
04778 case CLI_GENERATE:
04779 return NULL;
04780 }
04781
04782 if (a->argc != e->args)
04783 return CLI_SHOWUSAGE;
04784
04785 ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
04786 while (device) {
04787 ast_cli(a->fd, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
04788 device->name, device->id, device->lines, device->ha, device->session,
04789 device);
04790 line = device->lines;
04791 while (line) {
04792 ast_cli(a->fd,
04793 "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " device=%p line=%p\n",
04794 line->name, line->fullname, line->exten, line->cid_num,
04795 line->capability, line->parent, line);
04796 for (i = 0; i < MAX_SUBS; i++) {
04797 sub = line->subs[i];
04798 if (!sub)
04799 continue;
04800 if (!sub->owner)
04801 tmp = (void *) -42;
04802 else
04803 tmp = sub->owner->_bridge;
04804 if (sub->subtype != i)
04805 ast_cli(a->fd, "Warning ! subchannel->subs[%d] have a subtype=%d\n", i,
04806 sub->subtype);
04807 ast_cli(a->fd,
04808 "-->subtype=%d chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
04809 sub->subtype, sub->owner, sub->rtp, tmp, sub->parent,
04810 sub->alreadygone);
04811 }
04812 line = line->next;
04813 }
04814 device = device->next;
04815 }
04816 ast_cli(a->fd, "\nSessions:\n");
04817 ast_mutex_lock(&sessionlock);
04818 s = sessions;
04819 while (s) {
04820 ast_cli(a->fd,
04821 "sin=%s timeout=%u state=%d macaddr=%s device=%p session=%p\n",
04822 ast_inet_ntoa(s->sin.sin_addr), s->timeout, s->state, s->macaddr,
04823 s->device, s);
04824 s = s->next;
04825 }
04826 ast_mutex_unlock(&sessionlock);
04827
04828 return CLI_SUCCESS;
04829 }
04830
04831 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04832 {
04833 BUFFSEND;
04834 struct unistim_subchannel *sub;
04835 int i, j = 0, len;
04836 unsigned char c, cc;
04837 char tmp[256];
04838
04839 switch (cmd) {
04840 case CLI_INIT:
04841 e->command = "unistim send packet";
04842 e->usage =
04843 "Usage: unistim send packet USTM/line@name hexa\n"
04844 " unistim send packet USTM/1000@hans 19040004\n";
04845 return NULL;
04846
04847 case CLI_GENERATE:
04848 return NULL;
04849 }
04850
04851 if (a->argc < 5)
04852 return CLI_SHOWUSAGE;
04853
04854 if (strlen(a->argv[3]) < 9)
04855 return CLI_SHOWUSAGE;
04856
04857 len = strlen(a->argv[4]);
04858 if (len % 2)
04859 return CLI_SHOWUSAGE;
04860
04861 ast_copy_string(tmp, a->argv[3] + 5, sizeof(tmp));
04862 sub = find_subchannel_by_name(tmp);
04863 if (!sub) {
04864 ast_cli(a->fd, "Can't find '%s'\n", tmp);
04865 return CLI_SUCCESS;
04866 }
04867 if (!sub->parent->parent->session) {
04868 ast_cli(a->fd, "'%s' is not connected\n", tmp);
04869 return CLI_SUCCESS;
04870 }
04871 ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[4], tmp, sub->parent->parent->session);
04872 for (i = 0; i < len; i++) {
04873 c = a->argv[4][i];
04874 if (c >= 'a')
04875 c -= 'a' - 10;
04876 else
04877 c -= '0';
04878 i++;
04879 cc = a->argv[4][i];
04880 if (cc >= 'a')
04881 cc -= 'a' - 10;
04882 else
04883 cc -= '0';
04884 tmp[j++] = (c << 4) | cc;
04885 }
04886 memcpy(buffsend + SIZE_HEADER, tmp, j);
04887 send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
04888 return CLI_SUCCESS;
04889 }
04890
04891 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04892 {
04893 switch (cmd) {
04894 case CLI_INIT:
04895 e->command = "unistim set debug {on|off}";
04896 e->usage =
04897 "Usage: unistim set debug\n"
04898 " Display debug messages.\n";
04899 return NULL;
04900
04901 case CLI_GENERATE:
04902 return NULL;
04903 }
04904
04905 if (a->argc != e->args)
04906 return CLI_SHOWUSAGE;
04907
04908 if (!strcasecmp(a->argv[3], "on")) {
04909 unistimdebug = 1;
04910 ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
04911 } else if (!strcasecmp(a->argv[3], "off")) {
04912 unistimdebug = 0;
04913 ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
04914 } else
04915 return CLI_SHOWUSAGE;
04916
04917 return CLI_SUCCESS;
04918 }
04919
04920
04921
04922
04923
04924 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04925 {
04926 switch (cmd) {
04927 case CLI_INIT:
04928 e->command = "unistim reload";
04929 e->usage =
04930 "Usage: unistim reload\n"
04931 " Reloads UNISTIM configuration from unistim.conf\n";
04932 return NULL;
04933
04934 case CLI_GENERATE:
04935 return NULL;
04936 }
04937
04938 if (e && a && a->argc != e->args)
04939 return CLI_SHOWUSAGE;
04940
04941 if (unistimdebug)
04942 ast_verb(0, "reload unistim\n");
04943
04944 ast_mutex_lock(&unistim_reload_lock);
04945 if (!unistim_reloading)
04946 unistim_reloading = 1;
04947 ast_mutex_unlock(&unistim_reload_lock);
04948
04949 restart_monitor();
04950
04951 return CLI_SUCCESS;
04952 }
04953
04954 static struct ast_cli_entry unistim_cli[] = {
04955 AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
04956 AST_CLI_DEFINE(unistim_info, "Show UNISTIM info"),
04957 AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
04958 AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
04959 };
04960
04961 static void unquote(char *out, const char *src, int maxlen)
04962 {
04963 int len = strlen(src);
04964 if (!len)
04965 return;
04966 if ((len > 1) && src[0] == '\"') {
04967
04968 src++;
04969
04970 len--;
04971 if (maxlen > len - 1)
04972 maxlen = len - 1;
04973 memcpy(out, src, maxlen);
04974 ((char *) out)[maxlen] = '\0';
04975 } else
04976 memcpy(out, src, maxlen);
04977 return;
04978 }
04979
04980 static int ParseBookmark(const char *text, struct unistim_device *d)
04981 {
04982 char line[256];
04983 char *at;
04984 char *number;
04985 char *icon;
04986 int p;
04987 int len = strlen(text);
04988
04989 ast_copy_string(line, text, sizeof(line));
04990
04991 if ((len > 2) && (line[1] == '@')) {
04992 p = line[0];
04993 if ((p >= '0') && (p <= '5'))
04994 p -= '0';
04995 else {
04996 ast_log(LOG_WARNING,
04997 "Invalid position for bookmark : must be between 0 and 5\n");
04998 return 0;
04999 }
05000 if (d->softkeyicon[p] != 0) {
05001 ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used\n:", p);
05002 return 0;
05003 }
05004 memmove(line, line + 2, sizeof(line));
05005 } else {
05006
05007 for (p = 0; p <= 5; p++) {
05008 if (!d->softkeyicon[p])
05009 break;
05010 }
05011 if (p > 5) {
05012 ast_log(LOG_WARNING, "No more free bookmark position\n");
05013 return 0;
05014 }
05015 }
05016 at = strchr(line, '@');
05017 if (!at) {
05018 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
05019 return 0;
05020 }
05021 *at = '\0';
05022 at++;
05023 number = at;
05024 at = strchr(at, '@');
05025 if (ast_strlen_zero(number)) {
05026 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
05027 return 0;
05028 }
05029 if (ast_strlen_zero(line)) {
05030 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
05031 return 0;
05032 }
05033
05034 at = strchr(number, '@');
05035 if (!at)
05036 d->softkeyicon[p] = FAV_ICON_SHARP;
05037 else {
05038 *at = '\0';
05039 at++;
05040 icon = at;
05041 if (ast_strlen_zero(icon)) {
05042 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
05043 return 0;
05044 }
05045 if (strncmp(icon, "USTM/", 5))
05046 d->softkeyicon[p] = atoi(icon);
05047 else {
05048 d->softkeyicon[p] = 1;
05049 ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
05050 }
05051 }
05052 ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
05053 ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
05054 if (unistimdebug)
05055 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
05056 p, d->softkeylabel[p], d->softkeynumber[p], d->softkeyicon[p]);
05057 return 1;
05058 }
05059
05060
05061 static void finish_bookmark(void)
05062 {
05063 struct unistim_device *d = devices;
05064 int i;
05065 while (d) {
05066 for (i = 0; i < 6; i++) {
05067 if (d->softkeyicon[i] == 1) {
05068 struct unistim_device *d2 = devices;
05069 while (d2) {
05070 if (!strcmp(d->softkeydevice[i], d2->name)) {
05071 d->sp[i] = d2;
05072 d->softkeyicon[i] = 0;
05073 break;
05074 }
05075 d2 = d2->next;
05076 }
05077 if (d->sp[i] == NULL)
05078 ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
05079 d->softkeydevice[i]);
05080 }
05081 }
05082 d = d->next;
05083 }
05084 }
05085
05086 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
05087 {
05088 struct unistim_device *d;
05089 struct unistim_line *l = NULL;
05090 int create = 1;
05091 int nbsoftkey, dateformat, timeformat, callhistory;
05092 char linelabel[AST_MAX_EXTENSION];
05093 char context[AST_MAX_EXTENSION];
05094 char ringvolume, ringstyle;
05095
05096
05097
05098 ast_mutex_lock(&devicelock);
05099 d = devices;
05100 while (d) {
05101 if (!strcmp(d->name, cat)) {
05102
05103 if (unistimsock < 0) {
05104
05105 ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
05106 ast_mutex_unlock(&devicelock);
05107 return NULL;
05108 }
05109
05110 create = 0;
05111 l = d->lines;
05112 break;
05113 }
05114 d = d->next;
05115 }
05116 ast_mutex_unlock(&devicelock);
05117 if (create) {
05118 if (!(d = ast_calloc(1, sizeof(*d))))
05119 return NULL;
05120
05121 if (!(l = ast_calloc(1, sizeof(*l)))) {
05122 ast_free(d);
05123 return NULL;
05124 }
05125 ast_copy_string(d->name, cat, sizeof(d->name));
05126 }
05127 ast_copy_string(context, DEFAULTCONTEXT, sizeof(context));
05128 d->contrast = -1;
05129 d->output = OUTPUT_HANDSET;
05130 d->previous_output = OUTPUT_HANDSET;
05131 d->volume = VOLUME_LOW;
05132 d->mute = MUTE_OFF;
05133 d->height = DEFAULTHEIGHT;
05134 linelabel[0] = '\0';
05135 dateformat = 1;
05136 timeformat = 1;
05137 ringvolume = 2;
05138 callhistory = 1;
05139 ringstyle = 3;
05140 nbsoftkey = 0;
05141 while (v) {
05142 if (!strcasecmp(v->name, "rtp_port"))
05143 d->rtp_port = atoi(v->value);
05144 else if (!strcasecmp(v->name, "rtp_method"))
05145 d->rtp_method = atoi(v->value);
05146 else if (!strcasecmp(v->name, "status_method"))
05147 d->status_method = atoi(v->value);
05148 else if (!strcasecmp(v->name, "device"))
05149 ast_copy_string(d->id, v->value, sizeof(d->id));
05150 else if (!strcasecmp(v->name, "tn"))
05151 ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
05152 else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny"))
05153 d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
05154 else if (!strcasecmp(v->name, "context"))
05155 ast_copy_string(context, v->value, sizeof(context));
05156 else if (!strcasecmp(v->name, "maintext0"))
05157 unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
05158 else if (!strcasecmp(v->name, "maintext1"))
05159 unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
05160 else if (!strcasecmp(v->name, "maintext2"))
05161 unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
05162 else if (!strcasecmp(v->name, "titledefault"))
05163 unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
05164 else if (!strcasecmp(v->name, "dateformat"))
05165 dateformat = atoi(v->value);
05166 else if (!strcasecmp(v->name, "timeformat"))
05167 timeformat = atoi(v->value);
05168 else if (!strcasecmp(v->name, "contrast")) {
05169 d->contrast = atoi(v->value);
05170 if ((d->contrast < 0) || (d->contrast > 15)) {
05171 ast_log(LOG_WARNING, "constrast must be beetween 0 and 15");
05172 d->contrast = 8;
05173 }
05174 } else if (!strcasecmp(v->name, "nat"))
05175 d->nat = ast_true(v->value);
05176 else if (!strcasecmp(v->name, "ringvolume"))
05177 ringvolume = atoi(v->value);
05178 else if (!strcasecmp(v->name, "ringstyle"))
05179 ringstyle = atoi(v->value);
05180 else if (!strcasecmp(v->name, "callhistory"))
05181 callhistory = atoi(v->value);
05182 else if (!strcasecmp(v->name, "callerid")) {
05183 if (!strcasecmp(v->value, "asreceived"))
05184 l->cid_num[0] = '\0';
05185 else
05186 ast_copy_string(l->cid_num, v->value, sizeof(l->cid_num));
05187 } else if (!strcasecmp(v->name, "language"))
05188 ast_copy_string(l->language, v->value, sizeof(l->language));
05189 else if (!strcasecmp(v->name, "country"))
05190 ast_copy_string(d->country, v->value, sizeof(d->country));
05191 else if (!strcasecmp(v->name, "accountcode"))
05192 ast_copy_string(l->accountcode, v->value, sizeof(l->accountcode));
05193 else if (!strcasecmp(v->name, "amaflags")) {
05194 int y;
05195 y = ast_cdr_amaflags2int(v->value);
05196 if (y < 0)
05197 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
05198 v->lineno);
05199 else
05200 l->amaflags = y;
05201 } else if (!strcasecmp(v->name, "musiconhold"))
05202 ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass));
05203 else if (!strcasecmp(v->name, "callgroup"))
05204 l->callgroup = ast_get_group(v->value);
05205 else if (!strcasecmp(v->name, "pickupgroup"))
05206 l->pickupgroup = ast_get_group(v->value);
05207 else if (!strcasecmp(v->name, "mailbox"))
05208 ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
05209 else if (!strcasecmp(v->name, "parkinglot"))
05210 ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
05211 else if (!strcasecmp(v->name, "linelabel"))
05212 unquote(linelabel, v->value, sizeof(linelabel) - 1);
05213 else if (!strcasecmp(v->name, "extension")) {
05214 if (!strcasecmp(v->value, "none"))
05215 d->extension = EXTENSION_NONE;
05216 else if (!strcasecmp(v->value, "ask"))
05217 d->extension = EXTENSION_ASK;
05218 else if (!strcasecmp(v->value, "line"))
05219 d->extension = EXTENSION_LINE;
05220 else
05221 ast_log(LOG_WARNING, "Unknown extension option.\n");
05222 } else if (!strcasecmp(v->name, "bookmark")) {
05223 if (nbsoftkey > 5)
05224 ast_log(LOG_WARNING,
05225 "More than 6 softkeys defined. Ignoring new entries.\n");
05226 else {
05227 if (ParseBookmark(v->value, d))
05228 nbsoftkey++;
05229 }
05230 } else if (!strcasecmp(v->name, "line")) {
05231 int len = strlen(linelabel);
05232
05233 if (nbsoftkey) {
05234 ast_log(LOG_WARNING,
05235 "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
05236 if (create) {
05237 ast_free(d);
05238 ast_free(l);
05239 }
05240 return NULL;
05241 }
05242 if (create) {
05243 ast_mutex_init(&l->lock);
05244 } else {
05245 d->to_delete = 0;
05246
05247 memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
05248 memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
05249 memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
05250 memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
05251 memset(d->sp, 0, sizeof(d->sp));
05252 }
05253 ast_copy_string(l->name, v->value, sizeof(l->name));
05254 snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
05255 d->softkeyicon[0] = FAV_ICON_ONHOOK_BLACK;
05256 if (!len)
05257 ast_copy_string(d->softkeylabel[0], v->value, sizeof(d->softkeylabel[0]));
05258 else {
05259 if ((len > 2) && (linelabel[1] == '@')) {
05260 d->softkeylinepos = linelabel[0];
05261 if ((d->softkeylinepos >= '0') && (d->softkeylinepos <= '5')) {
05262 d->softkeylinepos -= '0';
05263 d->softkeyicon[0] = 0;
05264 } else {
05265 ast_log(LOG_WARNING,
05266 "Invalid position for linelabel : must be between 0 and 5\n");
05267 d->softkeylinepos = 0;
05268 }
05269 ast_copy_string(d->softkeylabel[d->softkeylinepos], linelabel + 2,
05270 sizeof(d->softkeylabel[d->softkeylinepos]));
05271 d->softkeyicon[d->softkeylinepos] = FAV_ICON_ONHOOK_BLACK;
05272 } else
05273 ast_copy_string(d->softkeylabel[0], linelabel,
05274 sizeof(d->softkeylabel[0]));
05275 }
05276 nbsoftkey++;
05277 ast_copy_string(l->context, context, sizeof(l->context));
05278 if (!ast_strlen_zero(l->mailbox)) {
05279 if (unistimdebug)
05280 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
05281 }
05282
05283 l->capability = CAPABILITY;
05284 l->parent = d;
05285
05286 if (create) {
05287 if (!alloc_sub(l, SUB_REAL)) {
05288 ast_mutex_destroy(&l->lock);
05289 ast_free(l);
05290 ast_free(d);
05291 return NULL;
05292 }
05293 l->next = d->lines;
05294 d->lines = l;
05295 }
05296 } else if (!strcasecmp(v->name, "height")) {
05297
05298
05299 d->height = atoi(v->value);
05300 } else
05301 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
05302 v->lineno);
05303 v = v->next;
05304 }
05305 d->ringvolume = ringvolume;
05306 d->ringstyle = ringstyle;
05307 d->callhistory = callhistory;
05308 d->tz = ast_get_indication_zone(d->country);
05309 if ((d->tz == NULL) && !ast_strlen_zero(d->country))
05310 ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
05311 d->country);
05312 d->datetimeformat = 56 + (dateformat * 4);
05313 d->datetimeformat += timeformat;
05314 if (!d->lines) {
05315 ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
05316 ast_mutex_destroy(&l->lock);
05317 ast_free(l);
05318 if (d->tz) {
05319 d->tz = ast_tone_zone_unref(d->tz);
05320 }
05321 ast_free(d);
05322 return NULL;
05323 }
05324 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
05325 (!ast_strlen_zero(d->extension_number))) {
05326 d->extension = EXTENSION_TN;
05327 if (!ast_strlen_zero(d->id))
05328 ast_log(LOG_WARNING,
05329 "tn= and device= can't be used together. Ignoring device= entry\n");
05330 d->id[0] = 'T';
05331 ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
05332 d->extension_number[0] = '\0';
05333 } else if (ast_strlen_zero(d->id)) {
05334 if (strcmp(d->name, "template")) {
05335 ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
05336 ast_mutex_destroy(&l->lock);
05337 ast_free(l);
05338 if (d->tz) {
05339 d->tz = ast_tone_zone_unref(d->tz);
05340 }
05341 ast_free(d);
05342 return NULL;
05343 } else
05344 strcpy(d->id, "000000000000");
05345 }
05346 if (!d->rtp_port)
05347 d->rtp_port = 10000;
05348 if (d->contrast == -1)
05349 d->contrast = 8;
05350 if (ast_strlen_zero(d->maintext0))
05351 strcpy(d->maintext0, "Welcome");
05352 if (ast_strlen_zero(d->maintext1))
05353 strcpy(d->maintext1, d->name);
05354 if (ast_strlen_zero(d->titledefault)) {
05355 struct ast_tm tm = { 0, };
05356 struct timeval cur_time = ast_tvnow();
05357
05358 if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
05359 display_last_error("Error in ast_localtime()");
05360 ast_copy_string(d->titledefault, "UNISTIM for*", 12);
05361 } else {
05362 if (strlen(tm.tm_zone) < 4) {
05363 strcpy(d->titledefault, "TimeZone ");
05364 strcat(d->titledefault, tm.tm_zone);
05365 } else if (strlen(tm.tm_zone) < 9) {
05366 strcpy(d->titledefault, "TZ ");
05367 strcat(d->titledefault, tm.tm_zone);
05368 } else
05369 ast_copy_string(d->titledefault, tm.tm_zone, 12);
05370 }
05371 }
05372
05373 if (create) {
05374 ast_mutex_lock(&devicelock);
05375 d->next = devices;
05376 devices = d;
05377 ast_mutex_unlock(&devicelock);
05378 ast_verb(3, "Added device '%s'\n", d->name);
05379 } else {
05380 ast_verb(3, "Device '%s' reloaded\n", d->name);
05381 }
05382 return d;
05383 }
05384
05385
05386 static int reload_config(void)
05387 {
05388 struct ast_config *cfg;
05389 struct ast_variable *v;
05390 struct ast_hostent ahp;
05391 struct hostent *hp;
05392 struct sockaddr_in bindaddr = { 0, };
05393 char *config = "unistim.conf";
05394 char *cat;
05395 struct unistim_device *d;
05396 const int reuseFlag = 1;
05397 struct unistimsession *s;
05398 struct ast_flags config_flags = { 0, };
05399
05400 cfg = ast_config_load(config, config_flags);
05401
05402 if (!cfg) {
05403 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
05404 return -1;
05405 } else if (cfg == CONFIG_STATUS_FILEINVALID) {
05406 ast_log(LOG_ERROR, "Config file %s is in an invalid format. Aborting.\n", config);
05407 return -1;
05408 }
05409
05410
05411 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
05412
05413 unistim_keepalive = 120;
05414 unistim_port = 0;
05415 v = ast_variable_browse(cfg, "general");
05416 while (v) {
05417
05418 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
05419 continue;
05420
05421 if (!strcasecmp(v->name, "keepalive"))
05422 unistim_keepalive = atoi(v->value);
05423 else if (!strcasecmp(v->name, "port"))
05424 unistim_port = atoi(v->value);
05425 else if (!strcasecmp(v->name, "tos")) {
05426 if (ast_str2tos(v->value, &qos.tos))
05427 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
05428 } else if (!strcasecmp(v->name, "tos_audio")) {
05429 if (ast_str2tos(v->value, &qos.tos_audio))
05430 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05431 } else if (!strcasecmp(v->name, "cos")) {
05432 if (ast_str2cos(v->value, &qos.cos))
05433 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
05434 } else if (!strcasecmp(v->name, "cos_audio")) {
05435 if (ast_str2cos(v->value, &qos.cos_audio))
05436 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05437 } else if (!strcasecmp(v->name, "autoprovisioning")) {
05438 if (!strcasecmp(v->value, "no"))
05439 autoprovisioning = AUTOPROVISIONING_NO;
05440 else if (!strcasecmp(v->value, "yes"))
05441 autoprovisioning = AUTOPROVISIONING_YES;
05442 else if (!strcasecmp(v->value, "db"))
05443 autoprovisioning = AUTOPROVISIONING_DB;
05444 else if (!strcasecmp(v->value, "tn"))
05445 autoprovisioning = AUTOPROVISIONING_TN;
05446 else
05447 ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
05448 } else if (!strcasecmp(v->name, "public_ip")) {
05449 if (!ast_strlen_zero(v->value)) {
05450 if (!(hp = ast_gethostbyname(v->value, &ahp)))
05451 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
05452 else {
05453 memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
05454 public_ip.sin_family = AF_INET;
05455 }
05456 }
05457 }
05458 v = v->next;
05459 }
05460 if ((unistim_keepalive < 10) ||
05461 (unistim_keepalive >
05462 255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
05463 ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
05464 ast_config_destroy(cfg);
05465 return -1;
05466 }
05467 packet_send_ping[4] =
05468 unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
05469 if ((unistim_port < 1) || (unistim_port > 65535)) {
05470 ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
05471 ast_config_destroy(cfg);
05472 return -1;
05473 }
05474 unistim_keepalive *= 1000;
05475
05476 ast_mutex_lock(&devicelock);
05477 d = devices;
05478 while (d) {
05479 if (d->to_delete >= 0)
05480 d->to_delete = 1;
05481 d = d->next;
05482 }
05483 ast_mutex_unlock(&devicelock);
05484
05485 cat = ast_category_browse(cfg, NULL);
05486 while (cat) {
05487 if (strcasecmp(cat, "general")) {
05488 d = build_device(cat, ast_variable_browse(cfg, cat));
05489 }
05490 cat = ast_category_browse(cfg, cat);
05491 }
05492 ast_mutex_lock(&devicelock);
05493 d = devices;
05494 while (d) {
05495 if (d->to_delete) {
05496 int i;
05497
05498 if (unistimdebug)
05499 ast_verb(0, "Removing device '%s'\n", d->name);
05500 if (!d->lines) {
05501 ast_log(LOG_ERROR, "Device '%s' without a line !, aborting\n", d->name);
05502 ast_config_destroy(cfg);
05503 return 0;
05504 }
05505 if (!d->lines->subs[0]) {
05506 ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
05507 d->name);
05508 ast_config_destroy(cfg);
05509 return 0;
05510 }
05511 if (d->lines->subs[0]->owner) {
05512 ast_log(LOG_WARNING,
05513 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
05514 d->name);
05515 d = d->next;
05516 continue;
05517 }
05518 ast_mutex_destroy(&d->lines->subs[0]->lock);
05519 ast_free(d->lines->subs[0]);
05520 for (i = 1; i < MAX_SUBS; i++) {
05521 if (d->lines->subs[i]) {
05522 ast_log(LOG_WARNING,
05523 "Device '%s' with threeway call subchannels allocated, aborting.\n",
05524 d->name);
05525 break;
05526 }
05527 }
05528 if (i < MAX_SUBS) {
05529 d = d->next;
05530 continue;
05531 }
05532 ast_mutex_destroy(&d->lines->lock);
05533 ast_free(d->lines);
05534 if (d->session) {
05535 if (sessions == d->session)
05536 sessions = d->session->next;
05537 else {
05538 s = sessions;
05539 while (s) {
05540 if (s->next == d->session) {
05541 s->next = d->session->next;
05542 break;
05543 }
05544 s = s->next;
05545 }
05546 }
05547 ast_mutex_destroy(&d->session->lock);
05548 ast_free(d->session);
05549 }
05550 if (devices == d)
05551 devices = d->next;
05552 else {
05553 struct unistim_device *d2 = devices;
05554 while (d2) {
05555 if (d2->next == d) {
05556 d2->next = d->next;
05557 break;
05558 }
05559 d2 = d2->next;
05560 }
05561 }
05562 if (d->tz) {
05563 d->tz = ast_tone_zone_unref(d->tz);
05564 }
05565 ast_free(d);
05566 d = devices;
05567 continue;
05568 }
05569 d = d->next;
05570 }
05571 finish_bookmark();
05572 ast_mutex_unlock(&devicelock);
05573 ast_config_destroy(cfg);
05574 ast_mutex_lock(&sessionlock);
05575 s = sessions;
05576 while (s) {
05577 if (s->device)
05578 refresh_all_favorite(s);
05579 s = s->next;
05580 }
05581 ast_mutex_unlock(&sessionlock);
05582
05583 if (unistimsock > -1)
05584 return 0;
05585 bindaddr.sin_addr.s_addr = INADDR_ANY;
05586 bindaddr.sin_port = htons(unistim_port);
05587 bindaddr.sin_family = AF_INET;
05588 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
05589 if (unistimsock < 0) {
05590 ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
05591 return -1;
05592 }
05593 #ifdef HAVE_PKTINFO
05594 {
05595 const int pktinfoFlag = 1;
05596 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
05597 sizeof(pktinfoFlag));
05598 }
05599 #else
05600 if (public_ip.sin_family == 0) {
05601 ast_log(LOG_WARNING,
05602 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
05603 unistimsock = -1;
05604 return -1;
05605 }
05606 #endif
05607 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
05608 sizeof(reuseFlag));
05609 if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
05610 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
05611 ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
05612 strerror(errno));
05613 close(unistimsock);
05614 unistimsock = -1;
05615 } else {
05616 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
05617 ast_netsock_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
05618 }
05619 return 0;
05620 }
05621
05622 static enum ast_rtp_glue_result unistim_get_rtp_peer(struct ast_channel *chan, struct ast_rtp_instance **instance)
05623 {
05624 struct unistim_subchannel *sub = chan->tech_pvt;
05625
05626 ao2_ref(sub->rtp, +1);
05627 *instance = sub->rtp;
05628
05629 return AST_RTP_GLUE_RESULT_LOCAL;
05630 }
05631
05632 static struct ast_rtp_glue unistim_rtp_glue = {
05633 .type = channel_type,
05634 .get_rtp_info = unistim_get_rtp_peer,
05635 };
05636
05637
05638 int load_module(void)
05639 {
05640 int res;
05641
05642 if (!(buff = ast_malloc(SIZE_PAGE)))
05643 goto buff_failed;
05644
05645 io = io_context_create();
05646 if (!io) {
05647 ast_log(LOG_ERROR, "Failed to allocate IO context\n");
05648 goto io_failed;
05649 }
05650
05651 sched = sched_context_create();
05652 if (!sched) {
05653 ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
05654 goto sched_failed;
05655 }
05656
05657 res = reload_config();
05658 if (res)
05659 return AST_MODULE_LOAD_DECLINE;
05660
05661
05662 if (ast_channel_register(&unistim_tech)) {
05663 ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
05664 goto chanreg_failed;
05665 }
05666
05667 ast_rtp_glue_register(&unistim_rtp_glue);
05668
05669 ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05670
05671 restart_monitor();
05672
05673 return AST_MODULE_LOAD_SUCCESS;
05674
05675 chanreg_failed:
05676
05677 sched_context_destroy(sched);
05678 sched = NULL;
05679 sched_failed:
05680 io_context_destroy(io);
05681 io = NULL;
05682 io_failed:
05683 ast_free(buff);
05684 buff = NULL;
05685 buff_failed:
05686 return AST_MODULE_LOAD_FAILURE;
05687 }
05688
05689 static int unload_module(void)
05690 {
05691
05692 if (sched)
05693 sched_context_destroy(sched);
05694
05695 ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05696
05697 ast_channel_unregister(&unistim_tech);
05698 ast_rtp_glue_unregister(&unistim_rtp_glue);
05699
05700 ast_mutex_lock(&monlock);
05701 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
05702 pthread_cancel(monitor_thread);
05703 pthread_kill(monitor_thread, SIGURG);
05704 pthread_join(monitor_thread, NULL);
05705 }
05706 monitor_thread = AST_PTHREADT_STOP;
05707 ast_mutex_unlock(&monlock);
05708
05709 if (buff)
05710 ast_free(buff);
05711 if (unistimsock > -1)
05712 close(unistimsock);
05713
05714 return 0;
05715 }
05716
05717
05718 int reload(void)
05719 {
05720 unistim_reload(NULL, 0, NULL);
05721 return 0;
05722 }
05723
05724 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
05725 .load = load_module,
05726 .unload = unload_module,
05727 .reload = reload,
05728 );