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