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