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: 192941 $")
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 struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass = digit, .src = "unistim" };
02474 struct unistim_subchannel *sub;
02475 sub = pte->device->lines->subs[SUB_REAL];
02476 if (!sub->owner || sub->alreadygone) {
02477 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
02478 return -1;
02479 }
02480
02481
02482 ast_queue_frame(sub->owner, &f);
02483
02484 if (unistimdebug)
02485 ast_verb(0, "Send Digit %c\n", digit);
02486 switch (digit) {
02487 case '0':
02488 send_tone(pte, 941, 1336);
02489 break;
02490 case '1':
02491 send_tone(pte, 697, 1209);
02492 break;
02493 case '2':
02494 send_tone(pte, 697, 1336);
02495 break;
02496 case '3':
02497 send_tone(pte, 697, 1477);
02498 break;
02499 case '4':
02500 send_tone(pte, 770, 1209);
02501 break;
02502 case '5':
02503 send_tone(pte, 770, 1336);
02504 break;
02505 case '6':
02506 send_tone(pte, 770, 1477);
02507 break;
02508 case '7':
02509 send_tone(pte, 852, 1209);
02510 break;
02511 case '8':
02512 send_tone(pte, 852, 1336);
02513 break;
02514 case '9':
02515 send_tone(pte, 852, 1477);
02516 break;
02517 case 'A':
02518 send_tone(pte, 697, 1633);
02519 break;
02520 case 'B':
02521 send_tone(pte, 770, 1633);
02522 break;
02523 case 'C':
02524 send_tone(pte, 852, 1633);
02525 break;
02526 case 'D':
02527 send_tone(pte, 941, 1633);
02528 break;
02529 case '*':
02530 send_tone(pte, 941, 1209);
02531 break;
02532 case '#':
02533 send_tone(pte, 941, 1477);
02534 break;
02535 default:
02536 send_tone(pte, 500, 2000);
02537 }
02538 usleep(150000);
02539 send_tone(pte, 0, 0);
02540 return 0;
02541 }
02542
02543 static void key_call(struct unistimsession *pte, char keycode)
02544 {
02545 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02546 if (keycode == KEY_SHARP)
02547 keycode = '#';
02548 else if (keycode == KEY_STAR)
02549 keycode = '*';
02550 else
02551 keycode -= 0x10;
02552 unistim_do_senddigit(pte, keycode);
02553 return;
02554 }
02555 switch (keycode) {
02556 case KEY_HANGUP:
02557 case KEY_FUNC1:
02558 close_call(pte);
02559 break;
02560 case KEY_FUNC2:
02561 TransferCallStep1(pte);
02562 break;
02563 case KEY_HEADPHN:
02564 if (pte->device->output == OUTPUT_HEADPHONE)
02565 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02566 else
02567 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02568 break;
02569 case KEY_LOUDSPK:
02570 if (pte->device->output != OUTPUT_SPEAKER)
02571 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02572 else
02573 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02574 MUTE_OFF);
02575 break;
02576 case KEY_MUTE:
02577 if (!pte->device->moh) {
02578 if (pte->device->mute == MUTE_ON)
02579 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
02580 else
02581 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
02582 break;
02583 }
02584 case KEY_ONHOLD:
02585 {
02586 struct unistim_subchannel *sub;
02587 struct ast_channel *bridgepeer = NULL;
02588 sub = pte->device->lines->subs[SUB_REAL];
02589 if (!sub->owner) {
02590 ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
02591 return;
02592 }
02593 if ((bridgepeer = ast_bridged_channel(sub->owner))) {
02594 if (pte->device->moh) {
02595 ast_moh_stop(bridgepeer);
02596 pte->device->moh = 0;
02597 send_select_output(pte, pte->device->output, pte->device->volume,
02598 MUTE_OFF);
02599 } else {
02600 ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
02601 pte->device->moh = 1;
02602 send_select_output(pte, pte->device->output, pte->device->volume,
02603 MUTE_ON);
02604 }
02605 } else
02606 ast_log(LOG_WARNING,
02607 "Unable to find peer subchannel for music on hold\n");
02608 break;
02609 }
02610 }
02611 return;
02612 }
02613
02614 static void key_ringing(struct unistimsession *pte, char keycode)
02615 {
02616 if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
02617 HandleCallIncoming(pte);
02618 return;
02619 }
02620 switch (keycode) {
02621 case KEY_HANGUP:
02622 case KEY_FUNC4:
02623 IgnoreCall(pte);
02624 break;
02625 case KEY_FUNC1:
02626 HandleCallIncoming(pte);
02627 break;
02628 }
02629 return;
02630 }
02631
02632 static void Keyfavorite(struct unistimsession *pte, char keycode)
02633 {
02634 int fav;
02635
02636 if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
02637 ast_log(LOG_WARNING, "It's not a favorite key\n");
02638 return;
02639 }
02640 if (keycode == KEY_FAV0)
02641 return;
02642 fav = keycode - KEY_FAV0;
02643 if (pte->device->softkeyicon[fav] == 0)
02644 return;
02645 ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
02646 sizeof(pte->device->phone_number));
02647 HandleCallOutgoing(pte);
02648 return;
02649 }
02650
02651 static void key_dial_page(struct unistimsession *pte, char keycode)
02652 {
02653 if (keycode == KEY_FUNC3) {
02654 if (pte->device->size_phone_number <= 1)
02655 keycode = KEY_FUNC4;
02656 else {
02657 pte->device->size_phone_number -= 2;
02658 keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
02659 }
02660 }
02661 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
02662 char tmpbuf[] = "Number : ...............";
02663 int i = 0;
02664
02665 if (pte->device->size_phone_number >= 15)
02666 return;
02667 if (pte->device->size_phone_number == 0)
02668 send_tone(pte, 0, 0);
02669 while (i < pte->device->size_phone_number) {
02670 tmpbuf[i + 9] = pte->device->phone_number[i];
02671 i++;
02672 }
02673 if (keycode == KEY_SHARP)
02674 keycode = '#';
02675 else if (keycode == KEY_STAR)
02676 keycode = '*';
02677 else
02678 keycode -= 0x10;
02679 tmpbuf[i + 9] = keycode;
02680 pte->device->phone_number[i] = keycode;
02681 pte->device->size_phone_number++;
02682 pte->device->phone_number[i + 1] = 0;
02683 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02684 send_blink_cursor(pte);
02685 send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
02686 return;
02687 }
02688 if (keycode == KEY_FUNC4) {
02689
02690 pte->device->size_phone_number = 0;
02691 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
02692 send_blink_cursor(pte);
02693 send_cursor_pos(pte, TEXT_LINE2 + 0x09);
02694 return;
02695 }
02696
02697 if (pte->device->call_forward[0] == -1) {
02698 if (keycode == KEY_FUNC1) {
02699 ast_copy_string(pte->device->call_forward, pte->device->phone_number,
02700 sizeof(pte->device->call_forward));
02701 show_main_page(pte);
02702 } else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
02703 pte->device->call_forward[0] = '\0';
02704 show_main_page(pte);
02705 }
02706 return;
02707 }
02708 switch (keycode) {
02709 case KEY_FUNC2:
02710 if (ast_strlen_zero(pte->device->redial_number))
02711 break;
02712 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
02713 sizeof(pte->device->phone_number));
02714 case KEY_FUNC1:
02715 HandleCallOutgoing(pte);
02716 break;
02717 case KEY_HANGUP:
02718 if (pte->device->lines->subs[SUB_REAL]->owner) {
02719
02720 if (pte->device->silence_generator) {
02721 if (unistimdebug)
02722 ast_verb(0, "Stopping silence generator\n");
02723 ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
02724 owner, pte->device->silence_generator);
02725 pte->device->silence_generator = NULL;
02726 }
02727 send_tone(pte, 0, 0);
02728 ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
02729 pte->device->moh = 0;
02730 pte->state = STATE_CALL;
02731 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
02732 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
02733 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
02734 send_text_status(pte, "Hangup Transf");
02735 } else
02736 show_main_page(pte);
02737 break;
02738 case KEY_FAV1:
02739 case KEY_FAV2:
02740 case KEY_FAV3:
02741 case KEY_FAV4:
02742 case KEY_FAV5:
02743 Keyfavorite(pte, keycode);
02744 break;
02745 case KEY_LOUDSPK:
02746 if (pte->device->output == OUTPUT_SPEAKER) {
02747 if (pte->device->receiver_state == STATE_OFFHOOK)
02748 send_select_output(pte, pte->device->previous_output, pte->device->volume,
02749 MUTE_OFF);
02750 else
02751 show_main_page(pte);
02752 } else
02753 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
02754 break;
02755 case KEY_HEADPHN:
02756 if (pte->device->output == OUTPUT_HEADPHONE) {
02757 if (pte->device->receiver_state == STATE_OFFHOOK)
02758 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
02759 else
02760 show_main_page(pte);
02761 } else
02762 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
02763 break;
02764 }
02765 return;
02766 }
02767
02768 #define SELECTCODEC_START_ENTRY_POS 15
02769 #define SELECTCODEC_MAX_LENGTH 2
02770 #define SELECTCODEC_MSG "Codec number : .."
02771 static void HandleSelectCodec(struct unistimsession *pte)
02772 {
02773 char buf[30], buf2[5];
02774
02775 pte->state = STATE_SELECTCODEC;
02776 strcpy(buf, "Using codec ");
02777 sprintf(buf2, "%d", pte->device->codec_number);
02778 strcat(buf, buf2);
02779 strcat(buf, " (G711u=0,");
02780
02781 send_text(TEXT_LINE0, TEXT_NORMAL, pte, buf);
02782 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "G723=4,G711a=8,G729A=18)");
02783 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02784 send_blink_cursor(pte);
02785 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02786 pte->size_buff_entry = 0;
02787 send_text_status(pte, "Select BackSpcErase Cancel");
02788 return;
02789 }
02790
02791 static void key_select_codec(struct unistimsession *pte, char keycode)
02792 {
02793 if (keycode == KEY_FUNC2) {
02794 if (pte->size_buff_entry <= 1)
02795 keycode = KEY_FUNC3;
02796 else {
02797 pte->size_buff_entry -= 2;
02798 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02799 }
02800 }
02801 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02802 char tmpbuf[] = SELECTCODEC_MSG;
02803 int i = 0;
02804
02805 if (pte->size_buff_entry >= SELECTCODEC_MAX_LENGTH)
02806 return;
02807
02808 while (i < pte->size_buff_entry) {
02809 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = pte->buff_entry[i];
02810 i++;
02811 }
02812 tmpbuf[i + SELECTCODEC_START_ENTRY_POS] = keycode - 0x10;
02813 pte->buff_entry[i] = keycode - 0x10;
02814 pte->size_buff_entry++;
02815 send_text(TEXT_LINE2, TEXT_INVERSE, pte, tmpbuf);
02816 send_blink_cursor(pte);
02817 send_cursor_pos(pte,
02818 (unsigned char) (TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS + 1 + i));
02819 return;
02820 }
02821
02822 switch (keycode) {
02823 case KEY_FUNC1:
02824 if (pte->size_buff_entry == 1)
02825 pte->device->codec_number = pte->buff_entry[0] - 48;
02826 else if (pte->size_buff_entry == 2)
02827 pte->device->codec_number =
02828 ((pte->buff_entry[0] - 48) * 10) + (pte->buff_entry[1] - 48);
02829 show_main_page(pte);
02830 break;
02831 case KEY_FUNC3:
02832 pte->size_buff_entry = 0;
02833 send_text(TEXT_LINE2, TEXT_INVERSE, pte, SELECTCODEC_MSG);
02834 send_blink_cursor(pte);
02835 send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
02836 break;
02837 case KEY_HANGUP:
02838 case KEY_FUNC4:
02839 show_main_page(pte);
02840 break;
02841 }
02842 return;
02843 }
02844
02845 #define SELECTEXTENSION_START_ENTRY_POS 0
02846 #define SELECTEXTENSION_MAX_LENGTH 10
02847 #define SELECTEXTENSION_MSG ".........."
02848 static void ShowExtensionPage(struct unistimsession *pte)
02849 {
02850 pte->state = STATE_EXTENSION;
02851
02852 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
02853 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
02854 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
02855 send_blink_cursor(pte);
02856 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
02857 send_text_status(pte, "Enter BackSpcErase");
02858 pte->size_buff_entry = 0;
02859 return;
02860 }
02861
02862 static void key_select_extension(struct unistimsession *pte, char keycode)
02863 {
02864 if (keycode == KEY_FUNC2) {
02865 if (pte->size_buff_entry <= 1)
02866 keycode = KEY_FUNC3;
02867 else {
02868 pte->size_buff_entry -= 2;
02869 keycode = pte->buff_entry[pte->size_buff_entry] + 0x10;
02870 }
02871 }
02872 if ((keycode >= KEY_0) && (keycode <= KEY_9)) {
02873 char tmpbuf[] = SELECTEXTENSION_MSG;
02874 int i = 0;
02875
02876 if (pte->size_buff_entry >= SELECTEXTENSION_MAX_LENGTH)
02877 return;
02878
02879 while (i < pte->size_buff_entry) {
02880 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = pte->buff_entry[i];
02881 i++;
02882 }
02883 tmpbuf[i + SELECTEXTENSION_START_ENTRY_POS] = keycode - 0x10;
02884 pte->buff_entry[i] = keycode - 0x10;
02885 pte->size_buff_entry++;
02886 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
02887 send_blink_cursor(pte);
02888 send_cursor_pos(pte,
02889 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS + 1 +
02890 i));
02891 return;
02892 }
02893
02894 switch (keycode) {
02895 case KEY_FUNC1:
02896 if (pte->size_buff_entry < 1)
02897 return;
02898 if (autoprovisioning == AUTOPROVISIONING_TN) {
02899 struct unistim_device *d;
02900
02901
02902 ast_mutex_lock(&devicelock);
02903 d = devices;
02904 pte->buff_entry[pte->size_buff_entry] = '\0';
02905 while (d) {
02906 if (d->id[0] == 'T') {
02907
02908 if (!strcmp((d->id) + 1, pte->buff_entry)) {
02909 pte->device = d;
02910 d->session = pte;
02911 d->codec_number = DEFAULT_CODEC;
02912 d->pos_fav = 0;
02913 d->missed_call = 0;
02914 d->receiver_state = STATE_ONHOOK;
02915 strcpy(d->id, pte->macaddr);
02916 pte->device->extension_number[0] = 'T';
02917 pte->device->extension = EXTENSION_TN;
02918 ast_copy_string((pte->device->extension_number) + 1,
02919 pte->buff_entry, pte->size_buff_entry + 1);
02920 ast_mutex_unlock(&devicelock);
02921 show_main_page(pte);
02922 refresh_all_favorite(pte);
02923 return;
02924 }
02925 }
02926 d = d->next;
02927 }
02928 ast_mutex_unlock(&devicelock);
02929 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
02930 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
02931 send_cursor_pos(pte,
02932 (unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
02933 pte->size_buff_entry));
02934 send_blink_cursor(pte);
02935 } else {
02936 ast_copy_string(pte->device->extension_number, pte->buff_entry,
02937 pte->size_buff_entry + 1);
02938 if (RegisterExtension(pte)) {
02939 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
02940 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
02941 send_cursor_pos(pte,
02942 (unsigned char) (TEXT_LINE2 +
02943 SELECTEXTENSION_START_ENTRY_POS +
02944 pte->size_buff_entry));
02945 send_blink_cursor(pte);
02946 } else
02947 show_main_page(pte);
02948 }
02949 break;
02950 case KEY_FUNC3:
02951 pte->size_buff_entry = 0;
02952 send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
02953 send_blink_cursor(pte);
02954 send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
02955 break;
02956 }
02957 return;
02958 }
02959
02960 static int ReformatNumber(char *number)
02961 {
02962 int pos = 0, i = 0, size = strlen(number);
02963
02964 for (; i < size; i++) {
02965 if ((number[i] >= '0') && (number[i] <= '9')) {
02966 if (i == pos) {
02967 pos++;
02968 continue;
02969 }
02970 number[pos] = number[i];
02971 pos++;
02972 }
02973 }
02974 number[pos] = 0;
02975 return pos;
02976 }
02977
02978 static void show_entry_history(struct unistimsession *pte, FILE ** f)
02979 {
02980 char line[TEXT_LENGTH_MAX + 1], status[STATUS_LENGTH_MAX + 1], func1[10], func2[10],
02981 func3[10];
02982
02983 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
02984 display_last_error("Can't read history date entry");
02985 fclose(*f);
02986 return;
02987 }
02988 line[sizeof(line) - 1] = '\0';
02989 send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
02990 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
02991 display_last_error("Can't read callerid entry");
02992 fclose(*f);
02993 return;
02994 }
02995 line[sizeof(line) - 1] = '\0';
02996 ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
02997 send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
02998 if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
02999 display_last_error("Can't read callername entry");
03000 fclose(*f);
03001 return;
03002 }
03003 line[sizeof(line) - 1] = '\0';
03004 send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
03005 fclose(*f);
03006
03007 snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
03008 pte->buff_entry[1]);
03009 send_texttitle(pte, line);
03010
03011 if (pte->buff_entry[2] == 1)
03012 strcpy(func1, " ");
03013 else
03014 strcpy(func1, "Prvious");
03015 if (pte->buff_entry[2] >= pte->buff_entry[1])
03016 strcpy(func2, " ");
03017 else
03018 strcpy(func2, "Next ");
03019 if (ReformatNumber(pte->device->lst_cid))
03020 strcpy(func3, "Redial ");
03021 else
03022 strcpy(func3, " ");
03023 snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
03024 send_text_status(pte, status);
03025 }
03026
03027 static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
03028 {
03029 char tmp[AST_CONFIG_MAX_PATH];
03030 char count;
03031
03032 snprintf(tmp, sizeof(tmp), "%s/%s/%s-%c.csv", ast_config_AST_LOG_DIR,
03033 USTM_LOG_DIR, pte->device->name, way);
03034 *f = fopen(tmp, "r");
03035 if (!*f) {
03036 display_last_error("Unable to open history file");
03037 return 0;
03038 }
03039 if (fread(&count, 1, 1, *f) != 1) {
03040 display_last_error("Unable to read history header - display.");
03041 fclose(*f);
03042 return 0;
03043 }
03044 if (count > MAX_ENTRY_LOG) {
03045 ast_log(LOG_WARNING, "Invalid count in history header of %s (%d max %d)\n", tmp,
03046 count, MAX_ENTRY_LOG);
03047 fclose(*f);
03048 return 0;
03049 }
03050 return count;
03051 }
03052
03053 static void show_history(struct unistimsession *pte, char way)
03054 {
03055 FILE *f;
03056 char count;
03057
03058 if (!pte->device)
03059 return;
03060 if (!pte->device->callhistory)
03061 return;
03062 count = OpenHistory(pte, way, &f);
03063 if (!count)
03064 return;
03065 pte->buff_entry[0] = way;
03066 pte->buff_entry[1] = count;
03067 pte->buff_entry[2] = 1;
03068 show_entry_history(pte, &f);
03069 pte->state = STATE_HISTORY;
03070 }
03071
03072 static void show_main_page(struct unistimsession *pte)
03073 {
03074 char tmpbuf[TEXT_LENGTH_MAX + 1];
03075
03076
03077 if ((pte->device->extension == EXTENSION_ASK) &&
03078 (ast_strlen_zero(pte->device->extension_number))) {
03079 ShowExtensionPage(pte);
03080 return;
03081 }
03082
03083 pte->state = STATE_MAINPAGE;
03084
03085 send_tone(pte, 0, 0);
03086 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
03087 pte->device->lines->lastmsgssent = 0;
03088 send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
03089 pte->device->softkeylabel[pte->device->softkeylinepos]);
03090 if (!ast_strlen_zero(pte->device->call_forward)) {
03091 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
03092 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
03093 Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
03094 send_text_status(pte, "Dial Redial NoForwd");
03095 } else {
03096 if ((pte->device->extension == EXTENSION_ASK) ||
03097 (pte->device->extension == EXTENSION_TN))
03098 send_text_status(pte, "Dial Redial ForwardUnregis");
03099 else
03100 send_text_status(pte, "Dial Redial Forward");
03101
03102 send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
03103 if (pte->device->missed_call == 0)
03104 send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
03105 else {
03106 sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
03107 send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
03108 Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
03109 }
03110 }
03111 if (ast_strlen_zero(pte->device->maintext2)) {
03112 strcpy(tmpbuf, "IP : ");
03113 strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03114 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
03115 } else
03116 send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
03117 send_texttitle(pte, pte->device->titledefault);
03118 change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
03119 }
03120
03121 static void key_main_page(struct unistimsession *pte, char keycode)
03122 {
03123 if (pte->device->missed_call) {
03124 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03125 pte->device->missed_call = 0;
03126 }
03127 if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
03128 handle_dial_page(pte);
03129 key_dial_page(pte, keycode);
03130 return;
03131 }
03132 switch (keycode) {
03133 case KEY_FUNC1:
03134 handle_dial_page(pte);
03135 break;
03136 case KEY_FUNC2:
03137 if (ast_strlen_zero(pte->device->redial_number))
03138 break;
03139 if ((pte->device->output == OUTPUT_HANDSET) &&
03140 (pte->device->receiver_state == STATE_ONHOOK))
03141 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03142 else
03143 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03144
03145 ast_copy_string(pte->device->phone_number, pte->device->redial_number,
03146 sizeof(pte->device->phone_number));
03147 HandleCallOutgoing(pte);
03148 break;
03149 case KEY_FUNC3:
03150 if (!ast_strlen_zero(pte->device->call_forward)) {
03151
03152 memmove(pte->device->call_forward + 1, pte->device->call_forward,
03153 sizeof(pte->device->call_forward));
03154 pte->device->call_forward[0] = '\0';
03155 Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
03156 pte->device->output = OUTPUT_HANDSET;
03157 show_main_page(pte);
03158 break;
03159 }
03160 pte->device->call_forward[0] = -1;
03161 handle_dial_page(pte);
03162 break;
03163 case KEY_FUNC4:
03164 if (pte->device->extension == EXTENSION_ASK) {
03165 UnregisterExtension(pte);
03166 pte->device->extension_number[0] = '\0';
03167 ShowExtensionPage(pte);
03168 } else if (pte->device->extension == EXTENSION_TN) {
03169 ast_mutex_lock(&devicelock);
03170 strcpy(pte->device->id, pte->device->extension_number);
03171 pte->buff_entry[0] = '\0';
03172 pte->size_buff_entry = 0;
03173 pte->device->session = NULL;
03174 pte->device = NULL;
03175 ast_mutex_unlock(&devicelock);
03176 ShowExtensionPage(pte);
03177 }
03178 break;
03179 case KEY_FAV0:
03180 handle_dial_page(pte);
03181 break;
03182 case KEY_FAV1:
03183 case KEY_FAV2:
03184 case KEY_FAV3:
03185 case KEY_FAV4:
03186 case KEY_FAV5:
03187 if ((pte->device->output == OUTPUT_HANDSET) &&
03188 (pte->device->receiver_state == STATE_ONHOOK))
03189 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03190 else
03191 send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
03192 Keyfavorite(pte, keycode);
03193 break;
03194 case KEY_CONF:
03195 HandleSelectCodec(pte);
03196 break;
03197 case KEY_LOUDSPK:
03198 send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
03199 handle_dial_page(pte);
03200 break;
03201 case KEY_HEADPHN:
03202 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03203 handle_dial_page(pte);
03204 break;
03205 case KEY_SNDHIST:
03206 show_history(pte, 'o');
03207 break;
03208 case KEY_RCVHIST:
03209 show_history(pte, 'i');
03210 break;
03211 }
03212 return;
03213 }
03214
03215 static void key_history(struct unistimsession *pte, char keycode)
03216 {
03217 FILE *f;
03218 char count;
03219 long offset;
03220
03221 switch (keycode) {
03222 case KEY_UP:
03223 case KEY_LEFT:
03224 case KEY_FUNC1:
03225 if (pte->buff_entry[2] <= 1)
03226 return;
03227 pte->buff_entry[2]--;
03228 count = OpenHistory(pte, pte->buff_entry[0], &f);
03229 if (!count)
03230 return;
03231 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03232 if (fseek(f, offset, SEEK_CUR)) {
03233 display_last_error("Unable to seek history entry.");
03234 fclose(f);
03235 return;
03236 }
03237 show_entry_history(pte, &f);
03238 break;
03239 case KEY_DOWN:
03240 case KEY_RIGHT:
03241 case KEY_FUNC2:
03242 if (pte->buff_entry[2] >= pte->buff_entry[1])
03243 return;
03244 pte->buff_entry[2]++;
03245 count = OpenHistory(pte, pte->buff_entry[0], &f);
03246 if (!count)
03247 return;
03248 offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
03249 if (fseek(f, offset, SEEK_CUR)) {
03250 display_last_error("Unable to seek history entry.");
03251 fclose(f);
03252 return;
03253 }
03254 show_entry_history(pte, &f);
03255 break;
03256 case KEY_FUNC3:
03257 if (!ReformatNumber(pte->device->lst_cid))
03258 break;
03259 ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
03260 sizeof(pte->device->redial_number));
03261 key_main_page(pte, KEY_FUNC2);
03262 break;
03263 case KEY_FUNC4:
03264 case KEY_HANGUP:
03265 show_main_page(pte);
03266 break;
03267 case KEY_SNDHIST:
03268 if (pte->buff_entry[0] == 'i')
03269 show_history(pte, 'o');
03270 else
03271 show_main_page(pte);
03272 break;
03273 case KEY_RCVHIST:
03274 if (pte->buff_entry[0] == 'i')
03275 show_main_page(pte);
03276 else
03277 show_history(pte, 'i');
03278 break;
03279 }
03280 return;
03281 }
03282
03283 static void init_phone_step2(struct unistimsession *pte)
03284 {
03285 BUFFSEND;
03286 if (unistimdebug)
03287 ast_verb(0, "Sending S4\n");
03288 memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
03289 send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
03290 send_date_time2(pte);
03291 send_date_time3(pte);
03292 if (unistimdebug)
03293 ast_verb(0, "Sending S7\n");
03294 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03295 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03296 if (unistimdebug)
03297 ast_verb(0, "Sending Contrast\n");
03298 memcpy(buffsend + SIZE_HEADER, packet_send_Contrast, sizeof(packet_send_Contrast));
03299 if (pte->device != NULL)
03300 buffsend[9] = pte->device->contrast;
03301 send_client(SIZE_HEADER + sizeof(packet_send_Contrast), buffsend, pte);
03302
03303 if (unistimdebug)
03304 ast_verb(0, "Sending S9\n");
03305 memcpy(buffsend + SIZE_HEADER, packet_send_s9, sizeof(packet_send_s9));
03306 send_client(SIZE_HEADER + sizeof(packet_send_s9), buffsend, pte);
03307 send_no_ring(pte);
03308
03309 if (unistimdebug)
03310 ast_verb(0, "Sending S7\n");
03311 memcpy(buffsend + SIZE_HEADER, packet_send_S7, sizeof(packet_send_S7));
03312 send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
03313 send_led_update(pte, 0);
03314 send_ping(pte);
03315 if (pte->state < STATE_MAINPAGE) {
03316 if (autoprovisioning == AUTOPROVISIONING_TN) {
03317 ShowExtensionPage(pte);
03318 return;
03319 } else {
03320 int i;
03321 char tmp[30];
03322
03323 for (i = 1; i < 6; i++)
03324 send_favorite(i, 0, pte, "");
03325 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
03326 send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
03327 strcpy(tmp, "MAC = ");
03328 strcat(tmp, pte->macaddr);
03329 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
03330 send_text_status(pte, "");
03331 send_texttitle(pte, "UNISTIM for*");
03332 return;
03333 }
03334 }
03335 show_main_page(pte);
03336 refresh_all_favorite(pte);
03337 if (unistimdebug)
03338 ast_verb(0, "Sending arrow\n");
03339 memcpy(buffsend + SIZE_HEADER, packet_send_arrow, sizeof(packet_send_arrow));
03340 send_client(SIZE_HEADER + sizeof(packet_send_arrow), buffsend, pte);
03341 return;
03342 }
03343
03344 static void process_request(int size, unsigned char *buf, struct unistimsession *pte)
03345 {
03346 char tmpbuf[255];
03347 if (memcmp
03348 (buf + SIZE_HEADER, packet_recv_resume_connection_with_server,
03349 sizeof(packet_recv_resume_connection_with_server)) == 0) {
03350 rcv_resume_connection_with_server(pte);
03351 return;
03352 }
03353 if (memcmp(buf + SIZE_HEADER, packet_recv_firm_version, sizeof(packet_recv_firm_version)) ==
03354 0) {
03355 buf[size] = 0;
03356 if (unistimdebug)
03357 ast_verb(0, "Got the firmware version : '%s'\n", buf + 13);
03358 init_phone_step2(pte);
03359 return;
03360 }
03361 if (memcmp(buf + SIZE_HEADER, packet_recv_mac_addr, sizeof(packet_recv_mac_addr)) == 0) {
03362 rcv_mac_addr(pte, buf);
03363 return;
03364 }
03365 if (memcmp(buf + SIZE_HEADER, packet_recv_r2, sizeof(packet_recv_r2)) == 0) {
03366 if (unistimdebug)
03367 ast_verb(0, "R2 received\n");
03368 return;
03369 }
03370
03371 if (pte->state < STATE_MAINPAGE) {
03372 if (unistimdebug)
03373 ast_verb(0, "Request not authorized in this state\n");
03374 return;
03375 }
03376 if (!memcmp(buf + SIZE_HEADER, packet_recv_pressed_key, sizeof(packet_recv_pressed_key))) {
03377 char keycode = buf[13];
03378
03379 if (unistimdebug)
03380 ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
03381 pte->state);
03382
03383 switch (pte->state) {
03384 case STATE_INIT:
03385 if (unistimdebug)
03386 ast_verb(0, "No keys allowed in the init state\n");
03387 break;
03388 case STATE_AUTHDENY:
03389 if (unistimdebug)
03390 ast_verb(0, "No keys allowed in authdeny state\n");
03391 break;
03392 case STATE_MAINPAGE:
03393 key_main_page(pte, keycode);
03394 break;
03395 case STATE_DIALPAGE:
03396 key_dial_page(pte, keycode);
03397 break;
03398 case STATE_RINGING:
03399 key_ringing(pte, keycode);
03400 break;
03401 case STATE_CALL:
03402 key_call(pte, keycode);
03403 break;
03404 case STATE_EXTENSION:
03405 key_select_extension(pte, keycode);
03406 break;
03407 case STATE_SELECTCODEC:
03408 key_select_codec(pte, keycode);
03409 break;
03410 case STATE_HISTORY:
03411 key_history(pte, keycode);
03412 break;
03413 default:
03414 ast_log(LOG_WARNING, "Key : Unknown state\n");
03415 }
03416 return;
03417 }
03418 if (memcmp(buf + SIZE_HEADER, packet_recv_pick_up, sizeof(packet_recv_pick_up)) == 0) {
03419 if (unistimdebug)
03420 ast_verb(0, "Handset off hook\n");
03421 if (!pte->device)
03422 return;
03423 pte->device->receiver_state = STATE_OFFHOOK;
03424 if (pte->device->output == OUTPUT_HEADPHONE)
03425 send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
03426 else
03427 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03428 if (pte->state == STATE_RINGING)
03429 HandleCallIncoming(pte);
03430 else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
03431 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03432 else if (pte->state == STATE_EXTENSION)
03433 return;
03434 else {
03435 send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
03436 handle_dial_page(pte);
03437 }
03438 return;
03439 }
03440 if (memcmp(buf + SIZE_HEADER, packet_recv_hangup, sizeof(packet_recv_hangup)) == 0) {
03441 if (unistimdebug)
03442 ast_verb(0, "Handset on hook\n");
03443 if (!pte->device)
03444 return;
03445 pte->device->receiver_state = STATE_ONHOOK;
03446 if (pte->state == STATE_CALL)
03447 close_call(pte);
03448 else if (pte->device->lines->subs[SUB_REAL]->owner)
03449 close_call(pte);
03450 else if (pte->state == STATE_EXTENSION)
03451 return;
03452 else
03453 show_main_page(pte);
03454 return;
03455 }
03456 strcpy(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
03457 strcat(tmpbuf, " Unknown request packet\n");
03458 if (unistimdebug)
03459 ast_debug(1, "%s", tmpbuf);
03460 return;
03461 }
03462
03463 static void parsing(int size, unsigned char *buf, struct unistimsession *pte,
03464 struct sockaddr_in *addr_from)
03465 {
03466 unsigned short *sbuf = (unsigned short *) buf;
03467 unsigned short seq;
03468 char tmpbuf[255];
03469
03470 strcpy(tmpbuf, ast_inet_ntoa(addr_from->sin_addr));
03471
03472 if (size < 10) {
03473 if (size == 0) {
03474 ast_log(LOG_WARNING, "%s Read error\n", tmpbuf);
03475 } else {
03476 ast_log(LOG_NOTICE, "%s Packet too short - ignoring\n", tmpbuf);
03477 }
03478 return;
03479 }
03480 if (sbuf[0] == 0xffff) {
03481 if (size != sizeof(packet_rcv_discovery)) {
03482 ast_log(LOG_NOTICE, "%s Invalid size of a discovery packet\n", tmpbuf);
03483 } else {
03484 if (memcmp(buf, packet_rcv_discovery, sizeof(packet_rcv_discovery)) == 0) {
03485 if (unistimdebug)
03486 ast_verb(0, "Discovery packet received - Sending Discovery ACK\n");
03487 if (pte) {
03488 if (pte->state == STATE_INIT) {
03489 if (unistimdebug)
03490 ast_verb(1, "Duplicated Discovery packet\n");
03491 send_raw_client(sizeof(packet_send_discovery_ack),
03492 packet_send_discovery_ack, addr_from, &pte->sout);
03493 pte->seq_phone = (short) 0x0000;
03494 } else {
03495 close_client(pte);
03496 if (create_client(addr_from))
03497 send_raw_client(sizeof(packet_send_discovery_ack),
03498 packet_send_discovery_ack, addr_from, &pte->sout);
03499 }
03500 } else {
03501
03502 if ((pte = create_client(addr_from)))
03503 send_raw_client(sizeof(packet_send_discovery_ack),
03504 packet_send_discovery_ack, addr_from, &pte->sout);
03505 }
03506 return;
03507 }
03508 ast_log(LOG_NOTICE, "%s Invalid discovery packet\n", tmpbuf);
03509 }
03510 return;
03511 }
03512 if (!pte) {
03513 if (unistimdebug)
03514 ast_verb(0, "%s Not a discovery packet from an unknown source : ignoring\n",
03515 tmpbuf);
03516 return;
03517 }
03518
03519 if (sbuf[0] != 0) {
03520 ast_log(LOG_NOTICE, "Unknown packet received - ignoring\n");
03521 return;
03522 }
03523 if (buf[5] != 2) {
03524 ast_log(LOG_NOTICE, "%s Wrong direction : got 0x%.2x expected 0x02\n", tmpbuf,
03525 buf[5]);
03526 return;
03527 }
03528 seq = ntohs(sbuf[1]);
03529 if (buf[4] == 1) {
03530 ast_mutex_lock(&pte->lock);
03531 if (unistimdebug)
03532 ast_verb(6, "ACK received for packet #0x%.4x\n", seq);
03533 pte->nb_retransmit = 0;
03534
03535 if ((pte->last_seq_ack) + 1 == seq) {
03536 pte->last_seq_ack++;
03537 check_send_queue(pte);
03538 ast_mutex_unlock(&pte->lock);
03539 return;
03540 }
03541 if (pte->last_seq_ack > seq) {
03542 if (pte->last_seq_ack == 0xffff) {
03543 ast_verb(0, "ACK at 0xffff, restarting counter.\n");
03544 pte->last_seq_ack = 0;
03545 } else
03546 ast_log(LOG_NOTICE,
03547 "%s Warning : ACK received for an already ACKed packet : #0x%.4x we are at #0x%.4x\n",
03548 tmpbuf, seq, pte->last_seq_ack);
03549 ast_mutex_unlock(&pte->lock);
03550 return;
03551 }
03552 if (pte->seq_server < seq) {
03553 ast_log(LOG_NOTICE,
03554 "%s Error : ACK received for a non-existent packet : #0x%.4x\n",
03555 tmpbuf, pte->seq_server);
03556 ast_mutex_unlock(&pte->lock);
03557 return;
03558 }
03559 if (unistimdebug)
03560 ast_verb(0, "%s ACK gap : Received ACK #0x%.4x, previous was #0x%.4x\n",
03561 tmpbuf, seq, pte->last_seq_ack);
03562 pte->last_seq_ack = seq;
03563 check_send_queue(pte);
03564 ast_mutex_unlock(&pte->lock);
03565 return;
03566 }
03567 if (buf[4] == 2) {
03568 if (unistimdebug)
03569 ast_verb(0, "Request received\n");
03570 if (pte->seq_phone == seq) {
03571
03572 buf[4] = 1;
03573 buf[5] = 1;
03574 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03575 pte->seq_phone++;
03576
03577 process_request(size, buf, pte);
03578 return;
03579 }
03580 if (pte->seq_phone > seq) {
03581 ast_log(LOG_NOTICE,
03582 "%s Warning : received a retransmitted packet : #0x%.4x (we are at #0x%.4x)\n",
03583 tmpbuf, seq, pte->seq_phone);
03584
03585
03586 buf[4] = 1;
03587 buf[5] = 1;
03588 send_raw_client(SIZE_HEADER, buf, addr_from, &pte->sout);
03589 return;
03590 }
03591 ast_log(LOG_NOTICE,
03592 "%s Warning : we lost a packet : received #0x%.4x (we are at #0x%.4x)\n",
03593 tmpbuf, seq, pte->seq_phone);
03594 return;
03595 }
03596 if (buf[4] == 0) {
03597 ast_log(LOG_NOTICE, "%s Retransmit request for packet #0x%.4x\n", tmpbuf, seq);
03598 if (pte->last_seq_ack > seq) {
03599 ast_log(LOG_NOTICE,
03600 "%s Error : received a request for an already ACKed packet : #0x%.4x\n",
03601 tmpbuf, pte->last_seq_ack);
03602 return;
03603 }
03604 if (pte->seq_server < seq) {
03605 ast_log(LOG_NOTICE,
03606 "%s Error : received a request for a non-existent packet : #0x%.4x\n",
03607 tmpbuf, pte->seq_server);
03608 return;
03609 }
03610 send_retransmit(pte);
03611 return;
03612 }
03613 ast_log(LOG_NOTICE, "%s Unknown request : got 0x%.2x expected 0x00,0x01 or 0x02\n",
03614 tmpbuf, buf[4]);
03615 return;
03616 }
03617
03618 static struct unistimsession *channel_to_session(struct ast_channel *ast)
03619 {
03620 struct unistim_subchannel *sub;
03621 if (!ast) {
03622 ast_log(LOG_WARNING, "Unistim callback function called with a null channel\n");
03623 return NULL;
03624 }
03625 if (!ast->tech_pvt) {
03626 ast_log(LOG_WARNING, "Unistim callback function called without a tech_pvt\n");
03627 return NULL;
03628 }
03629 sub = ast->tech_pvt;
03630
03631 if (!sub->parent) {
03632 ast_log(LOG_WARNING, "Unistim callback function called without a line\n");
03633 return NULL;
03634 }
03635 if (!sub->parent->parent) {
03636 ast_log(LOG_WARNING, "Unistim callback function called without a device\n");
03637 return NULL;
03638 }
03639 if (!sub->parent->parent->session) {
03640 ast_log(LOG_WARNING, "Unistim callback function called without a session\n");
03641 return NULL;
03642 }
03643 return sub->parent->parent->session;
03644 }
03645
03646
03647
03648 static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
03649 {
03650 int res = 0;
03651 struct unistim_subchannel *sub;
03652 struct unistimsession *session;
03653
03654 session = channel_to_session(ast);
03655 if (!session) {
03656 ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
03657 return -1;
03658 }
03659
03660 sub = ast->tech_pvt;
03661 if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
03662 ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
03663 ast->name);
03664 return -1;
03665 }
03666
03667 if (unistimdebug)
03668 ast_verb(3, "unistim_call(%s)\n", ast->name);
03669
03670 session->state = STATE_RINGING;
03671 Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
03672
03673 if (sub->owner) {
03674 if (sub->owner->cid.cid_num) {
03675 send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->cid.cid_num);
03676 change_callerid(session, 0, sub->owner->cid.cid_num);
03677 } else {
03678 send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
03679 change_callerid(session, 0, DEFAULTCALLERID);
03680 }
03681 if (sub->owner->cid.cid_name) {
03682 send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->cid.cid_name);
03683 change_callerid(session, 1, sub->owner->cid.cid_name);
03684 } else {
03685 send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
03686 change_callerid(session, 1, DEFAULTCALLERNAME);
03687 }
03688 }
03689 send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
03690 send_text_status(session, "Accept Ignore");
03691
03692 if (sub->ringstyle == -1)
03693 send_ring(session, session->device->ringvolume, session->device->ringstyle);
03694 else {
03695 if (sub->ringvolume == -1)
03696 send_ring(session, session->device->ringvolume, sub->ringstyle);
03697 else
03698 send_ring(session, sub->ringvolume, sub->ringstyle);
03699 }
03700 change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
03701
03702 ast_setstate(ast, AST_STATE_RINGING);
03703 ast_queue_control(ast, AST_CONTROL_RINGING);
03704 return res;
03705 }
03706
03707
03708 static int unistim_hangup(struct ast_channel *ast)
03709 {
03710 struct unistim_subchannel *sub;
03711 struct unistim_line *l;
03712 struct unistimsession *s;
03713
03714 s = channel_to_session(ast);
03715 sub = ast->tech_pvt;
03716 if (!s) {
03717 ast_debug(1, "Asked to hangup channel not connected\n");
03718 ast_mutex_lock(&sub->lock);
03719 sub->owner = NULL;
03720 ast->tech_pvt = NULL;
03721 sub->alreadygone = 0;
03722 ast_mutex_unlock(&sub->lock);
03723 if (sub->rtp) {
03724 if (unistimdebug)
03725 ast_verb(0, "Destroying RTP session\n");
03726 ast_rtp_destroy(sub->rtp);
03727 sub->rtp = NULL;
03728 }
03729 return 0;
03730 }
03731 l = sub->parent;
03732 if (unistimdebug)
03733 ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
03734
03735 if ((l->subs[SUB_THREEWAY]) && (sub->subtype == SUB_REAL)) {
03736 if (unistimdebug)
03737 ast_verb(0, "Real call disconnected while talking to threeway\n");
03738 sub->owner = NULL;
03739 ast->tech_pvt = NULL;
03740 return 0;
03741 }
03742 if ((l->subs[SUB_REAL]->owner) && (sub->subtype == SUB_THREEWAY) &&
03743 (sub->alreadygone == 0)) {
03744 if (unistimdebug)
03745 ast_verb(0, "threeway call disconnected, switching to real call\n");
03746 send_text(TEXT_LINE0, TEXT_NORMAL, s, "Three way call canceled,");
03747 send_text(TEXT_LINE1, TEXT_NORMAL, s, "switching back to");
03748 send_text(TEXT_LINE2, TEXT_NORMAL, s, "previous call.");
03749 send_text_status(s, "Hangup Transf");
03750 ast_moh_stop(ast_bridged_channel(l->subs[SUB_REAL]->owner));
03751 swap_subs(l, SUB_THREEWAY, SUB_REAL);
03752 l->parent->moh = 0;
03753 ast_mutex_lock(&sub->lock);
03754 sub->owner = NULL;
03755 ast->tech_pvt = NULL;
03756 ast_mutex_unlock(&sub->lock);
03757 unalloc_sub(l, SUB_THREEWAY);
03758 return 0;
03759 }
03760 ast_mutex_lock(&sub->lock);
03761 sub->owner = NULL;
03762 ast->tech_pvt = NULL;
03763 sub->alreadygone = 0;
03764 ast_mutex_unlock(&sub->lock);
03765 if (!s) {
03766 if (unistimdebug)
03767 ast_verb(0, "Asked to hangup channel not connected (no session)\n");
03768 if (sub->rtp) {
03769 if (unistimdebug)
03770 ast_verb(0, "Destroying RTP session\n");
03771 ast_rtp_destroy(sub->rtp);
03772 sub->rtp = NULL;
03773 }
03774 return 0;
03775 }
03776 if (sub->subtype == SUB_REAL) {
03777
03778 if (s->device->silence_generator) {
03779 if (unistimdebug)
03780 ast_verb(0, "Stopping silence generator\n");
03781 if (sub->owner)
03782 ast_channel_stop_silence_generator(sub->owner,
03783 s->device->silence_generator);
03784 else
03785 ast_log(LOG_WARNING,
03786 "Trying to stop silence generator on a null channel !\n");
03787 s->device->silence_generator = NULL;
03788 }
03789 }
03790 l->parent->moh = 0;
03791 send_no_ring(s);
03792 send_end_call(s);
03793 if (sub->rtp) {
03794 if (unistimdebug)
03795 ast_verb(0, "Destroying RTP session\n");
03796 ast_rtp_destroy(sub->rtp);
03797 sub->rtp = NULL;
03798 } else if (unistimdebug)
03799 ast_verb(0, "No RTP session to destroy\n");
03800 if (l->subs[SUB_THREEWAY]) {
03801 if (unistimdebug)
03802 ast_verb(0, "Cleaning other subchannels\n");
03803 unalloc_sub(l, SUB_THREEWAY);
03804 }
03805 if (s->state == STATE_RINGING)
03806 cancel_dial(s);
03807 else if (s->state == STATE_CALL)
03808 close_call(s);
03809
03810 return 0;
03811 }
03812
03813
03814 static int unistim_answer(struct ast_channel *ast)
03815 {
03816 int res = 0;
03817 struct unistim_subchannel *sub;
03818 struct unistim_line *l;
03819 struct unistimsession *s;
03820
03821 s = channel_to_session(ast);
03822 if (!s) {
03823 ast_log(LOG_WARNING, "unistim_answer on a disconnected device ?\n");
03824 return -1;
03825 }
03826 sub = ast->tech_pvt;
03827 l = sub->parent;
03828
03829 if ((!sub->rtp) && (!l->subs[SUB_THREEWAY]))
03830 start_rtp(sub);
03831 if (unistimdebug)
03832 ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast->name, l->name,
03833 l->parent->name, sub->subtype);
03834 send_text(TEXT_LINE2, TEXT_NORMAL, l->parent->session, "is now on-line");
03835 if (l->subs[SUB_THREEWAY])
03836 send_text_status(l->parent->session, "Transf Cancel");
03837 else
03838 send_text_status(l->parent->session, "Hangup Transf");
03839 send_start_timer(l->parent->session);
03840 if (ast->_state != AST_STATE_UP)
03841 ast_setstate(ast, AST_STATE_UP);
03842 return res;
03843 }
03844
03845
03846
03847 static int unistimsock_read(int *id, int fd, short events, void *ignore)
03848 {
03849 struct sockaddr_in addr_from = { 0, };
03850 struct unistimsession *cur = NULL;
03851 int found = 0;
03852 int tmp = 0;
03853 int dw_num_bytes_rcvd;
03854 #ifdef DUMP_PACKET
03855 int dw_num_bytes_rcvdd;
03856 char iabuf[INET_ADDRSTRLEN];
03857 #endif
03858
03859 dw_num_bytes_rcvd =
03860 recvfrom(unistimsock, buff, SIZE_PAGE, 0, (struct sockaddr *) &addr_from,
03861 &size_addr_from);
03862 if (dw_num_bytes_rcvd == -1) {
03863 if (errno == EAGAIN)
03864 ast_log(LOG_NOTICE, "UNISTIM: Received packet with bad UDP checksum\n");
03865 else if (errno != ECONNREFUSED)
03866 ast_log(LOG_WARNING, "Recv error %d (%s)\n", errno, strerror(errno));
03867 return 1;
03868 }
03869
03870
03871 ast_mutex_lock(&sessionlock);
03872 cur = sessions;
03873 while (cur) {
03874 if (cur->sin.sin_addr.s_addr == addr_from.sin_addr.s_addr) {
03875 found = 1;
03876 break;
03877 }
03878 tmp++;
03879 cur = cur->next;
03880 }
03881 ast_mutex_unlock(&sessionlock);
03882
03883 #ifdef DUMP_PACKET
03884 if (unistimdebug)
03885 ast_verb(0, "\n*** Dump %d bytes from %s - phone_table[%d] ***\n",
03886 dw_num_bytes_rcvd, ast_inet_ntoa(addr_from.sin_addr), tmp);
03887 for (dw_num_bytes_rcvdd = 0; dw_num_bytes_rcvdd < dw_num_bytes_rcvd;
03888 dw_num_bytes_rcvdd++)
03889 ast_verb(0, "%.2x ", (unsigned char) buff[dw_num_bytes_rcvdd]);
03890 ast_verb(0, "\n******************************************\n");
03891 #endif
03892
03893 if (!found) {
03894 if (unistimdebug)
03895 ast_verb(0, "Received a packet from an unknown source\n");
03896 parsing(dw_num_bytes_rcvd, buff, NULL, (struct sockaddr_in *) &addr_from);
03897
03898 } else
03899 parsing(dw_num_bytes_rcvd, buff, cur, (struct sockaddr_in *) &addr_from);
03900
03901 return 1;
03902 }
03903
03904 static struct ast_frame *unistim_rtp_read(const struct ast_channel *ast,
03905 const struct unistim_subchannel *sub)
03906 {
03907
03908 struct ast_frame *f;
03909
03910 if (!ast) {
03911 ast_log(LOG_WARNING, "Channel NULL while reading\n");
03912 return &ast_null_frame;
03913 }
03914
03915 if (!sub->rtp) {
03916 ast_log(LOG_WARNING, "RTP handle NULL while reading on subchannel %d\n",
03917 sub->subtype);
03918 return &ast_null_frame;
03919 }
03920
03921 switch (ast->fdno) {
03922 case 0:
03923 f = ast_rtp_read(sub->rtp);
03924 break;
03925 case 1:
03926 f = ast_rtcp_read(sub->rtp);
03927 break;
03928 default:
03929 f = &ast_null_frame;
03930 }
03931
03932 if (sub->owner) {
03933
03934 if (f->frametype == AST_FRAME_VOICE) {
03935 if (f->subclass != sub->owner->nativeformats) {
03936 ast_debug(1,
03937 "Oooh, format changed from %s (%d) to %s (%d)\n",
03938 ast_getformatname(sub->owner->nativeformats),
03939 sub->owner->nativeformats, ast_getformatname(f->subclass),
03940 f->subclass);
03941
03942 sub->owner->nativeformats = f->subclass;
03943 ast_set_read_format(sub->owner, sub->owner->readformat);
03944 ast_set_write_format(sub->owner, sub->owner->writeformat);
03945 }
03946 }
03947 }
03948
03949 return f;
03950 }
03951
03952 static struct ast_frame *unistim_read(struct ast_channel *ast)
03953 {
03954 struct ast_frame *fr;
03955 struct unistim_subchannel *sub = ast->tech_pvt;
03956
03957 ast_mutex_lock(&sub->lock);
03958 fr = unistim_rtp_read(ast, sub);
03959 ast_mutex_unlock(&sub->lock);
03960
03961 return fr;
03962 }
03963
03964 static int unistim_write(struct ast_channel *ast, struct ast_frame *frame)
03965 {
03966 struct unistim_subchannel *sub = ast->tech_pvt;
03967 int res = 0;
03968
03969 if (frame->frametype != AST_FRAME_VOICE) {
03970 if (frame->frametype == AST_FRAME_IMAGE)
03971 return 0;
03972 else {
03973 ast_log(LOG_WARNING, "Can't send %d type frames with unistim_write\n",
03974 frame->frametype);
03975 return 0;
03976 }
03977 } else {
03978 if (!(frame->subclass & ast->nativeformats)) {
03979 ast_log(LOG_WARNING,
03980 "Asked to transmit frame type %s (%d), while native formats is %s (%d) (read/write = %s (%d)/%d)\n",
03981 ast_getformatname(frame->subclass), frame->subclass,
03982 ast_getformatname(ast->nativeformats), ast->nativeformats,
03983 ast_getformatname(ast->readformat), ast->readformat,
03984 ast->writeformat);
03985 return -1;
03986 }
03987 }
03988
03989 if (sub) {
03990 ast_mutex_lock(&sub->lock);
03991 if (sub->rtp) {
03992 res = ast_rtp_write(sub->rtp, frame);
03993 }
03994 ast_mutex_unlock(&sub->lock);
03995 }
03996
03997 return res;
03998 }
03999
04000 static int unistim_fixup(struct ast_channel *oldchan, struct ast_channel *newchan)
04001 {
04002 struct unistim_subchannel *p = newchan->tech_pvt;
04003 struct unistim_line *l = p->parent;
04004
04005 ast_mutex_lock(&p->lock);
04006
04007 ast_debug(1, "New owner for channel USTM/%s@%s-%d is %s\n", l->name,
04008 l->parent->name, p->subtype, newchan->name);
04009
04010 if (p->owner != oldchan) {
04011 ast_log(LOG_WARNING, "old channel wasn't %s (%p) but was %s (%p)\n",
04012 oldchan->name, oldchan, p->owner->name, p->owner);
04013 return -1;
04014 }
04015
04016 p->owner = newchan;
04017
04018 ast_mutex_unlock(&p->lock);
04019
04020 return 0;
04021
04022 }
04023
04024 static char *control2str(int ind)
04025 {
04026 switch (ind) {
04027 case AST_CONTROL_HANGUP:
04028 return "Other end has hungup";
04029 case AST_CONTROL_RING:
04030 return "Local ring";
04031 case AST_CONTROL_RINGING:
04032 return "Remote end is ringing";
04033 case AST_CONTROL_ANSWER:
04034 return "Remote end has answered";
04035 case AST_CONTROL_BUSY:
04036 return "Remote end is busy";
04037 case AST_CONTROL_TAKEOFFHOOK:
04038 return "Make it go off hook";
04039 case AST_CONTROL_OFFHOOK:
04040 return "Line is off hook";
04041 case AST_CONTROL_CONGESTION:
04042 return "Congestion (circuits busy)";
04043 case AST_CONTROL_FLASH:
04044 return "Flash hook";
04045 case AST_CONTROL_WINK:
04046 return "Wink";
04047 case AST_CONTROL_OPTION:
04048 return "Set a low-level option";
04049 case AST_CONTROL_RADIO_KEY:
04050 return "Key Radio";
04051 case AST_CONTROL_RADIO_UNKEY:
04052 return "Un-Key Radio";
04053 case -1:
04054 return "Stop tone";
04055 }
04056 return "UNKNOWN";
04057 }
04058
04059 static void in_band_indication(struct ast_channel *ast, const struct tone_zone *tz,
04060 const char *indication)
04061 {
04062 const struct tone_zone_sound *ts = NULL;
04063
04064 ts = ast_get_indication_tone(tz, indication);
04065
04066 if (ts && ts->data[0])
04067 ast_playtones_start(ast, 0, ts->data, 1);
04068 else
04069 ast_log(LOG_WARNING, "Unable to get indication tone for %s\n", indication);
04070 }
04071
04072 static int unistim_indicate(struct ast_channel *ast, int ind, const void *data,
04073 size_t datalen)
04074 {
04075 struct unistim_subchannel *sub;
04076 struct unistim_line *l;
04077 struct unistimsession *s;
04078
04079 if (unistimdebug) {
04080 ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
04081 control2str(ind), ast->name);
04082 }
04083
04084 s = channel_to_session(ast);
04085 if (!s)
04086 return -1;
04087
04088 sub = ast->tech_pvt;
04089 l = sub->parent;
04090
04091 switch (ind) {
04092 case AST_CONTROL_RINGING:
04093 if (ast->_state != AST_STATE_UP) {
04094 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Ringing...");
04095 in_band_indication(ast, l->parent->tz, "ring");
04096 s->device->missed_call = -1;
04097 break;
04098 }
04099 return -1;
04100 case AST_CONTROL_BUSY:
04101 if (ast->_state != AST_STATE_UP) {
04102 sub->alreadygone = 1;
04103 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Busy");
04104 in_band_indication(ast, l->parent->tz, "busy");
04105 s->device->missed_call = -1;
04106 break;
04107 }
04108 return -1;
04109 case AST_CONTROL_CONGESTION:
04110 if (ast->_state != AST_STATE_UP) {
04111 sub->alreadygone = 1;
04112 send_text(TEXT_LINE2, TEXT_NORMAL, s, "Congestion");
04113 in_band_indication(ast, l->parent->tz, "congestion");
04114 s->device->missed_call = -1;
04115 break;
04116 }
04117 return -1;
04118 case AST_CONTROL_HOLD:
04119 ast_moh_start(ast, data, NULL);
04120 break;
04121 case AST_CONTROL_UNHOLD:
04122 ast_moh_stop(ast);
04123 break;
04124 case AST_CONTROL_PROGRESS:
04125 case AST_CONTROL_SRCUPDATE:
04126 break;
04127 case -1:
04128 ast_playtones_stop(ast);
04129 s->device->missed_call = 0;
04130 break;
04131 case AST_CONTROL_PROCEEDING:
04132 break;
04133 default:
04134 ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
04135 return -1;
04136 }
04137
04138 return 0;
04139 }
04140
04141 static struct unistim_subchannel *find_subchannel_by_name(const char *dest)
04142 {
04143 struct unistim_line *l;
04144 struct unistim_device *d;
04145 char line[256];
04146 char *at;
04147 char *device;
04148
04149 ast_copy_string(line, dest, sizeof(line));
04150 at = strchr(line, '@');
04151 if (!at) {
04152 ast_log(LOG_NOTICE, "Device '%s' has no @ (at) sign!\n", dest);
04153 return NULL;
04154 }
04155 *at = '\0';
04156 at++;
04157 device = at;
04158 ast_mutex_lock(&devicelock);
04159 d = devices;
04160 at = strchr(device, '/');
04161 if (at)
04162 *at = '\0';
04163 while (d) {
04164 if (!strcasecmp(d->name, device)) {
04165 if (unistimdebug)
04166 ast_verb(0, "Found device: %s\n", d->name);
04167
04168 l = d->lines;
04169 while (l) {
04170
04171 if (!strcasecmp(l->name, line)) {
04172 l->subs[SUB_REAL]->ringvolume = -1;
04173 l->subs[SUB_REAL]->ringstyle = -1;
04174 if (at) {
04175 at++;
04176 if (*at == 'r') {
04177 at++;
04178 if ((*at < '0') || (*at > '7'))
04179 ast_log(LOG_WARNING, "Invalid ring selection (%s)", at);
04180 else {
04181 char ring_volume = -1;
04182 char ring_style = *at - '0';
04183 at++;
04184 if ((*at >= '0') && (*at <= '3'))
04185 ring_volume = *at - '0';
04186 if (unistimdebug)
04187 ast_verb(0, "Distinctive ring : style #%d volume %d\n",
04188 ring_style, ring_volume);
04189 l->subs[SUB_REAL]->ringvolume = ring_volume;
04190 l->subs[SUB_REAL]->ringstyle = ring_style;
04191 }
04192 }
04193 }
04194 ast_mutex_unlock(&devicelock);
04195 return l->subs[SUB_REAL];
04196 }
04197 l = l->next;
04198 }
04199 }
04200 d = d->next;
04201 }
04202
04203 ast_mutex_unlock(&devicelock);
04204
04205 return NULL;
04206 }
04207
04208 static int unistim_senddigit_begin(struct ast_channel *ast, char digit)
04209 {
04210 struct unistimsession *pte = channel_to_session(ast);
04211
04212 if (!pte)
04213 return -1;
04214
04215 return unistim_do_senddigit(pte, digit);
04216 }
04217
04218 static int unistim_senddigit_end(struct ast_channel *ast, char digit, unsigned int duration)
04219 {
04220 struct unistimsession *pte = channel_to_session(ast);
04221 struct ast_frame f = { 0, };
04222 struct unistim_subchannel *sub;
04223
04224 sub = pte->device->lines->subs[SUB_REAL];
04225
04226 if (!sub->owner || sub->alreadygone) {
04227 ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
04228 return -1;
04229 }
04230
04231 if (unistimdebug)
04232 ast_verb(0, "Send Digit off %c\n", digit);
04233
04234 if (!pte)
04235 return -1;
04236
04237 send_tone(pte, 0, 0);
04238 f.frametype = AST_FRAME_DTMF;
04239 f.subclass = digit;
04240 f.src = "unistim";
04241 ast_queue_frame(sub->owner, &f);
04242
04243 return 0;
04244 }
04245
04246
04247
04248 static int unistim_sendtext(struct ast_channel *ast, const char *text)
04249 {
04250 struct unistimsession *pte = channel_to_session(ast);
04251 int size;
04252 char tmp[TEXT_LENGTH_MAX + 1];
04253
04254 if (unistimdebug)
04255 ast_verb(0, "unistim_sendtext called\n");
04256
04257 if (!text) {
04258 ast_log(LOG_WARNING, "unistim_sendtext called with a null text\n");
04259 return 1;
04260 }
04261
04262 size = strlen(text);
04263 if (text[0] == '@') {
04264 int pos = 0, i = 1, tok = 0, sz = 0;
04265 char label[11];
04266 char number[16];
04267 char icon = '\0';
04268 char cur = '\0';
04269
04270 memset(label, 0, 11);
04271 memset(number, 0, 16);
04272 while (text[i]) {
04273 cur = text[i++];
04274 switch (tok) {
04275 case 0:
04276 if ((cur < '0') && (cur > '5')) {
04277 ast_log(LOG_WARNING,
04278 "sendtext failed : position must be a number beetween 0 and 5\n");
04279 return 1;
04280 }
04281 pos = cur - '0';
04282 tok = 1;
04283 continue;
04284 case 1:
04285 if (cur != '@') {
04286 ast_log(LOG_WARNING, "sendtext failed : invalid position\n");
04287 return 1;
04288 }
04289 tok = 2;
04290 continue;
04291 case 2:
04292 if ((cur < '3') && (cur > '6')) {
04293 ast_log(LOG_WARNING,
04294 "sendtext failed : icon must be a number beetween 32 and 63 (first digit invalid)\n");
04295 return 1;
04296 }
04297 icon = (cur - '0') * 10;
04298 tok = 3;
04299 continue;
04300 case 3:
04301 if ((cur < '0') && (cur > '9')) {
04302 ast_log(LOG_WARNING,
04303 "sendtext failed : icon must be a number beetween 32 and 63 (second digit invalid)\n");
04304 return 1;
04305 }
04306 icon += (cur - '0');
04307 tok = 4;
04308 continue;
04309 case 4:
04310 if (cur != '@') {
04311 ast_log(LOG_WARNING,
04312 "sendtext failed : icon must be a number beetween 32 and 63 (too many digits)\n");
04313 return 1;
04314 }
04315 tok = 5;
04316 continue;
04317 case 5:
04318 if (cur == '@') {
04319 tok = 6;
04320 sz = 0;
04321 continue;
04322 }
04323 if (sz > 10)
04324 continue;
04325 label[sz] = cur;
04326 sz++;
04327 continue;
04328 case 6:
04329 if (sz > 15) {
04330 ast_log(LOG_WARNING,
04331 "sendtext failed : extension too long = %d (15 car max)\n",
04332 sz);
04333 return 1;
04334 }
04335 number[sz] = cur;
04336 sz++;
04337 continue;
04338 }
04339 }
04340 if (tok != 6) {
04341 ast_log(LOG_WARNING, "sendtext failed : incomplet command\n");
04342 return 1;
04343 }
04344 if (!pte->device) {
04345 ast_log(LOG_WARNING, "sendtext failed : no device ?\n");
04346 return 1;
04347 }
04348 strcpy(pte->device->softkeylabel[pos], label);
04349 strcpy(pte->device->softkeynumber[pos], number);
04350 pte->device->softkeyicon[pos] = icon;
04351 send_favorite(pos, icon, pte, label);
04352 return 0;
04353 }
04354
04355 if (size <= TEXT_LENGTH_MAX * 2) {
04356 send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Message :");
04357 send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
04358 if (size <= TEXT_LENGTH_MAX) {
04359 send_text(TEXT_LINE2, TEXT_NORMAL, pte, "");
04360 return 0;
04361 }
04362 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04363 tmp[sizeof(tmp) - 1] = '\0';
04364 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04365 return 0;
04366 }
04367 send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
04368 memcpy(tmp, text + TEXT_LENGTH_MAX, TEXT_LENGTH_MAX);
04369 tmp[sizeof(tmp) - 1] = '\0';
04370 send_text(TEXT_LINE1, TEXT_NORMAL, pte, tmp);
04371 memcpy(tmp, text + TEXT_LENGTH_MAX * 2, TEXT_LENGTH_MAX);
04372 tmp[sizeof(tmp) - 1] = '\0';
04373 send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
04374 return 0;
04375 }
04376
04377
04378 static int unistim_send_mwi_to_peer(struct unistimsession *s, unsigned int tick)
04379 {
04380 struct ast_event *event;
04381 int new;
04382 char *mailbox, *context;
04383 struct unistim_line *peer = s->device->lines;
04384
04385 context = mailbox = ast_strdupa(peer->mailbox);
04386 strsep(&context, "@");
04387 if (ast_strlen_zero(context))
04388 context = "default";
04389
04390 event = ast_event_get_cached(AST_EVENT_MWI,
04391 AST_EVENT_IE_MAILBOX, AST_EVENT_IE_PLTYPE_STR, mailbox,
04392 AST_EVENT_IE_CONTEXT, AST_EVENT_IE_PLTYPE_STR, context,
04393 AST_EVENT_IE_END);
04394
04395 if (event) {
04396 new = ast_event_get_ie_uint(event, AST_EVENT_IE_NEWMSGS);
04397 ast_event_destroy(event);
04398 } else {
04399 new = ast_app_has_voicemail(peer->mailbox, "INBOX");
04400 }
04401
04402 peer->nextmsgcheck = tick + TIMER_MWI;
04403
04404
04405 if (new == peer->lastmsgssent) {
04406 return 0;
04407 }
04408
04409 peer->lastmsgssent = new;
04410 if (new == 0) {
04411 send_led_update(s, 0);
04412 } else {
04413 send_led_update(s, 1);
04414 }
04415
04416 return 0;
04417 }
04418
04419
04420
04421 static struct ast_channel *unistim_new(struct unistim_subchannel *sub, int state)
04422 {
04423 struct ast_channel *tmp;
04424 struct unistim_line *l;
04425 int fmt;
04426
04427 if (!sub) {
04428 ast_log(LOG_WARNING, "subchannel null in unistim_new\n");
04429 return NULL;
04430 }
04431 if (!sub->parent) {
04432 ast_log(LOG_WARNING, "no line for subchannel %p\n", sub);
04433 return NULL;
04434 }
04435 l = sub->parent;
04436 tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
04437 l->context, l->amaflags, "%s-%08x", l->fullname, (int) (long) sub);
04438 if (unistimdebug)
04439 ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub->subtype, sub, tmp);
04440 if (!tmp) {
04441 ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
04442 return NULL;
04443 }
04444
04445 tmp->nativeformats = l->capability;
04446 if (!tmp->nativeformats)
04447 tmp->nativeformats = CAPABILITY;
04448 fmt = ast_best_codec(tmp->nativeformats);
04449 if (unistimdebug)
04450 ast_verb(0, "Best codec = %d from nativeformats %d (line cap=%d global=%d)\n", fmt,
04451 tmp->nativeformats, l->capability, CAPABILITY);
04452 ast_string_field_build(tmp, name, "USTM/%s@%s-%d", l->name, l->parent->name,
04453 sub->subtype);
04454 if ((sub->rtp) && (sub->subtype == 0)) {
04455 if (unistimdebug)
04456 ast_verb(0, "New unistim channel with a previous rtp handle ?\n");
04457 tmp->fds[0] = ast_rtp_fd(sub->rtp);
04458 tmp->fds[1] = ast_rtcp_fd(sub->rtp);
04459 }
04460 if (sub->rtp)
04461 ast_jb_configure(tmp, &global_jbconf);
04462
04463
04464 ast_setstate(tmp, state);
04465 if (state == AST_STATE_RING)
04466 tmp->rings = 1;
04467 tmp->adsicpe = AST_ADSI_UNAVAILABLE;
04468 tmp->writeformat = fmt;
04469 tmp->rawwriteformat = fmt;
04470 tmp->readformat = fmt;
04471 tmp->rawreadformat = fmt;
04472 tmp->tech_pvt = sub;
04473 tmp->tech = &unistim_tech;
04474 if (!ast_strlen_zero(l->language))
04475 ast_string_field_set(tmp, language, l->language);
04476 sub->owner = tmp;
04477 ast_mutex_lock(&usecnt_lock);
04478 usecnt++;
04479 ast_mutex_unlock(&usecnt_lock);
04480 ast_update_use_count();
04481 tmp->callgroup = l->callgroup;
04482 tmp->pickupgroup = l->pickupgroup;
04483 ast_string_field_set(tmp, call_forward, l->parent->call_forward);
04484 if (!ast_strlen_zero(l->cid_num)) {
04485 char *name, *loc, *instr;
04486 instr = ast_strdup(l->cid_num);
04487 if (instr) {
04488 ast_callerid_parse(instr, &name, &loc);
04489 tmp->cid.cid_num = ast_strdup(loc);
04490 tmp->cid.cid_name = ast_strdup(name);
04491 ast_free(instr);
04492 }
04493 }
04494 tmp->priority = 1;
04495 if (state != AST_STATE_DOWN) {
04496 if (unistimdebug)
04497 ast_verb(0, "Starting pbx in unistim_new\n");
04498 if (ast_pbx_start(tmp)) {
04499 ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
04500 ast_hangup(tmp);
04501 tmp = NULL;
04502 }
04503 }
04504
04505 return tmp;
04506 }
04507
04508 static void *do_monitor(void *data)
04509 {
04510 struct unistimsession *cur = NULL;
04511 unsigned int dw_timeout = 0;
04512 unsigned int tick;
04513 int res;
04514 int reloading;
04515
04516
04517 if (unistimsock > -1)
04518 ast_io_add(io, unistimsock, unistimsock_read, AST_IO_IN, NULL);
04519
04520
04521 for (;;) {
04522
04523
04524 tick = get_tick_count();
04525 dw_timeout = UINT_MAX;
04526 ast_mutex_lock(&sessionlock);
04527 cur = sessions;
04528 DEBUG_TIMER("checking timeout for session %p with tick = %u\n", cur, tick);
04529 while (cur) {
04530 DEBUG_TIMER("checking timeout for session %p timeout = %u\n", cur,
04531 cur->timeout);
04532
04533 if (cur->timeout <= tick) {
04534 DEBUG_TIMER("Event for session %p\n", cur);
04535
04536 if (cur->last_buf_available == 0)
04537 send_ping(cur);
04538 else {
04539 if (send_retransmit(cur)) {
04540 DEBUG_TIMER("The chained link was modified, restarting...\n");
04541 cur = sessions;
04542 dw_timeout = UINT_MAX;
04543 continue;
04544 }
04545 }
04546 }
04547 if (dw_timeout > cur->timeout - tick)
04548 dw_timeout = cur->timeout - tick;
04549
04550 if (cur->device) {
04551 if ((!ast_strlen_zero(cur->device->lines->mailbox)) &&
04552 ((tick >= cur->device->lines->nextmsgcheck))) {
04553 DEBUG_TIMER("Checking mailbox for MWI\n");
04554 unistim_send_mwi_to_peer(cur, tick);
04555 break;
04556 }
04557 }
04558 cur = cur->next;
04559 }
04560 ast_mutex_unlock(&sessionlock);
04561 DEBUG_TIMER("Waiting for %dus\n", dw_timeout);
04562 res = dw_timeout;
04563
04564 if ((res < 0) || (res > IDLE_WAIT))
04565 res = IDLE_WAIT;
04566
04567 res = ast_io_wait(io, res);
04568
04569 ast_mutex_lock(&unistim_reload_lock);
04570 reloading = unistim_reloading;
04571 unistim_reloading = 0;
04572 ast_mutex_unlock(&unistim_reload_lock);
04573 if (reloading) {
04574 ast_verb(1, "Reloading unistim.conf...\n");
04575 reload_config();
04576 }
04577 pthread_testcancel();
04578 }
04579
04580 return NULL;
04581 }
04582
04583
04584 static int restart_monitor(void)
04585 {
04586 pthread_attr_t attr;
04587
04588 if (monitor_thread == AST_PTHREADT_STOP)
04589 return 0;
04590 if (ast_mutex_lock(&monlock)) {
04591 ast_log(LOG_WARNING, "Unable to lock monitor\n");
04592 return -1;
04593 }
04594 if (monitor_thread == pthread_self()) {
04595 ast_mutex_unlock(&monlock);
04596 ast_log(LOG_WARNING, "Cannot kill myself\n");
04597 return -1;
04598 }
04599 if (monitor_thread != AST_PTHREADT_NULL) {
04600
04601 pthread_kill(monitor_thread, SIGURG);
04602 } else {
04603 pthread_attr_init(&attr);
04604 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
04605
04606 if (ast_pthread_create(&monitor_thread, &attr, do_monitor, NULL) < 0) {
04607 ast_mutex_unlock(&monlock);
04608 ast_log(LOG_ERROR, "Unable to start monitor thread.\n");
04609 return -1;
04610 }
04611 }
04612 ast_mutex_unlock(&monlock);
04613 return 0;
04614 }
04615
04616
04617
04618 static struct ast_channel *unistim_request(const char *type, int format, void *data,
04619 int *cause)
04620 {
04621 int oldformat;
04622 struct unistim_subchannel *sub;
04623 struct ast_channel *tmpc = NULL;
04624 char tmp[256];
04625 char *dest = data;
04626
04627 oldformat = format;
04628 format &= CAPABILITY;
04629 ast_log(LOG_NOTICE,
04630 "Asked to get a channel of format %s while capability is %d result : %s (%d) \n",
04631 ast_getformatname(oldformat), CAPABILITY, ast_getformatname(format), format);
04632 if (!format) {
04633 ast_log(LOG_NOTICE,
04634 "Asked to get a channel of unsupported format %s while capability is %s\n",
04635 ast_getformatname(oldformat), ast_getformatname(CAPABILITY));
04636 return NULL;
04637 }
04638
04639 ast_copy_string(tmp, dest, sizeof(tmp));
04640 if (ast_strlen_zero(tmp)) {
04641 ast_log(LOG_NOTICE, "Unistim channels require a device\n");
04642 return NULL;
04643 }
04644
04645 sub = find_subchannel_by_name(tmp);
04646 if (!sub) {
04647 ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
04648 *cause = AST_CAUSE_CONGESTION;
04649 return NULL;
04650 }
04651
04652 ast_verb(3, "unistim_request(%s)\n", tmp);
04653
04654 if (sub->owner) {
04655 if (unistimdebug)
04656 ast_verb(0, "Can't create channel : Busy !\n");
04657 *cause = AST_CAUSE_BUSY;
04658 return NULL;
04659 }
04660 sub->parent->capability = format;
04661 tmpc = unistim_new(sub, AST_STATE_DOWN);
04662 if (!tmpc)
04663 ast_log(LOG_WARNING, "Unable to make channel for '%s'\n", tmp);
04664 if (unistimdebug)
04665 ast_verb(0, "unistim_request owner = %p\n", sub->owner);
04666 restart_monitor();
04667
04668
04669 return tmpc;
04670 }
04671
04672 static char *unistim_info(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04673 {
04674 struct unistim_device *device = devices;
04675 struct unistim_line *line;
04676 struct unistim_subchannel *sub;
04677 struct unistimsession *s;
04678 int i;
04679 struct ast_channel *tmp;
04680
04681 switch (cmd) {
04682 case CLI_INIT:
04683 e->command = "unistim info";
04684 e->usage =
04685 "Usage: unistim info\n"
04686 " Dump internal structures.\n";
04687 return NULL;
04688
04689 case CLI_GENERATE:
04690 return NULL;
04691 }
04692
04693 if (a->argc != e->args)
04694 return CLI_SHOWUSAGE;
04695
04696 ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
04697 while (device) {
04698 ast_cli(a->fd, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
04699 device->name, device->id, device->lines, device->ha, device->session,
04700 device);
04701 line = device->lines;
04702 while (line) {
04703 ast_cli(a->fd,
04704 "->name=%s fullname=%s exten=%s callid=%s cap=%d device=%p line=%p\n",
04705 line->name, line->fullname, line->exten, line->cid_num,
04706 line->capability, line->parent, line);
04707 for (i = 0; i < MAX_SUBS; i++) {
04708 sub = line->subs[i];
04709 if (!sub)
04710 continue;
04711 if (!sub->owner)
04712 tmp = (void *) -42;
04713 else
04714 tmp = sub->owner->_bridge;
04715 if (sub->subtype != i)
04716 ast_cli(a->fd, "Warning ! subchannel->subs[%d] have a subtype=%d\n", i,
04717 sub->subtype);
04718 ast_cli(a->fd,
04719 "-->subtype=%d chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
04720 sub->subtype, sub->owner, sub->rtp, tmp, sub->parent,
04721 sub->alreadygone);
04722 }
04723 line = line->next;
04724 }
04725 device = device->next;
04726 }
04727 ast_cli(a->fd, "\nSessions:\n");
04728 ast_mutex_lock(&sessionlock);
04729 s = sessions;
04730 while (s) {
04731 ast_cli(a->fd,
04732 "sin=%s timeout=%u state=%d macaddr=%s device=%p session=%p\n",
04733 ast_inet_ntoa(s->sin.sin_addr), s->timeout, s->state, s->macaddr,
04734 s->device, s);
04735 s = s->next;
04736 }
04737 ast_mutex_unlock(&sessionlock);
04738
04739 return CLI_SUCCESS;
04740 }
04741
04742 static char *unistim_sp(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04743 {
04744 BUFFSEND;
04745 struct unistim_subchannel *sub;
04746 int i, j = 0, len;
04747 unsigned char c, cc;
04748 char tmp[256];
04749
04750 switch (cmd) {
04751 case CLI_INIT:
04752 e->command = "unistim sp";
04753 e->usage =
04754 "Usage: unistim sp USTM/line@name hexa\n"
04755 " unistim sp USTM/1000@hans 19040004\n";
04756 return NULL;
04757
04758 case CLI_GENERATE:
04759 return NULL;
04760 }
04761
04762 if (a->argc < 4)
04763 return CLI_SHOWUSAGE;
04764
04765 if (strlen(a->argv[2]) < 9)
04766 return CLI_SHOWUSAGE;
04767
04768 len = strlen(a->argv[3]);
04769 if (len % 2)
04770 return CLI_SHOWUSAGE;
04771
04772 ast_copy_string(tmp, a->argv[2] + 5, sizeof(tmp));
04773 sub = find_subchannel_by_name(tmp);
04774 if (!sub) {
04775 ast_cli(a->fd, "Can't find '%s'\n", tmp);
04776 return CLI_SUCCESS;
04777 }
04778 if (!sub->parent->parent->session) {
04779 ast_cli(a->fd, "'%s' is not connected\n", tmp);
04780 return CLI_SUCCESS;
04781 }
04782 ast_cli(a->fd, "Sending '%s' to %s (%p)\n", a->argv[3], tmp, sub->parent->parent->session);
04783 for (i = 0; i < len; i++) {
04784 c = a->argv[3][i];
04785 if (c >= 'a')
04786 c -= 'a' - 10;
04787 else
04788 c -= '0';
04789 i++;
04790 cc = a->argv[3][i];
04791 if (cc >= 'a')
04792 cc -= 'a' - 10;
04793 else
04794 cc -= '0';
04795 tmp[j++] = (c << 4) | cc;
04796 }
04797 memcpy(buffsend + SIZE_HEADER, tmp, j);
04798 send_client(SIZE_HEADER + j, buffsend, sub->parent->parent->session);
04799 return CLI_SUCCESS;
04800 }
04801
04802 static char *unistim_do_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04803 {
04804 switch (cmd) {
04805 case CLI_INIT:
04806 e->command = "unistim set debug {on|off}";
04807 e->usage =
04808 "Usage: unistim set debug\n"
04809 " Display debug messages.\n";
04810 return NULL;
04811
04812 case CLI_GENERATE:
04813 return NULL;
04814 }
04815
04816 if (a->argc != e->args)
04817 return CLI_SHOWUSAGE;
04818
04819 if (!strcasecmp(a->argv[3], "on")) {
04820 unistimdebug = 1;
04821 ast_cli(a->fd, "UNISTIM Debugging Enabled\n");
04822 } else if (!strcasecmp(a->argv[3], "off")) {
04823 unistimdebug = 0;
04824 ast_cli(a->fd, "UNISTIM Debugging Disabled\n");
04825 } else
04826 return CLI_SHOWUSAGE;
04827
04828 return CLI_SUCCESS;
04829 }
04830
04831
04832
04833
04834
04835 static char *unistim_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04836 {
04837 switch (cmd) {
04838 case CLI_INIT:
04839 e->command = "unistim reload";
04840 e->usage =
04841 "Usage: unistim reload\n"
04842 " Reloads UNISTIM configuration from unistim.conf\n";
04843 return NULL;
04844
04845 case CLI_GENERATE:
04846 return NULL;
04847 }
04848
04849 if (e && a && a->argc != e->args)
04850 return CLI_SHOWUSAGE;
04851
04852 if (unistimdebug)
04853 ast_verb(0, "reload unistim\n");
04854
04855 ast_mutex_lock(&unistim_reload_lock);
04856 if (!unistim_reloading)
04857 unistim_reloading = 1;
04858 ast_mutex_unlock(&unistim_reload_lock);
04859
04860 restart_monitor();
04861
04862 return CLI_SUCCESS;
04863 }
04864
04865 static struct ast_cli_entry unistim_cli[] = {
04866 AST_CLI_DEFINE(unistim_reload, "Reload UNISTIM configuration"),
04867 AST_CLI_DEFINE(unistim_info, "Show UNISTIM info"),
04868 AST_CLI_DEFINE(unistim_sp, "Send packet (for reverse engineering)"),
04869 AST_CLI_DEFINE(unistim_do_debug, "Toggle UNITSTIM debugging"),
04870 };
04871
04872 static void unquote(char *out, const char *src, int maxlen)
04873 {
04874 int len = strlen(src);
04875 if (!len)
04876 return;
04877 if ((len > 1) && src[0] == '\"') {
04878
04879 src++;
04880
04881 len--;
04882 if (maxlen > len - 1)
04883 maxlen = len - 1;
04884 memcpy(out, src, maxlen);
04885 ((char *) out)[maxlen] = '\0';
04886 } else
04887 memcpy(out, src, maxlen);
04888 return;
04889 }
04890
04891 static int ParseBookmark(const char *text, struct unistim_device *d)
04892 {
04893 char line[256];
04894 char *at;
04895 char *number;
04896 char *icon;
04897 int p;
04898 int len = strlen(text);
04899
04900 ast_copy_string(line, text, sizeof(line));
04901
04902 if ((len > 2) && (line[1] == '@')) {
04903 p = line[0];
04904 if ((p >= '0') && (p <= '5'))
04905 p -= '0';
04906 else {
04907 ast_log(LOG_WARNING,
04908 "Invalid position for bookmark : must be between 0 and 5\n");
04909 return 0;
04910 }
04911 if (d->softkeyicon[p] != 0) {
04912 ast_log(LOG_WARNING, "Invalid position %d for bookmark : already used\n:", p);
04913 return 0;
04914 }
04915 memmove(line, line + 2, sizeof(line));
04916 } else {
04917
04918 for (p = 0; p <= 5; p++) {
04919 if (!d->softkeyicon[p])
04920 break;
04921 }
04922 if (p > 5) {
04923 ast_log(LOG_WARNING, "No more free bookmark position\n");
04924 return 0;
04925 }
04926 }
04927 at = strchr(line, '@');
04928 if (!at) {
04929 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no @ (at) sign!\n", text);
04930 return 0;
04931 }
04932 *at = '\0';
04933 at++;
04934 number = at;
04935 at = strchr(at, '@');
04936 if (ast_strlen_zero(number)) {
04937 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no number\n", text);
04938 return 0;
04939 }
04940 if (ast_strlen_zero(line)) {
04941 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no description\n", text);
04942 return 0;
04943 }
04944
04945 at = strchr(number, '@');
04946 if (!at)
04947 d->softkeyicon[p] = FAV_ICON_SHARP;
04948 else {
04949 *at = '\0';
04950 at++;
04951 icon = at;
04952 if (ast_strlen_zero(icon)) {
04953 ast_log(LOG_NOTICE, "Bookmark entry '%s' has no icon value\n", text);
04954 return 0;
04955 }
04956 if (strncmp(icon, "USTM/", 5))
04957 d->softkeyicon[p] = atoi(icon);
04958 else {
04959 d->softkeyicon[p] = 1;
04960 ast_copy_string(d->softkeydevice[p], icon + 5, sizeof(d->softkeydevice[p]));
04961 }
04962 }
04963 ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
04964 ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
04965 if (unistimdebug)
04966 ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
04967 p, d->softkeylabel[p], d->softkeynumber[p], d->softkeyicon[p]);
04968 return 1;
04969 }
04970
04971
04972 static void finish_bookmark(void)
04973 {
04974 struct unistim_device *d = devices;
04975 int i;
04976 while (d) {
04977 for (i = 0; i < 6; i++) {
04978 if (d->softkeyicon[i] == 1) {
04979 struct unistim_device *d2 = devices;
04980 while (d2) {
04981 if (!strcmp(d->softkeydevice[i], d2->name)) {
04982 d->sp[i] = d2;
04983 d->softkeyicon[i] = 0;
04984 break;
04985 }
04986 d2 = d2->next;
04987 }
04988 if (d->sp[i] == NULL)
04989 ast_log(LOG_NOTICE, "Bookmark entry with device %s not found\n",
04990 d->softkeydevice[i]);
04991 }
04992 }
04993 d = d->next;
04994 }
04995 }
04996
04997 static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
04998 {
04999 struct unistim_device *d;
05000 struct unistim_line *l = NULL;
05001 int create = 1;
05002 int nbsoftkey, dateformat, timeformat, callhistory;
05003 char linelabel[AST_MAX_EXTENSION];
05004 char context[AST_MAX_EXTENSION];
05005 char ringvolume, ringstyle;
05006
05007
05008
05009 ast_mutex_lock(&devicelock);
05010 d = devices;
05011 while (d) {
05012 if (!strcmp(d->name, cat)) {
05013
05014 if (unistimsock < 0) {
05015
05016 ast_log(LOG_WARNING, "Duplicate entry found (%s), ignoring.\n", cat);
05017 ast_mutex_unlock(&devicelock);
05018 return NULL;
05019 }
05020
05021 create = 0;
05022 l = d->lines;
05023 break;
05024 }
05025 d = d->next;
05026 }
05027 ast_mutex_unlock(&devicelock);
05028 if (create) {
05029 if (!(d = ast_calloc(1, sizeof(*d))))
05030 return NULL;
05031
05032 if (!(l = ast_calloc(1, sizeof(*l)))) {
05033 ast_free(d);
05034 return NULL;
05035 }
05036 ast_copy_string(d->name, cat, sizeof(d->name));
05037 }
05038 ast_copy_string(context, DEFAULTCONTEXT, sizeof(context));
05039 d->contrast = -1;
05040 d->output = OUTPUT_HANDSET;
05041 d->previous_output = OUTPUT_HANDSET;
05042 d->volume = VOLUME_LOW;
05043 d->mute = MUTE_OFF;
05044 linelabel[0] = '\0';
05045 dateformat = 1;
05046 timeformat = 1;
05047 ringvolume = 2;
05048 callhistory = 1;
05049 ringstyle = 3;
05050 nbsoftkey = 0;
05051 while (v) {
05052 if (!strcasecmp(v->name, "rtp_port"))
05053 d->rtp_port = atoi(v->value);
05054 else if (!strcasecmp(v->name, "rtp_method"))
05055 d->rtp_method = atoi(v->value);
05056 else if (!strcasecmp(v->name, "status_method"))
05057 d->status_method = atoi(v->value);
05058 else if (!strcasecmp(v->name, "device"))
05059 ast_copy_string(d->id, v->value, sizeof(d->id));
05060 else if (!strcasecmp(v->name, "tn"))
05061 ast_copy_string(d->extension_number, v->value, sizeof(d->extension_number));
05062 else if (!strcasecmp(v->name, "permit") || !strcasecmp(v->name, "deny"))
05063 d->ha = ast_append_ha(v->name, v->value, d->ha, NULL);
05064 else if (!strcasecmp(v->name, "context"))
05065 ast_copy_string(context, v->value, sizeof(context));
05066 else if (!strcasecmp(v->name, "maintext0"))
05067 unquote(d->maintext0, v->value, sizeof(d->maintext0) - 1);
05068 else if (!strcasecmp(v->name, "maintext1"))
05069 unquote(d->maintext1, v->value, sizeof(d->maintext1) - 1);
05070 else if (!strcasecmp(v->name, "maintext2"))
05071 unquote(d->maintext2, v->value, sizeof(d->maintext2) - 1);
05072 else if (!strcasecmp(v->name, "titledefault"))
05073 unquote(d->titledefault, v->value, sizeof(d->titledefault) - 1);
05074 else if (!strcasecmp(v->name, "dateformat"))
05075 dateformat = atoi(v->value);
05076 else if (!strcasecmp(v->name, "timeformat"))
05077 timeformat = atoi(v->value);
05078 else if (!strcasecmp(v->name, "contrast")) {
05079 d->contrast = atoi(v->value);
05080 if ((d->contrast < 0) || (d->contrast > 15)) {
05081 ast_log(LOG_WARNING, "constrast must be beetween 0 and 15");
05082 d->contrast = 8;
05083 }
05084 } else if (!strcasecmp(v->name, "nat"))
05085 d->nat = ast_true(v->value);
05086 else if (!strcasecmp(v->name, "ringvolume"))
05087 ringvolume = atoi(v->value);
05088 else if (!strcasecmp(v->name, "ringstyle"))
05089 ringstyle = atoi(v->value);
05090 else if (!strcasecmp(v->name, "callhistory"))
05091 callhistory = atoi(v->value);
05092 else if (!strcasecmp(v->name, "callerid")) {
05093 if (!strcasecmp(v->value, "asreceived"))
05094 l->cid_num[0] = '\0';
05095 else
05096 ast_copy_string(l->cid_num, v->value, sizeof(l->cid_num));
05097 } else if (!strcasecmp(v->name, "language"))
05098 ast_copy_string(l->language, v->value, sizeof(l->language));
05099 else if (!strcasecmp(v->name, "country"))
05100 ast_copy_string(d->country, v->value, sizeof(d->country));
05101 else if (!strcasecmp(v->name, "accountcode"))
05102 ast_copy_string(l->accountcode, v->value, sizeof(l->accountcode));
05103 else if (!strcasecmp(v->name, "amaflags")) {
05104 int y;
05105 y = ast_cdr_amaflags2int(v->value);
05106 if (y < 0)
05107 ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
05108 v->lineno);
05109 else
05110 l->amaflags = y;
05111 } else if (!strcasecmp(v->name, "musiconhold"))
05112 ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass));
05113 else if (!strcasecmp(v->name, "callgroup"))
05114 l->callgroup = ast_get_group(v->value);
05115 else if (!strcasecmp(v->name, "pickupgroup"))
05116 l->pickupgroup = ast_get_group(v->value);
05117 else if (!strcasecmp(v->name, "mailbox"))
05118 ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
05119 else if (!strcasecmp(v->name, "parkinglot"))
05120 ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
05121 else if (!strcasecmp(v->name, "linelabel"))
05122 unquote(linelabel, v->value, sizeof(linelabel) - 1);
05123 else if (!strcasecmp(v->name, "extension")) {
05124 if (!strcasecmp(v->value, "none"))
05125 d->extension = EXTENSION_NONE;
05126 else if (!strcasecmp(v->value, "ask"))
05127 d->extension = EXTENSION_ASK;
05128 else if (!strcasecmp(v->value, "line"))
05129 d->extension = EXTENSION_LINE;
05130 else
05131 ast_log(LOG_WARNING, "Unknown extension option.\n");
05132 } else if (!strcasecmp(v->name, "bookmark")) {
05133 if (nbsoftkey > 5)
05134 ast_log(LOG_WARNING,
05135 "More than 6 softkeys defined. Ignoring new entries.\n");
05136 else {
05137 if (ParseBookmark(v->value, d))
05138 nbsoftkey++;
05139 }
05140 } else if (!strcasecmp(v->name, "line")) {
05141 int len = strlen(linelabel);
05142
05143 if (nbsoftkey) {
05144 ast_log(LOG_WARNING,
05145 "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
05146 if (create) {
05147 ast_free(d);
05148 ast_free(l);
05149 }
05150 return NULL;
05151 }
05152 if (create) {
05153 ast_mutex_init(&l->lock);
05154 } else {
05155 d->to_delete = 0;
05156
05157 memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
05158 memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
05159 memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
05160 memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
05161 memset(d->sp, 0, sizeof(d->sp));
05162 }
05163 ast_copy_string(l->name, v->value, sizeof(l->name));
05164 snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
05165 d->softkeyicon[0] = FAV_ICON_ONHOOK_BLACK;
05166 if (!len)
05167 ast_copy_string(d->softkeylabel[0], v->value, sizeof(d->softkeylabel[0]));
05168 else {
05169 if ((len > 2) && (linelabel[1] == '@')) {
05170 d->softkeylinepos = linelabel[0];
05171 if ((d->softkeylinepos >= '0') && (d->softkeylinepos <= '5')) {
05172 d->softkeylinepos -= '0';
05173 d->softkeyicon[0] = 0;
05174 } else {
05175 ast_log(LOG_WARNING,
05176 "Invalid position for linelabel : must be between 0 and 5\n");
05177 d->softkeylinepos = 0;
05178 }
05179 ast_copy_string(d->softkeylabel[d->softkeylinepos], linelabel + 2,
05180 sizeof(d->softkeylabel[d->softkeylinepos]));
05181 d->softkeyicon[d->softkeylinepos] = FAV_ICON_ONHOOK_BLACK;
05182 } else
05183 ast_copy_string(d->softkeylabel[0], linelabel,
05184 sizeof(d->softkeylabel[0]));
05185 }
05186 nbsoftkey++;
05187 ast_copy_string(l->context, context, sizeof(l->context));
05188 if (!ast_strlen_zero(l->mailbox)) {
05189 if (unistimdebug)
05190 ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
05191 }
05192
05193 l->capability = CAPABILITY;
05194 l->parent = d;
05195
05196 if (create) {
05197 if (!alloc_sub(l, SUB_REAL)) {
05198 ast_mutex_destroy(&l->lock);
05199 ast_free(l);
05200 ast_free(d);
05201 return NULL;
05202 }
05203 l->next = d->lines;
05204 d->lines = l;
05205 }
05206 } else
05207 ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
05208 v->lineno);
05209 v = v->next;
05210 }
05211 d->ringvolume = ringvolume;
05212 d->ringstyle = ringstyle;
05213 d->callhistory = callhistory;
05214 d->tz = ast_get_indication_zone(d->country);
05215 if ((d->tz == NULL) && !ast_strlen_zero(d->country))
05216 ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
05217 d->country);
05218 d->datetimeformat = 56 + (dateformat * 4);
05219 d->datetimeformat += timeformat;
05220 if (!d->lines) {
05221 ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
05222 ast_mutex_destroy(&l->lock);
05223 ast_free(l);
05224 ast_free(d);
05225 return NULL;
05226 }
05227 if ((autoprovisioning == AUTOPROVISIONING_TN) &&
05228 (!ast_strlen_zero(d->extension_number))) {
05229 d->extension = EXTENSION_TN;
05230 if (!ast_strlen_zero(d->id))
05231 ast_log(LOG_WARNING,
05232 "tn= and device= can't be used together. Ignoring device= entry\n");
05233 d->id[0] = 'T';
05234 ast_copy_string((d->id) + 1, d->extension_number, sizeof(d->id) - 1);
05235 d->extension_number[0] = '\0';
05236 } else if (ast_strlen_zero(d->id)) {
05237 if (strcmp(d->name, "template")) {
05238 ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
05239 ast_mutex_destroy(&l->lock);
05240 ast_free(l);
05241 ast_free(d);
05242 return NULL;
05243 } else
05244 strcpy(d->id, "000000000000");
05245 }
05246 if (!d->rtp_port)
05247 d->rtp_port = 10000;
05248 if (d->contrast == -1)
05249 d->contrast = 8;
05250 if (ast_strlen_zero(d->maintext0))
05251 strcpy(d->maintext0, "Welcome");
05252 if (ast_strlen_zero(d->maintext1))
05253 strcpy(d->maintext1, d->name);
05254 if (ast_strlen_zero(d->titledefault)) {
05255 struct ast_tm tm = { 0, };
05256 struct timeval cur_time = ast_tvnow();
05257
05258 if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
05259 display_last_error("Error in ast_localtime()");
05260 ast_copy_string(d->titledefault, "UNISTIM for*", 12);
05261 } else {
05262 if (strlen(tm.tm_zone) < 4) {
05263 strcpy(d->titledefault, "TimeZone ");
05264 strcat(d->titledefault, tm.tm_zone);
05265 } else if (strlen(tm.tm_zone) < 9) {
05266 strcpy(d->titledefault, "TZ ");
05267 strcat(d->titledefault, tm.tm_zone);
05268 } else
05269 ast_copy_string(d->titledefault, tm.tm_zone, 12);
05270 }
05271 }
05272
05273 if (create) {
05274 ast_mutex_lock(&devicelock);
05275 d->next = devices;
05276 devices = d;
05277 ast_mutex_unlock(&devicelock);
05278 ast_verb(3, "Added device '%s'\n", d->name);
05279 } else {
05280 ast_verb(3, "Device '%s' reloaded\n", d->name);
05281 }
05282 return d;
05283 }
05284
05285
05286 static int reload_config(void)
05287 {
05288 struct ast_config *cfg;
05289 struct ast_variable *v;
05290 struct ast_hostent ahp;
05291 struct hostent *hp;
05292 struct sockaddr_in bindaddr = { 0, };
05293 char *config = "unistim.conf";
05294 char *cat;
05295 struct unistim_device *d;
05296 const int reuseFlag = 1;
05297 struct unistimsession *s;
05298 struct ast_flags config_flags = { 0, };
05299
05300 cfg = ast_config_load(config, config_flags);
05301
05302 if (!cfg) {
05303 ast_log(LOG_ERROR, "Unable to load config %s\n", config);
05304 return -1;
05305 }
05306
05307
05308 memcpy(&global_jbconf, &default_jbconf, sizeof(struct ast_jb_conf));
05309
05310 unistim_keepalive = 120;
05311 unistim_port = 0;
05312 v = ast_variable_browse(cfg, "general");
05313 while (v) {
05314
05315 if (!ast_jb_read_conf(&global_jbconf, v->name, v->value))
05316 continue;
05317
05318 if (!strcasecmp(v->name, "keepalive"))
05319 unistim_keepalive = atoi(v->value);
05320 else if (!strcasecmp(v->name, "port"))
05321 unistim_port = atoi(v->value);
05322 else if (!strcasecmp(v->name, "tos")) {
05323 if (ast_str2tos(v->value, &qos.tos))
05324 ast_log(LOG_WARNING, "Invalid tos value at line %d, refer to QoS documentation\n", v->lineno);
05325 } else if (!strcasecmp(v->name, "tos_audio")) {
05326 if (ast_str2tos(v->value, &qos.tos_audio))
05327 ast_log(LOG_WARNING, "Invalid tos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05328 } else if (!strcasecmp(v->name, "cos")) {
05329 if (ast_str2cos(v->value, &qos.cos))
05330 ast_log(LOG_WARNING, "Invalid cos value at line %d, refer to QoS documentation\n", v->lineno);
05331 } else if (!strcasecmp(v->name, "cos_audio")) {
05332 if (ast_str2cos(v->value, &qos.cos_audio))
05333 ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
05334 } else if (!strcasecmp(v->name, "autoprovisioning")) {
05335 if (!strcasecmp(v->value, "no"))
05336 autoprovisioning = AUTOPROVISIONING_NO;
05337 else if (!strcasecmp(v->value, "yes"))
05338 autoprovisioning = AUTOPROVISIONING_YES;
05339 else if (!strcasecmp(v->value, "db"))
05340 autoprovisioning = AUTOPROVISIONING_DB;
05341 else if (!strcasecmp(v->value, "tn"))
05342 autoprovisioning = AUTOPROVISIONING_TN;
05343 else
05344 ast_log(LOG_WARNING, "Unknown autoprovisioning option.\n");
05345 } else if (!strcasecmp(v->name, "public_ip")) {
05346 if (!ast_strlen_zero(v->value)) {
05347 if (!(hp = ast_gethostbyname(v->value, &ahp)))
05348 ast_log(LOG_WARNING, "Invalid address: %s\n", v->value);
05349 else {
05350 memcpy(&public_ip.sin_addr, hp->h_addr, sizeof(public_ip.sin_addr));
05351 public_ip.sin_family = AF_INET;
05352 }
05353 }
05354 }
05355 v = v->next;
05356 }
05357 if ((unistim_keepalive < 10) ||
05358 (unistim_keepalive >
05359 255 - (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000))) {
05360 ast_log(LOG_ERROR, "keepalive is invalid in %s\n", config);
05361 ast_config_destroy(cfg);
05362 return -1;
05363 }
05364 packet_send_ping[4] =
05365 unistim_keepalive + (((NB_MAX_RETRANSMIT + 1) * RETRANSMIT_TIMER) / 1000);
05366 if ((unistim_port < 1) || (unistim_port > 65535)) {
05367 ast_log(LOG_ERROR, "port is not set or invalid in %s\n", config);
05368 ast_config_destroy(cfg);
05369 return -1;
05370 }
05371 unistim_keepalive *= 1000;
05372
05373 ast_mutex_lock(&devicelock);
05374 d = devices;
05375 while (d) {
05376 if (d->to_delete >= 0)
05377 d->to_delete = 1;
05378 d = d->next;
05379 }
05380 ast_mutex_unlock(&devicelock);
05381
05382 cat = ast_category_browse(cfg, NULL);
05383 while (cat) {
05384 if (strcasecmp(cat, "general")) {
05385 d = build_device(cat, ast_variable_browse(cfg, cat));
05386 }
05387 cat = ast_category_browse(cfg, cat);
05388 }
05389 ast_mutex_lock(&devicelock);
05390 d = devices;
05391 while (d) {
05392 if (d->to_delete) {
05393 int i;
05394
05395 if (unistimdebug)
05396 ast_verb(0, "Removing device '%s'\n", d->name);
05397 if (!d->lines) {
05398 ast_log(LOG_ERROR, "Device '%s' without a line !, aborting\n", d->name);
05399 ast_config_destroy(cfg);
05400 return 0;
05401 }
05402 if (!d->lines->subs[0]) {
05403 ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
05404 d->name);
05405 ast_config_destroy(cfg);
05406 return 0;
05407 }
05408 if (d->lines->subs[0]->owner) {
05409 ast_log(LOG_WARNING,
05410 "Device '%s' was not deleted : a call is in progress. Try again later.\n",
05411 d->name);
05412 d = d->next;
05413 continue;
05414 }
05415 ast_mutex_destroy(&d->lines->subs[0]->lock);
05416 ast_free(d->lines->subs[0]);
05417 for (i = 1; i < MAX_SUBS; i++) {
05418 if (d->lines->subs[i]) {
05419 ast_log(LOG_WARNING,
05420 "Device '%s' with threeway call subchannels allocated, aborting.\n",
05421 d->name);
05422 break;
05423 }
05424 }
05425 if (i < MAX_SUBS) {
05426 d = d->next;
05427 continue;
05428 }
05429 ast_mutex_destroy(&d->lines->lock);
05430 ast_free(d->lines);
05431 if (d->session) {
05432 if (sessions == d->session)
05433 sessions = d->session->next;
05434 else {
05435 s = sessions;
05436 while (s) {
05437 if (s->next == d->session) {
05438 s->next = d->session->next;
05439 break;
05440 }
05441 s = s->next;
05442 }
05443 }
05444 ast_mutex_destroy(&d->session->lock);
05445 ast_free(d->session);
05446 }
05447 if (devices == d)
05448 devices = d->next;
05449 else {
05450 struct unistim_device *d2 = devices;
05451 while (d2) {
05452 if (d2->next == d) {
05453 d2->next = d->next;
05454 break;
05455 }
05456 d2 = d2->next;
05457 }
05458 }
05459 ast_free(d);
05460 d = devices;
05461 continue;
05462 }
05463 d = d->next;
05464 }
05465 finish_bookmark();
05466 ast_mutex_unlock(&devicelock);
05467 ast_config_destroy(cfg);
05468 ast_mutex_lock(&sessionlock);
05469 s = sessions;
05470 while (s) {
05471 if (s->device)
05472 refresh_all_favorite(s);
05473 s = s->next;
05474 }
05475 ast_mutex_unlock(&sessionlock);
05476
05477 if (unistimsock > -1)
05478 return 0;
05479 bindaddr.sin_addr.s_addr = INADDR_ANY;
05480 bindaddr.sin_port = htons(unistim_port);
05481 bindaddr.sin_family = AF_INET;
05482 unistimsock = socket(AF_INET, SOCK_DGRAM, 0);
05483 if (unistimsock < 0) {
05484 ast_log(LOG_WARNING, "Unable to create UNISTIM socket: %s\n", strerror(errno));
05485 return -1;
05486 }
05487 #ifdef HAVE_PKTINFO
05488 {
05489 const int pktinfoFlag = 1;
05490 setsockopt(unistimsock, IPPROTO_IP, IP_PKTINFO, &pktinfoFlag,
05491 sizeof(pktinfoFlag));
05492 }
05493 #else
05494 if (public_ip.sin_family == 0) {
05495 ast_log(LOG_WARNING,
05496 "Your OS does not support IP_PKTINFO, you must set public_ip.\n");
05497 unistimsock = -1;
05498 return -1;
05499 }
05500 #endif
05501 setsockopt(unistimsock, SOL_SOCKET, SO_REUSEADDR, (const char *) &reuseFlag,
05502 sizeof(reuseFlag));
05503 if (bind(unistimsock, (struct sockaddr *) &bindaddr, sizeof(bindaddr)) < 0) {
05504 ast_log(LOG_WARNING, "Failed to bind to %s:%d: %s\n",
05505 ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port),
05506 strerror(errno));
05507 close(unistimsock);
05508 unistimsock = -1;
05509 } else {
05510 ast_verb(2, "UNISTIM Listening on %s:%d\n", ast_inet_ntoa(bindaddr.sin_addr), htons(bindaddr.sin_port));
05511 ast_netsock_set_qos(unistimsock, qos.tos, qos.cos, "UNISTIM");
05512 }
05513 return 0;
05514 }
05515
05516 static enum ast_rtp_get_result unistim_get_vrtp_peer(struct ast_channel *chan,
05517 struct ast_rtp **rtp)
05518 {
05519 return AST_RTP_TRY_NATIVE;
05520 }
05521
05522 static enum ast_rtp_get_result unistim_get_rtp_peer(struct ast_channel *chan,
05523 struct ast_rtp **rtp)
05524 {
05525 struct unistim_subchannel *sub;
05526 enum ast_rtp_get_result res = AST_RTP_GET_FAILED;
05527
05528 if (unistimdebug)
05529 ast_verb(0, "unistim_get_rtp_peer called\n");
05530
05531 sub = chan->tech_pvt;
05532 if (sub && sub->rtp) {
05533 *rtp = sub->rtp;
05534 res = AST_RTP_TRY_NATIVE;
05535 }
05536
05537 return res;
05538 }
05539
05540 static int unistim_set_rtp_peer(struct ast_channel *chan, struct ast_rtp *rtp,
05541 struct ast_rtp *vrtp, struct ast_rtp *trtp, int codecs, int nat_active)
05542 {
05543 struct unistim_subchannel *sub;
05544
05545 if (unistimdebug)
05546 ast_verb(0, "unistim_set_rtp_peer called\n");
05547
05548 sub = chan->tech_pvt;
05549
05550 if (sub)
05551 return 0;
05552
05553 return -1;
05554 }
05555
05556 static struct ast_rtp_protocol unistim_rtp = {
05557 .type = channel_type,
05558 .get_rtp_info = unistim_get_rtp_peer,
05559 .get_vrtp_info = unistim_get_vrtp_peer,
05560 .set_rtp_peer = unistim_set_rtp_peer,
05561 };
05562
05563
05564 int load_module(void)
05565 {
05566 int res;
05567
05568 if (!(buff = ast_malloc(SIZE_PAGE)))
05569 goto buff_failed;
05570
05571 io = io_context_create();
05572 if (!io) {
05573 ast_log(LOG_ERROR, "Failed to allocate IO context\n");
05574 goto io_failed;
05575 }
05576
05577 sched = sched_context_create();
05578 if (!sched) {
05579 ast_log(LOG_ERROR, "Failed to allocate scheduler context\n");
05580 goto sched_failed;
05581 }
05582
05583 res = reload_config();
05584 if (res)
05585 return AST_MODULE_LOAD_DECLINE;
05586
05587
05588 if (ast_channel_register(&unistim_tech)) {
05589 ast_log(LOG_ERROR, "Unable to register channel type '%s'\n", channel_type);
05590 goto chanreg_failed;
05591 }
05592
05593 ast_rtp_proto_register(&unistim_rtp);
05594
05595 ast_cli_register_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05596
05597 restart_monitor();
05598
05599 return AST_MODULE_LOAD_SUCCESS;
05600
05601 chanreg_failed:
05602
05603 sched_context_destroy(sched);
05604 sched = NULL;
05605 sched_failed:
05606 io_context_destroy(io);
05607 io = NULL;
05608 io_failed:
05609 ast_free(buff);
05610 buff = NULL;
05611 buff_failed:
05612 return AST_MODULE_LOAD_FAILURE;
05613 }
05614
05615 static int unload_module(void)
05616 {
05617
05618 if (sched)
05619 sched_context_destroy(sched);
05620
05621 ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));
05622
05623 ast_channel_unregister(&unistim_tech);
05624 ast_rtp_proto_unregister(&unistim_rtp);
05625
05626 ast_mutex_lock(&monlock);
05627 if (monitor_thread && (monitor_thread != AST_PTHREADT_STOP) && (monitor_thread != AST_PTHREADT_NULL)) {
05628 pthread_cancel(monitor_thread);
05629 pthread_kill(monitor_thread, SIGURG);
05630 pthread_join(monitor_thread, NULL);
05631 }
05632 monitor_thread = AST_PTHREADT_STOP;
05633 ast_mutex_unlock(&monlock);
05634
05635 if (buff)
05636 ast_free(buff);
05637 if (unistimsock > -1)
05638 close(unistimsock);
05639
05640 return 0;
05641 }
05642
05643
05644 int reload(void)
05645 {
05646 unistim_reload(NULL, 0, NULL);
05647 return 0;
05648 }
05649
05650 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "UNISTIM Protocol (USTM)",
05651 .load = load_module,
05652 .unload = unload_module,
05653 .reload = reload,
05654 );