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