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