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