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