00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #include "asterisk.h"
00061
00062 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 398236 $")
00063
00064 #include <pthread.h>
00065 #include <sys/socket.h>
00066 #include <sys/time.h>
00067 #include <arpa/inet.h>
00068 #include <fcntl.h>
00069 #include <sys/ioctl.h>
00070 #include <signal.h>
00071 #include <sys/file.h>
00072 #include <semaphore.h>
00073 #include <ctype.h>
00074 #include <time.h>
00075
00076 #include "asterisk/channel.h"
00077 #include "asterisk/config.h"
00078 #include "asterisk/module.h"
00079 #include "asterisk/pbx.h"
00080 #include "asterisk/io.h"
00081 #include "asterisk/frame.h"
00082 #include "asterisk/translate.h"
00083 #include "asterisk/cli.h"
00084 #include "asterisk/musiconhold.h"
00085 #include "asterisk/dsp.h"
00086 #include "asterisk/file.h"
00087 #include "asterisk/callerid.h"
00088 #include "asterisk/indications.h"
00089 #include "asterisk/app.h"
00090 #include "asterisk/features.h"
00091 #include "asterisk/term.h"
00092 #include "asterisk/sched.h"
00093 #include "asterisk/stringfields.h"
00094 #include "asterisk/abstract_jb.h"
00095 #include "asterisk/causes.h"
00096 #include "asterisk/format.h"
00097 #include "asterisk/format_cap.h"
00098
00099 #include "chan_misdn_config.h"
00100 #include "isdn_lib.h"
00101
00102 static char global_tracefile[BUFFERSIZE + 1];
00103
00104 static int g_config_initialized = 0;
00105
00106 struct misdn_jb{
00107 int size;
00108 int upper_threshold;
00109 char *samples, *ok;
00110 int wp,rp;
00111 int state_empty;
00112 int state_full;
00113 int state_buffer;
00114 int bytes_wrote;
00115 ast_mutex_t mutexjb;
00116 };
00117
00118
00119 struct misdn_jb *misdn_jb_init(int size, int upper_threshold);
00120
00121
00122 void misdn_jb_destroy(struct misdn_jb *jb);
00123
00124
00125
00126 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len);
00127
00128
00129
00130
00131 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len);
00132
00133 static char *complete_ch(struct ast_cli_args *a);
00134 static char *complete_debug_port(struct ast_cli_args *a);
00135 static char *complete_show_config(struct ast_cli_args *a);
00136
00137
00138
00139 #if defined(AST_MISDN_ENHANCEMENTS)
00140
00141
00142
00143
00144 #define MISDN_CC_RECORD_AGE_MAX (6UL * 60 * 60)
00145
00146 #define MISDN_CC_REQUEST_WAIT_MAX 5
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 struct misdn_cc_caller {
00159
00160 struct ast_channel *chan;
00161 };
00162
00163 struct misdn_cc_notify {
00164
00165 int priority;
00166
00167
00168 char context[AST_MAX_CONTEXT];
00169
00170
00171 char exten[AST_MAX_EXTENSION];
00172 };
00173
00174
00175 struct misdn_cc_record {
00176
00177 AST_LIST_ENTRY(misdn_cc_record) list;
00178
00179
00180 time_t time_created;
00181
00182
00183 long record_id;
00184
00185
00186
00187
00188
00189 int port;
00190
00191
00192 int ptp;
00193
00194
00195 union {
00196
00197 struct {
00198
00199
00200
00201
00202 struct misdn_bchannel *bc;
00203
00204
00205
00206
00207
00208 int requested_retention;
00209
00210
00211
00212
00213 int retention_enabled;
00214 } ptp;
00215
00216
00217 struct {
00218
00219 int linkage_id;
00220
00221
00222 int reference_id;
00223
00224
00225 int recall_mode;
00226 } ptmp;
00227 } mode;
00228
00229
00230 int activated;
00231
00232
00233 int invoke_id;
00234
00235
00236 int outstanding_message;
00237
00238
00239 int activation_requested;
00240
00241
00242
00243
00244
00245
00246 int party_a_free;
00247
00248
00249 enum FacErrorCode error_code;
00250
00251
00252 enum FacRejectCode reject_code;
00253
00254
00255
00256
00257
00258 struct {
00259
00260 struct misdn_party_id caller;
00261
00262
00263 struct misdn_party_dialing dialed;
00264
00265
00266 struct Q931_Bc_Hlc_Llc setup_bc_hlc_llc;
00267
00268
00269 int capability;
00270
00271
00272 int hdlc;
00273 } redial;
00274
00275
00276 struct misdn_cc_notify remote_user_free;
00277
00278
00279 struct misdn_cc_notify b_free;
00280 };
00281
00282
00283 static AST_LIST_HEAD_STATIC(misdn_cc_records_db, misdn_cc_record);
00284
00285 static __u16 misdn_cc_record_id;
00286
00287 static __s16 misdn_invoke_id;
00288
00289 static const char misdn_no_response_from_network[] = "No response from network";
00290 static const char misdn_cc_record_not_found[] = "Call completion record not found";
00291
00292
00293 #define MISDN_CC_RECORD_ID "MISDN_CC_RECORD_ID"
00294 #define MISDN_CC_STATUS "MISDN_CC_STATUS"
00295 #define MISDN_ERROR_MSG "MISDN_ERROR_MSG"
00296 #endif
00297
00298 static ast_mutex_t release_lock;
00299
00300 enum misdn_chan_state {
00301 MISDN_NOTHING = 0,
00302 MISDN_WAITING4DIGS,
00303 MISDN_EXTCANTMATCH,
00304 MISDN_INCOMING_SETUP,
00305 MISDN_DIALING,
00306 MISDN_PROGRESS,
00307 MISDN_PROCEEDING,
00308 MISDN_CALLING,
00309 MISDN_CALLING_ACKNOWLEDGE,
00310 MISDN_ALERTING,
00311 MISDN_BUSY,
00312 MISDN_CONNECTED,
00313 MISDN_DISCONNECTED,
00314 MISDN_CLEANING,
00315 };
00316
00317
00318 #define ORG_AST 1
00319
00320 #define ORG_MISDN 2
00321
00322 enum misdn_hold_state {
00323 MISDN_HOLD_IDLE,
00324 MISDN_HOLD_ACTIVE,
00325 MISDN_HOLD_TRANSFER,
00326 MISDN_HOLD_DISCONNECT,
00327 };
00328 struct hold_info {
00329
00330
00331
00332 enum misdn_hold_state state;
00333
00334
00335
00336
00337 int port;
00338
00339
00340
00341
00342
00343 int channel;
00344 };
00345
00346 #define chan_list_ref(obj, debug) (ao2_t_ref((obj), +1, (debug)), (obj))
00347 #define chan_list_unref(obj, debug) (ao2_t_ref((obj), -1, (debug)), NULL)
00348
00349
00350
00351
00352 struct chan_list {
00353
00354
00355
00356 char allowed_bearers[BUFFERSIZE + 1];
00357
00358
00359
00360
00361 enum misdn_chan_state state;
00362
00363
00364
00365
00366
00367 int need_queue_hangup;
00368
00369
00370
00371
00372 int need_hangup;
00373
00374
00375
00376
00377 int need_busy;
00378
00379
00380
00381
00382 int originator;
00383
00384
00385
00386
00387
00388 int noautorespond_on_setup;
00389
00390 int norxtone;
00391
00392
00393
00394
00395 int notxtone;
00396
00397
00398
00399
00400 int toggle_ec;
00401
00402
00403
00404
00405
00406
00407 int incoming_early_audio;
00408
00409
00410
00411
00412
00413 int ignore_dtmf;
00414
00415
00416
00417
00418
00419 int pipe[2];
00420
00421
00422
00423
00424 char ast_rd_buf[4096];
00425
00426
00427
00428
00429 struct ast_frame frame;
00430
00431
00432
00433
00434
00435
00436 int faxdetect;
00437
00438
00439
00440
00441
00442
00443 int faxdetect_timeout;
00444
00445
00446
00447
00448 struct timeval faxdetect_tv;
00449
00450
00451
00452
00453 int faxhandled;
00454
00455
00456
00457
00458
00459 int ast_dsp;
00460
00461
00462
00463
00464
00465 int jb_len;
00466
00467
00468
00469
00470
00471 int jb_upper_threshold;
00472
00473
00474
00475
00476
00477
00478 struct misdn_jb *jb;
00479
00480
00481
00482
00483
00484
00485 struct ast_dsp *dsp;
00486
00487
00488
00489
00490 struct ast_channel * ast;
00491
00492
00493
00494
00495 struct misdn_bchannel *bc;
00496
00497 #if defined(AST_MISDN_ENHANCEMENTS)
00498
00499
00500
00501 struct misdn_cc_caller *peer;
00502
00503
00504 long record_id;
00505 #endif
00506
00507
00508
00509
00510 struct hold_info hold;
00511
00512
00513
00514
00515
00516 unsigned int l3id;
00517
00518
00519
00520
00521
00522 int addr;
00523
00524
00525
00526
00527
00528 char context[AST_MAX_CONTEXT];
00529
00530
00531
00532
00533
00534 char mohinterpret[MAX_MUSICCLASS];
00535
00536
00537
00538
00539 int dropped_frame_cnt;
00540
00541
00542
00543
00544
00545 int far_alerting;
00546
00547
00548
00549
00550
00551 int nttimeout;
00552
00553
00554
00555
00556
00557 struct ast_tone_zone_sound *ts;
00558
00559
00560
00561
00562
00563 int overlap_dial;
00564
00565
00566
00567
00568 int overlap_dial_task;
00569
00570
00571
00572
00573 ast_mutex_t overlap_tv_lock;
00574
00575
00576
00577
00578 struct timeval overlap_tv;
00579
00580
00581
00582
00583 struct chan_list *next;
00584 };
00585
00586
00587 int MAXTICS = 8;
00588
00589
00590 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00591 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch);
00592 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame);
00593
00594 struct robin_list {
00595 char *group;
00596 int port;
00597 int channel;
00598 struct robin_list *next;
00599 struct robin_list *prev;
00600 };
00601 static struct robin_list *robin = NULL;
00602
00603
00604 static void free_robin_list(void)
00605 {
00606 struct robin_list *r;
00607 struct robin_list *next;
00608
00609 for (r = robin, robin = NULL; r; r = next) {
00610 next = r->next;
00611 ast_free(r->group);
00612 ast_free(r);
00613 }
00614 }
00615
00616 static struct robin_list *get_robin_position(char *group)
00617 {
00618 struct robin_list *new;
00619 struct robin_list *iter = robin;
00620 for (; iter; iter = iter->next) {
00621 if (!strcasecmp(iter->group, group)) {
00622 return iter;
00623 }
00624 }
00625 new = ast_calloc(1, sizeof(*new));
00626 if (!new) {
00627 return NULL;
00628 }
00629 new->group = ast_strdup(group);
00630 if (!new->group) {
00631 ast_free(new);
00632 return NULL;
00633 }
00634 new->channel = 1;
00635 if (robin) {
00636 new->next = robin;
00637 robin->prev = new;
00638 }
00639 robin = new;
00640 return robin;
00641 }
00642
00643
00644
00645 static struct ast_sched_context *misdn_tasks = NULL;
00646 static pthread_t misdn_tasks_thread;
00647
00648 static int *misdn_ports;
00649
00650 static void chan_misdn_log(int level, int port, char *tmpl, ...)
00651 __attribute__((format(printf, 3, 4)));
00652
00653 static struct ast_channel *misdn_new(struct chan_list *cl, int state, char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c);
00654 static void send_digit_to_chan(struct chan_list *cl, char digit);
00655
00656 static int pbx_start_chan(struct chan_list *ch);
00657
00658 #define MISDN_ASTERISK_TECH_PVT(ast) ast_channel_tech_pvt(ast)
00659 #define MISDN_ASTERISK_TECH_PVT_SET(ast, value) ast_channel_tech_pvt_set(ast, value)
00660
00661 #include "asterisk/strings.h"
00662
00663
00664
00665 static const char misdn_type[] = "mISDN";
00666
00667 static int tracing = 0;
00668
00669
00670 static struct ast_format prefformat;
00671
00672 static int *misdn_debug;
00673 static int *misdn_debug_only;
00674 static int max_ports;
00675
00676 static int *misdn_in_calls;
00677 static int *misdn_out_calls;
00678
00679
00680
00681
00682 static struct chan_list *cl_te=NULL;
00683 static ast_mutex_t cl_te_lock;
00684
00685 static enum event_response_e
00686 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data);
00687
00688 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch);
00689
00690 static void cl_queue_chan(struct chan_list *chan);
00691
00692 static int dialtone_indicate(struct chan_list *cl);
00693 static void hanguptone_indicate(struct chan_list *cl);
00694 static int stop_indicate(struct chan_list *cl);
00695
00696 static int start_bc_tones(struct chan_list *cl);
00697 static int stop_bc_tones(struct chan_list *cl);
00698 static void release_chan_early(struct chan_list *ch);
00699 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc);
00700
00701 #if defined(AST_MISDN_ENHANCEMENTS)
00702 static const char misdn_command_name[] = "misdn_command";
00703 static int misdn_command_exec(struct ast_channel *chan, const char *data);
00704 #endif
00705 static int misdn_check_l2l1(struct ast_channel *chan, const char *data);
00706 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data);
00707 static int misdn_facility_exec(struct ast_channel *chan, const char *data);
00708
00709 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len);
00710
00711 void debug_numtype(int port, int numtype, char *type);
00712
00713 int add_out_calls(int port);
00714 int add_in_calls(int port);
00715
00716
00717 #ifdef MISDN_1_2
00718 static int update_pipeline_config(struct misdn_bchannel *bc);
00719 #else
00720 static int update_ec_config(struct misdn_bchannel *bc);
00721 #endif
00722
00723
00724
00725
00726
00727 static int misdn_chan_is_valid(struct chan_list *ch)
00728 {
00729 struct chan_list *list;
00730
00731 ast_mutex_lock(&cl_te_lock);
00732 for (list = cl_te; list; list = list->next) {
00733 if (list == ch) {
00734 ast_mutex_unlock(&cl_te_lock);
00735 return 1;
00736 }
00737 }
00738 ast_mutex_unlock(&cl_te_lock);
00739
00740 return 0;
00741 }
00742
00743
00744 static struct chan_list *get_chan_by_ast(struct ast_channel *ast)
00745 {
00746 struct chan_list *tmp;
00747
00748 ast_mutex_lock(&cl_te_lock);
00749 for (tmp = cl_te; tmp; tmp = tmp->next) {
00750 if (tmp->ast == ast) {
00751 chan_list_ref(tmp, "Found chan_list by ast");
00752 ast_mutex_unlock(&cl_te_lock);
00753 return tmp;
00754 }
00755 }
00756 ast_mutex_unlock(&cl_te_lock);
00757
00758 return NULL;
00759 }
00760
00761
00762 static struct chan_list *get_chan_by_ast_name(const char *name)
00763 {
00764 struct chan_list *tmp;
00765
00766 ast_mutex_lock(&cl_te_lock);
00767 for (tmp = cl_te; tmp; tmp = tmp->next) {
00768 if (tmp->ast && strcmp(ast_channel_name(tmp->ast), name) == 0) {
00769 chan_list_ref(tmp, "Found chan_list by ast name");
00770 ast_mutex_unlock(&cl_te_lock);
00771 return tmp;
00772 }
00773 }
00774 ast_mutex_unlock(&cl_te_lock);
00775
00776 return NULL;
00777 }
00778
00779 #if defined(AST_MISDN_ENHANCEMENTS)
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803 static void misdn_cc_ds_destroy(void *data)
00804 {
00805 struct misdn_cc_caller *cc_caller = data;
00806
00807 ao2_lock(cc_caller);
00808 cc_caller->chan = NULL;
00809 ao2_unlock(cc_caller);
00810
00811 ao2_ref(cc_caller, -1);
00812 }
00813 #endif
00814
00815 #if defined(AST_MISDN_ENHANCEMENTS)
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827 static void *misdn_cc_ds_duplicate(void *data)
00828 {
00829 struct misdn_cc_caller *cc_caller = data;
00830
00831 ao2_ref(cc_caller, +1);
00832
00833 return cc_caller;
00834 }
00835 #endif
00836
00837 #if defined(AST_MISDN_ENHANCEMENTS)
00838 static const struct ast_datastore_info misdn_cc_ds_info = {
00839 .type = "misdn_cc",
00840 .destroy = misdn_cc_ds_destroy,
00841 .duplicate = misdn_cc_ds_duplicate,
00842 };
00843 #endif
00844
00845 #if defined(AST_MISDN_ENHANCEMENTS)
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 static void misdn_cc_set_peer_var(struct misdn_cc_caller *peer, const char *var,
00860 const char *value)
00861 {
00862 ao2_lock(peer);
00863
00864
00865 while (peer->chan && ast_channel_trylock(peer->chan)) {
00866 ao2_unlock(peer);
00867 sched_yield();
00868 ao2_lock(peer);
00869 }
00870
00871 if (peer->chan) {
00872 pbx_builtin_setvar_helper(peer->chan, var, value);
00873 ast_channel_unlock(peer->chan);
00874 }
00875
00876 ao2_unlock(peer);
00877 }
00878 #endif
00879
00880 #if defined(AST_MISDN_ENHANCEMENTS)
00881
00882
00883
00884
00885 static struct misdn_cc_caller *misdn_cc_caller_get(struct ast_channel *chan)
00886 {
00887 struct ast_datastore *datastore;
00888 struct misdn_cc_caller *cc_caller;
00889
00890 ast_channel_lock(chan);
00891
00892 if (!(datastore = ast_channel_datastore_find(chan, &misdn_cc_ds_info, NULL))) {
00893 ast_channel_unlock(chan);
00894 return NULL;
00895 }
00896
00897 ao2_ref(datastore->data, +1);
00898 cc_caller = datastore->data;
00899
00900 ast_channel_unlock(chan);
00901
00902 return cc_caller;
00903 }
00904 #endif
00905
00906 #if defined(AST_MISDN_ENHANCEMENTS)
00907
00908
00909
00910
00911
00912
00913
00914
00915
00916
00917
00918 static struct misdn_cc_record *misdn_cc_find_by_id(long record_id)
00919 {
00920 struct misdn_cc_record *current;
00921
00922 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
00923 if (current->record_id == record_id) {
00924
00925 break;
00926 }
00927 }
00928
00929 return current;
00930 }
00931 #endif
00932
00933 #if defined(AST_MISDN_ENHANCEMENTS)
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946 static struct misdn_cc_record *misdn_cc_find_by_linkage(int port, int linkage_id)
00947 {
00948 struct misdn_cc_record *current;
00949
00950 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
00951 if (current->port == port
00952 && !current->ptp
00953 && current->mode.ptmp.linkage_id == linkage_id) {
00954
00955 break;
00956 }
00957 }
00958
00959 return current;
00960 }
00961 #endif
00962
00963 #if defined(AST_MISDN_ENHANCEMENTS)
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976 static struct misdn_cc_record *misdn_cc_find_by_invoke(int port, int invoke_id)
00977 {
00978 struct misdn_cc_record *current;
00979
00980 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
00981 if (current->outstanding_message
00982 && current->invoke_id == invoke_id
00983 && current->port == port) {
00984
00985 break;
00986 }
00987 }
00988
00989 return current;
00990 }
00991 #endif
00992
00993 #if defined(AST_MISDN_ENHANCEMENTS)
00994
00995
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006 static struct misdn_cc_record *misdn_cc_find_by_reference(int port, int reference_id)
01007 {
01008 struct misdn_cc_record *current;
01009
01010 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
01011 if (current->activated
01012 && current->port == port
01013 && !current->ptp
01014 && current->mode.ptmp.reference_id == reference_id) {
01015
01016 break;
01017 }
01018 }
01019
01020 return current;
01021 }
01022 #endif
01023
01024 #if defined(AST_MISDN_ENHANCEMENTS)
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036 static struct misdn_cc_record *misdn_cc_find_by_bc(const struct misdn_bchannel *bc)
01037 {
01038 struct misdn_cc_record *current;
01039
01040 if (bc) {
01041 AST_LIST_TRAVERSE(&misdn_cc_records_db, current, list) {
01042 if (current->ptp
01043 && current->mode.ptp.bc == bc) {
01044
01045 break;
01046 }
01047 }
01048 } else {
01049 current = NULL;
01050 }
01051
01052 return current;
01053 }
01054 #endif
01055
01056 #if defined(AST_MISDN_ENHANCEMENTS)
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 static void misdn_cc_delete(struct misdn_cc_record *doomed)
01068 {
01069 struct misdn_cc_record *current;
01070
01071 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
01072 if (current == doomed) {
01073 AST_LIST_REMOVE_CURRENT(list);
01074 ast_free(current);
01075 return;
01076 }
01077 }
01078 AST_LIST_TRAVERSE_SAFE_END;
01079
01080
01081 }
01082 #endif
01083
01084 #if defined(AST_MISDN_ENHANCEMENTS)
01085
01086
01087
01088
01089
01090
01091
01092
01093 static void misdn_cc_remove_old(void)
01094 {
01095 struct misdn_cc_record *current;
01096 time_t now;
01097
01098 now = time(NULL);
01099 AST_LIST_TRAVERSE_SAFE_BEGIN(&misdn_cc_records_db, current, list) {
01100 if (MISDN_CC_RECORD_AGE_MAX < now - current->time_created) {
01101 if (current->ptp && current->mode.ptp.bc) {
01102
01103 current->mode.ptp.bc->fac_out.Function = Fac_None;
01104 current->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
01105 misdn_lib_send_event(current->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
01106 }
01107
01108
01109 AST_LIST_REMOVE_CURRENT(list);
01110 ast_free(current);
01111 }
01112 }
01113 AST_LIST_TRAVERSE_SAFE_END;
01114 }
01115 #endif
01116
01117 #if defined(AST_MISDN_ENHANCEMENTS)
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127 static long misdn_cc_record_id_new(void)
01128 {
01129 long record_id;
01130 long first_id;
01131
01132 record_id = ++misdn_cc_record_id;
01133 first_id = record_id;
01134 while (misdn_cc_find_by_id(record_id)) {
01135 record_id = ++misdn_cc_record_id;
01136 if (record_id == first_id) {
01137
01138
01139
01140
01141 chan_misdn_log(0, 0, " --> ERROR Too many call completion records!\n");
01142 record_id = -1;
01143 break;
01144 }
01145 }
01146
01147 return record_id;
01148 }
01149 #endif
01150
01151 #if defined(AST_MISDN_ENHANCEMENTS)
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161 static struct misdn_cc_record *misdn_cc_new(void)
01162 {
01163 struct misdn_cc_record *cc_record;
01164 long record_id;
01165
01166 misdn_cc_remove_old();
01167
01168 cc_record = ast_calloc(1, sizeof(*cc_record));
01169 if (cc_record) {
01170 record_id = misdn_cc_record_id_new();
01171 if (record_id < 0) {
01172 ast_free(cc_record);
01173 return NULL;
01174 }
01175
01176
01177 cc_record->record_id = record_id;
01178 cc_record->port = -1;
01179 cc_record->invoke_id = ++misdn_invoke_id;
01180 cc_record->party_a_free = 1;
01181 cc_record->error_code = FacError_None;
01182 cc_record->reject_code = FacReject_None;
01183 cc_record->time_created = time(NULL);
01184
01185
01186 AST_LIST_INSERT_HEAD(&misdn_cc_records_db, cc_record, list);
01187 }
01188 return cc_record;
01189 }
01190 #endif
01191
01192 #if defined(AST_MISDN_ENHANCEMENTS)
01193
01194
01195
01196
01197
01198
01199 static void misdn_cc_destroy(void)
01200 {
01201 struct misdn_cc_record *current;
01202
01203 while ((current = AST_LIST_REMOVE_HEAD(&misdn_cc_records_db, list))) {
01204
01205 ast_free(current);
01206 }
01207 }
01208 #endif
01209
01210 #if defined(AST_MISDN_ENHANCEMENTS)
01211
01212
01213
01214
01215
01216
01217 static void misdn_cc_init(void)
01218 {
01219 misdn_cc_record_id = 0;
01220 }
01221 #endif
01222
01223 #if defined(AST_MISDN_ENHANCEMENTS)
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233 static int misdn_cc_response_check(void *data)
01234 {
01235 int not_responded;
01236 struct misdn_cc_record *cc_record;
01237
01238 AST_LIST_LOCK(&misdn_cc_records_db);
01239 cc_record = misdn_cc_find_by_id(*(long *) data);
01240 if (cc_record) {
01241 if (cc_record->outstanding_message) {
01242 not_responded = -1;
01243 } else {
01244 not_responded = 0;
01245 }
01246 } else {
01247
01248 not_responded = 0;
01249 }
01250 AST_LIST_UNLOCK(&misdn_cc_records_db);
01251
01252 return not_responded;
01253 }
01254 #endif
01255
01256 #if defined(AST_MISDN_ENHANCEMENTS)
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268 static void misdn_cc_response_wait(struct ast_channel *chan, int wait_seconds, long record_id)
01269 {
01270 unsigned count;
01271
01272 for (count = 2 * MISDN_CC_REQUEST_WAIT_MAX; count--;) {
01273
01274 if (ast_safe_sleep_conditional(chan, 500, misdn_cc_response_check, &record_id) != 0) {
01275
01276 break;
01277 }
01278 }
01279 }
01280 #endif
01281
01282 #if defined(AST_MISDN_ENHANCEMENTS)
01283
01284
01285
01286
01287
01288
01289
01290
01291 static const char *misdn_to_str_reject_code(enum FacRejectCode code)
01292 {
01293 static const struct {
01294 enum FacRejectCode code;
01295 char *name;
01296 } arr[] = {
01297
01298 { FacReject_None, "No reject occurred" },
01299 { FacReject_Unknown, "Unknown reject code" },
01300
01301 { FacReject_Gen_UnrecognizedComponent, "General: Unrecognized Component" },
01302 { FacReject_Gen_MistypedComponent, "General: Mistyped Component" },
01303 { FacReject_Gen_BadlyStructuredComponent, "General: Badly Structured Component" },
01304
01305 { FacReject_Inv_DuplicateInvocation, "Invoke: Duplicate Invocation" },
01306 { FacReject_Inv_UnrecognizedOperation, "Invoke: Unrecognized Operation" },
01307 { FacReject_Inv_MistypedArgument, "Invoke: Mistyped Argument" },
01308 { FacReject_Inv_ResourceLimitation, "Invoke: Resource Limitation" },
01309 { FacReject_Inv_InitiatorReleasing, "Invoke: Initiator Releasing" },
01310 { FacReject_Inv_UnrecognizedLinkedID, "Invoke: Unrecognized Linked ID" },
01311 { FacReject_Inv_LinkedResponseUnexpected, "Invoke: Linked Response Unexpected" },
01312 { FacReject_Inv_UnexpectedChildOperation, "Invoke: Unexpected Child Operation" },
01313
01314 { FacReject_Res_UnrecognizedInvocation, "Result: Unrecognized Invocation" },
01315 { FacReject_Res_ResultResponseUnexpected, "Result: Result Response Unexpected" },
01316 { FacReject_Res_MistypedResult, "Result: Mistyped Result" },
01317
01318 { FacReject_Err_UnrecognizedInvocation, "Error: Unrecognized Invocation" },
01319 { FacReject_Err_ErrorResponseUnexpected, "Error: Error Response Unexpected" },
01320 { FacReject_Err_UnrecognizedError, "Error: Unrecognized Error" },
01321 { FacReject_Err_UnexpectedError, "Error: Unexpected Error" },
01322 { FacReject_Err_MistypedParameter, "Error: Mistyped Parameter" },
01323
01324 };
01325
01326 unsigned index;
01327
01328 for (index = 0; index < ARRAY_LEN(arr); ++index) {
01329 if (arr[index].code == code) {
01330 return arr[index].name;
01331 }
01332 }
01333
01334 return "unknown";
01335 }
01336 #endif
01337
01338 #if defined(AST_MISDN_ENHANCEMENTS)
01339
01340
01341
01342
01343
01344
01345
01346
01347 static const char *misdn_to_str_error_code(enum FacErrorCode code)
01348 {
01349 static const struct {
01350 enum FacErrorCode code;
01351 char *name;
01352 } arr[] = {
01353
01354 { FacError_None, "No error occurred" },
01355 { FacError_Unknown, "Unknown OID error code" },
01356
01357 { FacError_Gen_NotSubscribed, "General: Not Subscribed" },
01358 { FacError_Gen_NotAvailable, "General: Not Available" },
01359 { FacError_Gen_NotImplemented, "General: Not Implemented" },
01360 { FacError_Gen_InvalidServedUserNr, "General: Invalid Served User Number" },
01361 { FacError_Gen_InvalidCallState, "General: Invalid Call State" },
01362 { FacError_Gen_BasicServiceNotProvided, "General: Basic Service Not Provided" },
01363 { FacError_Gen_NotIncomingCall, "General: Not Incoming Call" },
01364 { FacError_Gen_SupplementaryServiceInteractionNotAllowed,"General: Supplementary Service Interaction Not Allowed" },
01365 { FacError_Gen_ResourceUnavailable, "General: Resource Unavailable" },
01366
01367 { FacError_Div_InvalidDivertedToNr, "Diversion: Invalid Diverted To Number" },
01368 { FacError_Div_SpecialServiceNr, "Diversion: Special Service Number" },
01369 { FacError_Div_DiversionToServedUserNr, "Diversion: Diversion To Served User Number" },
01370 { FacError_Div_IncomingCallAccepted, "Diversion: Incoming Call Accepted" },
01371 { FacError_Div_NumberOfDiversionsExceeded, "Diversion: Number Of Diversions Exceeded" },
01372 { FacError_Div_NotActivated, "Diversion: Not Activated" },
01373 { FacError_Div_RequestAlreadyAccepted, "Diversion: Request Already Accepted" },
01374
01375 { FacError_AOC_NoChargingInfoAvailable, "AOC: No Charging Info Available" },
01376
01377 { FacError_CCBS_InvalidCallLinkageID, "CCBS: Invalid Call Linkage ID" },
01378 { FacError_CCBS_InvalidCCBSReference, "CCBS: Invalid CCBS Reference" },
01379 { FacError_CCBS_LongTermDenial, "CCBS: Long Term Denial" },
01380 { FacError_CCBS_ShortTermDenial, "CCBS: Short Term Denial" },
01381 { FacError_CCBS_IsAlreadyActivated, "CCBS: Is Already Activated" },
01382 { FacError_CCBS_AlreadyAccepted, "CCBS: Already Accepted" },
01383 { FacError_CCBS_OutgoingCCBSQueueFull, "CCBS: Outgoing CCBS Queue Full" },
01384 { FacError_CCBS_CallFailureReasonNotBusy, "CCBS: Call Failure Reason Not Busy" },
01385 { FacError_CCBS_NotReadyForCall, "CCBS: Not Ready For Call" },
01386
01387 { FacError_CCBS_T_LongTermDenial, "CCBS-T: Long Term Denial" },
01388 { FacError_CCBS_T_ShortTermDenial, "CCBS-T: Short Term Denial" },
01389
01390 { FacError_ECT_LinkIdNotAssignedByNetwork, "ECT: Link ID Not Assigned By Network" },
01391
01392 };
01393
01394 unsigned index;
01395
01396 for (index = 0; index < ARRAY_LEN(arr); ++index) {
01397 if (arr[index].code == code) {
01398 return arr[index].name;
01399 }
01400 }
01401
01402 return "unknown";
01403 }
01404 #endif
01405
01406 #if defined(AST_MISDN_ENHANCEMENTS)
01407
01408
01409
01410
01411
01412
01413
01414
01415 static unsigned misdn_to_diversion_reason(enum mISDN_REDIRECTING_REASON reason)
01416 {
01417 unsigned diversion_reason;
01418
01419 switch (reason) {
01420 case mISDN_REDIRECTING_REASON_CALL_FWD:
01421 diversion_reason = 1;
01422 break;
01423 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
01424 diversion_reason = 2;
01425 break;
01426 case mISDN_REDIRECTING_REASON_NO_REPLY:
01427 diversion_reason = 3;
01428 break;
01429 default:
01430 diversion_reason = 0;
01431 break;
01432 }
01433
01434 return diversion_reason;
01435 }
01436 #endif
01437
01438 #if defined(AST_MISDN_ENHANCEMENTS)
01439
01440
01441
01442
01443
01444
01445
01446
01447 static enum mISDN_REDIRECTING_REASON diversion_reason_to_misdn(unsigned diversion_reason)
01448 {
01449 enum mISDN_REDIRECTING_REASON reason;
01450
01451 switch (diversion_reason) {
01452 case 1:
01453 reason = mISDN_REDIRECTING_REASON_CALL_FWD;
01454 break;
01455 case 2:
01456 reason = mISDN_REDIRECTING_REASON_CALL_FWD_BUSY;
01457 break;
01458 case 3:
01459 reason = mISDN_REDIRECTING_REASON_NO_REPLY;
01460 break;
01461 default:
01462 reason = mISDN_REDIRECTING_REASON_UNKNOWN;
01463 break;
01464 }
01465
01466 return reason;
01467 }
01468 #endif
01469
01470 #if defined(AST_MISDN_ENHANCEMENTS)
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480 static unsigned misdn_to_PresentedNumberUnscreened_type(int presentation, int number_present)
01481 {
01482 unsigned type;
01483
01484 switch (presentation) {
01485 case 0:
01486 if (number_present) {
01487 type = 0;
01488 } else {
01489 type = 2;
01490 }
01491 break;
01492 case 1:
01493 if (number_present) {
01494 type = 3;
01495 } else {
01496 type = 1;
01497 }
01498 break;
01499 default:
01500 type = 2;
01501 break;
01502 }
01503
01504 return type;
01505 }
01506 #endif
01507
01508 #if defined(AST_MISDN_ENHANCEMENTS)
01509
01510
01511
01512
01513
01514
01515
01516
01517 static int PresentedNumberUnscreened_to_misdn_pres(unsigned type)
01518 {
01519 int presentation;
01520
01521 switch (type) {
01522 default:
01523 case 0:
01524 presentation = 0;
01525 break;
01526
01527 case 1:
01528 case 3:
01529 presentation = 1;
01530 break;
01531
01532 case 2:
01533 presentation = 2;
01534 break;
01535 }
01536
01537 return presentation;
01538 }
01539 #endif
01540
01541 #if defined(AST_MISDN_ENHANCEMENTS)
01542
01543
01544
01545
01546
01547
01548
01549
01550 static unsigned misdn_to_PartyNumber_plan(enum mISDN_NUMBER_PLAN number_plan)
01551 {
01552 unsigned party_plan;
01553
01554 switch (number_plan) {
01555 default:
01556 case NUMPLAN_UNKNOWN:
01557 party_plan = 0;
01558 break;
01559
01560 case NUMPLAN_ISDN:
01561 party_plan = 1;
01562 break;
01563
01564 case NUMPLAN_DATA:
01565 party_plan = 3;
01566 break;
01567
01568 case NUMPLAN_TELEX:
01569 party_plan = 4;
01570 break;
01571
01572 case NUMPLAN_NATIONAL:
01573 party_plan = 8;
01574 break;
01575
01576 case NUMPLAN_PRIVATE:
01577 party_plan = 5;
01578 break;
01579 }
01580
01581 return party_plan;
01582 }
01583 #endif
01584
01585 #if defined(AST_MISDN_ENHANCEMENTS)
01586
01587
01588
01589
01590
01591
01592
01593
01594 static enum mISDN_NUMBER_PLAN PartyNumber_to_misdn_plan(unsigned party_plan)
01595 {
01596 enum mISDN_NUMBER_PLAN number_plan;
01597
01598 switch (party_plan) {
01599 default:
01600 case 0:
01601 number_plan = NUMPLAN_UNKNOWN;
01602 break;
01603 case 1:
01604 number_plan = NUMPLAN_ISDN;
01605 break;
01606 case 3:
01607 number_plan = NUMPLAN_DATA;
01608 break;
01609 case 4:
01610 number_plan = NUMPLAN_TELEX;
01611 break;
01612 case 8:
01613 number_plan = NUMPLAN_NATIONAL;
01614 break;
01615 case 5:
01616 number_plan = NUMPLAN_PRIVATE;
01617 break;
01618 }
01619
01620 return number_plan;
01621 }
01622 #endif
01623
01624 #if defined(AST_MISDN_ENHANCEMENTS)
01625
01626
01627
01628
01629
01630
01631
01632
01633 static unsigned misdn_to_PartyNumber_ton_public(enum mISDN_NUMBER_TYPE ton)
01634 {
01635 unsigned party_ton;
01636
01637 switch (ton) {
01638 default:
01639 case NUMTYPE_UNKNOWN:
01640 party_ton = 0;
01641 break;
01642
01643 case NUMTYPE_INTERNATIONAL:
01644 party_ton = 1;
01645 break;
01646
01647 case NUMTYPE_NATIONAL:
01648 party_ton = 2;
01649 break;
01650
01651 case NUMTYPE_NETWORK_SPECIFIC:
01652 party_ton = 3;
01653 break;
01654
01655 case NUMTYPE_SUBSCRIBER:
01656 party_ton = 4;
01657 break;
01658
01659 case NUMTYPE_ABBREVIATED:
01660 party_ton = 6;
01661 break;
01662 }
01663
01664 return party_ton;
01665 }
01666 #endif
01667
01668 #if defined(AST_MISDN_ENHANCEMENTS)
01669
01670
01671
01672
01673
01674
01675
01676
01677 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_public(unsigned party_ton)
01678 {
01679 enum mISDN_NUMBER_TYPE ton;
01680
01681 switch (party_ton) {
01682 default:
01683 case 0:
01684 ton = NUMTYPE_UNKNOWN;
01685 break;
01686
01687 case 1:
01688 ton = NUMTYPE_INTERNATIONAL;
01689 break;
01690
01691 case 2:
01692 ton = NUMTYPE_NATIONAL;
01693 break;
01694
01695 case 3:
01696 ton = NUMTYPE_NETWORK_SPECIFIC;
01697 break;
01698
01699 case 4:
01700 ton = NUMTYPE_SUBSCRIBER;
01701 break;
01702
01703 case 6:
01704 ton = NUMTYPE_ABBREVIATED;
01705 break;
01706 }
01707
01708 return ton;
01709 }
01710 #endif
01711
01712 #if defined(AST_MISDN_ENHANCEMENTS)
01713
01714
01715
01716
01717
01718
01719
01720
01721 static unsigned misdn_to_PartyNumber_ton_private(enum mISDN_NUMBER_TYPE ton)
01722 {
01723 unsigned party_ton;
01724
01725 switch (ton) {
01726 default:
01727 case NUMTYPE_UNKNOWN:
01728 party_ton = 0;
01729 break;
01730
01731 case NUMTYPE_INTERNATIONAL:
01732 party_ton = 1;
01733 break;
01734
01735 case NUMTYPE_NATIONAL:
01736 party_ton = 2;
01737 break;
01738
01739 case NUMTYPE_NETWORK_SPECIFIC:
01740 party_ton = 3;
01741 break;
01742
01743 case NUMTYPE_SUBSCRIBER:
01744 party_ton = 4;
01745 break;
01746
01747 case NUMTYPE_ABBREVIATED:
01748 party_ton = 6;
01749 break;
01750 }
01751
01752 return party_ton;
01753 }
01754 #endif
01755
01756 #if defined(AST_MISDN_ENHANCEMENTS)
01757
01758
01759
01760
01761
01762
01763
01764
01765 static enum mISDN_NUMBER_TYPE PartyNumber_to_misdn_ton_private(unsigned party_ton)
01766 {
01767 enum mISDN_NUMBER_TYPE ton;
01768
01769 switch (party_ton) {
01770 default:
01771 case 0:
01772 ton = NUMTYPE_UNKNOWN;
01773 break;
01774
01775 case 1:
01776 ton = NUMTYPE_INTERNATIONAL;
01777 break;
01778
01779 case 2:
01780 ton = NUMTYPE_NATIONAL;
01781 break;
01782
01783 case 3:
01784 ton = NUMTYPE_NETWORK_SPECIFIC;
01785 break;
01786
01787 case 4:
01788 ton = NUMTYPE_SUBSCRIBER;
01789 break;
01790
01791 case 6:
01792 ton = NUMTYPE_ABBREVIATED;
01793 break;
01794 }
01795
01796 return ton;
01797 }
01798 #endif
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808 static const char *misdn_to_str_ton(enum mISDN_NUMBER_TYPE number_type)
01809 {
01810 const char *str;
01811
01812 switch (number_type) {
01813 default:
01814 case NUMTYPE_UNKNOWN:
01815 str = "Unknown";
01816 break;
01817
01818 case NUMTYPE_INTERNATIONAL:
01819 str = "International";
01820 break;
01821
01822 case NUMTYPE_NATIONAL:
01823 str = "National";
01824 break;
01825
01826 case NUMTYPE_NETWORK_SPECIFIC:
01827 str = "Network Specific";
01828 break;
01829
01830 case NUMTYPE_SUBSCRIBER:
01831 str = "Subscriber";
01832 break;
01833
01834 case NUMTYPE_ABBREVIATED:
01835 str = "Abbreviated";
01836 break;
01837 }
01838
01839 return str;
01840 }
01841
01842
01843
01844
01845
01846
01847
01848
01849
01850 static int misdn_to_ast_ton(enum mISDN_NUMBER_TYPE number_type)
01851 {
01852 int ast_number_type;
01853
01854 switch (number_type) {
01855 default:
01856 case NUMTYPE_UNKNOWN:
01857 ast_number_type = NUMTYPE_UNKNOWN << 4;
01858 break;
01859
01860 case NUMTYPE_INTERNATIONAL:
01861 ast_number_type = NUMTYPE_INTERNATIONAL << 4;
01862 break;
01863
01864 case NUMTYPE_NATIONAL:
01865 ast_number_type = NUMTYPE_NATIONAL << 4;
01866 break;
01867
01868 case NUMTYPE_NETWORK_SPECIFIC:
01869 ast_number_type = NUMTYPE_NETWORK_SPECIFIC << 4;
01870 break;
01871
01872 case NUMTYPE_SUBSCRIBER:
01873 ast_number_type = NUMTYPE_SUBSCRIBER << 4;
01874 break;
01875
01876 case NUMTYPE_ABBREVIATED:
01877 ast_number_type = NUMTYPE_ABBREVIATED << 4;
01878 break;
01879 }
01880
01881 return ast_number_type;
01882 }
01883
01884
01885
01886
01887
01888
01889
01890
01891
01892 static enum mISDN_NUMBER_TYPE ast_to_misdn_ton(unsigned ast_number_type)
01893 {
01894 enum mISDN_NUMBER_TYPE number_type;
01895
01896 switch ((ast_number_type >> 4) & 0x07) {
01897 default:
01898 case NUMTYPE_UNKNOWN:
01899 number_type = NUMTYPE_UNKNOWN;
01900 break;
01901
01902 case NUMTYPE_INTERNATIONAL:
01903 number_type = NUMTYPE_INTERNATIONAL;
01904 break;
01905
01906 case NUMTYPE_NATIONAL:
01907 number_type = NUMTYPE_NATIONAL;
01908 break;
01909
01910 case NUMTYPE_NETWORK_SPECIFIC:
01911 number_type = NUMTYPE_NETWORK_SPECIFIC;
01912 break;
01913
01914 case NUMTYPE_SUBSCRIBER:
01915 number_type = NUMTYPE_SUBSCRIBER;
01916 break;
01917
01918 case NUMTYPE_ABBREVIATED:
01919 number_type = NUMTYPE_ABBREVIATED;
01920 break;
01921 }
01922
01923 return number_type;
01924 }
01925
01926
01927
01928
01929
01930
01931
01932
01933
01934 static const char *misdn_to_str_plan(enum mISDN_NUMBER_PLAN number_plan)
01935 {
01936 const char *str;
01937
01938 switch (number_plan) {
01939 default:
01940 case NUMPLAN_UNKNOWN:
01941 str = "Unknown";
01942 break;
01943
01944 case NUMPLAN_ISDN:
01945 str = "ISDN";
01946 break;
01947
01948 case NUMPLAN_DATA:
01949 str = "Data";
01950 break;
01951
01952 case NUMPLAN_TELEX:
01953 str = "Telex";
01954 break;
01955
01956 case NUMPLAN_NATIONAL:
01957 str = "National";
01958 break;
01959
01960 case NUMPLAN_PRIVATE:
01961 str = "Private";
01962 break;
01963 }
01964
01965 return str;
01966 }
01967
01968
01969
01970
01971
01972
01973
01974
01975
01976 static int misdn_to_ast_plan(enum mISDN_NUMBER_PLAN number_plan)
01977 {
01978 int ast_number_plan;
01979
01980 switch (number_plan) {
01981 default:
01982 case NUMPLAN_UNKNOWN:
01983 ast_number_plan = NUMPLAN_UNKNOWN;
01984 break;
01985
01986 case NUMPLAN_ISDN:
01987 ast_number_plan = NUMPLAN_ISDN;
01988 break;
01989
01990 case NUMPLAN_DATA:
01991 ast_number_plan = NUMPLAN_DATA;
01992 break;
01993
01994 case NUMPLAN_TELEX:
01995 ast_number_plan = NUMPLAN_TELEX;
01996 break;
01997
01998 case NUMPLAN_NATIONAL:
01999 ast_number_plan = NUMPLAN_NATIONAL;
02000 break;
02001
02002 case NUMPLAN_PRIVATE:
02003 ast_number_plan = NUMPLAN_PRIVATE;
02004 break;
02005 }
02006
02007 return ast_number_plan;
02008 }
02009
02010
02011
02012
02013
02014
02015
02016
02017
02018 static enum mISDN_NUMBER_PLAN ast_to_misdn_plan(unsigned ast_number_plan)
02019 {
02020 enum mISDN_NUMBER_PLAN number_plan;
02021
02022 switch (ast_number_plan & 0x0F) {
02023 default:
02024 case NUMPLAN_UNKNOWN:
02025 number_plan = NUMPLAN_UNKNOWN;
02026 break;
02027
02028 case NUMPLAN_ISDN:
02029 number_plan = NUMPLAN_ISDN;
02030 break;
02031
02032 case NUMPLAN_DATA:
02033 number_plan = NUMPLAN_DATA;
02034 break;
02035
02036 case NUMPLAN_TELEX:
02037 number_plan = NUMPLAN_TELEX;
02038 break;
02039
02040 case NUMPLAN_NATIONAL:
02041 number_plan = NUMPLAN_NATIONAL;
02042 break;
02043
02044 case NUMPLAN_PRIVATE:
02045 number_plan = NUMPLAN_PRIVATE;
02046 break;
02047 }
02048
02049 return number_plan;
02050 }
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060 static const char *misdn_to_str_pres(int presentation)
02061 {
02062 const char *str;
02063
02064 switch (presentation) {
02065 case 0:
02066 str = "Allowed";
02067 break;
02068
02069 case 1:
02070 str = "Restricted";
02071 break;
02072
02073 case 2:
02074 str = "Unavailable";
02075 break;
02076
02077 default:
02078 str = "Unknown";
02079 break;
02080 }
02081
02082 return str;
02083 }
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093 static int misdn_to_ast_pres(int presentation)
02094 {
02095 switch (presentation) {
02096 default:
02097 case 0:
02098 presentation = AST_PRES_ALLOWED;
02099 break;
02100
02101 case 1:
02102 presentation = AST_PRES_RESTRICTED;
02103 break;
02104
02105 case 2:
02106 presentation = AST_PRES_UNAVAILABLE;
02107 break;
02108 }
02109
02110 return presentation;
02111 }
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121 static int ast_to_misdn_pres(int presentation)
02122 {
02123 switch (presentation & AST_PRES_RESTRICTION) {
02124 default:
02125 case AST_PRES_ALLOWED:
02126 presentation = 0;
02127 break;
02128
02129 case AST_PRES_RESTRICTED:
02130 presentation = 1;
02131 break;
02132
02133 case AST_PRES_UNAVAILABLE:
02134 presentation = 2;
02135 break;
02136 }
02137
02138 return presentation;
02139 }
02140
02141
02142
02143
02144
02145
02146
02147
02148
02149 static const char *misdn_to_str_screen(int screening)
02150 {
02151 const char *str;
02152
02153 switch (screening) {
02154 case 0:
02155 str = "Unscreened";
02156 break;
02157
02158 case 1:
02159 str = "Passed Screen";
02160 break;
02161
02162 case 2:
02163 str = "Failed Screen";
02164 break;
02165
02166 case 3:
02167 str = "Network Number";
02168 break;
02169
02170 default:
02171 str = "Unknown";
02172 break;
02173 }
02174
02175 return str;
02176 }
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186 static int misdn_to_ast_screen(int screening)
02187 {
02188 switch (screening) {
02189 default:
02190 case 0:
02191 screening = AST_PRES_USER_NUMBER_UNSCREENED;
02192 break;
02193
02194 case 1:
02195 screening = AST_PRES_USER_NUMBER_PASSED_SCREEN;
02196 break;
02197
02198 case 2:
02199 screening = AST_PRES_USER_NUMBER_FAILED_SCREEN;
02200 break;
02201
02202 case 3:
02203 screening = AST_PRES_NETWORK_NUMBER;
02204 break;
02205 }
02206
02207 return screening;
02208 }
02209
02210
02211
02212
02213
02214
02215
02216
02217
02218 static int ast_to_misdn_screen(int screening)
02219 {
02220 switch (screening & AST_PRES_NUMBER_TYPE) {
02221 default:
02222 case AST_PRES_USER_NUMBER_UNSCREENED:
02223 screening = 0;
02224 break;
02225
02226 case AST_PRES_USER_NUMBER_PASSED_SCREEN:
02227 screening = 1;
02228 break;
02229
02230 case AST_PRES_USER_NUMBER_FAILED_SCREEN:
02231 screening = 2;
02232 break;
02233
02234 case AST_PRES_NETWORK_NUMBER:
02235 screening = 3;
02236 break;
02237 }
02238
02239 return screening;
02240 }
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250 static enum mISDN_REDIRECTING_REASON ast_to_misdn_reason(const enum AST_REDIRECTING_REASON ast)
02251 {
02252 unsigned index;
02253
02254 static const struct misdn_reasons {
02255 enum AST_REDIRECTING_REASON ast;
02256 enum mISDN_REDIRECTING_REASON q931;
02257 } misdn_reason_table[] = {
02258
02259 { AST_REDIRECTING_REASON_UNKNOWN, mISDN_REDIRECTING_REASON_UNKNOWN },
02260 { AST_REDIRECTING_REASON_USER_BUSY, mISDN_REDIRECTING_REASON_CALL_FWD_BUSY },
02261 { AST_REDIRECTING_REASON_NO_ANSWER, mISDN_REDIRECTING_REASON_NO_REPLY },
02262 { AST_REDIRECTING_REASON_UNAVAILABLE, mISDN_REDIRECTING_REASON_NO_REPLY },
02263 { AST_REDIRECTING_REASON_UNCONDITIONAL, mISDN_REDIRECTING_REASON_CALL_FWD },
02264 { AST_REDIRECTING_REASON_TIME_OF_DAY, mISDN_REDIRECTING_REASON_UNKNOWN },
02265 { AST_REDIRECTING_REASON_DO_NOT_DISTURB, mISDN_REDIRECTING_REASON_UNKNOWN },
02266 { AST_REDIRECTING_REASON_DEFLECTION, mISDN_REDIRECTING_REASON_DEFLECTION },
02267 { AST_REDIRECTING_REASON_FOLLOW_ME, mISDN_REDIRECTING_REASON_UNKNOWN },
02268 { AST_REDIRECTING_REASON_OUT_OF_ORDER, mISDN_REDIRECTING_REASON_OUT_OF_ORDER },
02269 { AST_REDIRECTING_REASON_AWAY, mISDN_REDIRECTING_REASON_UNKNOWN },
02270 { AST_REDIRECTING_REASON_CALL_FWD_DTE, mISDN_REDIRECTING_REASON_CALL_FWD_DTE }
02271
02272 };
02273
02274 for (index = 0; index < ARRAY_LEN(misdn_reason_table); ++index) {
02275 if (misdn_reason_table[index].ast == ast) {
02276 return misdn_reason_table[index].q931;
02277 }
02278 }
02279 return mISDN_REDIRECTING_REASON_UNKNOWN;
02280 }
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290 static enum AST_REDIRECTING_REASON misdn_to_ast_reason(const enum mISDN_REDIRECTING_REASON q931)
02291 {
02292 enum AST_REDIRECTING_REASON ast;
02293
02294 switch (q931) {
02295 default:
02296 case mISDN_REDIRECTING_REASON_UNKNOWN:
02297 ast = AST_REDIRECTING_REASON_UNKNOWN;
02298 break;
02299
02300 case mISDN_REDIRECTING_REASON_CALL_FWD_BUSY:
02301 ast = AST_REDIRECTING_REASON_USER_BUSY;
02302 break;
02303
02304 case mISDN_REDIRECTING_REASON_NO_REPLY:
02305 ast = AST_REDIRECTING_REASON_NO_ANSWER;
02306 break;
02307
02308 case mISDN_REDIRECTING_REASON_DEFLECTION:
02309 ast = AST_REDIRECTING_REASON_DEFLECTION;
02310 break;
02311
02312 case mISDN_REDIRECTING_REASON_OUT_OF_ORDER:
02313 ast = AST_REDIRECTING_REASON_OUT_OF_ORDER;
02314 break;
02315
02316 case mISDN_REDIRECTING_REASON_CALL_FWD_DTE:
02317 ast = AST_REDIRECTING_REASON_CALL_FWD_DTE;
02318 break;
02319
02320 case mISDN_REDIRECTING_REASON_CALL_FWD:
02321 ast = AST_REDIRECTING_REASON_UNCONDITIONAL;
02322 break;
02323 }
02324
02325 return ast;
02326 }
02327
02328
02329
02330 struct allowed_bearers {
02331 char *name;
02332 char *display;
02333 int cap;
02334 int deprecated;
02335 };
02336
02337
02338 static const struct allowed_bearers allowed_bearers_array[] = {
02339
02340 { "speech", "Speech", INFO_CAPABILITY_SPEECH, 0 },
02341 { "3_1khz", "3.1KHz Audio", INFO_CAPABILITY_AUDIO_3_1K, 0 },
02342 { "digital_unrestricted", "Unrestricted Digital", INFO_CAPABILITY_DIGITAL_UNRESTRICTED, 0 },
02343 { "digital_restricted", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 0 },
02344 { "digital_restriced", "Restricted Digital", INFO_CAPABILITY_DIGITAL_RESTRICTED, 1 },
02345 { "video", "Video", INFO_CAPABILITY_VIDEO, 0 }
02346 };
02347
02348
02349 static const char *bearer2str(int cap)
02350 {
02351 unsigned index;
02352
02353 for (index = 0; index < ARRAY_LEN(allowed_bearers_array); ++index) {
02354 if (allowed_bearers_array[index].cap == cap) {
02355 return allowed_bearers_array[index].display;
02356 }
02357 }
02358
02359 return "Unknown Bearer";
02360 }
02361
02362 #if defined(AST_MISDN_ENHANCEMENTS)
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372 static void misdn_PartyNumber_fill(struct FacPartyNumber *party, const struct misdn_party_id *id)
02373 {
02374 ast_copy_string((char *) party->Number, id->number, sizeof(party->Number));
02375 party->LengthOfNumber = strlen((char *) party->Number);
02376 party->Type = misdn_to_PartyNumber_plan(id->number_plan);
02377 switch (party->Type) {
02378 case 1:
02379 party->TypeOfNumber = misdn_to_PartyNumber_ton_public(id->number_type);
02380 break;
02381 case 5:
02382 party->TypeOfNumber = misdn_to_PartyNumber_ton_private(id->number_type);
02383 break;
02384 default:
02385 party->TypeOfNumber = 0;
02386 break;
02387 }
02388 }
02389 #endif
02390
02391 #if defined(AST_MISDN_ENHANCEMENTS)
02392
02393
02394
02395
02396
02397
02398
02399
02400
02401 static void misdn_PartyNumber_extract(struct misdn_party_id *id, const struct FacPartyNumber *party)
02402 {
02403 if (party->LengthOfNumber) {
02404 ast_copy_string(id->number, (char *) party->Number, sizeof(id->number));
02405 id->number_plan = PartyNumber_to_misdn_plan(party->Type);
02406 switch (party->Type) {
02407 case 1:
02408 id->number_type = PartyNumber_to_misdn_ton_public(party->TypeOfNumber);
02409 break;
02410 case 5:
02411 id->number_type = PartyNumber_to_misdn_ton_private(party->TypeOfNumber);
02412 break;
02413 default:
02414 id->number_type = NUMTYPE_UNKNOWN;
02415 break;
02416 }
02417 } else {
02418
02419 id->number_type = NUMTYPE_UNKNOWN;
02420 id->number_plan = NUMPLAN_ISDN;
02421 id->number[0] = 0;
02422 }
02423 }
02424 #endif
02425
02426 #if defined(AST_MISDN_ENHANCEMENTS)
02427
02428
02429
02430
02431
02432
02433
02434
02435
02436 static void misdn_Address_fill(struct FacAddress *Address, const struct misdn_party_id *id)
02437 {
02438 misdn_PartyNumber_fill(&Address->Party, id);
02439
02440
02441 Address->Subaddress.Length = 0;
02442 }
02443 #endif
02444
02445 #if defined(AST_MISDN_ENHANCEMENTS)
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455 static void misdn_PresentedNumberUnscreened_fill(struct FacPresentedNumberUnscreened *presented, const struct misdn_party_id *id)
02456 {
02457 presented->Type = misdn_to_PresentedNumberUnscreened_type(id->presentation, id->number[0] ? 1 : 0);
02458 misdn_PartyNumber_fill(&presented->Unscreened, id);
02459 }
02460 #endif
02461
02462 #if defined(AST_MISDN_ENHANCEMENTS)
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472 static void misdn_PresentedNumberUnscreened_extract(struct misdn_party_id *id, const struct FacPresentedNumberUnscreened *presented)
02473 {
02474 id->presentation = PresentedNumberUnscreened_to_misdn_pres(presented->Type);
02475 id->screening = 0;
02476 switch (presented->Type) {
02477 case 0:
02478 case 3:
02479 misdn_PartyNumber_extract(id, &presented->Unscreened);
02480 break;
02481 case 1:
02482 case 2:
02483 default:
02484
02485 id->number_type = NUMTYPE_UNKNOWN;
02486 id->number_plan = NUMPLAN_ISDN;
02487 id->number[0] = 0;
02488 break;
02489 }
02490 }
02491 #endif
02492
02493 #if defined(AST_MISDN_ENHANCEMENTS)
02494 static const char Level_Spacing[] = " ";
02495 #endif
02496
02497 #if defined(AST_MISDN_ENHANCEMENTS)
02498 static void print_facility_PartyNumber(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
02499 {
02500 if (Party->LengthOfNumber) {
02501 const char *Spacing;
02502
02503 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02504 chan_misdn_log(1, bc->port, " -->%s PartyNumber: Type:%d\n",
02505 Spacing, Party->Type);
02506 switch (Party->Type) {
02507 case 0:
02508 chan_misdn_log(1, bc->port, " -->%s Unknown: %s\n",
02509 Spacing, Party->Number);
02510 break;
02511 case 1:
02512 chan_misdn_log(1, bc->port, " -->%s Public TON:%d %s\n",
02513 Spacing, Party->TypeOfNumber, Party->Number);
02514 break;
02515 case 2:
02516 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
02517 Spacing, Party->Number);
02518 break;
02519 case 3:
02520 chan_misdn_log(1, bc->port, " -->%s Data: %s\n",
02521 Spacing, Party->Number);
02522 break;
02523 case 4:
02524 chan_misdn_log(1, bc->port, " -->%s Telex: %s\n",
02525 Spacing, Party->Number);
02526 break;
02527 case 5:
02528 chan_misdn_log(1, bc->port, " -->%s Private TON:%d %s\n",
02529 Spacing, Party->TypeOfNumber, Party->Number);
02530 break;
02531 case 8:
02532 chan_misdn_log(1, bc->port, " -->%s National: %s\n",
02533 Spacing, Party->Number);
02534 break;
02535 default:
02536 break;
02537 }
02538 }
02539 }
02540 #endif
02541
02542 #if defined(AST_MISDN_ENHANCEMENTS)
02543 static void print_facility_Subaddress(unsigned Level, const struct FacPartySubaddress *Subaddress, const struct misdn_bchannel *bc)
02544 {
02545 if (Subaddress->Length) {
02546 const char *Spacing;
02547
02548 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02549 chan_misdn_log(1, bc->port, " -->%s Subaddress: Type:%d\n",
02550 Spacing, Subaddress->Type);
02551 switch (Subaddress->Type) {
02552 case 0:
02553 if (Subaddress->u.UserSpecified.OddCountPresent) {
02554 chan_misdn_log(1, bc->port, " -->%s User BCD OddCount:%d NumOctets:%d\n",
02555 Spacing, Subaddress->u.UserSpecified.OddCount, Subaddress->Length);
02556 } else {
02557 chan_misdn_log(1, bc->port, " -->%s User: %s\n",
02558 Spacing, Subaddress->u.UserSpecified.Information);
02559 }
02560 break;
02561 case 1:
02562 chan_misdn_log(1, bc->port, " -->%s NSAP: %s\n",
02563 Spacing, Subaddress->u.Nsap);
02564 break;
02565 default:
02566 break;
02567 }
02568 }
02569 }
02570 #endif
02571
02572 #if defined(AST_MISDN_ENHANCEMENTS)
02573 static void print_facility_Address(unsigned Level, const struct FacAddress *Address, const struct misdn_bchannel *bc)
02574 {
02575 print_facility_PartyNumber(Level, &Address->Party, bc);
02576 print_facility_Subaddress(Level, &Address->Subaddress, bc);
02577 }
02578 #endif
02579
02580 #if defined(AST_MISDN_ENHANCEMENTS)
02581 static void print_facility_PresentedNumberUnscreened(unsigned Level, const struct FacPresentedNumberUnscreened *Presented, const struct misdn_bchannel *bc)
02582 {
02583 const char *Spacing;
02584
02585 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02586 chan_misdn_log(1, bc->port, " -->%s Unscreened Type:%d\n", Spacing, Presented->Type);
02587 switch (Presented->Type) {
02588 case 0:
02589 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
02590 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
02591 break;
02592 case 1:
02593 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
02594 break;
02595 case 2:
02596 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
02597 break;
02598 case 3:
02599 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
02600 print_facility_PartyNumber(Level + 2, &Presented->Unscreened, bc);
02601 break;
02602 default:
02603 break;
02604 }
02605 }
02606 #endif
02607
02608 #if defined(AST_MISDN_ENHANCEMENTS)
02609 static void print_facility_AddressScreened(unsigned Level, const struct FacAddressScreened *Address, const struct misdn_bchannel *bc)
02610 {
02611 const char *Spacing;
02612
02613 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02614 chan_misdn_log(1, bc->port, " -->%s ScreeningIndicator:%d\n", Spacing, Address->ScreeningIndicator);
02615 print_facility_PartyNumber(Level, &Address->Party, bc);
02616 print_facility_Subaddress(Level, &Address->Subaddress, bc);
02617 }
02618 #endif
02619
02620 #if defined(AST_MISDN_ENHANCEMENTS)
02621 static void print_facility_PresentedAddressScreened(unsigned Level, const struct FacPresentedAddressScreened *Presented, const struct misdn_bchannel *bc)
02622 {
02623 const char *Spacing;
02624
02625 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02626 chan_misdn_log(1, bc->port, " -->%s Screened Type:%d\n", Spacing, Presented->Type);
02627 switch (Presented->Type) {
02628 case 0:
02629 chan_misdn_log(1, bc->port, " -->%s Allowed:\n", Spacing);
02630 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
02631 break;
02632 case 1:
02633 chan_misdn_log(1, bc->port, " -->%s Restricted\n", Spacing);
02634 break;
02635 case 2:
02636 chan_misdn_log(1, bc->port, " -->%s Not Available\n", Spacing);
02637 break;
02638 case 3:
02639 chan_misdn_log(1, bc->port, " -->%s Restricted:\n", Spacing);
02640 print_facility_AddressScreened(Level + 2, &Presented->Address, bc);
02641 break;
02642 default:
02643 break;
02644 }
02645 }
02646 #endif
02647
02648 #if defined(AST_MISDN_ENHANCEMENTS)
02649 static void print_facility_Q931_Bc_Hlc_Llc(unsigned Level, const struct Q931_Bc_Hlc_Llc *Q931ie, const struct misdn_bchannel *bc)
02650 {
02651 const char *Spacing;
02652
02653 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02654 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
02655 if (Q931ie->Bc.Length) {
02656 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
02657 }
02658 if (Q931ie->Hlc.Length) {
02659 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
02660 }
02661 if (Q931ie->Llc.Length) {
02662 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
02663 }
02664 }
02665 #endif
02666
02667 #if defined(AST_MISDN_ENHANCEMENTS)
02668 static void print_facility_Q931_Bc_Hlc_Llc_Uu(unsigned Level, const struct Q931_Bc_Hlc_Llc_Uu *Q931ie, const struct misdn_bchannel *bc)
02669 {
02670 const char *Spacing;
02671
02672 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02673 chan_misdn_log(1, bc->port, " -->%s Q931ie:\n", Spacing);
02674 if (Q931ie->Bc.Length) {
02675 chan_misdn_log(1, bc->port, " -->%s Bc Len:%d\n", Spacing, Q931ie->Bc.Length);
02676 }
02677 if (Q931ie->Hlc.Length) {
02678 chan_misdn_log(1, bc->port, " -->%s Hlc Len:%d\n", Spacing, Q931ie->Hlc.Length);
02679 }
02680 if (Q931ie->Llc.Length) {
02681 chan_misdn_log(1, bc->port, " -->%s Llc Len:%d\n", Spacing, Q931ie->Llc.Length);
02682 }
02683 if (Q931ie->UserInfo.Length) {
02684 chan_misdn_log(1, bc->port, " -->%s UserInfo Len:%d\n", Spacing, Q931ie->UserInfo.Length);
02685 }
02686 }
02687 #endif
02688
02689 #if defined(AST_MISDN_ENHANCEMENTS)
02690 static void print_facility_CallInformation(unsigned Level, const struct FacCallInformation *CallInfo, const struct misdn_bchannel *bc)
02691 {
02692 const char *Spacing;
02693
02694 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02695 chan_misdn_log(1, bc->port, " -->%s CCBSReference:%d\n",
02696 Spacing, CallInfo->CCBSReference);
02697 chan_misdn_log(1, bc->port, " -->%s AddressOfB:\n", Spacing);
02698 print_facility_Address(Level + 1, &CallInfo->AddressOfB, bc);
02699 print_facility_Q931_Bc_Hlc_Llc(Level, &CallInfo->Q931ie, bc);
02700 if (CallInfo->SubaddressOfA.Length) {
02701 chan_misdn_log(1, bc->port, " -->%s SubaddressOfA:\n", Spacing);
02702 print_facility_Subaddress(Level + 1, &CallInfo->SubaddressOfA, bc);
02703 }
02704 }
02705 #endif
02706
02707 #if defined(AST_MISDN_ENHANCEMENTS)
02708 static void print_facility_ServedUserNr(unsigned Level, const struct FacPartyNumber *Party, const struct misdn_bchannel *bc)
02709 {
02710 const char *Spacing;
02711
02712 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02713 if (Party->LengthOfNumber) {
02714 print_facility_PartyNumber(Level, Party, bc);
02715 } else {
02716 chan_misdn_log(1, bc->port, " -->%s All Numbers\n", Spacing);
02717 }
02718 }
02719 #endif
02720
02721 #if defined(AST_MISDN_ENHANCEMENTS)
02722 static void print_facility_IntResult(unsigned Level, const struct FacForwardingRecord *ForwardingRecord, const struct misdn_bchannel *bc)
02723 {
02724 const char *Spacing;
02725
02726 Spacing = &Level_Spacing[sizeof(Level_Spacing) - 1 - Level];
02727 chan_misdn_log(1, bc->port, " -->%s Procedure:%d BasicService:%d\n",
02728 Spacing,
02729 ForwardingRecord->Procedure,
02730 ForwardingRecord->BasicService);
02731 chan_misdn_log(1, bc->port, " -->%s ForwardedTo:\n", Spacing);
02732 print_facility_Address(Level + 1, &ForwardingRecord->ForwardedTo, bc);
02733 chan_misdn_log(1, bc->port, " -->%s ServedUserNr:\n", Spacing);
02734 print_facility_ServedUserNr(Level + 1, &ForwardingRecord->ServedUser, bc);
02735 }
02736 #endif
02737
02738 static void print_facility(const struct FacParm *fac, const struct misdn_bchannel *bc)
02739 {
02740 #if defined(AST_MISDN_ENHANCEMENTS)
02741 unsigned Index;
02742 #endif
02743
02744 switch (fac->Function) {
02745 #if defined(AST_MISDN_ENHANCEMENTS)
02746 case Fac_ActivationDiversion:
02747 chan_misdn_log(1, bc->port, " --> ActivationDiversion: InvokeID:%d\n",
02748 fac->u.ActivationDiversion.InvokeID);
02749 switch (fac->u.ActivationDiversion.ComponentType) {
02750 case FacComponent_Invoke:
02751 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
02752 fac->u.ActivationDiversion.Component.Invoke.Procedure,
02753 fac->u.ActivationDiversion.Component.Invoke.BasicService);
02754 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
02755 print_facility_Address(3, &fac->u.ActivationDiversion.Component.Invoke.ForwardedTo, bc);
02756 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
02757 print_facility_ServedUserNr(3, &fac->u.ActivationDiversion.Component.Invoke.ServedUser, bc);
02758 break;
02759 case FacComponent_Result:
02760 chan_misdn_log(1, bc->port, " --> Result\n");
02761 break;
02762 default:
02763 break;
02764 }
02765 break;
02766 case Fac_DeactivationDiversion:
02767 chan_misdn_log(1, bc->port, " --> DeactivationDiversion: InvokeID:%d\n",
02768 fac->u.DeactivationDiversion.InvokeID);
02769 switch (fac->u.DeactivationDiversion.ComponentType) {
02770 case FacComponent_Invoke:
02771 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
02772 fac->u.DeactivationDiversion.Component.Invoke.Procedure,
02773 fac->u.DeactivationDiversion.Component.Invoke.BasicService);
02774 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
02775 print_facility_ServedUserNr(3, &fac->u.DeactivationDiversion.Component.Invoke.ServedUser, bc);
02776 break;
02777 case FacComponent_Result:
02778 chan_misdn_log(1, bc->port, " --> Result\n");
02779 break;
02780 default:
02781 break;
02782 }
02783 break;
02784 case Fac_ActivationStatusNotificationDiv:
02785 chan_misdn_log(1, bc->port, " --> ActivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
02786 fac->u.ActivationStatusNotificationDiv.InvokeID,
02787 fac->u.ActivationStatusNotificationDiv.Procedure,
02788 fac->u.ActivationStatusNotificationDiv.BasicService);
02789 chan_misdn_log(1, bc->port, " --> ForwardedTo:\n");
02790 print_facility_Address(2, &fac->u.ActivationStatusNotificationDiv.ForwardedTo, bc);
02791 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
02792 print_facility_ServedUserNr(2, &fac->u.ActivationStatusNotificationDiv.ServedUser, bc);
02793 break;
02794 case Fac_DeactivationStatusNotificationDiv:
02795 chan_misdn_log(1, bc->port, " --> DeactivationStatusNotificationDiv: InvokeID:%d Procedure:%d BasicService:%d\n",
02796 fac->u.DeactivationStatusNotificationDiv.InvokeID,
02797 fac->u.DeactivationStatusNotificationDiv.Procedure,
02798 fac->u.DeactivationStatusNotificationDiv.BasicService);
02799 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
02800 print_facility_ServedUserNr(2, &fac->u.DeactivationStatusNotificationDiv.ServedUser, bc);
02801 break;
02802 case Fac_InterrogationDiversion:
02803 chan_misdn_log(1, bc->port, " --> InterrogationDiversion: InvokeID:%d\n",
02804 fac->u.InterrogationDiversion.InvokeID);
02805 switch (fac->u.InterrogationDiversion.ComponentType) {
02806 case FacComponent_Invoke:
02807 chan_misdn_log(1, bc->port, " --> Invoke: Procedure:%d BasicService:%d\n",
02808 fac->u.InterrogationDiversion.Component.Invoke.Procedure,
02809 fac->u.InterrogationDiversion.Component.Invoke.BasicService);
02810 chan_misdn_log(1, bc->port, " --> ServedUserNr:\n");
02811 print_facility_ServedUserNr(3, &fac->u.InterrogationDiversion.Component.Invoke.ServedUser, bc);
02812 break;
02813 case FacComponent_Result:
02814 chan_misdn_log(1, bc->port, " --> Result:\n");
02815 if (fac->u.InterrogationDiversion.Component.Result.NumRecords) {
02816 for (Index = 0; Index < fac->u.InterrogationDiversion.Component.Result.NumRecords; ++Index) {
02817 chan_misdn_log(1, bc->port, " --> IntResult[%d]:\n", Index);
02818 print_facility_IntResult(3, &fac->u.InterrogationDiversion.Component.Result.List[Index], bc);
02819 }
02820 }
02821 break;
02822 default:
02823 break;
02824 }
02825 break;
02826 case Fac_DiversionInformation:
02827 chan_misdn_log(1, bc->port, " --> DiversionInformation: InvokeID:%d Reason:%d BasicService:%d\n",
02828 fac->u.DiversionInformation.InvokeID,
02829 fac->u.DiversionInformation.DiversionReason,
02830 fac->u.DiversionInformation.BasicService);
02831 if (fac->u.DiversionInformation.ServedUserSubaddress.Length) {
02832 chan_misdn_log(1, bc->port, " --> ServedUserSubaddress:\n");
02833 print_facility_Subaddress(2, &fac->u.DiversionInformation.ServedUserSubaddress, bc);
02834 }
02835 if (fac->u.DiversionInformation.CallingAddressPresent) {
02836 chan_misdn_log(1, bc->port, " --> CallingAddress:\n");
02837 print_facility_PresentedAddressScreened(2, &fac->u.DiversionInformation.CallingAddress, bc);
02838 }
02839 if (fac->u.DiversionInformation.OriginalCalledPresent) {
02840 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
02841 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.OriginalCalled, bc);
02842 }
02843 if (fac->u.DiversionInformation.LastDivertingPresent) {
02844 chan_misdn_log(1, bc->port, " --> LastDivertingNr:\n");
02845 print_facility_PresentedNumberUnscreened(2, &fac->u.DiversionInformation.LastDiverting, bc);
02846 }
02847 if (fac->u.DiversionInformation.LastDivertingReasonPresent) {
02848 chan_misdn_log(1, bc->port, " --> LastDivertingReason:%d\n", fac->u.DiversionInformation.LastDivertingReason);
02849 }
02850 if (fac->u.DiversionInformation.UserInfo.Length) {
02851 chan_misdn_log(1, bc->port, " --> UserInfo Length:%d\n", fac->u.DiversionInformation.UserInfo.Length);
02852 }
02853 break;
02854 case Fac_CallDeflection:
02855 chan_misdn_log(1, bc->port, " --> CallDeflection: InvokeID:%d\n",
02856 fac->u.CallDeflection.InvokeID);
02857 switch (fac->u.CallDeflection.ComponentType) {
02858 case FacComponent_Invoke:
02859 chan_misdn_log(1, bc->port, " --> Invoke:\n");
02860 if (fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
02861 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
02862 fac->u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser);
02863 }
02864 chan_misdn_log(1, bc->port, " --> DeflectionAddress:\n");
02865 print_facility_Address(3, &fac->u.CallDeflection.Component.Invoke.Deflection, bc);
02866 break;
02867 case FacComponent_Result:
02868 chan_misdn_log(1, bc->port, " --> Result\n");
02869 break;
02870 default:
02871 break;
02872 }
02873 break;
02874 case Fac_CallRerouteing:
02875 chan_misdn_log(1, bc->port, " --> CallRerouteing: InvokeID:%d\n",
02876 fac->u.CallRerouteing.InvokeID);
02877 switch (fac->u.CallRerouteing.ComponentType) {
02878 case FacComponent_Invoke:
02879 chan_misdn_log(1, bc->port, " --> Invoke: Reason:%d Counter:%d\n",
02880 fac->u.CallRerouteing.Component.Invoke.ReroutingReason,
02881 fac->u.CallRerouteing.Component.Invoke.ReroutingCounter);
02882 chan_misdn_log(1, bc->port, " --> CalledAddress:\n");
02883 print_facility_Address(3, &fac->u.CallRerouteing.Component.Invoke.CalledAddress, bc);
02884 print_facility_Q931_Bc_Hlc_Llc_Uu(2, &fac->u.CallRerouteing.Component.Invoke.Q931ie, bc);
02885 chan_misdn_log(1, bc->port, " --> LastReroutingNr:\n");
02886 print_facility_PresentedNumberUnscreened(3, &fac->u.CallRerouteing.Component.Invoke.LastRerouting, bc);
02887 chan_misdn_log(1, bc->port, " --> SubscriptionOption:%d\n",
02888 fac->u.CallRerouteing.Component.Invoke.SubscriptionOption);
02889 if (fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length) {
02890 chan_misdn_log(1, bc->port, " --> CallingParty:\n");
02891 print_facility_Subaddress(3, &fac->u.CallRerouteing.Component.Invoke.CallingPartySubaddress, bc);
02892 }
02893 break;
02894 case FacComponent_Result:
02895 chan_misdn_log(1, bc->port, " --> Result\n");
02896 break;
02897 default:
02898 break;
02899 }
02900 break;
02901 case Fac_InterrogateServedUserNumbers:
02902 chan_misdn_log(1, bc->port, " --> InterrogateServedUserNumbers: InvokeID:%d\n",
02903 fac->u.InterrogateServedUserNumbers.InvokeID);
02904 switch (fac->u.InterrogateServedUserNumbers.ComponentType) {
02905 case FacComponent_Invoke:
02906 chan_misdn_log(1, bc->port, " --> Invoke\n");
02907 break;
02908 case FacComponent_Result:
02909 chan_misdn_log(1, bc->port, " --> Result:\n");
02910 if (fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords) {
02911 for (Index = 0; Index < fac->u.InterrogateServedUserNumbers.Component.Result.NumRecords; ++Index) {
02912 chan_misdn_log(1, bc->port, " --> ServedUserNr[%d]:\n", Index);
02913 print_facility_PartyNumber(3, &fac->u.InterrogateServedUserNumbers.Component.Result.List[Index], bc);
02914 }
02915 }
02916 break;
02917 default:
02918 break;
02919 }
02920 break;
02921 case Fac_DivertingLegInformation1:
02922 chan_misdn_log(1, bc->port, " --> DivertingLegInformation1: InvokeID:%d Reason:%d SubscriptionOption:%d\n",
02923 fac->u.DivertingLegInformation1.InvokeID,
02924 fac->u.DivertingLegInformation1.DiversionReason,
02925 fac->u.DivertingLegInformation1.SubscriptionOption);
02926 if (fac->u.DivertingLegInformation1.DivertedToPresent) {
02927 chan_misdn_log(1, bc->port, " --> DivertedToNr:\n");
02928 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation1.DivertedTo, bc);
02929 }
02930 break;
02931 case Fac_DivertingLegInformation2:
02932 chan_misdn_log(1, bc->port, " --> DivertingLegInformation2: InvokeID:%d Reason:%d Count:%d\n",
02933 fac->u.DivertingLegInformation2.InvokeID,
02934 fac->u.DivertingLegInformation2.DiversionReason,
02935 fac->u.DivertingLegInformation2.DiversionCounter);
02936 if (fac->u.DivertingLegInformation2.DivertingPresent) {
02937 chan_misdn_log(1, bc->port, " --> DivertingNr:\n");
02938 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.Diverting, bc);
02939 }
02940 if (fac->u.DivertingLegInformation2.OriginalCalledPresent) {
02941 chan_misdn_log(1, bc->port, " --> OriginalCalledNr:\n");
02942 print_facility_PresentedNumberUnscreened(2, &fac->u.DivertingLegInformation2.OriginalCalled, bc);
02943 }
02944 break;
02945 case Fac_DivertingLegInformation3:
02946 chan_misdn_log(1, bc->port, " --> DivertingLegInformation3: InvokeID:%d PresentationAllowed:%d\n",
02947 fac->u.DivertingLegInformation3.InvokeID,
02948 fac->u.DivertingLegInformation3.PresentationAllowedIndicator);
02949 break;
02950
02951 #else
02952
02953 case Fac_CD:
02954 chan_misdn_log(1, bc->port, " --> calldeflect to: %s, presentable: %s\n", fac->u.CDeflection.DeflectedToNumber,
02955 fac->u.CDeflection.PresentationAllowed ? "yes" : "no");
02956 break;
02957 #endif
02958 case Fac_AOCDCurrency:
02959 if (fac->u.AOCDcur.chargeNotAvailable) {
02960 chan_misdn_log(1, bc->port, " --> AOCD currency: charge not available\n");
02961 } else if (fac->u.AOCDcur.freeOfCharge) {
02962 chan_misdn_log(1, bc->port, " --> AOCD currency: free of charge\n");
02963 } else if (fac->u.AOCDchu.billingId >= 0) {
02964 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s billingId:%d\n",
02965 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
02966 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDcur.billingId);
02967 } else {
02968 chan_misdn_log(1, bc->port, " --> AOCD currency: currency:%s amount:%d multiplier:%d typeOfChargingInfo:%s\n",
02969 fac->u.AOCDcur.currency, fac->u.AOCDcur.currencyAmount, fac->u.AOCDcur.multiplier,
02970 (fac->u.AOCDcur.typeOfChargingInfo == 0) ? "subTotal" : "total");
02971 }
02972 break;
02973 case Fac_AOCDChargingUnit:
02974 if (fac->u.AOCDchu.chargeNotAvailable) {
02975 chan_misdn_log(1, bc->port, " --> AOCD charging unit: charge not available\n");
02976 } else if (fac->u.AOCDchu.freeOfCharge) {
02977 chan_misdn_log(1, bc->port, " --> AOCD charging unit: free of charge\n");
02978 } else if (fac->u.AOCDchu.billingId >= 0) {
02979 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s billingId:%d\n",
02980 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total", fac->u.AOCDchu.billingId);
02981 } else {
02982 chan_misdn_log(1, bc->port, " --> AOCD charging unit: recordedUnits:%d typeOfChargingInfo:%s\n",
02983 fac->u.AOCDchu.recordedUnits, (fac->u.AOCDchu.typeOfChargingInfo == 0) ? "subTotal" : "total");
02984 }
02985 break;
02986 #if defined(AST_MISDN_ENHANCEMENTS)
02987 case Fac_ERROR:
02988 chan_misdn_log(1, bc->port, " --> ERROR: InvokeID:%d, Code:0x%02x\n",
02989 fac->u.ERROR.invokeId, fac->u.ERROR.errorValue);
02990 break;
02991 case Fac_RESULT:
02992 chan_misdn_log(1, bc->port, " --> RESULT: InvokeID:%d\n",
02993 fac->u.RESULT.InvokeID);
02994 break;
02995 case Fac_REJECT:
02996 if (fac->u.REJECT.InvokeIDPresent) {
02997 chan_misdn_log(1, bc->port, " --> REJECT: InvokeID:%d, Code:0x%02x\n",
02998 fac->u.REJECT.InvokeID, fac->u.REJECT.Code);
02999 } else {
03000 chan_misdn_log(1, bc->port, " --> REJECT: Code:0x%02x\n",
03001 fac->u.REJECT.Code);
03002 }
03003 break;
03004 case Fac_EctExecute:
03005 chan_misdn_log(1, bc->port, " --> EctExecute: InvokeID:%d\n",
03006 fac->u.EctExecute.InvokeID);
03007 break;
03008 case Fac_ExplicitEctExecute:
03009 chan_misdn_log(1, bc->port, " --> ExplicitEctExecute: InvokeID:%d LinkID:%d\n",
03010 fac->u.ExplicitEctExecute.InvokeID,
03011 fac->u.ExplicitEctExecute.LinkID);
03012 break;
03013 case Fac_RequestSubaddress:
03014 chan_misdn_log(1, bc->port, " --> RequestSubaddress: InvokeID:%d\n",
03015 fac->u.RequestSubaddress.InvokeID);
03016 break;
03017 case Fac_SubaddressTransfer:
03018 chan_misdn_log(1, bc->port, " --> SubaddressTransfer: InvokeID:%d\n",
03019 fac->u.SubaddressTransfer.InvokeID);
03020 print_facility_Subaddress(1, &fac->u.SubaddressTransfer.Subaddress, bc);
03021 break;
03022 case Fac_EctLinkIdRequest:
03023 chan_misdn_log(1, bc->port, " --> EctLinkIdRequest: InvokeID:%d\n",
03024 fac->u.EctLinkIdRequest.InvokeID);
03025 switch (fac->u.EctLinkIdRequest.ComponentType) {
03026 case FacComponent_Invoke:
03027 chan_misdn_log(1, bc->port, " --> Invoke\n");
03028 break;
03029 case FacComponent_Result:
03030 chan_misdn_log(1, bc->port, " --> Result: LinkID:%d\n",
03031 fac->u.EctLinkIdRequest.Component.Result.LinkID);
03032 break;
03033 default:
03034 break;
03035 }
03036 break;
03037 case Fac_EctInform:
03038 chan_misdn_log(1, bc->port, " --> EctInform: InvokeID:%d Status:%d\n",
03039 fac->u.EctInform.InvokeID,
03040 fac->u.EctInform.Status);
03041 if (fac->u.EctInform.RedirectionPresent) {
03042 chan_misdn_log(1, bc->port, " --> Redirection Number\n");
03043 print_facility_PresentedNumberUnscreened(2, &fac->u.EctInform.Redirection, bc);
03044 }
03045 break;
03046 case Fac_EctLoopTest:
03047 chan_misdn_log(1, bc->port, " --> EctLoopTest: InvokeID:%d\n",
03048 fac->u.EctLoopTest.InvokeID);
03049 switch (fac->u.EctLoopTest.ComponentType) {
03050 case FacComponent_Invoke:
03051 chan_misdn_log(1, bc->port, " --> Invoke: CallTransferID:%d\n",
03052 fac->u.EctLoopTest.Component.Invoke.CallTransferID);
03053 break;
03054 case FacComponent_Result:
03055 chan_misdn_log(1, bc->port, " --> Result: LoopResult:%d\n",
03056 fac->u.EctLoopTest.Component.Result.LoopResult);
03057 break;
03058 default:
03059 break;
03060 }
03061 break;
03062 case Fac_StatusRequest:
03063 chan_misdn_log(1, bc->port, " --> StatusRequest: InvokeID:%d\n",
03064 fac->u.StatusRequest.InvokeID);
03065 switch (fac->u.StatusRequest.ComponentType) {
03066 case FacComponent_Invoke:
03067 chan_misdn_log(1, bc->port, " --> Invoke: Compatibility:%d\n",
03068 fac->u.StatusRequest.Component.Invoke.CompatibilityMode);
03069 break;
03070 case FacComponent_Result:
03071 chan_misdn_log(1, bc->port, " --> Result: Status:%d\n",
03072 fac->u.StatusRequest.Component.Result.Status);
03073 break;
03074 default:
03075 break;
03076 }
03077 break;
03078 case Fac_CallInfoRetain:
03079 chan_misdn_log(1, bc->port, " --> CallInfoRetain: InvokeID:%d, LinkageID:%d\n",
03080 fac->u.CallInfoRetain.InvokeID, fac->u.CallInfoRetain.CallLinkageID);
03081 break;
03082 case Fac_CCBSDeactivate:
03083 chan_misdn_log(1, bc->port, " --> CCBSDeactivate: InvokeID:%d\n",
03084 fac->u.CCBSDeactivate.InvokeID);
03085 switch (fac->u.CCBSDeactivate.ComponentType) {
03086 case FacComponent_Invoke:
03087 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d\n",
03088 fac->u.CCBSDeactivate.Component.Invoke.CCBSReference);
03089 break;
03090 case FacComponent_Result:
03091 chan_misdn_log(1, bc->port, " --> Result\n");
03092 break;
03093 default:
03094 break;
03095 }
03096 break;
03097 case Fac_CCBSErase:
03098 chan_misdn_log(1, bc->port, " --> CCBSErase: InvokeID:%d, CCBSReference:%d RecallMode:%d, Reason:%d\n",
03099 fac->u.CCBSErase.InvokeID, fac->u.CCBSErase.CCBSReference,
03100 fac->u.CCBSErase.RecallMode, fac->u.CCBSErase.Reason);
03101 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
03102 print_facility_Address(2, &fac->u.CCBSErase.AddressOfB, bc);
03103 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSErase.Q931ie, bc);
03104 break;
03105 case Fac_CCBSRemoteUserFree:
03106 chan_misdn_log(1, bc->port, " --> CCBSRemoteUserFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
03107 fac->u.CCBSRemoteUserFree.InvokeID, fac->u.CCBSRemoteUserFree.CCBSReference,
03108 fac->u.CCBSRemoteUserFree.RecallMode);
03109 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
03110 print_facility_Address(2, &fac->u.CCBSRemoteUserFree.AddressOfB, bc);
03111 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSRemoteUserFree.Q931ie, bc);
03112 break;
03113 case Fac_CCBSCall:
03114 chan_misdn_log(1, bc->port, " --> CCBSCall: InvokeID:%d, CCBSReference:%d\n",
03115 fac->u.CCBSCall.InvokeID, fac->u.CCBSCall.CCBSReference);
03116 break;
03117 case Fac_CCBSStatusRequest:
03118 chan_misdn_log(1, bc->port, " --> CCBSStatusRequest: InvokeID:%d\n",
03119 fac->u.CCBSStatusRequest.InvokeID);
03120 switch (fac->u.CCBSStatusRequest.ComponentType) {
03121 case FacComponent_Invoke:
03122 chan_misdn_log(1, bc->port, " --> Invoke: CCBSReference:%d RecallMode:%d\n",
03123 fac->u.CCBSStatusRequest.Component.Invoke.CCBSReference,
03124 fac->u.CCBSStatusRequest.Component.Invoke.RecallMode);
03125 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBSStatusRequest.Component.Invoke.Q931ie, bc);
03126 break;
03127 case FacComponent_Result:
03128 chan_misdn_log(1, bc->port, " --> Result: Free:%d\n",
03129 fac->u.CCBSStatusRequest.Component.Result.Free);
03130 break;
03131 default:
03132 break;
03133 }
03134 break;
03135 case Fac_CCBSBFree:
03136 chan_misdn_log(1, bc->port, " --> CCBSBFree: InvokeID:%d, CCBSReference:%d RecallMode:%d\n",
03137 fac->u.CCBSBFree.InvokeID, fac->u.CCBSBFree.CCBSReference,
03138 fac->u.CCBSBFree.RecallMode);
03139 chan_misdn_log(1, bc->port, " --> AddressOfB\n");
03140 print_facility_Address(2, &fac->u.CCBSBFree.AddressOfB, bc);
03141 print_facility_Q931_Bc_Hlc_Llc(1, &fac->u.CCBSBFree.Q931ie, bc);
03142 break;
03143 case Fac_EraseCallLinkageID:
03144 chan_misdn_log(1, bc->port, " --> EraseCallLinkageID: InvokeID:%d, LinkageID:%d\n",
03145 fac->u.EraseCallLinkageID.InvokeID, fac->u.EraseCallLinkageID.CallLinkageID);
03146 break;
03147 case Fac_CCBSStopAlerting:
03148 chan_misdn_log(1, bc->port, " --> CCBSStopAlerting: InvokeID:%d, CCBSReference:%d\n",
03149 fac->u.CCBSStopAlerting.InvokeID, fac->u.CCBSStopAlerting.CCBSReference);
03150 break;
03151 case Fac_CCBSRequest:
03152 chan_misdn_log(1, bc->port, " --> CCBSRequest: InvokeID:%d\n",
03153 fac->u.CCBSRequest.InvokeID);
03154 switch (fac->u.CCBSRequest.ComponentType) {
03155 case FacComponent_Invoke:
03156 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
03157 fac->u.CCBSRequest.Component.Invoke.CallLinkageID);
03158 break;
03159 case FacComponent_Result:
03160 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
03161 fac->u.CCBSRequest.Component.Result.CCBSReference,
03162 fac->u.CCBSRequest.Component.Result.RecallMode);
03163 break;
03164 default:
03165 break;
03166 }
03167 break;
03168 case Fac_CCBSInterrogate:
03169 chan_misdn_log(1, bc->port, " --> CCBSInterrogate: InvokeID:%d\n",
03170 fac->u.CCBSInterrogate.InvokeID);
03171 switch (fac->u.CCBSInterrogate.ComponentType) {
03172 case FacComponent_Invoke:
03173 chan_misdn_log(1, bc->port, " --> Invoke\n");
03174 if (fac->u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent) {
03175 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
03176 fac->u.CCBSInterrogate.Component.Invoke.CCBSReference);
03177 }
03178 if (fac->u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber) {
03179 chan_misdn_log(1, bc->port, " --> AParty\n");
03180 print_facility_PartyNumber(3, &fac->u.CCBSInterrogate.Component.Invoke.AParty, bc);
03181 }
03182 break;
03183 case FacComponent_Result:
03184 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
03185 fac->u.CCBSInterrogate.Component.Result.RecallMode);
03186 if (fac->u.CCBSInterrogate.Component.Result.NumRecords) {
03187 for (Index = 0; Index < fac->u.CCBSInterrogate.Component.Result.NumRecords; ++Index) {
03188 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
03189 print_facility_CallInformation(3, &fac->u.CCBSInterrogate.Component.Result.CallDetails[Index], bc);
03190 }
03191 }
03192 break;
03193 default:
03194 break;
03195 }
03196 break;
03197 case Fac_CCNRRequest:
03198 chan_misdn_log(1, bc->port, " --> CCNRRequest: InvokeID:%d\n",
03199 fac->u.CCNRRequest.InvokeID);
03200 switch (fac->u.CCNRRequest.ComponentType) {
03201 case FacComponent_Invoke:
03202 chan_misdn_log(1, bc->port, " --> Invoke: LinkageID:%d\n",
03203 fac->u.CCNRRequest.Component.Invoke.CallLinkageID);
03204 break;
03205 case FacComponent_Result:
03206 chan_misdn_log(1, bc->port, " --> Result: CCBSReference:%d RecallMode:%d\n",
03207 fac->u.CCNRRequest.Component.Result.CCBSReference,
03208 fac->u.CCNRRequest.Component.Result.RecallMode);
03209 break;
03210 default:
03211 break;
03212 }
03213 break;
03214 case Fac_CCNRInterrogate:
03215 chan_misdn_log(1, bc->port, " --> CCNRInterrogate: InvokeID:%d\n",
03216 fac->u.CCNRInterrogate.InvokeID);
03217 switch (fac->u.CCNRInterrogate.ComponentType) {
03218 case FacComponent_Invoke:
03219 chan_misdn_log(1, bc->port, " --> Invoke\n");
03220 if (fac->u.CCNRInterrogate.Component.Invoke.CCBSReferencePresent) {
03221 chan_misdn_log(1, bc->port, " --> CCBSReference:%d\n",
03222 fac->u.CCNRInterrogate.Component.Invoke.CCBSReference);
03223 }
03224 if (fac->u.CCNRInterrogate.Component.Invoke.AParty.LengthOfNumber) {
03225 chan_misdn_log(1, bc->port, " --> AParty\n");
03226 print_facility_PartyNumber(3, &fac->u.CCNRInterrogate.Component.Invoke.AParty, bc);
03227 }
03228 break;
03229 case FacComponent_Result:
03230 chan_misdn_log(1, bc->port, " --> Result: RecallMode:%d\n",
03231 fac->u.CCNRInterrogate.Component.Result.RecallMode);
03232 if (fac->u.CCNRInterrogate.Component.Result.NumRecords) {
03233 for (Index = 0; Index < fac->u.CCNRInterrogate.Component.Result.NumRecords; ++Index) {
03234 chan_misdn_log(1, bc->port, " --> CallDetails[%d]:\n", Index);
03235 print_facility_CallInformation(3, &fac->u.CCNRInterrogate.Component.Result.CallDetails[Index], bc);
03236 }
03237 }
03238 break;
03239 default:
03240 break;
03241 }
03242 break;
03243 case Fac_CCBS_T_Call:
03244 chan_misdn_log(1, bc->port, " --> CCBS_T_Call: InvokeID:%d\n",
03245 fac->u.CCBS_T_Call.InvokeID);
03246 break;
03247 case Fac_CCBS_T_Suspend:
03248 chan_misdn_log(1, bc->port, " --> CCBS_T_Suspend: InvokeID:%d\n",
03249 fac->u.CCBS_T_Suspend.InvokeID);
03250 break;
03251 case Fac_CCBS_T_Resume:
03252 chan_misdn_log(1, bc->port, " --> CCBS_T_Resume: InvokeID:%d\n",
03253 fac->u.CCBS_T_Resume.InvokeID);
03254 break;
03255 case Fac_CCBS_T_RemoteUserFree:
03256 chan_misdn_log(1, bc->port, " --> CCBS_T_RemoteUserFree: InvokeID:%d\n",
03257 fac->u.CCBS_T_RemoteUserFree.InvokeID);
03258 break;
03259 case Fac_CCBS_T_Available:
03260 chan_misdn_log(1, bc->port, " --> CCBS_T_Available: InvokeID:%d\n",
03261 fac->u.CCBS_T_Available.InvokeID);
03262 break;
03263 case Fac_CCBS_T_Request:
03264 chan_misdn_log(1, bc->port, " --> CCBS_T_Request: InvokeID:%d\n",
03265 fac->u.CCBS_T_Request.InvokeID);
03266 switch (fac->u.CCBS_T_Request.ComponentType) {
03267 case FacComponent_Invoke:
03268 chan_misdn_log(1, bc->port, " --> Invoke\n");
03269 chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
03270 print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Destination, bc);
03271 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCBS_T_Request.Component.Invoke.Q931ie, bc);
03272 if (fac->u.CCBS_T_Request.Component.Invoke.RetentionSupported) {
03273 chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
03274 }
03275 if (fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
03276 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
03277 fac->u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator);
03278 }
03279 if (fac->u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
03280 chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
03281 print_facility_Address(3, &fac->u.CCBS_T_Request.Component.Invoke.Originating, bc);
03282 }
03283 break;
03284 case FacComponent_Result:
03285 chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
03286 fac->u.CCBS_T_Request.Component.Result.RetentionSupported);
03287 break;
03288 default:
03289 break;
03290 }
03291 break;
03292 case Fac_CCNR_T_Request:
03293 chan_misdn_log(1, bc->port, " --> CCNR_T_Request: InvokeID:%d\n",
03294 fac->u.CCNR_T_Request.InvokeID);
03295 switch (fac->u.CCNR_T_Request.ComponentType) {
03296 case FacComponent_Invoke:
03297 chan_misdn_log(1, bc->port, " --> Invoke\n");
03298 chan_misdn_log(1, bc->port, " --> DestinationAddress:\n");
03299 print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Destination, bc);
03300 print_facility_Q931_Bc_Hlc_Llc(2, &fac->u.CCNR_T_Request.Component.Invoke.Q931ie, bc);
03301 if (fac->u.CCNR_T_Request.Component.Invoke.RetentionSupported) {
03302 chan_misdn_log(1, bc->port, " --> RetentionSupported:1\n");
03303 }
03304 if (fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent) {
03305 chan_misdn_log(1, bc->port, " --> PresentationAllowed:%d\n",
03306 fac->u.CCNR_T_Request.Component.Invoke.PresentationAllowedIndicator);
03307 }
03308 if (fac->u.CCNR_T_Request.Component.Invoke.Originating.Party.LengthOfNumber) {
03309 chan_misdn_log(1, bc->port, " --> OriginatingAddress:\n");
03310 print_facility_Address(3, &fac->u.CCNR_T_Request.Component.Invoke.Originating, bc);
03311 }
03312 break;
03313 case FacComponent_Result:
03314 chan_misdn_log(1, bc->port, " --> Result: RetentionSupported:%d\n",
03315 fac->u.CCNR_T_Request.Component.Result.RetentionSupported);
03316 break;
03317 default:
03318 break;
03319 }
03320 break;
03321 #endif
03322 case Fac_None:
03323
03324 break;
03325 default:
03326 chan_misdn_log(1, bc->port, " --> unknown facility\n");
03327 break;
03328 }
03329 }
03330
03331 static void print_bearer(struct misdn_bchannel *bc)
03332 {
03333 chan_misdn_log(2, bc->port, " --> Bearer: %s\n", bearer2str(bc->capability));
03334
03335 switch(bc->law) {
03336 case INFO_CODEC_ALAW:
03337 chan_misdn_log(2, bc->port, " --> Codec: Alaw\n");
03338 break;
03339 case INFO_CODEC_ULAW:
03340 chan_misdn_log(2, bc->port, " --> Codec: Ulaw\n");
03341 break;
03342 }
03343 }
03344
03345
03346
03347
03348
03349
03350
03351
03352
03353
03354
03355
03356
03357 static void misdn_prefix_string(const char *str_prefix, char *str_main, size_t size)
03358 {
03359 size_t len_over;
03360 size_t len_total;
03361 size_t len_main;
03362 size_t len_prefix;
03363
03364 len_prefix = strlen(str_prefix);
03365 if (!len_prefix) {
03366
03367 return;
03368 }
03369 len_main = strlen(str_main);
03370 len_total = len_prefix + len_main;
03371 if (size <= len_total) {
03372
03373 len_over = len_total + 1 - size;
03374 if (len_over <= len_main) {
03375 len_main -= len_over;
03376 } else {
03377 len_over -= len_main;
03378 len_main = 0;
03379 len_prefix -= len_over;
03380 }
03381 }
03382 if (len_main) {
03383 memmove(str_main + len_prefix, str_main, len_main);
03384 }
03385 memcpy(str_main, str_prefix, len_prefix);
03386 str_main[len_prefix + len_main] = '\0';
03387 }
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397
03398
03399
03400 static void misdn_add_number_prefix(int port, enum mISDN_NUMBER_TYPE number_type, char *number, size_t size)
03401 {
03402 enum misdn_cfg_elements type_prefix;
03403 char num_prefix[MISDN_MAX_NUMBER_LEN];
03404
03405
03406 switch (number_type) {
03407 case NUMTYPE_UNKNOWN:
03408 type_prefix = MISDN_CFG_TON_PREFIX_UNKNOWN;
03409 break;
03410 case NUMTYPE_INTERNATIONAL:
03411 type_prefix = MISDN_CFG_TON_PREFIX_INTERNATIONAL;
03412 break;
03413 case NUMTYPE_NATIONAL:
03414 type_prefix = MISDN_CFG_TON_PREFIX_NATIONAL;
03415 break;
03416 case NUMTYPE_NETWORK_SPECIFIC:
03417 type_prefix = MISDN_CFG_TON_PREFIX_NETWORK_SPECIFIC;
03418 break;
03419 case NUMTYPE_SUBSCRIBER:
03420 type_prefix = MISDN_CFG_TON_PREFIX_SUBSCRIBER;
03421 break;
03422 case NUMTYPE_ABBREVIATED:
03423 type_prefix = MISDN_CFG_TON_PREFIX_ABBREVIATED;
03424 break;
03425 default:
03426
03427 return;
03428 }
03429 misdn_cfg_get(port, type_prefix, num_prefix, sizeof(num_prefix));
03430
03431 misdn_prefix_string(num_prefix, number, size);
03432 }
03433
03434 static void export_aoc_vars(int originator, struct ast_channel *ast, struct misdn_bchannel *bc)
03435 {
03436 char buf[128];
03437
03438 if (!bc->AOCD_need_export || !ast) {
03439 return;
03440 }
03441
03442 if (originator == ORG_AST) {
03443 ast = ast_bridged_channel(ast);
03444 if (!ast) {
03445 return;
03446 }
03447 }
03448
03449 switch (bc->AOCDtype) {
03450 case Fac_AOCDCurrency:
03451 pbx_builtin_setvar_helper(ast, "AOCD_Type", "currency");
03452 if (bc->AOCD.currency.chargeNotAvailable) {
03453 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
03454 } else {
03455 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
03456 if (bc->AOCD.currency.freeOfCharge) {
03457 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
03458 } else {
03459 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
03460 if (snprintf(buf, sizeof(buf), "%d %s", bc->AOCD.currency.currencyAmount * bc->AOCD.currency.multiplier, bc->AOCD.currency.currency) < sizeof(buf)) {
03461 pbx_builtin_setvar_helper(ast, "AOCD_Amount", buf);
03462 if (bc->AOCD.currency.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.currency.billingId) < sizeof(buf)) {
03463 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
03464 }
03465 }
03466 }
03467 }
03468 break;
03469 case Fac_AOCDChargingUnit:
03470 pbx_builtin_setvar_helper(ast, "AOCD_Type", "charging_unit");
03471 if (bc->AOCD.chargingUnit.chargeNotAvailable) {
03472 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "no");
03473 } else {
03474 pbx_builtin_setvar_helper(ast, "AOCD_ChargeAvailable", "yes");
03475 if (bc->AOCD.chargingUnit.freeOfCharge) {
03476 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "yes");
03477 } else {
03478 pbx_builtin_setvar_helper(ast, "AOCD_FreeOfCharge", "no");
03479 if (snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.recordedUnits) < sizeof(buf)) {
03480 pbx_builtin_setvar_helper(ast, "AOCD_RecordedUnits", buf);
03481 if (bc->AOCD.chargingUnit.billingId >= 0 && snprintf(buf, sizeof(buf), "%d", bc->AOCD.chargingUnit.billingId) < sizeof(buf)) {
03482 pbx_builtin_setvar_helper(ast, "AOCD_BillingId", buf);
03483 }
03484 }
03485 }
03486 }
03487 break;
03488 default:
03489 break;
03490 }
03491
03492 bc->AOCD_need_export = 0;
03493 }
03494
03495
03496
03497 static void sighandler(int sig)
03498 {
03499 }
03500
03501 static void *misdn_tasks_thread_func(void *data)
03502 {
03503 int wait;
03504 struct sigaction sa;
03505
03506 sa.sa_handler = sighandler;
03507 sa.sa_flags = SA_NODEFER;
03508 sigemptyset(&sa.sa_mask);
03509 sigaddset(&sa.sa_mask, SIGUSR1);
03510 sigaction(SIGUSR1, &sa, NULL);
03511
03512 sem_post((sem_t *)data);
03513
03514 while (1) {
03515 wait = ast_sched_wait(misdn_tasks);
03516 if (wait < 0) {
03517 wait = 8000;
03518 }
03519 if (poll(NULL, 0, wait) < 0) {
03520 chan_misdn_log(4, 0, "Waking up misdn_tasks thread\n");
03521 }
03522 ast_sched_runq(misdn_tasks);
03523 }
03524 return NULL;
03525 }
03526
03527 static void misdn_tasks_init(void)
03528 {
03529 sem_t blocker;
03530 int i = 5;
03531
03532 if (sem_init(&blocker, 0, 0)) {
03533 perror("chan_misdn: Failed to initialize semaphore!");
03534 exit(1);
03535 }
03536
03537 chan_misdn_log(4, 0, "Starting misdn_tasks thread\n");
03538
03539 misdn_tasks = ast_sched_context_create();
03540 pthread_create(&misdn_tasks_thread, NULL, misdn_tasks_thread_func, &blocker);
03541
03542 while (sem_wait(&blocker) && --i) {
03543 }
03544 sem_destroy(&blocker);
03545 }
03546
03547 static void misdn_tasks_destroy(void)
03548 {
03549 if (misdn_tasks) {
03550 chan_misdn_log(4, 0, "Killing misdn_tasks thread\n");
03551 if (pthread_cancel(misdn_tasks_thread) == 0) {
03552 cb_log(4, 0, "Joining misdn_tasks thread\n");
03553 pthread_join(misdn_tasks_thread, NULL);
03554 }
03555 ast_sched_context_destroy(misdn_tasks);
03556 }
03557 }
03558
03559 static inline void misdn_tasks_wakeup(void)
03560 {
03561 pthread_kill(misdn_tasks_thread, SIGUSR1);
03562 }
03563
03564 static inline int _misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data, int variable)
03565 {
03566 int task_id;
03567
03568 if (!misdn_tasks) {
03569 misdn_tasks_init();
03570 }
03571 task_id = ast_sched_add_variable(misdn_tasks, timeout, callback, data, variable);
03572 misdn_tasks_wakeup();
03573
03574 return task_id;
03575 }
03576
03577 static int misdn_tasks_add(int timeout, ast_sched_cb callback, const void *data)
03578 {
03579 return _misdn_tasks_add_variable(timeout, callback, data, 0);
03580 }
03581
03582 static int misdn_tasks_add_variable(int timeout, ast_sched_cb callback, const void *data)
03583 {
03584 return _misdn_tasks_add_variable(timeout, callback, data, 1);
03585 }
03586
03587 static void misdn_tasks_remove(int task_id)
03588 {
03589 AST_SCHED_DEL(misdn_tasks, task_id);
03590 }
03591
03592 static int misdn_l1_task(const void *vdata)
03593 {
03594 const int *data = vdata;
03595
03596 misdn_lib_isdn_l1watcher(*data);
03597 chan_misdn_log(5, *data, "L1watcher timeout\n");
03598 return 1;
03599 }
03600
03601 static int misdn_overlap_dial_task(const void *data)
03602 {
03603 struct timeval tv_end, tv_now;
03604 int diff;
03605 struct chan_list *ch = (struct chan_list *) data;
03606 char *dad;
03607
03608 chan_misdn_log(4, ch->bc->port, "overlap dial task, chan_state: %d\n", ch->state);
03609
03610 if (ch->state != MISDN_WAITING4DIGS) {
03611 ch->overlap_dial_task = -1;
03612 return 0;
03613 }
03614
03615 ast_mutex_lock(&ch->overlap_tv_lock);
03616 tv_end = ch->overlap_tv;
03617 ast_mutex_unlock(&ch->overlap_tv_lock);
03618
03619 tv_end.tv_sec += ch->overlap_dial;
03620 tv_now = ast_tvnow();
03621
03622 diff = ast_tvdiff_ms(tv_end, tv_now);
03623 if (100 < diff) {
03624 return diff;
03625 }
03626
03627
03628 stop_indicate(ch);
03629
03630 if (ast_strlen_zero(ch->bc->dialed.number)) {
03631 dad = "s";
03632 ast_channel_exten_set(ch->ast, dad);
03633 } else {
03634 dad = ch->bc->dialed.number;
03635 }
03636
03637 if (ast_exists_extension(ch->ast, ch->context, dad, 1, ch->bc->caller.number)) {
03638 ch->state = MISDN_DIALING;
03639 if (pbx_start_chan(ch) < 0) {
03640 chan_misdn_log(-1, ch->bc->port, "ast_pbx_start returned < 0 in misdn_overlap_dial_task\n");
03641 goto misdn_overlap_dial_task_disconnect;
03642 }
03643 } else {
03644 misdn_overlap_dial_task_disconnect:
03645 hanguptone_indicate(ch);
03646 ch->bc->out_cause = AST_CAUSE_UNALLOCATED;
03647 ch->state = MISDN_CLEANING;
03648 misdn_lib_send_event(ch->bc, EVENT_DISCONNECT);
03649 }
03650 ch->overlap_dial_task = -1;
03651 return 0;
03652 }
03653
03654 static void send_digit_to_chan(struct chan_list *cl, char digit)
03655 {
03656 static const char * const dtmf_tones[] = {
03657
03658 "!941+1336/100,!0/100",
03659 "!697+1209/100,!0/100",
03660 "!697+1336/100,!0/100",
03661 "!697+1477/100,!0/100",
03662 "!770+1209/100,!0/100",
03663 "!770+1336/100,!0/100",
03664 "!770+1477/100,!0/100",
03665 "!852+1209/100,!0/100",
03666 "!852+1336/100,!0/100",
03667 "!852+1477/100,!0/100",
03668 "!697+1633/100,!0/100",
03669 "!770+1633/100,!0/100",
03670 "!852+1633/100,!0/100",
03671 "!941+1633/100,!0/100",
03672 "!941+1209/100,!0/100",
03673 "!941+1477/100,!0/100",
03674
03675 };
03676 struct ast_channel *chan = cl->ast;
03677
03678 if (digit >= '0' && digit <='9') {
03679 ast_playtones_start(chan, 0, dtmf_tones[digit - '0'], 0);
03680 } else if (digit >= 'A' && digit <= 'D') {
03681 ast_playtones_start(chan, 0, dtmf_tones[digit - 'A' + 10], 0);
03682 } else if (digit == '*') {
03683 ast_playtones_start(chan, 0, dtmf_tones[14], 0);
03684 } else if (digit == '#') {
03685 ast_playtones_start(chan, 0, dtmf_tones[15], 0);
03686 } else {
03687
03688 ast_debug(1, "Unable to handle DTMF tone '%c' for '%s'\n", digit, ast_channel_name(chan));
03689 }
03690 }
03691
03692
03693 static char *handle_cli_misdn_set_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03694 {
03695 int level;
03696
03697 switch (cmd) {
03698 case CLI_INIT:
03699 e->command = "misdn set debug [on|off]";
03700 e->usage =
03701 "Usage: misdn set debug {on|off|<level>} [only] | [port <port> [only]]\n"
03702 " Set the debug level of the mISDN channel.\n";
03703 return NULL;
03704 case CLI_GENERATE:
03705 return complete_debug_port(a);
03706 }
03707
03708 if (a->argc < 4 || a->argc > 7) {
03709 return CLI_SHOWUSAGE;
03710 }
03711
03712 if (!strcasecmp(a->argv[3], "on")) {
03713 level = 1;
03714 } else if (!strcasecmp(a->argv[3], "off")) {
03715 level = 0;
03716 } else if (isdigit(a->argv[3][0])) {
03717 level = atoi(a->argv[3]);
03718 } else {
03719 return CLI_SHOWUSAGE;
03720 }
03721
03722 switch (a->argc) {
03723 case 4:
03724 case 5:
03725 {
03726 int i;
03727 int only = 0;
03728 if (a->argc == 5) {
03729 if (strncasecmp(a->argv[4], "only", strlen(a->argv[4]))) {
03730 return CLI_SHOWUSAGE;
03731 } else {
03732 only = 1;
03733 }
03734 }
03735
03736 for (i = 0; i <= max_ports; i++) {
03737 misdn_debug[i] = level;
03738 misdn_debug_only[i] = only;
03739 }
03740 ast_cli(a->fd, "changing debug level for all ports to %d%s\n", misdn_debug[0], only ? " (only)" : "");
03741 }
03742 break;
03743 case 6:
03744 case 7:
03745 {
03746 int port;
03747 if (strncasecmp(a->argv[4], "port", strlen(a->argv[4])))
03748 return CLI_SHOWUSAGE;
03749 port = atoi(a->argv[5]);
03750 if (port <= 0 || port > max_ports) {
03751 switch (max_ports) {
03752 case 0:
03753 ast_cli(a->fd, "port number not valid! no ports available so you won't get lucky with any number here...\n");
03754 break;
03755 case 1:
03756 ast_cli(a->fd, "port number not valid! only port 1 is available.\n");
03757 break;
03758 default:
03759 ast_cli(a->fd, "port number not valid! only ports 1 to %d are available.\n", max_ports);
03760 }
03761 return 0;
03762 }
03763 if (a->argc == 7) {
03764 if (strncasecmp(a->argv[6], "only", strlen(a->argv[6]))) {
03765 return CLI_SHOWUSAGE;
03766 } else {
03767 misdn_debug_only[port] = 1;
03768 }
03769 } else {
03770 misdn_debug_only[port] = 0;
03771 }
03772 misdn_debug[port] = level;
03773 ast_cli(a->fd, "changing debug level to %d%s for port %d\n", misdn_debug[port], misdn_debug_only[port] ? " (only)" : "", port);
03774 }
03775 }
03776
03777 return CLI_SUCCESS;
03778 }
03779
03780 static char *handle_cli_misdn_set_crypt_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03781 {
03782 switch (cmd) {
03783 case CLI_INIT:
03784 e->command = "misdn set crypt debug";
03785 e->usage =
03786 "Usage: misdn set crypt debug <level>\n"
03787 " Set the crypt debug level of the mISDN channel. Level\n"
03788 " must be 1 or 2.\n";
03789 return NULL;
03790 case CLI_GENERATE:
03791 return NULL;
03792 }
03793
03794 if (a->argc != 5) {
03795 return CLI_SHOWUSAGE;
03796 }
03797
03798
03799
03800 return CLI_SUCCESS;
03801 }
03802
03803 static char *handle_cli_misdn_port_block(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03804 {
03805 switch (cmd) {
03806 case CLI_INIT:
03807 e->command = "misdn port block";
03808 e->usage =
03809 "Usage: misdn port block <port>\n"
03810 " Block the specified port by <port>.\n";
03811 return NULL;
03812 case CLI_GENERATE:
03813 return NULL;
03814 }
03815
03816 if (a->argc != 4) {
03817 return CLI_SHOWUSAGE;
03818 }
03819
03820 misdn_lib_port_block(atoi(a->argv[3]));
03821
03822 return CLI_SUCCESS;
03823 }
03824
03825 static char *handle_cli_misdn_port_unblock(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03826 {
03827 switch (cmd) {
03828 case CLI_INIT:
03829 e->command = "misdn port unblock";
03830 e->usage =
03831 "Usage: misdn port unblock <port>\n"
03832 " Unblock the port specified by <port>.\n";
03833 return NULL;
03834 case CLI_GENERATE:
03835 return NULL;
03836 }
03837
03838 if (a->argc != 4) {
03839 return CLI_SHOWUSAGE;
03840 }
03841
03842 misdn_lib_port_unblock(atoi(a->argv[3]));
03843
03844 return CLI_SUCCESS;
03845 }
03846
03847 static char *handle_cli_misdn_restart_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03848 {
03849 switch (cmd) {
03850 case CLI_INIT:
03851 e->command = "misdn restart port";
03852 e->usage =
03853 "Usage: misdn restart port <port>\n"
03854 " Restart the given port.\n";
03855 return NULL;
03856 case CLI_GENERATE:
03857 return NULL;
03858 }
03859
03860 if (a->argc != 4) {
03861 return CLI_SHOWUSAGE;
03862 }
03863
03864 misdn_lib_port_restart(atoi(a->argv[3]));
03865
03866 return CLI_SUCCESS;
03867 }
03868
03869 static char *handle_cli_misdn_restart_pid(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03870 {
03871 switch (cmd) {
03872 case CLI_INIT:
03873 e->command = "misdn restart pid";
03874 e->usage =
03875 "Usage: misdn restart pid <pid>\n"
03876 " Restart the given pid\n";
03877 return NULL;
03878 case CLI_GENERATE:
03879 return NULL;
03880 }
03881
03882 if (a->argc != 4) {
03883 return CLI_SHOWUSAGE;
03884 }
03885
03886 misdn_lib_pid_restart(atoi(a->argv[3]));
03887
03888 return CLI_SUCCESS;
03889 }
03890
03891 static char *handle_cli_misdn_port_up(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03892 {
03893 switch (cmd) {
03894 case CLI_INIT:
03895 e->command = "misdn port up";
03896 e->usage =
03897 "Usage: misdn port up <port>\n"
03898 " Try to establish L1 on the given port.\n";
03899 return NULL;
03900 case CLI_GENERATE:
03901 return NULL;
03902 }
03903
03904 if (a->argc != 4) {
03905 return CLI_SHOWUSAGE;
03906 }
03907
03908 misdn_lib_get_port_up(atoi(a->argv[3]));
03909
03910 return CLI_SUCCESS;
03911 }
03912
03913 static char *handle_cli_misdn_port_down(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03914 {
03915 switch (cmd) {
03916 case CLI_INIT:
03917 e->command = "misdn port down";
03918 e->usage =
03919 "Usage: misdn port down <port>\n"
03920 " Try to deactivate the L1 on the given port.\n";
03921 return NULL;
03922 case CLI_GENERATE:
03923 return NULL;
03924 }
03925
03926 if (a->argc != 4) {
03927 return CLI_SHOWUSAGE;
03928 }
03929
03930 misdn_lib_get_port_down(atoi(a->argv[3]));
03931
03932 return CLI_SUCCESS;
03933 }
03934
03935 static inline void show_config_description(int fd, enum misdn_cfg_elements elem)
03936 {
03937 char section[BUFFERSIZE];
03938 char name[BUFFERSIZE];
03939 char desc[BUFFERSIZE];
03940 char def[BUFFERSIZE];
03941 char tmp[BUFFERSIZE];
03942
03943 misdn_cfg_get_name(elem, tmp, sizeof(tmp));
03944 term_color(name, tmp, COLOR_BRWHITE, 0, sizeof(tmp));
03945 misdn_cfg_get_desc(elem, desc, sizeof(desc), def, sizeof(def));
03946
03947 if (elem < MISDN_CFG_LAST) {
03948 term_color(section, "PORTS SECTION", COLOR_YELLOW, 0, sizeof(section));
03949 } else {
03950 term_color(section, "GENERAL SECTION", COLOR_YELLOW, 0, sizeof(section));
03951 }
03952
03953 if (*def) {
03954 ast_cli(fd, "[%s] %s (Default: %s)\n\t%s\n", section, name, def, desc);
03955 } else {
03956 ast_cli(fd, "[%s] %s\n\t%s\n", section, name, desc);
03957 }
03958 }
03959
03960 static char *handle_cli_misdn_show_config(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03961 {
03962 char buffer[BUFFERSIZE];
03963 enum misdn_cfg_elements elem;
03964 int linebreak;
03965 int onlyport = -1;
03966 int ok = 0;
03967
03968 switch (cmd) {
03969 case CLI_INIT:
03970 e->command = "misdn show config";
03971 e->usage =
03972 "Usage: misdn show config [<port> | description <config element> | descriptions [general|ports]]\n"
03973 " Use 0 for <port> to only print the general config.\n";
03974 return NULL;
03975 case CLI_GENERATE:
03976 return complete_show_config(a);
03977 }
03978
03979 if (a->argc >= 4) {
03980 if (!strcmp(a->argv[3], "description")) {
03981 if (a->argc == 5) {
03982 enum misdn_cfg_elements elem = misdn_cfg_get_elem(a->argv[4]);
03983 if (elem == MISDN_CFG_FIRST) {
03984 ast_cli(a->fd, "Unknown element: %s\n", a->argv[4]);
03985 } else {
03986 show_config_description(a->fd, elem);
03987 }
03988 return CLI_SUCCESS;
03989 }
03990 return CLI_SHOWUSAGE;
03991 } else if (!strcmp(a->argv[3], "descriptions")) {
03992 if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "general"))) {
03993 for (elem = MISDN_GEN_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
03994 show_config_description(a->fd, elem);
03995 ast_cli(a->fd, "\n");
03996 }
03997 ok = 1;
03998 }
03999 if ((a->argc == 4) || ((a->argc == 5) && !strcmp(a->argv[4], "ports"))) {
04000 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_CFG_LAST - 1 ; ++elem) {
04001 show_config_description(a->fd, elem);
04002 ast_cli(a->fd, "\n");
04003 }
04004 ok = 1;
04005 }
04006 return ok ? CLI_SUCCESS : CLI_SHOWUSAGE;
04007 } else if (!sscanf(a->argv[3], "%5d", &onlyport) || onlyport < 0) {
04008 ast_cli(a->fd, "Unknown option: %s\n", a->argv[3]);
04009 return CLI_SHOWUSAGE;
04010 }
04011 }
04012
04013 if (a->argc == 3 || onlyport == 0) {
04014 ast_cli(a->fd, "mISDN General-Config:\n");
04015 for (elem = MISDN_GEN_FIRST + 1, linebreak = 1; elem < MISDN_GEN_LAST; elem++, linebreak++) {
04016 misdn_cfg_get_config_string(0, elem, buffer, sizeof(buffer));
04017 ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04018 }
04019 ast_cli(a->fd, "\n");
04020 }
04021
04022 if (onlyport < 0) {
04023 int port = misdn_cfg_get_next_port(0);
04024
04025 for (; port > 0; port = misdn_cfg_get_next_port(port)) {
04026 ast_cli(a->fd, "\n[PORT %d]\n", port);
04027 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04028 misdn_cfg_get_config_string(port, elem, buffer, sizeof(buffer));
04029 ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04030 }
04031 ast_cli(a->fd, "\n");
04032 }
04033 }
04034
04035 if (onlyport > 0) {
04036 if (misdn_cfg_is_port_valid(onlyport)) {
04037 ast_cli(a->fd, "[PORT %d]\n", onlyport);
04038 for (elem = MISDN_CFG_FIRST + 1, linebreak = 1; elem < MISDN_CFG_LAST; elem++, linebreak++) {
04039 misdn_cfg_get_config_string(onlyport, elem, buffer, sizeof(buffer));
04040 ast_cli(a->fd, "%-36s%s", buffer, !(linebreak % 2) ? "\n" : "");
04041 }
04042 ast_cli(a->fd, "\n");
04043 } else {
04044 ast_cli(a->fd, "Port %d is not active!\n", onlyport);
04045 }
04046 }
04047
04048 return CLI_SUCCESS;
04049 }
04050
04051 struct state_struct {
04052 enum misdn_chan_state state;
04053 char txt[255];
04054 };
04055
04056 static const struct state_struct state_array[] = {
04057
04058 { MISDN_NOTHING, "NOTHING" },
04059 { MISDN_WAITING4DIGS, "WAITING4DIGS" },
04060 { MISDN_EXTCANTMATCH, "EXTCANTMATCH" },
04061 { MISDN_INCOMING_SETUP, "INCOMING SETUP" },
04062 { MISDN_DIALING, "DIALING" },
04063 { MISDN_PROGRESS, "PROGRESS" },
04064 { MISDN_PROCEEDING, "PROCEEDING" },
04065 { MISDN_CALLING, "CALLING" },
04066 { MISDN_CALLING_ACKNOWLEDGE, "CALLING_ACKNOWLEDGE" },
04067 { MISDN_ALERTING, "ALERTING" },
04068 { MISDN_BUSY, "BUSY" },
04069 { MISDN_CONNECTED, "CONNECTED" },
04070 { MISDN_DISCONNECTED, "DISCONNECTED" },
04071 { MISDN_CLEANING, "CLEANING" },
04072
04073 };
04074
04075 static const char *misdn_get_ch_state(struct chan_list *p)
04076 {
04077 int i;
04078 static char state[8];
04079
04080 if (!p) {
04081 return NULL;
04082 }
04083
04084 for (i = 0; i < ARRAY_LEN(state_array); i++) {
04085 if (state_array[i].state == p->state) {
04086 return state_array[i].txt;
04087 }
04088 }
04089
04090 snprintf(state, sizeof(state), "%d", p->state) ;
04091
04092 return state;
04093 }
04094
04095
04096 static void reload_config(void)
04097 {
04098 int i, cfg_debug;
04099
04100 if (!g_config_initialized) {
04101 ast_log(LOG_WARNING, "chan_misdn is not initialized properly, still reloading ?\n");
04102 return ;
04103 }
04104
04105 free_robin_list();
04106 misdn_cfg_reload();
04107 misdn_cfg_update_ptp();
04108 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
04109 misdn_cfg_get(0, MISDN_GEN_DEBUG, &cfg_debug, sizeof(cfg_debug));
04110
04111 for (i = 0; i <= max_ports; i++) {
04112 misdn_debug[i] = cfg_debug;
04113 misdn_debug_only[i] = 0;
04114 }
04115 }
04116
04117 static char *handle_cli_misdn_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04118 {
04119 switch (cmd) {
04120 case CLI_INIT:
04121 e->command = "misdn reload";
04122 e->usage =
04123 "Usage: misdn reload\n"
04124 " Reload internal mISDN config, read from the config\n"
04125 " file.\n";
04126 return NULL;
04127 case CLI_GENERATE:
04128 return NULL;
04129 }
04130
04131 if (a->argc != 2) {
04132 return CLI_SHOWUSAGE;
04133 }
04134
04135 ast_cli(a->fd, "Reloading mISDN configuration\n");
04136 reload_config();
04137 return CLI_SUCCESS;
04138 }
04139
04140 static void print_bc_info(int fd, struct chan_list *help, struct misdn_bchannel *bc)
04141 {
04142 struct ast_channel *ast = help->ast;
04143
04144 ast_cli(fd,
04145 "* Pid:%d Port:%d Ch:%d Mode:%s Orig:%s dialed:%s\n"
04146 " --> caller:\"%s\" <%s>\n"
04147 " --> redirecting-from:\"%s\" <%s>\n"
04148 " --> redirecting-to:\"%s\" <%s>\n"
04149 " --> context:%s state:%s\n",
04150 bc->pid,
04151 bc->port,
04152 bc->channel,
04153 bc->nt ? "NT" : "TE",
04154 help->originator == ORG_AST ? "*" : "I",
04155 ast ? ast_channel_exten(ast) : "",
04156 (ast && ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
04157 ? ast_channel_caller(ast)->id.name.str : "",
04158 (ast && ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
04159 ? ast_channel_caller(ast)->id.number.str : "",
04160 bc->redirecting.from.name,
04161 bc->redirecting.from.number,
04162 bc->redirecting.to.name,
04163 bc->redirecting.to.number,
04164 ast ? ast_channel_context(ast) : "",
04165 misdn_get_ch_state(help));
04166 if (misdn_debug[bc->port] > 0) {
04167 ast_cli(fd,
04168 " --> astname: %s\n"
04169 " --> ch_l3id: %x\n"
04170 " --> ch_addr: %x\n"
04171 " --> bc_addr: %x\n"
04172 " --> bc_l3id: %x\n"
04173 " --> display: %s\n"
04174 " --> activated: %d\n"
04175 " --> state: %s\n"
04176 " --> capability: %s\n"
04177 #ifdef MISDN_1_2
04178 " --> pipeline: %s\n"
04179 #else
04180 " --> echo_cancel: %d\n"
04181 #endif
04182 " --> notone : rx %d tx:%d\n"
04183 " --> bc_hold: %d\n",
04184 ast ? ast_channel_name(ast) : "",
04185 help->l3id,
04186 help->addr,
04187 bc->addr,
04188 bc->l3_id,
04189 bc->display,
04190 bc->active,
04191 bc_state2str(bc->bc_state),
04192 bearer2str(bc->capability),
04193 #ifdef MISDN_1_2
04194 bc->pipeline,
04195 #else
04196 bc->ec_enable,
04197 #endif
04198 help->norxtone, help->notxtone,
04199 bc->holded);
04200 }
04201 }
04202
04203 static char *handle_cli_misdn_show_channels(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04204 {
04205 struct chan_list *help;
04206
04207 switch (cmd) {
04208 case CLI_INIT:
04209 e->command = "misdn show channels";
04210 e->usage =
04211 "Usage: misdn show channels\n"
04212 " Show the internal mISDN channel list\n";
04213 return NULL;
04214 case CLI_GENERATE:
04215 return NULL;
04216 }
04217
04218 if (a->argc != 3) {
04219 return CLI_SHOWUSAGE;
04220 }
04221
04222 ast_cli(a->fd, "Channel List: %p\n", cl_te);
04223
04224
04225
04226
04227
04228
04229
04230 ast_mutex_lock(&cl_te_lock);
04231 for (help = cl_te; help; help = help->next) {
04232 struct misdn_bchannel *bc = help->bc;
04233 struct ast_channel *ast = help->ast;
04234 if (!ast) {
04235 if (!bc) {
04236 ast_cli(a->fd, "chan_list obj. with l3id:%x has no bc and no ast Leg\n", help->l3id);
04237 continue;
04238 }
04239 ast_cli(a->fd, "bc with pid:%d has no Ast Leg\n", bc->pid);
04240 }
04241
04242 if (misdn_debug[0] > 2) {
04243 ast_cli(a->fd, "Bc:%p Ast:%p\n", bc, ast);
04244 }
04245 if (bc) {
04246 print_bc_info(a->fd, help, bc);
04247 } else {
04248 if (help->hold.state != MISDN_HOLD_IDLE) {
04249 ast_cli(a->fd, "ITS A HELD CALL BC:\n");
04250 ast_cli(a->fd, " --> l3_id: %x\n"
04251 " --> dialed:%s\n"
04252 " --> caller:\"%s\" <%s>\n"
04253 " --> hold_port: %d\n"
04254 " --> hold_channel: %d\n",
04255 help->l3id,
04256 ast_channel_exten(ast),
04257 S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
04258 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
04259 help->hold.port,
04260 help->hold.channel
04261 );
04262 } else {
04263 ast_cli(a->fd, "* Channel in unknown STATE !!! Exten:%s, Callerid:%s\n",
04264 ast_channel_exten(ast),
04265 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
04266 }
04267 }
04268 }
04269 ast_mutex_unlock(&cl_te_lock);
04270
04271 misdn_dump_chanlist();
04272
04273 return CLI_SUCCESS;
04274 }
04275
04276 static char *handle_cli_misdn_show_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04277 {
04278 struct chan_list *help;
04279
04280 switch (cmd) {
04281 case CLI_INIT:
04282 e->command = "misdn show channel";
04283 e->usage =
04284 "Usage: misdn show channel <channel>\n"
04285 " Show an internal mISDN channel\n.";
04286 return NULL;
04287 case CLI_GENERATE:
04288 return complete_ch(a);
04289 }
04290
04291 if (a->argc != 4) {
04292 return CLI_SHOWUSAGE;
04293 }
04294
04295 ast_mutex_lock(&cl_te_lock);
04296 for (help = cl_te; help; help = help->next) {
04297 struct misdn_bchannel *bc = help->bc;
04298 struct ast_channel *ast = help->ast;
04299
04300 if (bc && ast) {
04301 if (!strcasecmp(ast_channel_name(ast), a->argv[3])) {
04302 print_bc_info(a->fd, help, bc);
04303 break;
04304 }
04305 }
04306 }
04307 ast_mutex_unlock(&cl_te_lock);
04308
04309 return CLI_SUCCESS;
04310 }
04311
04312 static char *handle_cli_misdn_set_tics(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04313 {
04314 switch (cmd) {
04315 case CLI_INIT:
04316 e->command = "misdn set tics";
04317 e->usage =
04318 "Usage: misdn set tics <value>\n";
04319 return NULL;
04320 case CLI_GENERATE:
04321 return NULL;
04322 }
04323
04324 if (a->argc != 4) {
04325 return CLI_SHOWUSAGE;
04326 }
04327
04328
04329 MAXTICS = atoi(a->argv[3]);
04330
04331 return CLI_SUCCESS;
04332 }
04333
04334 static char *handle_cli_misdn_show_stacks(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04335 {
04336 int port;
04337
04338 switch (cmd) {
04339 case CLI_INIT:
04340 e->command = "misdn show stacks";
04341 e->usage =
04342 "Usage: misdn show stacks\n"
04343 " Show internal mISDN stack_list.\n";
04344 return NULL;
04345 case CLI_GENERATE:
04346 return NULL;
04347 }
04348
04349 if (a->argc != 3) {
04350 return CLI_SHOWUSAGE;
04351 }
04352
04353 ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04354 for (port = misdn_cfg_get_next_port(0); port > 0;
04355 port = misdn_cfg_get_next_port(port)) {
04356 char buf[128];
04357
04358 get_show_stack_details(port, buf);
04359 ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04360 }
04361
04362 return CLI_SUCCESS;
04363 }
04364
04365 static char *handle_cli_misdn_show_ports_stats(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04366 {
04367 int port;
04368
04369 switch (cmd) {
04370 case CLI_INIT:
04371 e->command = "misdn show ports stats";
04372 e->usage =
04373 "Usage: misdn show ports stats\n"
04374 " Show mISDNs channel's call statistics per port.\n";
04375 return NULL;
04376 case CLI_GENERATE:
04377 return NULL;
04378 }
04379
04380 if (a->argc != 4) {
04381 return CLI_SHOWUSAGE;
04382 }
04383
04384 ast_cli(a->fd, "Port\tin_calls\tout_calls\n");
04385 for (port = misdn_cfg_get_next_port(0); port > 0;
04386 port = misdn_cfg_get_next_port(port)) {
04387 ast_cli(a->fd, "%d\t%d\t\t%d\n", port, misdn_in_calls[port], misdn_out_calls[port]);
04388 }
04389 ast_cli(a->fd, "\n");
04390
04391 return CLI_SUCCESS;
04392 }
04393
04394 static char *handle_cli_misdn_show_port(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
04395 {
04396 int port;
04397 char buf[128];
04398
04399 switch (cmd) {
04400 case CLI_INIT:
04401 e->command = "misdn show port";
04402 e->usage =
04403 "Usage: misdn show port <port>\n"
04404 " Show detailed information for given port.\n";
04405 return NULL;
04406 case CLI_GENERATE:
04407 return NULL;
04408 }
04409
04410 if (a->argc != 4) {
04411 return CLI_SHOWUSAGE;
04412 }
04413
04414 port = atoi(a->argv[3]);
04415
04416 ast_cli(a->fd, "BEGIN STACK_LIST:\n");
04417 get_show_stack_details(port, buf);
04418 ast_cli(a->fd, " %s Debug:%d%s\n", buf, misdn_debug[port], misdn_debug_only[port] ? "(only)" : "");
04419
04420 return CLI_SUCCESS;
04421 }
04422
04423 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
04424 static const struct FacParm Fac_Msgs[] = {
04425
04426 [0].Function = Fac_ERROR,
04427 [0].u.ERROR.invokeId = 8,
04428 [0].u.ERROR.errorValue = FacError_CCBS_AlreadyAccepted,
04429
04430 [1].Function = Fac_RESULT,
04431 [1].u.RESULT.InvokeID = 9,
04432
04433 [2].Function = Fac_REJECT,
04434 [2].u.REJECT.Code = FacReject_Gen_BadlyStructuredComponent,
04435
04436 [3].Function = Fac_REJECT,
04437 [3].u.REJECT.InvokeIDPresent = 1,
04438 [3].u.REJECT.InvokeID = 10,
04439 [3].u.REJECT.Code = FacReject_Inv_InitiatorReleasing,
04440
04441 [4].Function = Fac_REJECT,
04442 [4].u.REJECT.InvokeIDPresent = 1,
04443 [4].u.REJECT.InvokeID = 11,
04444 [4].u.REJECT.Code = FacReject_Res_MistypedResult,
04445
04446 [5].Function = Fac_REJECT,
04447 [5].u.REJECT.InvokeIDPresent = 1,
04448 [5].u.REJECT.InvokeID = 12,
04449 [5].u.REJECT.Code = FacReject_Err_ErrorResponseUnexpected,
04450
04451 [6].Function = Fac_StatusRequest,
04452 [6].u.StatusRequest.InvokeID = 13,
04453 [6].u.StatusRequest.ComponentType = FacComponent_Invoke,
04454 [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
04455 [6].u.StatusRequest.Component.Invoke.Q931ie.Bc.Contents = "AB",
04456 [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Length = 3,
04457 [6].u.StatusRequest.Component.Invoke.Q931ie.Llc.Contents = "CDE",
04458 [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Length = 4,
04459 [6].u.StatusRequest.Component.Invoke.Q931ie.Hlc.Contents = "FGHI",
04460 [6].u.StatusRequest.Component.Invoke.CompatibilityMode = 1,
04461
04462 [7].Function = Fac_StatusRequest,
04463 [7].u.StatusRequest.InvokeID = 14,
04464 [7].u.StatusRequest.ComponentType = FacComponent_Result,
04465 [7].u.StatusRequest.Component.Result.Status = 2,
04466
04467 [8].Function = Fac_CallInfoRetain,
04468 [8].u.CallInfoRetain.InvokeID = 15,
04469 [8].u.CallInfoRetain.CallLinkageID = 115,
04470
04471 [9].Function = Fac_EraseCallLinkageID,
04472 [9].u.EraseCallLinkageID.InvokeID = 16,
04473 [9].u.EraseCallLinkageID.CallLinkageID = 105,
04474
04475 [10].Function = Fac_CCBSDeactivate,
04476 [10].u.CCBSDeactivate.InvokeID = 17,
04477 [10].u.CCBSDeactivate.ComponentType = FacComponent_Invoke,
04478 [10].u.CCBSDeactivate.Component.Invoke.CCBSReference = 2,
04479
04480 [11].Function = Fac_CCBSDeactivate,
04481 [11].u.CCBSDeactivate.InvokeID = 18,
04482 [11].u.CCBSDeactivate.ComponentType = FacComponent_Result,
04483
04484 [12].Function = Fac_CCBSErase,
04485 [12].u.CCBSErase.InvokeID = 19,
04486 [12].u.CCBSErase.Q931ie.Bc.Length = 2,
04487 [12].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04488 [12].u.CCBSErase.AddressOfB.Party.Type = 0,
04489 [12].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 5,
04490 [12].u.CCBSErase.AddressOfB.Party.Number = "33403",
04491 [12].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
04492 [12].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
04493 [12].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
04494 [12].u.CCBSErase.RecallMode = 1,
04495 [12].u.CCBSErase.CCBSReference = 102,
04496 [12].u.CCBSErase.Reason = 3,
04497
04498 [13].Function = Fac_CCBSErase,
04499 [13].u.CCBSErase.InvokeID = 20,
04500 [13].u.CCBSErase.Q931ie.Bc.Length = 2,
04501 [13].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04502 [13].u.CCBSErase.AddressOfB.Party.Type = 1,
04503 [13].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
04504 [13].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 1,
04505 [13].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
04506 [13].u.CCBSErase.AddressOfB.Subaddress.Type = 0,
04507 [13].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
04508 [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCountPresent = 1,
04509 [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.OddCount = 1,
04510 [13].u.CCBSErase.AddressOfB.Subaddress.u.UserSpecified.Information = "3748",
04511 [13].u.CCBSErase.RecallMode = 1,
04512 [13].u.CCBSErase.CCBSReference = 102,
04513 [13].u.CCBSErase.Reason = 3,
04514
04515 [14].Function = Fac_CCBSErase,
04516 [14].u.CCBSErase.InvokeID = 21,
04517 [14].u.CCBSErase.Q931ie.Bc.Length = 2,
04518 [14].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04519 [14].u.CCBSErase.AddressOfB.Party.Type = 2,
04520 [14].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
04521 [14].u.CCBSErase.AddressOfB.Party.Number = "1803",
04522 [14].u.CCBSErase.AddressOfB.Subaddress.Type = 1,
04523 [14].u.CCBSErase.AddressOfB.Subaddress.Length = 4,
04524 [14].u.CCBSErase.AddressOfB.Subaddress.u.Nsap = "6492",
04525 [14].u.CCBSErase.RecallMode = 1,
04526 [14].u.CCBSErase.CCBSReference = 102,
04527 [14].u.CCBSErase.Reason = 3,
04528
04529 [15].Function = Fac_CCBSErase,
04530 [15].u.CCBSErase.InvokeID = 22,
04531 [15].u.CCBSErase.Q931ie.Bc.Length = 2,
04532 [15].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04533 [15].u.CCBSErase.AddressOfB.Party.Type = 3,
04534 [15].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
04535 [15].u.CCBSErase.AddressOfB.Party.Number = "1803",
04536 [15].u.CCBSErase.RecallMode = 1,
04537 [15].u.CCBSErase.CCBSReference = 102,
04538 [15].u.CCBSErase.Reason = 3,
04539
04540 [16].Function = Fac_CCBSErase,
04541 [16].u.CCBSErase.InvokeID = 23,
04542 [16].u.CCBSErase.Q931ie.Bc.Length = 2,
04543 [16].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04544 [16].u.CCBSErase.AddressOfB.Party.Type = 4,
04545 [16].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
04546 [16].u.CCBSErase.AddressOfB.Party.Number = "1803",
04547 [16].u.CCBSErase.RecallMode = 1,
04548 [16].u.CCBSErase.CCBSReference = 102,
04549 [16].u.CCBSErase.Reason = 3,
04550
04551 [17].Function = Fac_CCBSErase,
04552 [17].u.CCBSErase.InvokeID = 24,
04553 [17].u.CCBSErase.Q931ie.Bc.Length = 2,
04554 [17].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04555 [17].u.CCBSErase.AddressOfB.Party.Type = 5,
04556 [17].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 11,
04557 [17].u.CCBSErase.AddressOfB.Party.TypeOfNumber = 4,
04558 [17].u.CCBSErase.AddressOfB.Party.Number = "18003020102",
04559 [17].u.CCBSErase.RecallMode = 1,
04560 [17].u.CCBSErase.CCBSReference = 102,
04561 [17].u.CCBSErase.Reason = 3,
04562
04563 [18].Function = Fac_CCBSErase,
04564 [18].u.CCBSErase.InvokeID = 25,
04565 [18].u.CCBSErase.Q931ie.Bc.Length = 2,
04566 [18].u.CCBSErase.Q931ie.Bc.Contents = "JK",
04567 [18].u.CCBSErase.AddressOfB.Party.Type = 8,
04568 [18].u.CCBSErase.AddressOfB.Party.LengthOfNumber = 4,
04569 [18].u.CCBSErase.AddressOfB.Party.Number = "1803",
04570 [18].u.CCBSErase.RecallMode = 1,
04571 [18].u.CCBSErase.CCBSReference = 102,
04572 [18].u.CCBSErase.Reason = 3,
04573
04574 [19].Function = Fac_CCBSRemoteUserFree,
04575 [19].u.CCBSRemoteUserFree.InvokeID = 26,
04576 [19].u.CCBSRemoteUserFree.Q931ie.Bc.Length = 2,
04577 [19].u.CCBSRemoteUserFree.Q931ie.Bc.Contents = "JK",
04578 [19].u.CCBSRemoteUserFree.AddressOfB.Party.Type = 8,
04579 [19].u.CCBSRemoteUserFree.AddressOfB.Party.LengthOfNumber = 4,
04580 [19].u.CCBSRemoteUserFree.AddressOfB.Party.Number = "1803",
04581 [19].u.CCBSRemoteUserFree.RecallMode = 1,
04582 [19].u.CCBSRemoteUserFree.CCBSReference = 102,
04583
04584 [20].Function = Fac_CCBSCall,
04585 [20].u.CCBSCall.InvokeID = 27,
04586 [20].u.CCBSCall.CCBSReference = 115,
04587
04588 [21].Function = Fac_CCBSStatusRequest,
04589 [21].u.CCBSStatusRequest.InvokeID = 28,
04590 [21].u.CCBSStatusRequest.ComponentType = FacComponent_Invoke,
04591 [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Length = 2,
04592 [21].u.CCBSStatusRequest.Component.Invoke.Q931ie.Bc.Contents = "JK",
04593 [21].u.CCBSStatusRequest.Component.Invoke.RecallMode = 1,
04594 [21].u.CCBSStatusRequest.Component.Invoke.CCBSReference = 102,
04595
04596 [22].Function = Fac_CCBSStatusRequest,
04597 [22].u.CCBSStatusRequest.InvokeID = 29,
04598 [22].u.CCBSStatusRequest.ComponentType = FacComponent_Result,
04599 [22].u.CCBSStatusRequest.Component.Result.Free = 1,
04600
04601 [23].Function = Fac_CCBSBFree,
04602 [23].u.CCBSBFree.InvokeID = 30,
04603 [23].u.CCBSBFree.Q931ie.Bc.Length = 2,
04604 [23].u.CCBSBFree.Q931ie.Bc.Contents = "JK",
04605 [23].u.CCBSBFree.AddressOfB.Party.Type = 8,
04606 [23].u.CCBSBFree.AddressOfB.Party.LengthOfNumber = 4,
04607 [23].u.CCBSBFree.AddressOfB.Party.Number = "1803",
04608 [23].u.CCBSBFree.RecallMode = 1,
04609 [23].u.CCBSBFree.CCBSReference = 14,
04610
04611 [24].Function = Fac_CCBSStopAlerting,
04612 [24].u.CCBSStopAlerting.InvokeID = 31,
04613 [24].u.CCBSStopAlerting.CCBSReference = 37,
04614
04615 [25].Function = Fac_CCBSRequest,
04616 [25].u.CCBSRequest.InvokeID = 32,
04617 [25].u.CCBSRequest.ComponentType = FacComponent_Invoke,
04618 [25].u.CCBSRequest.Component.Invoke.CallLinkageID = 57,
04619
04620 [26].Function = Fac_CCBSRequest,
04621 [26].u.CCBSRequest.InvokeID = 33,
04622 [26].u.CCBSRequest.ComponentType = FacComponent_Result,
04623 [26].u.CCBSRequest.Component.Result.RecallMode = 1,
04624 [26].u.CCBSRequest.Component.Result.CCBSReference = 102,
04625
04626 [27].Function = Fac_CCBSInterrogate,
04627 [27].u.CCBSInterrogate.InvokeID = 34,
04628 [27].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
04629 [27].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
04630 [27].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
04631 [27].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
04632 [27].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
04633 [27].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
04634
04635 [28].Function = Fac_CCBSInterrogate,
04636 [28].u.CCBSInterrogate.InvokeID = 35,
04637 [28].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
04638 [28].u.CCBSInterrogate.Component.Invoke.AParty.Type = 8,
04639 [28].u.CCBSInterrogate.Component.Invoke.AParty.LengthOfNumber = 4,
04640 [28].u.CCBSInterrogate.Component.Invoke.AParty.Number = "1803",
04641
04642 [29].Function = Fac_CCBSInterrogate,
04643 [29].u.CCBSInterrogate.InvokeID = 36,
04644 [29].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
04645 [29].u.CCBSInterrogate.Component.Invoke.CCBSReferencePresent = 1,
04646 [29].u.CCBSInterrogate.Component.Invoke.CCBSReference = 76,
04647
04648 [30].Function = Fac_CCBSInterrogate,
04649 [30].u.CCBSInterrogate.InvokeID = 37,
04650 [30].u.CCBSInterrogate.ComponentType = FacComponent_Invoke,
04651
04652 [31].Function = Fac_CCBSInterrogate,
04653 [31].u.CCBSInterrogate.InvokeID = 38,
04654 [31].u.CCBSInterrogate.ComponentType = FacComponent_Result,
04655 [31].u.CCBSInterrogate.Component.Result.RecallMode = 1,
04656
04657 [32].Function = Fac_CCBSInterrogate,
04658 [32].u.CCBSInterrogate.InvokeID = 39,
04659 [32].u.CCBSInterrogate.ComponentType = FacComponent_Result,
04660 [32].u.CCBSInterrogate.Component.Result.RecallMode = 1,
04661 [32].u.CCBSInterrogate.Component.Result.NumRecords = 1,
04662 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
04663 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
04664 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
04665 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
04666 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
04667 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
04668 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Type = 1,
04669 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.Length = 4,
04670 [32].u.CCBSInterrogate.Component.Result.CallDetails[0].SubaddressOfA.u.Nsap = "6492",
04671
04672 [33].Function = Fac_CCBSInterrogate,
04673 [33].u.CCBSInterrogate.InvokeID = 40,
04674 [33].u.CCBSInterrogate.ComponentType = FacComponent_Result,
04675 [33].u.CCBSInterrogate.Component.Result.RecallMode = 1,
04676 [33].u.CCBSInterrogate.Component.Result.NumRecords = 2,
04677 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].CCBSReference = 12,
04678 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Length = 2,
04679 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].Q931ie.Bc.Contents = "JK",
04680 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Type = 8,
04681 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.LengthOfNumber = 4,
04682 [33].u.CCBSInterrogate.Component.Result.CallDetails[0].AddressOfB.Party.Number = "1803",
04683 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].CCBSReference = 102,
04684 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Length = 2,
04685 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].Q931ie.Bc.Contents = "LM",
04686 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Type = 8,
04687 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.LengthOfNumber = 4,
04688 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Party.Number = "6229",
04689 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Type = 1,
04690 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.Length = 4,
04691 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].AddressOfB.Subaddress.u.Nsap = "8592",
04692 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Type = 1,
04693 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.Length = 4,
04694 [33].u.CCBSInterrogate.Component.Result.CallDetails[1].SubaddressOfA.u.Nsap = "6492",
04695
04696 [34].Function = Fac_CCNRRequest,
04697 [34].u.CCNRRequest.InvokeID = 512,
04698 [34].u.CCNRRequest.ComponentType = FacComponent_Invoke,
04699 [34].u.CCNRRequest.Component.Invoke.CallLinkageID = 57,
04700
04701 [35].Function = Fac_CCNRRequest,
04702 [35].u.CCNRRequest.InvokeID = 150,
04703 [35].u.CCNRRequest.ComponentType = FacComponent_Result,
04704 [35].u.CCNRRequest.Component.Result.RecallMode = 1,
04705 [35].u.CCNRRequest.Component.Result.CCBSReference = 102,
04706
04707 [36].Function = Fac_CCNRInterrogate,
04708 [36].u.CCNRInterrogate.InvokeID = -129,
04709 [36].u.CCNRInterrogate.ComponentType = FacComponent_Invoke,
04710
04711 [37].Function = Fac_CCNRInterrogate,
04712 [37].u.CCNRInterrogate.InvokeID = -3,
04713 [37].u.CCNRInterrogate.ComponentType = FacComponent_Result,
04714 [37].u.CCNRInterrogate.Component.Result.RecallMode = 1,
04715
04716 [38].Function = Fac_CCBS_T_Call,
04717 [38].u.EctExecute.InvokeID = 41,
04718
04719 [39].Function = Fac_CCBS_T_Suspend,
04720 [39].u.EctExecute.InvokeID = 42,
04721
04722 [40].Function = Fac_CCBS_T_Resume,
04723 [40].u.EctExecute.InvokeID = 43,
04724
04725 [41].Function = Fac_CCBS_T_RemoteUserFree,
04726 [41].u.EctExecute.InvokeID = 44,
04727
04728 [42].Function = Fac_CCBS_T_Available,
04729 [42].u.EctExecute.InvokeID = 45,
04730
04731 [43].Function = Fac_CCBS_T_Request,
04732 [43].u.CCBS_T_Request.InvokeID = 46,
04733 [43].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
04734 [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
04735 [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04736 [43].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04737 [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04738 [43].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04739 [43].u.CCBS_T_Request.Component.Invoke.RetentionSupported = 1,
04740 [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
04741 [43].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
04742 [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
04743 [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
04744 [43].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
04745
04746 [44].Function = Fac_CCBS_T_Request,
04747 [44].u.CCBS_T_Request.InvokeID = 47,
04748 [44].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
04749 [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
04750 [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04751 [44].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04752 [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04753 [44].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04754 [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
04755 [44].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
04756 [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
04757 [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
04758 [44].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
04759
04760 [45].Function = Fac_CCBS_T_Request,
04761 [45].u.CCBS_T_Request.InvokeID = 48,
04762 [45].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
04763 [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
04764 [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04765 [45].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04766 [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04767 [45].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04768 [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Type = 8,
04769 [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.LengthOfNumber = 4,
04770 [45].u.CCBS_T_Request.Component.Invoke.Originating.Party.Number = "9864",
04771
04772 [46].Function = Fac_CCBS_T_Request,
04773 [46].u.CCBS_T_Request.InvokeID = 49,
04774 [46].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
04775 [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
04776 [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04777 [46].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04778 [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04779 [46].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04780 [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1,
04781 [46].u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator = 1,
04782
04783 [47].Function = Fac_CCBS_T_Request,
04784 [47].u.CCBS_T_Request.InvokeID = 50,
04785 [47].u.CCBS_T_Request.ComponentType = FacComponent_Invoke,
04786 [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Type = 8,
04787 [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04788 [47].u.CCBS_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04789 [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04790 [47].u.CCBS_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04791
04792 [48].Function = Fac_CCBS_T_Request,
04793 [48].u.CCBS_T_Request.InvokeID = 51,
04794 [48].u.CCBS_T_Request.ComponentType = FacComponent_Result,
04795 [48].u.CCBS_T_Request.Component.Result.RetentionSupported = 1,
04796
04797 [49].Function = Fac_CCNR_T_Request,
04798 [49].u.CCNR_T_Request.InvokeID = 52,
04799 [49].u.CCNR_T_Request.ComponentType = FacComponent_Invoke,
04800 [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Type = 8,
04801 [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.LengthOfNumber = 4,
04802 [49].u.CCNR_T_Request.Component.Invoke.Destination.Party.Number = "6229",
04803 [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Length = 2,
04804 [49].u.CCNR_T_Request.Component.Invoke.Q931ie.Bc.Contents = "LM",
04805
04806 [50].Function = Fac_CCNR_T_Request,
04807 [50].u.CCNR_T_Request.InvokeID = 53,
04808 [50].u.CCNR_T_Request.ComponentType = FacComponent_Result,
04809 [50].u.CCNR_T_Request.Component.Result.RetentionSupported = 1,
04810
04811 [51].Function = Fac_EctExecute,
04812 [51].u.EctExecute.InvokeID = 54,
04813
04814 [52].Function = Fac_ExplicitEctExecute,
04815 [52].u.ExplicitEctExecute.InvokeID = 55,
04816 [52].u.ExplicitEctExecute.LinkID = 23,
04817
04818 [53].Function = Fac_RequestSubaddress,
04819 [53].u.RequestSubaddress.InvokeID = 56,
04820
04821 [54].Function = Fac_SubaddressTransfer,
04822 [54].u.SubaddressTransfer.InvokeID = 57,
04823 [54].u.SubaddressTransfer.Subaddress.Type = 1,
04824 [54].u.SubaddressTransfer.Subaddress.Length = 4,
04825 [54].u.SubaddressTransfer.Subaddress.u.Nsap = "6492",
04826
04827 [55].Function = Fac_EctLinkIdRequest,
04828 [55].u.EctLinkIdRequest.InvokeID = 58,
04829 [55].u.EctLinkIdRequest.ComponentType = FacComponent_Invoke,
04830
04831 [56].Function = Fac_EctLinkIdRequest,
04832 [56].u.EctLinkIdRequest.InvokeID = 59,
04833 [56].u.EctLinkIdRequest.ComponentType = FacComponent_Result,
04834 [56].u.EctLinkIdRequest.Component.Result.LinkID = 76,
04835
04836 [57].Function = Fac_EctInform,
04837 [57].u.EctInform.InvokeID = 60,
04838 [57].u.EctInform.Status = 1,
04839 [57].u.EctInform.RedirectionPresent = 1,
04840 [57].u.EctInform.Redirection.Type = 0,
04841 [57].u.EctInform.Redirection.Unscreened.Type = 8,
04842 [57].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
04843 [57].u.EctInform.Redirection.Unscreened.Number = "6229",
04844
04845 [58].Function = Fac_EctInform,
04846 [58].u.EctInform.InvokeID = 61,
04847 [58].u.EctInform.Status = 1,
04848 [58].u.EctInform.RedirectionPresent = 1,
04849 [58].u.EctInform.Redirection.Type = 1,
04850
04851 [59].Function = Fac_EctInform,
04852 [59].u.EctInform.InvokeID = 62,
04853 [59].u.EctInform.Status = 1,
04854 [59].u.EctInform.RedirectionPresent = 1,
04855 [59].u.EctInform.Redirection.Type = 2,
04856
04857 [60].Function = Fac_EctInform,
04858 [60].u.EctInform.InvokeID = 63,
04859 [60].u.EctInform.Status = 1,
04860 [60].u.EctInform.RedirectionPresent = 1,
04861 [60].u.EctInform.Redirection.Type = 3,
04862 [60].u.EctInform.Redirection.Unscreened.Type = 8,
04863 [60].u.EctInform.Redirection.Unscreened.LengthOfNumber = 4,
04864 [60].u.EctInform.Redirection.Unscreened.Number = "3340",
04865
04866 [61].Function = Fac_EctInform,
04867 [61].u.EctInform.InvokeID = 64,
04868 [61].u.EctInform.Status = 1,
04869 [61].u.EctInform.RedirectionPresent = 0,
04870
04871 [62].Function = Fac_EctLoopTest,
04872 [62].u.EctLoopTest.InvokeID = 65,
04873 [62].u.EctLoopTest.ComponentType = FacComponent_Invoke,
04874 [62].u.EctLoopTest.Component.Invoke.CallTransferID = 7,
04875
04876 [63].Function = Fac_EctLoopTest,
04877 [63].u.EctLoopTest.InvokeID = 66,
04878 [63].u.EctLoopTest.ComponentType = FacComponent_Result,
04879 [63].u.EctLoopTest.Component.Result.LoopResult = 2,
04880
04881 [64].Function = Fac_ActivationDiversion,
04882 [64].u.ActivationDiversion.InvokeID = 67,
04883 [64].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
04884 [64].u.ActivationDiversion.Component.Invoke.Procedure = 2,
04885 [64].u.ActivationDiversion.Component.Invoke.BasicService = 3,
04886 [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
04887 [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
04888 [64].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
04889 [64].u.ActivationDiversion.Component.Invoke.ServedUser.Type = 4,
04890 [64].u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber = 4,
04891 [64].u.ActivationDiversion.Component.Invoke.ServedUser.Number = "5398",
04892
04893 [65].Function = Fac_ActivationDiversion,
04894 [65].u.ActivationDiversion.InvokeID = 68,
04895 [65].u.ActivationDiversion.ComponentType = FacComponent_Invoke,
04896 [65].u.ActivationDiversion.Component.Invoke.Procedure = 1,
04897 [65].u.ActivationDiversion.Component.Invoke.BasicService = 5,
04898 [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 4,
04899 [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber = 4,
04900 [65].u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number = "1803",
04901
04902 [66].Function = Fac_ActivationDiversion,
04903 [66].u.ActivationDiversion.InvokeID = 69,
04904 [66].u.ActivationDiversion.ComponentType = FacComponent_Result,
04905
04906 [67].Function = Fac_DeactivationDiversion,
04907 [67].u.DeactivationDiversion.InvokeID = 70,
04908 [67].u.DeactivationDiversion.ComponentType = FacComponent_Invoke,
04909 [67].u.DeactivationDiversion.Component.Invoke.Procedure = 1,
04910 [67].u.DeactivationDiversion.Component.Invoke.BasicService = 5,
04911
04912 [68].Function = Fac_DeactivationDiversion,
04913 [68].u.DeactivationDiversion.InvokeID = 71,
04914 [68].u.DeactivationDiversion.ComponentType = FacComponent_Result,
04915
04916 [69].Function = Fac_ActivationStatusNotificationDiv,
04917 [69].u.ActivationStatusNotificationDiv.InvokeID = 72,
04918 [69].u.ActivationStatusNotificationDiv.Procedure = 1,
04919 [69].u.ActivationStatusNotificationDiv.BasicService = 5,
04920 [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Type = 4,
04921 [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.LengthOfNumber = 4,
04922 [69].u.ActivationStatusNotificationDiv.ForwardedTo.Party.Number = "1803",
04923
04924 [70].Function = Fac_DeactivationStatusNotificationDiv,
04925 [70].u.DeactivationStatusNotificationDiv.InvokeID = 73,
04926 [70].u.DeactivationStatusNotificationDiv.Procedure = 1,
04927 [70].u.DeactivationStatusNotificationDiv.BasicService = 5,
04928
04929 [71].Function = Fac_InterrogationDiversion,
04930 [71].u.InterrogationDiversion.InvokeID = 74,
04931 [71].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
04932 [71].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
04933 [71].u.InterrogationDiversion.Component.Invoke.BasicService = 5,
04934
04935 [72].Function = Fac_InterrogationDiversion,
04936 [72].u.InterrogationDiversion.InvokeID = 75,
04937 [72].u.InterrogationDiversion.ComponentType = FacComponent_Invoke,
04938 [72].u.InterrogationDiversion.Component.Invoke.Procedure = 1,
04939
04940 [73].Function = Fac_InterrogationDiversion,
04941 [73].u.InterrogationDiversion.InvokeID = 76,
04942 [73].u.InterrogationDiversion.ComponentType = FacComponent_Result,
04943 [73].u.InterrogationDiversion.Component.Result.NumRecords = 2,
04944 [73].u.InterrogationDiversion.Component.Result.List[0].Procedure = 2,
04945 [73].u.InterrogationDiversion.Component.Result.List[0].BasicService = 5,
04946 [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Type = 4,
04947 [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.LengthOfNumber = 4,
04948 [73].u.InterrogationDiversion.Component.Result.List[0].ForwardedTo.Party.Number = "1803",
04949 [73].u.InterrogationDiversion.Component.Result.List[1].Procedure = 1,
04950 [73].u.InterrogationDiversion.Component.Result.List[1].BasicService = 3,
04951 [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Type = 4,
04952 [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.LengthOfNumber = 4,
04953 [73].u.InterrogationDiversion.Component.Result.List[1].ForwardedTo.Party.Number = "1903",
04954 [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Type = 4,
04955 [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.LengthOfNumber = 4,
04956 [73].u.InterrogationDiversion.Component.Result.List[1].ServedUser.Number = "5398",
04957
04958 [74].Function = Fac_DiversionInformation,
04959 [74].u.DiversionInformation.InvokeID = 77,
04960 [74].u.DiversionInformation.DiversionReason = 3,
04961 [74].u.DiversionInformation.BasicService = 5,
04962 [74].u.DiversionInformation.ServedUserSubaddress.Type = 1,
04963 [74].u.DiversionInformation.ServedUserSubaddress.Length = 4,
04964 [74].u.DiversionInformation.ServedUserSubaddress.u.Nsap = "6492",
04965 [74].u.DiversionInformation.CallingAddressPresent = 1,
04966 [74].u.DiversionInformation.CallingAddress.Type = 0,
04967 [74].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 3,
04968 [74].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
04969 [74].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
04970 [74].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
04971 [74].u.DiversionInformation.OriginalCalledPresent = 1,
04972 [74].u.DiversionInformation.OriginalCalled.Type = 1,
04973 [74].u.DiversionInformation.LastDivertingPresent = 1,
04974 [74].u.DiversionInformation.LastDiverting.Type = 2,
04975 [74].u.DiversionInformation.LastDivertingReasonPresent = 1,
04976 [74].u.DiversionInformation.LastDivertingReason = 3,
04977 [74].u.DiversionInformation.UserInfo.Length = 5,
04978 [74].u.DiversionInformation.UserInfo.Contents = "79828",
04979
04980 [75].Function = Fac_DiversionInformation,
04981 [75].u.DiversionInformation.InvokeID = 78,
04982 [75].u.DiversionInformation.DiversionReason = 3,
04983 [75].u.DiversionInformation.BasicService = 5,
04984 [75].u.DiversionInformation.CallingAddressPresent = 1,
04985 [75].u.DiversionInformation.CallingAddress.Type = 1,
04986 [75].u.DiversionInformation.OriginalCalledPresent = 1,
04987 [75].u.DiversionInformation.OriginalCalled.Type = 2,
04988 [75].u.DiversionInformation.LastDivertingPresent = 1,
04989 [75].u.DiversionInformation.LastDiverting.Type = 1,
04990
04991 [76].Function = Fac_DiversionInformation,
04992 [76].u.DiversionInformation.InvokeID = 79,
04993 [76].u.DiversionInformation.DiversionReason = 2,
04994 [76].u.DiversionInformation.BasicService = 3,
04995 [76].u.DiversionInformation.CallingAddressPresent = 1,
04996 [76].u.DiversionInformation.CallingAddress.Type = 2,
04997
04998 [77].Function = Fac_DiversionInformation,
04999 [77].u.DiversionInformation.InvokeID = 80,
05000 [77].u.DiversionInformation.DiversionReason = 3,
05001 [77].u.DiversionInformation.BasicService = 5,
05002 [77].u.DiversionInformation.CallingAddressPresent = 1,
05003 [77].u.DiversionInformation.CallingAddress.Type = 3,
05004 [77].u.DiversionInformation.CallingAddress.Address.ScreeningIndicator = 2,
05005 [77].u.DiversionInformation.CallingAddress.Address.Party.Type = 4,
05006 [77].u.DiversionInformation.CallingAddress.Address.Party.LengthOfNumber = 4,
05007 [77].u.DiversionInformation.CallingAddress.Address.Party.Number = "1803",
05008
05009 [78].Function = Fac_DiversionInformation,
05010 [78].u.DiversionInformation.InvokeID = 81,
05011 [78].u.DiversionInformation.DiversionReason = 2,
05012 [78].u.DiversionInformation.BasicService = 4,
05013 [78].u.DiversionInformation.UserInfo.Length = 5,
05014 [78].u.DiversionInformation.UserInfo.Contents = "79828",
05015
05016 [79].Function = Fac_DiversionInformation,
05017 [79].u.DiversionInformation.InvokeID = 82,
05018 [79].u.DiversionInformation.DiversionReason = 2,
05019 [79].u.DiversionInformation.BasicService = 4,
05020
05021 [80].Function = Fac_CallDeflection,
05022 [80].u.CallDeflection.InvokeID = 83,
05023 [80].u.CallDeflection.ComponentType = FacComponent_Invoke,
05024 [80].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
05025 [80].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
05026 [80].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
05027 [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
05028 [80].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 1,
05029
05030 [81].Function = Fac_CallDeflection,
05031 [81].u.CallDeflection.InvokeID = 84,
05032 [81].u.CallDeflection.ComponentType = FacComponent_Invoke,
05033 [81].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
05034 [81].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
05035 [81].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
05036 [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1,
05037 [81].u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0,
05038
05039 [82].Function = Fac_CallDeflection,
05040 [82].u.CallDeflection.InvokeID = 85,
05041 [82].u.CallDeflection.ComponentType = FacComponent_Invoke,
05042 [82].u.CallDeflection.Component.Invoke.Deflection.Party.Type = 4,
05043 [82].u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = 4,
05044 [82].u.CallDeflection.Component.Invoke.Deflection.Party.Number = "1803",
05045
05046 [83].Function = Fac_CallDeflection,
05047 [83].u.CallDeflection.InvokeID = 86,
05048 [83].u.CallDeflection.ComponentType = FacComponent_Result,
05049
05050 [84].Function = Fac_CallRerouteing,
05051 [84].u.CallRerouteing.InvokeID = 87,
05052 [84].u.CallRerouteing.ComponentType = FacComponent_Invoke,
05053 [84].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
05054 [84].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
05055 [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
05056 [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
05057 [84].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
05058 [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
05059 [84].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
05060 [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 3,
05061 [84].u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Contents = "RTG",
05062 [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 2,
05063 [84].u.CallRerouteing.Component.Invoke.Q931ie.Llc.Contents = "MY",
05064 [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 5,
05065 [84].u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Contents = "YEHAW",
05066 [84].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
05067 [84].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
05068 [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Type = 1,
05069 [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 4,
05070 [84].u.CallRerouteing.Component.Invoke.CallingPartySubaddress.u.Nsap = "6492",
05071
05072 [85].Function = Fac_CallRerouteing,
05073 [85].u.CallRerouteing.InvokeID = 88,
05074 [85].u.CallRerouteing.ComponentType = FacComponent_Invoke,
05075 [85].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
05076 [85].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
05077 [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
05078 [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
05079 [85].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
05080 [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
05081 [85].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
05082 [85].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1,
05083 [85].u.CallRerouteing.Component.Invoke.SubscriptionOption = 2,
05084
05085 [86].Function = Fac_CallRerouteing,
05086 [86].u.CallRerouteing.InvokeID = 89,
05087 [86].u.CallRerouteing.ComponentType = FacComponent_Invoke,
05088 [86].u.CallRerouteing.Component.Invoke.ReroutingReason = 3,
05089 [86].u.CallRerouteing.Component.Invoke.ReroutingCounter = 2,
05090 [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 4,
05091 [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = 4,
05092 [86].u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number = "1803",
05093 [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 2,
05094 [86].u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents = "RT",
05095 [86].u.CallRerouteing.Component.Invoke.LastRerouting.Type = 2,
05096
05097 [87].Function = Fac_CallRerouteing,
05098 [87].u.CallRerouteing.InvokeID = 90,
05099 [87].u.CallRerouteing.ComponentType = FacComponent_Result,
05100
05101 [88].Function = Fac_InterrogateServedUserNumbers,
05102 [88].u.InterrogateServedUserNumbers.InvokeID = 91,
05103 [88].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Invoke,
05104
05105 [89].Function = Fac_InterrogateServedUserNumbers,
05106 [89].u.InterrogateServedUserNumbers.InvokeID = 92,
05107 [89].u.InterrogateServedUserNumbers.ComponentType = FacComponent_Result,
05108 [89].u.InterrogateServedUserNumbers.Component.Result.NumRecords = 2,
05109 [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Type = 4,
05110 [89].u.InterrogateServedUserNumbers.Component.Result.List[0].LengthOfNumber = 4,
05111 [89].u.InterrogateServedUserNumbers.Component.Result.List[0].Number = "1803",
05112 [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Type = 4,
05113 [89].u.InterrogateServedUserNumbers.Component.Result.List[1].LengthOfNumber = 4,
05114 [89].u.InterrogateServedUserNumbers.Component.Result.List[1].Number = "5786",
05115
05116 [90].Function = Fac_DivertingLegInformation1,
05117 [90].u.DivertingLegInformation1.InvokeID = 93,
05118 [90].u.DivertingLegInformation1.DiversionReason = 4,
05119 [90].u.DivertingLegInformation1.SubscriptionOption = 1,
05120 [90].u.DivertingLegInformation1.DivertedToPresent = 1,
05121 [90].u.DivertingLegInformation1.DivertedTo.Type = 2,
05122
05123 [91].Function = Fac_DivertingLegInformation1,
05124 [91].u.DivertingLegInformation1.InvokeID = 94,
05125 [91].u.DivertingLegInformation1.DiversionReason = 4,
05126 [91].u.DivertingLegInformation1.SubscriptionOption = 1,
05127
05128 [92].Function = Fac_DivertingLegInformation2,
05129 [92].u.DivertingLegInformation2.InvokeID = 95,
05130 [92].u.DivertingLegInformation2.DiversionCounter = 3,
05131 [92].u.DivertingLegInformation2.DiversionReason = 2,
05132 [92].u.DivertingLegInformation2.DivertingPresent = 1,
05133 [92].u.DivertingLegInformation2.Diverting.Type = 2,
05134 [92].u.DivertingLegInformation2.OriginalCalledPresent = 1,
05135 [92].u.DivertingLegInformation2.OriginalCalled.Type = 1,
05136
05137 [93].Function = Fac_DivertingLegInformation2,
05138 [93].u.DivertingLegInformation2.InvokeID = 96,
05139 [93].u.DivertingLegInformation2.DiversionCounter = 3,
05140 [93].u.DivertingLegInformation2.DiversionReason = 2,
05141 [93].u.DivertingLegInformation2.OriginalCalledPresent = 1,
05142 [93].u.DivertingLegInformation2.OriginalCalled.Type = 1,
05143
05144 [94].Function = Fac_DivertingLegInformation2,
05145 [94].u.DivertingLegInformation2.InvokeID = 97,
05146 [94].u.DivertingLegInformation2.DiversionCounter = 1,
05147 [94].u.DivertingLegInformation2.DiversionReason = 2,
05148
05149 [95].Function = Fac_DivertingLegInformation3,
05150 [95].u.DivertingLegInformation3.InvokeID = 98,
05151 [95].u.DivertingLegInformation3.PresentationAllowedIndicator = 1,
05152
05153 };
05154 #endif
05155
05156 static char *handle_cli_misdn_send_facility(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05157 {
05158 const char *channame;
05159 const char *nr;
05160 struct chan_list *tmp;
05161 int port;
05162 const char *served_nr;
05163 struct misdn_bchannel dummy, *bc=&dummy;
05164 unsigned max_len;
05165
05166 switch (cmd) {
05167 case CLI_INIT:
05168 e->command = "misdn send facility";
05169 e->usage = "Usage: misdn send facility <type> <channel|port> \"<args>\" \n"
05170 "\t type is one of:\n"
05171 "\t - calldeflect\n"
05172 #if defined(AST_MISDN_ENHANCEMENTS)
05173 "\t - callrerouting\n"
05174 #endif
05175 "\t - CFActivate\n"
05176 "\t - CFDeactivate\n";
05177
05178 return NULL;
05179 case CLI_GENERATE:
05180 return complete_ch(a);
05181 }
05182
05183 if (a->argc < 5) {
05184 return CLI_SHOWUSAGE;
05185 }
05186
05187 if (strstr(a->argv[3], "calldeflect")) {
05188 if (a->argc < 6) {
05189 ast_verbose("calldeflect requires 1 arg: ToNumber\n\n");
05190 return 0;
05191 }
05192 channame = a->argv[4];
05193 nr = a->argv[5];
05194
05195 ast_verbose("Sending Calldeflection (%s) to %s\n", nr, channame);
05196 tmp = get_chan_by_ast_name(channame);
05197 if (!tmp) {
05198 ast_verbose("Sending CD with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05199 return 0;
05200 }
05201 ao2_lock(tmp);
05202
05203 #if defined(AST_MISDN_ENHANCEMENTS)
05204 max_len = sizeof(tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
05205 if (max_len < strlen(nr)) {
05206 ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05207 nr, channame, max_len);
05208 ao2_unlock(tmp);
05209 chan_list_unref(tmp, "Number too long");
05210 return 0;
05211 }
05212 tmp->bc->fac_out.Function = Fac_CallDeflection;
05213 tmp->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
05214 tmp->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
05215 tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
05216 tmp->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
05217 tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;
05218 tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(nr);
05219 strcpy((char *) tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, nr);
05220 tmp->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
05221
05222 #else
05223
05224 max_len = sizeof(tmp->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
05225 if (max_len < strlen(nr)) {
05226 ast_verbose("Sending CD with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05227 nr, channame, max_len);
05228 ao2_unlock(tmp);
05229 chan_list_unref(tmp, "Number too long");
05230 return 0;
05231 }
05232 tmp->bc->fac_out.Function = Fac_CD;
05233 tmp->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
05234
05235 strcpy((char *) tmp->bc->fac_out.u.CDeflection.DeflectedToNumber, nr);
05236 #endif
05237
05238
05239 print_facility(&tmp->bc->fac_out, tmp->bc);
05240 ao2_unlock(tmp);
05241 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05242 chan_list_unref(tmp, "Send facility complete");
05243 #if defined(AST_MISDN_ENHANCEMENTS)
05244 } else if (strstr(a->argv[3], "callrerouteing") || strstr(a->argv[3], "callrerouting")) {
05245 if (a->argc < 6) {
05246 ast_verbose("callrerouting requires 1 arg: ToNumber\n\n");
05247 return 0;
05248 }
05249 channame = a->argv[4];
05250 nr = a->argv[5];
05251
05252 ast_verbose("Sending Callrerouting (%s) to %s\n", nr, channame);
05253 tmp = get_chan_by_ast_name(channame);
05254 if (!tmp) {
05255 ast_verbose("Sending Call Rerouting with nr %s to %s failed: Channel does not exist.\n", nr, channame);
05256 return 0;
05257 }
05258 ao2_lock(tmp);
05259
05260 max_len = sizeof(tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
05261 if (max_len < strlen(nr)) {
05262 ast_verbose("Sending Call Rerouting with nr %s to %s failed: Number too long (up to %u digits are allowed).\n",
05263 nr, channame, max_len);
05264 ao2_unlock(tmp);
05265 chan_list_unref(tmp, "Number too long");
05266 return 0;
05267 }
05268 tmp->bc->fac_out.Function = Fac_CallRerouteing;
05269 tmp->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
05270 tmp->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
05271
05272 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;
05273 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
05274
05275 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;
05276 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(nr);
05277 strcpy((char *) tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, nr);
05278 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
05279
05280 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
05281
05282
05283 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
05284 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
05285 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
05286 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
05287 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
05288 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
05289 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
05290
05291 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;
05292 tmp->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;
05293
05294
05295 print_facility(&tmp->bc->fac_out, tmp->bc);
05296 ao2_unlock(tmp);
05297 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05298 chan_list_unref(tmp, "Send facility complete");
05299 #endif
05300 } else if (strstr(a->argv[3], "CFActivate")) {
05301 if (a->argc < 7) {
05302 ast_verbose("CFActivate requires 2 args: 1.FromNumber, 2.ToNumber\n\n");
05303 return 0;
05304 }
05305 port = atoi(a->argv[4]);
05306 served_nr = a->argv[5];
05307 nr = a->argv[6];
05308
05309 misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05310
05311 ast_verbose("Sending CFActivate Port:(%d) FromNr. (%s) to Nr. (%s)\n", port, served_nr, nr);
05312
05313 #if defined(AST_MISDN_ENHANCEMENTS)
05314 bc->fac_out.Function = Fac_ActivationDiversion;
05315 bc->fac_out.u.ActivationDiversion.InvokeID = ++misdn_invoke_id;
05316 bc->fac_out.u.ActivationDiversion.ComponentType = FacComponent_Invoke;
05317 bc->fac_out.u.ActivationDiversion.Component.Invoke.BasicService = 0;
05318 bc->fac_out.u.ActivationDiversion.Component.Invoke.Procedure = 0;
05319 ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number,
05320 served_nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number));
05321 bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05322 strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Number);
05323 bc->fac_out.u.ActivationDiversion.Component.Invoke.ServedUser.Type = 0;
05324 ast_copy_string((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number,
05325 nr, sizeof(bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number));
05326 bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.LengthOfNumber =
05327 strlen((char *) bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Number);
05328 bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Party.Type = 0;
05329 bc->fac_out.u.ActivationDiversion.Component.Invoke.ForwardedTo.Subaddress.Length = 0;
05330
05331 #else
05332
05333 bc->fac_out.Function = Fac_CFActivate;
05334 bc->fac_out.u.CFActivate.BasicService = 0;
05335 bc->fac_out.u.CFActivate.Procedure = 0;
05336 ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05337 ast_copy_string((char *) bc->fac_out.u.CFActivate.ForwardedToNumber, nr, sizeof(bc->fac_out.u.CFActivate.ForwardedToNumber));
05338 #endif
05339
05340
05341 print_facility(&bc->fac_out, bc);
05342 misdn_lib_send_event(bc, EVENT_FACILITY);
05343 } else if (strstr(a->argv[3], "CFDeactivate")) {
05344 if (a->argc < 6) {
05345 ast_verbose("CFDeactivate requires 1 arg: FromNumber\n\n");
05346 return 0;
05347 }
05348 port = atoi(a->argv[4]);
05349 served_nr = a->argv[5];
05350
05351 misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05352 ast_verbose("Sending CFDeactivate Port:(%d) FromNr. (%s)\n", port, served_nr);
05353
05354 #if defined(AST_MISDN_ENHANCEMENTS)
05355 bc->fac_out.Function = Fac_DeactivationDiversion;
05356 bc->fac_out.u.DeactivationDiversion.InvokeID = ++misdn_invoke_id;
05357 bc->fac_out.u.DeactivationDiversion.ComponentType = FacComponent_Invoke;
05358 bc->fac_out.u.DeactivationDiversion.Component.Invoke.BasicService = 0;
05359 bc->fac_out.u.DeactivationDiversion.Component.Invoke.Procedure = 0;
05360 ast_copy_string((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number,
05361 served_nr, sizeof(bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number));
05362 bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.LengthOfNumber =
05363 strlen((char *) bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Number);
05364 bc->fac_out.u.DeactivationDiversion.Component.Invoke.ServedUser.Type = 0;
05365
05366 #else
05367
05368 bc->fac_out.Function = Fac_CFDeactivate;
05369 bc->fac_out.u.CFDeactivate.BasicService = 0;
05370 bc->fac_out.u.CFDeactivate.Procedure = 0;
05371 ast_copy_string((char *) bc->fac_out.u.CFActivate.ServedUserNumber, served_nr, sizeof(bc->fac_out.u.CFActivate.ServedUserNumber));
05372 #endif
05373
05374
05375 print_facility(&bc->fac_out, bc);
05376 misdn_lib_send_event(bc, EVENT_FACILITY);
05377 #if defined(AST_MISDN_ENHANCEMENTS) && defined(CCBS_TEST_MESSAGES)
05378 } else if (strstr(a->argv[3], "test")) {
05379 int msg_number;
05380
05381 if (a->argc < 5) {
05382 ast_verbose("test (<port> [<msg#>]) | (<channel-name> <msg#>)\n\n");
05383 return 0;
05384 }
05385 port = atoi(a->argv[4]);
05386
05387 channame = a->argv[4];
05388 tmp = get_chan_by_ast_name(channame);
05389 if (tmp) {
05390
05391 msg_number = atoi(a->argv[5]);
05392 if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05393 ao2_lock(tmp);
05394 tmp->bc->fac_out = Fac_Msgs[msg_number];
05395
05396
05397 print_facility(&tmp->bc->fac_out, tmp->bc);
05398 ao2_unlock(tmp);
05399 misdn_lib_send_event(tmp->bc, EVENT_FACILITY);
05400 } else {
05401 ast_verbose("test <channel-name> <msg#>\n\n");
05402 }
05403 chan_list_unref(tmp, "Facility test done");
05404 } else if (a->argc < 6) {
05405 for (msg_number = 0; msg_number < ARRAY_LEN(Fac_Msgs); ++msg_number) {
05406 misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05407 bc->fac_out = Fac_Msgs[msg_number];
05408
05409
05410 print_facility(&bc->fac_out, bc);
05411 misdn_lib_send_event(bc, EVENT_FACILITY);
05412 sleep(1);
05413 }
05414 } else {
05415 msg_number = atoi(a->argv[5]);
05416 if (msg_number < ARRAY_LEN(Fac_Msgs)) {
05417 misdn_make_dummy(bc, port, 0, misdn_lib_port_is_nt(port), 0);
05418 bc->fac_out = Fac_Msgs[msg_number];
05419
05420
05421 print_facility(&bc->fac_out, bc);
05422 misdn_lib_send_event(bc, EVENT_FACILITY);
05423 } else {
05424 ast_verbose("test <port> [<msg#>]\n\n");
05425 }
05426 }
05427 } else if (strstr(a->argv[3], "register")) {
05428 if (a->argc < 5) {
05429 ast_verbose("register <port>\n\n");
05430 return 0;
05431 }
05432 port = atoi(a->argv[4]);
05433
05434 bc = misdn_lib_get_register_bc(port);
05435 if (!bc) {
05436 ast_verbose("Could not allocate REGISTER bc struct\n\n");
05437 return 0;
05438 }
05439 bc->fac_out = Fac_Msgs[45];
05440
05441
05442 print_facility(&bc->fac_out, bc);
05443 misdn_lib_send_event(bc, EVENT_REGISTER);
05444 #endif
05445 }
05446
05447 return CLI_SUCCESS;
05448 }
05449
05450 static char *handle_cli_misdn_send_restart(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05451 {
05452 int port;
05453 int channel;
05454
05455 switch (cmd) {
05456 case CLI_INIT:
05457 e->command = "misdn send restart";
05458 e->usage =
05459 "Usage: misdn send restart [port [channel]]\n"
05460 " Send a restart for every bchannel on the given port.\n";
05461 return NULL;
05462 case CLI_GENERATE:
05463 return NULL;
05464 }
05465
05466 if (a->argc < 4 || a->argc > 5) {
05467 return CLI_SHOWUSAGE;
05468 }
05469
05470 port = atoi(a->argv[3]);
05471
05472 if (a->argc == 5) {
05473 channel = atoi(a->argv[4]);
05474 misdn_lib_send_restart(port, channel);
05475 } else {
05476 misdn_lib_send_restart(port, -1);
05477 }
05478
05479 return CLI_SUCCESS;
05480 }
05481
05482 static char *handle_cli_misdn_send_digit(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05483 {
05484 const char *channame;
05485 const char *msg;
05486 struct chan_list *tmp;
05487 int i, msglen;
05488
05489 switch (cmd) {
05490 case CLI_INIT:
05491 e->command = "misdn send digit";
05492 e->usage =
05493 "Usage: misdn send digit <channel> \"<msg>\" \n"
05494 " Send <digit> to <channel> as DTMF Tone\n"
05495 " when channel is a mISDN channel\n";
05496 return NULL;
05497 case CLI_GENERATE:
05498 return complete_ch(a);
05499 }
05500
05501 if (a->argc != 5) {
05502 return CLI_SHOWUSAGE;
05503 }
05504
05505 channame = a->argv[3];
05506 msg = a->argv[4];
05507 msglen = strlen(msg);
05508
05509 ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05510
05511 tmp = get_chan_by_ast_name(channame);
05512 if (!tmp) {
05513 ast_cli(a->fd, "Sending %s to %s failed Channel does not exist\n", msg, channame);
05514 return CLI_SUCCESS;
05515 }
05516 #if 1
05517 for (i = 0; i < msglen; i++) {
05518 if (!tmp->ast) {
05519 break;
05520 }
05521 ast_cli(a->fd, "Sending: %c\n", msg[i]);
05522 send_digit_to_chan(tmp, msg[i]);
05523
05524 usleep(250000);
05525
05526 }
05527 #else
05528 if (tmp->ast) {
05529 ast_dtmf_stream(tmp->ast, NULL, msg, 250);
05530 }
05531 #endif
05532 chan_list_unref(tmp, "Digit(s) sent");
05533
05534 return CLI_SUCCESS;
05535 }
05536
05537 static char *handle_cli_misdn_toggle_echocancel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05538 {
05539 const char *channame;
05540 struct chan_list *tmp;
05541
05542 switch (cmd) {
05543 case CLI_INIT:
05544 e->command = "misdn toggle echocancel";
05545 e->usage =
05546 "Usage: misdn toggle echocancel <channel>\n"
05547 " Toggle EchoCancel on mISDN Channel.\n";
05548 return NULL;
05549 case CLI_GENERATE:
05550 return complete_ch(a);
05551 }
05552
05553 if (a->argc != 4) {
05554 return CLI_SHOWUSAGE;
05555 }
05556
05557 channame = a->argv[3];
05558
05559 ast_cli(a->fd, "Toggling EchoCancel on %s\n", channame);
05560
05561 tmp = get_chan_by_ast_name(channame);
05562 if (!tmp) {
05563 ast_cli(a->fd, "Toggling EchoCancel %s failed Channel does not exist\n", channame);
05564 return CLI_SUCCESS;
05565 }
05566
05567 tmp->toggle_ec = tmp->toggle_ec ? 0 : 1;
05568
05569 if (tmp->toggle_ec) {
05570 #ifdef MISDN_1_2
05571 update_pipeline_config(tmp->bc);
05572 #else
05573 update_ec_config(tmp->bc);
05574 #endif
05575 manager_ec_enable(tmp->bc);
05576 } else {
05577 manager_ec_disable(tmp->bc);
05578 }
05579 chan_list_unref(tmp, "Done toggling echo cancel");
05580
05581 return CLI_SUCCESS;
05582 }
05583
05584 static char *handle_cli_misdn_send_display(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
05585 {
05586 const char *channame;
05587 const char *msg;
05588 struct chan_list *tmp;
05589
05590 switch (cmd) {
05591 case CLI_INIT:
05592 e->command = "misdn send display";
05593 e->usage =
05594 "Usage: misdn send display <channel> \"<msg>\" \n"
05595 " Send <msg> to <channel> as Display Message\n"
05596 " when channel is a mISDN channel\n";
05597 return NULL;
05598 case CLI_GENERATE:
05599 return complete_ch(a);
05600 }
05601
05602 if (a->argc != 5) {
05603 return CLI_SHOWUSAGE;
05604 }
05605
05606 channame = a->argv[3];
05607 msg = a->argv[4];
05608
05609 ast_cli(a->fd, "Sending %s to %s\n", msg, channame);
05610
05611 tmp = get_chan_by_ast_name(channame);
05612 if (tmp && tmp->bc) {
05613 ast_copy_string(tmp->bc->display, msg, sizeof(tmp->bc->display));
05614 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
05615 chan_list_unref(tmp, "Done sending display");
05616 } else {
05617 if (tmp) {
05618 chan_list_unref(tmp, "Display failed");
05619 }
05620 ast_cli(a->fd, "No such channel %s\n", channame);
05621 return CLI_SUCCESS;
05622 }
05623
05624 return CLI_SUCCESS;
05625 }
05626
05627 static char *complete_ch(struct ast_cli_args *a)
05628 {
05629 return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
05630 }
05631
05632 static char *complete_debug_port(struct ast_cli_args *a)
05633 {
05634 if (a->n) {
05635 return NULL;
05636 }
05637
05638 switch (a->pos) {
05639 case 4:
05640 if (a->word[0] == 'p') {
05641 return ast_strdup("port");
05642 } else if (a->word[0] == 'o') {
05643 return ast_strdup("only");
05644 }
05645 break;
05646 case 6:
05647 if (a->word[0] == 'o') {
05648 return ast_strdup("only");
05649 }
05650 break;
05651 }
05652 return NULL;
05653 }
05654
05655 static char *complete_show_config(struct ast_cli_args *a)
05656 {
05657 char buffer[BUFFERSIZE];
05658 enum misdn_cfg_elements elem;
05659 int wordlen = strlen(a->word);
05660 int which = 0;
05661 int port = 0;
05662
05663 switch (a->pos) {
05664 case 3:
05665 if ((!strncmp(a->word, "description", wordlen)) && (++which > a->n)) {
05666 return ast_strdup("description");
05667 }
05668 if ((!strncmp(a->word, "descriptions", wordlen)) && (++which > a->n)) {
05669 return ast_strdup("descriptions");
05670 }
05671 if ((!strncmp(a->word, "0", wordlen)) && (++which > a->n)) {
05672 return ast_strdup("0");
05673 }
05674 while ((port = misdn_cfg_get_next_port(port)) != -1) {
05675 snprintf(buffer, sizeof(buffer), "%d", port);
05676 if ((!strncmp(a->word, buffer, wordlen)) && (++which > a->n)) {
05677 return ast_strdup(buffer);
05678 }
05679 }
05680 break;
05681 case 4:
05682 if (strstr(a->line, "description ")) {
05683 for (elem = MISDN_CFG_FIRST + 1; elem < MISDN_GEN_LAST; ++elem) {
05684 if ((elem == MISDN_CFG_LAST) || (elem == MISDN_GEN_FIRST)) {
05685 continue;
05686 }
05687 misdn_cfg_get_name(elem, buffer, sizeof(buffer));
05688 if (!wordlen || !strncmp(a->word, buffer, wordlen)) {
05689 if (++which > a->n) {
05690 return ast_strdup(buffer);
05691 }
05692 }
05693 }
05694 } else if (strstr(a->line, "descriptions ")) {
05695 if ((!wordlen || !strncmp(a->word, "general", wordlen)) && (++which > a->n)) {
05696 return ast_strdup("general");
05697 }
05698 if ((!wordlen || !strncmp(a->word, "ports", wordlen)) && (++which > a->n)) {
05699 return ast_strdup("ports");
05700 }
05701 }
05702 break;
05703 }
05704 return NULL;
05705 }
05706
05707 static struct ast_cli_entry chan_misdn_clis[] = {
05708
05709 AST_CLI_DEFINE(handle_cli_misdn_port_block, "Block the given port"),
05710 AST_CLI_DEFINE(handle_cli_misdn_port_down, "Try to deactivate the L1 on the given port"),
05711 AST_CLI_DEFINE(handle_cli_misdn_port_unblock, "Unblock the given port"),
05712 AST_CLI_DEFINE(handle_cli_misdn_port_up, "Try to establish L1 on the given port"),
05713 AST_CLI_DEFINE(handle_cli_misdn_reload, "Reload internal mISDN config, read from the config file"),
05714 AST_CLI_DEFINE(handle_cli_misdn_restart_pid, "Restart the given pid"),
05715 AST_CLI_DEFINE(handle_cli_misdn_restart_port, "Restart the given port"),
05716 AST_CLI_DEFINE(handle_cli_misdn_show_channel, "Show an internal mISDN channel"),
05717 AST_CLI_DEFINE(handle_cli_misdn_show_channels, "Show the internal mISDN channel list"),
05718 AST_CLI_DEFINE(handle_cli_misdn_show_config, "Show internal mISDN config, read from the config file"),
05719 AST_CLI_DEFINE(handle_cli_misdn_show_port, "Show detailed information for given port"),
05720 AST_CLI_DEFINE(handle_cli_misdn_show_ports_stats, "Show mISDNs channel's call statistics per port"),
05721 AST_CLI_DEFINE(handle_cli_misdn_show_stacks, "Show internal mISDN stack_list"),
05722 AST_CLI_DEFINE(handle_cli_misdn_send_facility, "Sends a Facility Message to the mISDN Channel"),
05723 AST_CLI_DEFINE(handle_cli_misdn_send_digit, "Send DTMF digit to mISDN Channel"),
05724 AST_CLI_DEFINE(handle_cli_misdn_send_display, "Send Text to mISDN Channel"),
05725 AST_CLI_DEFINE(handle_cli_misdn_send_restart, "Send a restart for every bchannel on the given port"),
05726 AST_CLI_DEFINE(handle_cli_misdn_set_crypt_debug, "Set CryptDebuglevel of chan_misdn, at the moment, level={1,2}"),
05727 AST_CLI_DEFINE(handle_cli_misdn_set_debug, "Set Debuglevel of chan_misdn"),
05728 AST_CLI_DEFINE(handle_cli_misdn_set_tics, "???"),
05729 AST_CLI_DEFINE(handle_cli_misdn_toggle_echocancel, "Toggle EchoCancel on mISDN Channel"),
05730
05731 };
05732
05733
05734 static void update_config(struct chan_list *ch)
05735 {
05736 struct ast_channel *ast;
05737 struct misdn_bchannel *bc;
05738 int port;
05739 int hdlc = 0;
05740 int pres;
05741 int screen;
05742
05743 if (!ch) {
05744 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
05745 return;
05746 }
05747
05748 ast = ch->ast;
05749 bc = ch->bc;
05750 if (! ast || ! bc) {
05751 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
05752 return;
05753 }
05754
05755 port = bc->port;
05756
05757 chan_misdn_log(7, port, "update_config: Getting Config\n");
05758
05759 misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(int));
05760 if (hdlc) {
05761 switch (bc->capability) {
05762 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
05763 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
05764 chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
05765 bc->hdlc = 1;
05766 break;
05767 }
05768 }
05769
05770
05771 misdn_cfg_get(port, MISDN_CFG_PRES, &pres, sizeof(pres));
05772 misdn_cfg_get(port, MISDN_CFG_SCREEN, &screen, sizeof(screen));
05773 chan_misdn_log(2, port, " --> pres: %d screen: %d\n", pres, screen);
05774
05775 if (pres < 0 || screen < 0) {
05776 chan_misdn_log(2, port, " --> pres: %x\n", ast_channel_connected(ast)->id.number.presentation);
05777
05778 bc->caller.presentation = ast_to_misdn_pres(ast_channel_connected(ast)->id.number.presentation);
05779 chan_misdn_log(2, port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
05780
05781 bc->caller.screening = ast_to_misdn_screen(ast_channel_connected(ast)->id.number.presentation);
05782 chan_misdn_log(2, port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
05783 } else {
05784 bc->caller.screening = screen;
05785 bc->caller.presentation = pres;
05786 }
05787 }
05788
05789
05790 static void config_jitterbuffer(struct chan_list *ch)
05791 {
05792 struct misdn_bchannel *bc = ch->bc;
05793 int len = ch->jb_len;
05794 int threshold = ch->jb_upper_threshold;
05795
05796 chan_misdn_log(5, bc->port, "config_jb: Called\n");
05797
05798 if (!len) {
05799 chan_misdn_log(1, bc->port, "config_jb: Deactivating Jitterbuffer\n");
05800 bc->nojitter = 1;
05801 } else {
05802 if (len <= 100 || len > 8000) {
05803 chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer out of Bounds, setting to 1000\n");
05804 len = 1000;
05805 }
05806
05807 if (threshold > len) {
05808 chan_misdn_log(0, bc->port, "config_jb: Jitterbuffer Threshold > Jitterbuffer setting to Jitterbuffer -1\n");
05809 }
05810
05811 if (ch->jb) {
05812 cb_log(0, bc->port, "config_jb: We've got a Jitterbuffer Already on this port.\n");
05813 misdn_jb_destroy(ch->jb);
05814 ch->jb = NULL;
05815 }
05816
05817 ch->jb = misdn_jb_init(len, threshold);
05818
05819 if (!ch->jb) {
05820 bc->nojitter = 1;
05821 }
05822 }
05823 }
05824
05825
05826 void debug_numtype(int port, int numtype, char *type)
05827 {
05828 switch (numtype) {
05829 case NUMTYPE_UNKNOWN:
05830 chan_misdn_log(2, port, " --> %s: Unknown\n", type);
05831 break;
05832 case NUMTYPE_INTERNATIONAL:
05833 chan_misdn_log(2, port, " --> %s: International\n", type);
05834 break;
05835 case NUMTYPE_NATIONAL:
05836 chan_misdn_log(2, port, " --> %s: National\n", type);
05837 break;
05838 case NUMTYPE_NETWORK_SPECIFIC:
05839 chan_misdn_log(2, port, " --> %s: Network Specific\n", type);
05840 break;
05841 case NUMTYPE_SUBSCRIBER:
05842 chan_misdn_log(2, port, " --> %s: Subscriber\n", type);
05843 break;
05844 case NUMTYPE_ABBREVIATED:
05845 chan_misdn_log(2, port, " --> %s: Abbreviated\n", type);
05846 break;
05847
05848 default:
05849 chan_misdn_log(0, port, " --> !!!! Wrong dialplan setting, please see the misdn.conf sample file\n ");
05850 break;
05851 }
05852 }
05853
05854
05855 #ifdef MISDN_1_2
05856 static int update_pipeline_config(struct misdn_bchannel *bc)
05857 {
05858 int ec;
05859
05860 misdn_cfg_get(bc->port, MISDN_CFG_PIPELINE, bc->pipeline, sizeof(bc->pipeline));
05861
05862 if (*bc->pipeline) {
05863 return 0;
05864 }
05865
05866 misdn_cfg_get(bc->port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
05867 if (ec == 1) {
05868 ast_copy_string(bc->pipeline, "mg2ec", sizeof(bc->pipeline));
05869 } else if (ec > 1) {
05870 snprintf(bc->pipeline, sizeof(bc->pipeline), "mg2ec(deftaps=%d)", ec);
05871 }
05872
05873 return 0;
05874 }
05875 #else
05876 static int update_ec_config(struct misdn_bchannel *bc)
05877 {
05878 int ec;
05879 int port = bc->port;
05880
05881 misdn_cfg_get(port, MISDN_CFG_ECHOCANCEL, &ec, sizeof(ec));
05882
05883 if (ec == 1) {
05884 bc->ec_enable = 1;
05885 } else if (ec > 1) {
05886 bc->ec_enable = 1;
05887 bc->ec_deftaps = ec;
05888 }
05889
05890 return 0;
05891 }
05892 #endif
05893
05894
05895 static int read_config(struct chan_list *ch)
05896 {
05897 struct ast_channel *ast;
05898 struct misdn_bchannel *bc;
05899 int port;
05900 int hdlc = 0;
05901 char lang[BUFFERSIZE + 1];
05902 char faxdetect[BUFFERSIZE + 1];
05903 char buf[256];
05904 char buf2[256];
05905 ast_group_t pg;
05906 ast_group_t cg;
05907 struct ast_namedgroups *npg;
05908 struct ast_namedgroups *ncg;
05909 struct ast_str *tmp_str;
05910
05911 if (!ch) {
05912 ast_log(LOG_WARNING, "Cannot configure without chanlist\n");
05913 return -1;
05914 }
05915
05916 ast = ch->ast;
05917 bc = ch->bc;
05918 if (! ast || ! bc) {
05919 ast_log(LOG_WARNING, "Cannot configure without ast || bc\n");
05920 return -1;
05921 }
05922
05923 port = bc->port;
05924 chan_misdn_log(1, port, "read_config: Getting Config\n");
05925
05926 misdn_cfg_get(port, MISDN_CFG_LANGUAGE, lang, sizeof(lang));
05927 ast_channel_language_set(ast, lang);
05928
05929 misdn_cfg_get(port, MISDN_CFG_MUSICCLASS, ch->mohinterpret, sizeof(ch->mohinterpret));
05930
05931 misdn_cfg_get(port, MISDN_CFG_TXGAIN, &bc->txgain, sizeof(bc->txgain));
05932 misdn_cfg_get(port, MISDN_CFG_RXGAIN, &bc->rxgain, sizeof(bc->rxgain));
05933
05934 misdn_cfg_get(port, MISDN_CFG_INCOMING_EARLY_AUDIO, &ch->incoming_early_audio, sizeof(ch->incoming_early_audio));
05935
05936 misdn_cfg_get(port, MISDN_CFG_SENDDTMF, &bc->send_dtmf, sizeof(bc->send_dtmf));
05937
05938 misdn_cfg_get(port, MISDN_CFG_ASTDTMF, &ch->ast_dsp, sizeof(int));
05939 if (ch->ast_dsp) {
05940 ch->ignore_dtmf = 1;
05941 }
05942
05943 misdn_cfg_get(port, MISDN_CFG_NEED_MORE_INFOS, &bc->need_more_infos, sizeof(bc->need_more_infos));
05944 misdn_cfg_get(port, MISDN_CFG_NTTIMEOUT, &ch->nttimeout, sizeof(ch->nttimeout));
05945
05946 misdn_cfg_get(port, MISDN_CFG_NOAUTORESPOND_ON_SETUP, &ch->noautorespond_on_setup, sizeof(ch->noautorespond_on_setup));
05947
05948 misdn_cfg_get(port, MISDN_CFG_FAR_ALERTING, &ch->far_alerting, sizeof(ch->far_alerting));
05949
05950 misdn_cfg_get(port, MISDN_CFG_ALLOWED_BEARERS, &ch->allowed_bearers, sizeof(ch->allowed_bearers));
05951
05952 misdn_cfg_get(port, MISDN_CFG_FAXDETECT, faxdetect, sizeof(faxdetect));
05953
05954 misdn_cfg_get(port, MISDN_CFG_HDLC, &hdlc, sizeof(hdlc));
05955 if (hdlc) {
05956 switch (bc->capability) {
05957 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
05958 case INFO_CAPABILITY_DIGITAL_RESTRICTED:
05959 chan_misdn_log(1, bc->port, " --> CONF HDLC\n");
05960 bc->hdlc = 1;
05961 break;
05962 }
05963
05964 }
05965
05966 misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER, &ch->jb_len, sizeof(ch->jb_len));
05967 misdn_cfg_get(port, MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, &ch->jb_upper_threshold, sizeof(ch->jb_upper_threshold));
05968
05969 config_jitterbuffer(ch);
05970
05971 misdn_cfg_get(bc->port, MISDN_CFG_CONTEXT, ch->context, sizeof(ch->context));
05972
05973 ast_channel_context_set(ast, ch->context);
05974
05975 #ifdef MISDN_1_2
05976 update_pipeline_config(bc);
05977 #else
05978 update_ec_config(bc);
05979 #endif
05980
05981 misdn_cfg_get(bc->port, MISDN_CFG_EARLY_BCONNECT, &bc->early_bconnect, sizeof(bc->early_bconnect));
05982
05983 misdn_cfg_get(port, MISDN_CFG_DISPLAY_CONNECTED, &bc->display_connected, sizeof(bc->display_connected));
05984 misdn_cfg_get(port, MISDN_CFG_DISPLAY_SETUP, &bc->display_setup, sizeof(bc->display_setup));
05985 misdn_cfg_get(port, MISDN_CFG_OUTGOING_COLP, &bc->outgoing_colp, sizeof(bc->outgoing_colp));
05986
05987 misdn_cfg_get(port, MISDN_CFG_PICKUPGROUP, &pg, sizeof(pg));
05988 misdn_cfg_get(port, MISDN_CFG_CALLGROUP, &cg, sizeof(cg));
05989 chan_misdn_log(5, port, " --> * CallGrp:%s PickupGrp:%s\n", ast_print_group(buf, sizeof(buf), cg), ast_print_group(buf2, sizeof(buf2), pg));
05990 ast_channel_pickupgroup_set(ast, pg);
05991 ast_channel_callgroup_set(ast, cg);
05992
05993 misdn_cfg_get(port, MISDN_CFG_NAMEDPICKUPGROUP, &npg, sizeof(npg));
05994 misdn_cfg_get(port, MISDN_CFG_NAMEDCALLGROUP, &ncg, sizeof(ncg));
05995
05996 tmp_str = ast_str_create(1024);
05997 if (tmp_str) {
05998 chan_misdn_log(5, port, " --> * NamedCallGrp:%s\n", ast_print_namedgroups(&tmp_str, ncg));
05999 ast_str_reset(tmp_str);
06000 chan_misdn_log(5, port, " --> * NamedPickupGrp:%s\n", ast_print_namedgroups(&tmp_str, npg));
06001 ast_free(tmp_str);
06002 }
06003
06004 ast_channel_named_pickupgroups_set(ast, npg);
06005 ast_channel_named_callgroups_set(ast, ncg);
06006
06007 if (ch->originator == ORG_AST) {
06008 char callerid[BUFFERSIZE + 1];
06009
06010
06011
06012 misdn_cfg_get(port, MISDN_CFG_TE_CHOOSE_CHANNEL, &(bc->te_choose_channel), sizeof(bc->te_choose_channel));
06013
06014 if (strstr(faxdetect, "outgoing") || strstr(faxdetect, "both")) {
06015 ch->faxdetect = strstr(faxdetect, "nojump") ? 2 : 1;
06016 }
06017
06018 misdn_cfg_get(port, MISDN_CFG_CALLERID, callerid, sizeof(callerid));
06019 if (!ast_strlen_zero(callerid)) {
06020 char *cid_name = NULL;
06021 char *cid_num = NULL;
06022
06023 ast_callerid_parse(callerid, &cid_name, &cid_num);
06024 if (cid_name) {
06025 ast_copy_string(bc->caller.name, cid_name, sizeof(bc->caller.name));
06026 } else {
06027 bc->caller.name[0] = '\0';
06028 }
06029 if (cid_num) {
06030 ast_copy_string(bc->caller.number, cid_num, sizeof(bc->caller.number));
06031 } else {
06032 bc->caller.number[0] = '\0';
06033 }
06034 chan_misdn_log(1, port, " --> * Setting caller to \"%s\" <%s>\n", bc->caller.name, bc->caller.number);
06035 }
06036
06037 misdn_cfg_get(port, MISDN_CFG_DIALPLAN, &bc->dialed.number_type, sizeof(bc->dialed.number_type));
06038 bc->dialed.number_plan = NUMPLAN_ISDN;
06039 debug_numtype(port, bc->dialed.number_type, "TON");
06040
06041 ch->overlap_dial = 0;
06042 } else {
06043
06044
06045 if (strstr(faxdetect, "incoming") || strstr(faxdetect, "both")) {
06046 ch->faxdetect = (strstr(faxdetect, "nojump")) ? 2 : 1;
06047 }
06048
06049
06050 misdn_add_number_prefix(bc->port, bc->caller.number_type, bc->caller.number, sizeof(bc->caller.number));
06051
06052 if (ast_strlen_zero(bc->dialed.number) && !ast_strlen_zero(bc->keypad)) {
06053 ast_copy_string(bc->dialed.number, bc->keypad, sizeof(bc->dialed.number));
06054 }
06055
06056
06057 misdn_add_number_prefix(bc->port, bc->dialed.number_type, bc->dialed.number, sizeof(bc->dialed.number));
06058
06059 ast_channel_exten_set(ast, bc->dialed.number);
06060
06061 misdn_cfg_get(bc->port, MISDN_CFG_OVERLAP_DIAL, &ch->overlap_dial, sizeof(ch->overlap_dial));
06062 ast_mutex_init(&ch->overlap_tv_lock);
06063 }
06064
06065 misdn_cfg_get(port, MISDN_CFG_INCOMING_CALLERID_TAG, bc->incoming_cid_tag, sizeof(bc->incoming_cid_tag));
06066 if (!ast_strlen_zero(bc->incoming_cid_tag)) {
06067 chan_misdn_log(1, port, " --> * Setting incoming caller id tag to \"%s\"\n", bc->incoming_cid_tag);
06068 }
06069 ch->overlap_dial_task = -1;
06070
06071 if (ch->faxdetect || ch->ast_dsp) {
06072 misdn_cfg_get(port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
06073 if (!ch->dsp) {
06074 ch->dsp = ast_dsp_new();
06075 }
06076 if (ch->dsp) {
06077 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | (ch->faxdetect ? DSP_FEATURE_FAX_DETECT : 0));
06078 }
06079 }
06080
06081
06082 bc->AOCDtype = Fac_None;
06083
06084 return 0;
06085 }
06086
06087
06088
06089
06090
06091
06092
06093
06094
06095
06096
06097
06098 static void misdn_queue_connected_line_update(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
06099 {
06100 struct ast_party_connected_line connected;
06101 struct ast_set_party_connected_line update_connected;
06102
06103 ast_party_connected_line_init(&connected);
06104 memset(&update_connected, 0, sizeof(update_connected));
06105 update_connected.id.number = 1;
06106 connected.id.number.valid = 1;
06107 connected.id.number.str = (char *) id->number;
06108 connected.id.number.plan = misdn_to_ast_ton(id->number_type)
06109 | misdn_to_ast_plan(id->number_plan);
06110 connected.id.number.presentation = misdn_to_ast_pres(id->presentation)
06111 | misdn_to_ast_screen(id->screening);
06112
06113
06114
06115
06116
06117 ast_set_party_id_all(&update_connected.priv);
06118
06119 connected.id.tag = cid_tag;
06120 connected.source = source;
06121 ast_channel_queue_connected_line_update(ast, &connected, &update_connected);
06122 }
06123
06124
06125
06126
06127
06128
06129
06130
06131
06132
06133
06134 static void misdn_update_caller_id(struct ast_channel *ast, const struct misdn_party_id *id, char *cid_tag)
06135 {
06136 struct ast_party_caller caller;
06137 struct ast_set_party_caller update_caller;
06138
06139 memset(&update_caller, 0, sizeof(update_caller));
06140 update_caller.id.number = 1;
06141 update_caller.ani.number = 1;
06142
06143 ast_channel_lock(ast);
06144 ast_party_caller_set_init(&caller, ast_channel_caller(ast));
06145
06146 caller.id.number.valid = 1;
06147 caller.id.number.str = (char *) id->number;
06148 caller.id.number.plan = misdn_to_ast_ton(id->number_type)
06149 | misdn_to_ast_plan(id->number_plan);
06150 caller.id.number.presentation = misdn_to_ast_pres(id->presentation)
06151 | misdn_to_ast_screen(id->screening);
06152
06153 caller.ani.number = caller.id.number;
06154
06155 caller.id.tag = cid_tag;
06156 caller.ani.tag = cid_tag;
06157
06158 ast_channel_set_caller_event(ast, &caller, &update_caller);
06159 ast_channel_unlock(ast);
06160 }
06161
06162
06163
06164
06165
06166
06167
06168
06169
06170
06171
06172
06173 static void misdn_update_remote_party(struct ast_channel *ast, const struct misdn_party_id *id, enum AST_CONNECTED_LINE_UPDATE_SOURCE source, char *cid_tag)
06174 {
06175 misdn_update_caller_id(ast, id, cid_tag);
06176 misdn_queue_connected_line_update(ast, id, source, cid_tag);
06177 }
06178
06179
06180
06181
06182
06183
06184
06185
06186
06187
06188
06189 static void misdn_get_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
06190 {
06191 int number_type;
06192 struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
06193
06194 if (originator == ORG_MISDN) {
06195
06196
06197 ast_copy_string(bc->connected.name,
06198 S_COR(connected_id.name.valid, connected_id.name.str, ""),
06199 sizeof(bc->connected.name));
06200 if (connected_id.number.valid) {
06201 ast_copy_string(bc->connected.number, S_OR(connected_id.number.str, ""),
06202 sizeof(bc->connected.number));
06203 bc->connected.presentation = ast_to_misdn_pres(connected_id.number.presentation);
06204 bc->connected.screening = ast_to_misdn_screen(connected_id.number.presentation);
06205 bc->connected.number_type = ast_to_misdn_ton(connected_id.number.plan);
06206 bc->connected.number_plan = ast_to_misdn_plan(connected_id.number.plan);
06207 } else {
06208 bc->connected.number[0] = '\0';
06209 bc->connected.presentation = 0;
06210 bc->connected.screening = 0;
06211 bc->connected.number_type = NUMTYPE_UNKNOWN;
06212 bc->connected.number_plan = NUMPLAN_UNKNOWN;
06213 }
06214
06215 misdn_cfg_get(bc->port, MISDN_CFG_CPNDIALPLAN, &number_type, sizeof(number_type));
06216 if (0 <= number_type) {
06217
06218 bc->connected.number_type = number_type;
06219 bc->connected.number_plan = NUMPLAN_ISDN;
06220 }
06221 debug_numtype(bc->port, bc->connected.number_type, "CTON");
06222 } else {
06223
06224
06225 ast_copy_string(bc->caller.name,
06226 S_COR(connected_id.name.valid, connected_id.name.str, ""),
06227 sizeof(bc->caller.name));
06228 if (connected_id.number.valid) {
06229 ast_copy_string(bc->caller.number, S_OR(connected_id.number.str, ""),
06230 sizeof(bc->caller.number));
06231 bc->caller.presentation = ast_to_misdn_pres(connected_id.number.presentation);
06232 bc->caller.screening = ast_to_misdn_screen(connected_id.number.presentation);
06233 bc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
06234 bc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
06235 } else {
06236 bc->caller.number[0] = '\0';
06237 bc->caller.presentation = 0;
06238 bc->caller.screening = 0;
06239 bc->caller.number_type = NUMTYPE_UNKNOWN;
06240 bc->caller.number_plan = NUMPLAN_UNKNOWN;
06241 }
06242
06243 misdn_cfg_get(bc->port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
06244 if (0 <= number_type) {
06245
06246 bc->caller.number_type = number_type;
06247 bc->caller.number_plan = NUMPLAN_ISDN;
06248 }
06249 debug_numtype(bc->port, bc->caller.number_type, "LTON");
06250 }
06251 }
06252
06253
06254
06255
06256
06257
06258
06259
06260
06261
06262
06263 static void misdn_update_connected_line(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
06264 {
06265 struct chan_list *ch;
06266
06267 misdn_get_connected_line(ast, bc, originator);
06268 if (originator == ORG_MISDN) {
06269 bc->redirecting.to = bc->connected;
06270 } else {
06271 bc->redirecting.to = bc->caller;
06272 }
06273 switch (bc->outgoing_colp) {
06274 case 1:
06275 bc->redirecting.to.presentation = 1;
06276 break;
06277 case 2:
06278
06279 return;
06280 default:
06281 break;
06282 }
06283
06284 ch = MISDN_ASTERISK_TECH_PVT(ast);
06285 if (ch->state == MISDN_CONNECTED
06286 || originator != ORG_MISDN) {
06287 int is_ptmp;
06288
06289 is_ptmp = !misdn_lib_is_ptp(bc->port);
06290 if (is_ptmp) {
06291
06292
06293
06294
06295
06296
06297 if (!misdn_lib_port_is_nt(bc->port)) {
06298 return;
06299 }
06300 if (ch->state != MISDN_CONNECTED) {
06301
06302 bc->redirecting.to_changed = 1;
06303 bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
06304 misdn_lib_send_event(bc, EVENT_NOTIFY);
06305 #if defined(AST_MISDN_ENHANCEMENTS)
06306 } else {
06307
06308 bc->redirecting.to_changed = 1;
06309 bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE;
06310 bc->fac_out.Function = Fac_RequestSubaddress;
06311 bc->fac_out.u.RequestSubaddress.InvokeID = ++misdn_invoke_id;
06312
06313
06314 print_facility(&bc->fac_out, bc);
06315 misdn_lib_send_event(bc, EVENT_FACILITY);
06316 #endif
06317 }
06318 #if defined(AST_MISDN_ENHANCEMENTS)
06319 } else {
06320
06321 bc->fac_out.Function = Fac_EctInform;
06322 bc->fac_out.u.EctInform.InvokeID = ++misdn_invoke_id;
06323 bc->fac_out.u.EctInform.Status = 1;
06324 bc->fac_out.u.EctInform.RedirectionPresent = 1;
06325 misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.EctInform.Redirection,
06326 &bc->redirecting.to);
06327
06328
06329 print_facility(&bc->fac_out, bc);
06330 misdn_lib_send_event(bc, EVENT_FACILITY);
06331 #endif
06332 }
06333 }
06334 }
06335
06336
06337
06338
06339
06340
06341
06342
06343
06344
06345 static void misdn_copy_redirecting_from_ast(struct misdn_bchannel *bc, struct ast_channel *ast)
06346 {
06347 struct ast_party_id from_id = ast_channel_redirecting_effective_from(ast);
06348 struct ast_party_id to_id = ast_channel_redirecting_effective_to(ast);
06349
06350 ast_copy_string(bc->redirecting.from.name,
06351 S_COR(from_id.name.valid, from_id.name.str, ""),
06352 sizeof(bc->redirecting.from.name));
06353 if (from_id.number.valid) {
06354 ast_copy_string(bc->redirecting.from.number, S_OR(from_id.number.str, ""),
06355 sizeof(bc->redirecting.from.number));
06356 bc->redirecting.from.presentation = ast_to_misdn_pres(from_id.number.presentation);
06357 bc->redirecting.from.screening = ast_to_misdn_screen(from_id.number.presentation);
06358 bc->redirecting.from.number_type = ast_to_misdn_ton(from_id.number.plan);
06359 bc->redirecting.from.number_plan = ast_to_misdn_plan(from_id.number.plan);
06360 } else {
06361 bc->redirecting.from.number[0] = '\0';
06362 bc->redirecting.from.presentation = 0;
06363 bc->redirecting.from.screening = 0;
06364 bc->redirecting.from.number_type = NUMTYPE_UNKNOWN;
06365 bc->redirecting.from.number_plan = NUMPLAN_UNKNOWN;
06366 }
06367
06368 ast_copy_string(bc->redirecting.to.name,
06369 S_COR(to_id.name.valid, to_id.name.str, ""),
06370 sizeof(bc->redirecting.to.name));
06371 if (to_id.number.valid) {
06372 ast_copy_string(bc->redirecting.to.number, S_OR(to_id.number.str, ""),
06373 sizeof(bc->redirecting.to.number));
06374 bc->redirecting.to.presentation = ast_to_misdn_pres(to_id.number.presentation);
06375 bc->redirecting.to.screening = ast_to_misdn_screen(to_id.number.presentation);
06376 bc->redirecting.to.number_type = ast_to_misdn_ton(to_id.number.plan);
06377 bc->redirecting.to.number_plan = ast_to_misdn_plan(to_id.number.plan);
06378 } else {
06379 bc->redirecting.to.number[0] = '\0';
06380 bc->redirecting.to.presentation = 0;
06381 bc->redirecting.to.screening = 0;
06382 bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
06383 bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
06384 }
06385
06386 bc->redirecting.reason = ast_to_misdn_reason(ast_channel_redirecting(ast)->reason);
06387 bc->redirecting.count = ast_channel_redirecting(ast)->count;
06388 }
06389
06390
06391
06392
06393
06394
06395
06396
06397
06398
06399
06400 static void misdn_copy_redirecting_to_ast(struct ast_channel *ast, const struct misdn_party_redirecting *redirect, char *tag)
06401 {
06402 struct ast_party_redirecting redirecting;
06403 struct ast_set_party_redirecting update_redirecting;
06404
06405 ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(ast));
06406 memset(&update_redirecting, 0, sizeof(update_redirecting));
06407
06408 update_redirecting.from.number = 1;
06409 redirecting.from.number.valid = 1;
06410 redirecting.from.number.str = (char *) redirect->from.number;
06411 redirecting.from.number.plan =
06412 misdn_to_ast_ton(redirect->from.number_type)
06413 | misdn_to_ast_plan(redirect->from.number_plan);
06414 redirecting.from.number.presentation =
06415 misdn_to_ast_pres(redirect->from.presentation)
06416 | misdn_to_ast_screen(redirect->from.screening);
06417 redirecting.from.tag = tag;
06418
06419 update_redirecting.to.number = 1;
06420 redirecting.to.number.valid = 1;
06421 redirecting.to.number.str = (char *) redirect->to.number;
06422 redirecting.to.number.plan =
06423 misdn_to_ast_ton(redirect->to.number_type)
06424 | misdn_to_ast_plan(redirect->to.number_plan);
06425 redirecting.to.number.presentation =
06426 misdn_to_ast_pres(redirect->to.presentation)
06427 | misdn_to_ast_screen(redirect->to.screening);
06428 redirecting.to.tag = tag;
06429
06430 redirecting.reason = misdn_to_ast_reason(redirect->reason);
06431 redirecting.count = redirect->count;
06432
06433 ast_channel_set_redirecting(ast, &redirecting, &update_redirecting);
06434 }
06435
06436
06437
06438
06439
06440
06441
06442
06443
06444
06445
06446 static void misdn_update_redirecting(struct ast_channel *ast, struct misdn_bchannel *bc, int originator)
06447 {
06448 int is_ptmp;
06449
06450 misdn_copy_redirecting_from_ast(bc, ast);
06451 switch (bc->outgoing_colp) {
06452 case 1:
06453 bc->redirecting.to.presentation = 1;
06454 break;
06455 case 2:
06456
06457 return;
06458 default:
06459 break;
06460 }
06461
06462 if (originator != ORG_MISDN) {
06463 return;
06464 }
06465
06466 is_ptmp = !misdn_lib_is_ptp(bc->port);
06467 if (is_ptmp) {
06468
06469
06470
06471
06472
06473
06474 if (!misdn_lib_port_is_nt(bc->port)) {
06475 return;
06476 }
06477
06478 bc->redirecting.to_changed = 1;
06479 bc->notify_description_code = mISDN_NOTIFY_CODE_CALL_IS_DIVERTING;
06480 misdn_lib_send_event(bc, EVENT_NOTIFY);
06481 #if defined(AST_MISDN_ENHANCEMENTS)
06482 } else {
06483 int match;
06484
06485 match = (strcmp(ast_channel_exten(ast), bc->redirecting.to.number) == 0) ? 1 : 0;
06486 if (!bc->div_leg_3_tx_pending
06487 || !match) {
06488
06489 bc->fac_out.Function = Fac_DivertingLegInformation1;
06490 bc->fac_out.u.DivertingLegInformation1.InvokeID = ++misdn_invoke_id;
06491 bc->fac_out.u.DivertingLegInformation1.DiversionReason =
06492 misdn_to_diversion_reason(bc->redirecting.reason);
06493 bc->fac_out.u.DivertingLegInformation1.SubscriptionOption = 2;
06494 bc->fac_out.u.DivertingLegInformation1.DivertedToPresent = 1;
06495 misdn_PresentedNumberUnscreened_fill(&bc->fac_out.u.DivertingLegInformation1.DivertedTo, &bc->redirecting.to);
06496 print_facility(&bc->fac_out, bc);
06497 misdn_lib_send_event(bc, EVENT_FACILITY);
06498 }
06499 bc->div_leg_3_tx_pending = 0;
06500
06501
06502 bc->fac_out.Function = Fac_DivertingLegInformation3;
06503 bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
06504 bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
06505 bc->redirecting.to.presentation == 0 ? 1 : 0;
06506 print_facility(&bc->fac_out, bc);
06507 misdn_lib_send_event(bc, EVENT_FACILITY);
06508 #endif
06509 }
06510 }
06511
06512
06513
06514
06515
06516
06517 static int misdn_call(struct ast_channel *ast, const char *dest, int timeout)
06518 {
06519 int port = 0;
06520 int r;
06521 int exceed;
06522 int number_type;
06523 struct chan_list *ch;
06524 struct misdn_bchannel *newbc;
06525 char *dest_cp;
06526 int append_msn = 0;
06527
06528 AST_DECLARE_APP_ARGS(args,
06529 AST_APP_ARG(intf);
06530 AST_APP_ARG(ext);
06531 AST_APP_ARG(opts);
06532 );
06533
06534 if (!ast) {
06535 ast_log(LOG_WARNING, " --> ! misdn_call called on ast_channel *ast where ast == NULL\n");
06536 return -1;
06537 }
06538
06539 if (((ast_channel_state(ast) != AST_STATE_DOWN) && (ast_channel_state(ast) != AST_STATE_RESERVED)) || !dest) {
06540 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, neither down nor reserved (or dest==NULL)\n", ast_channel_name(ast));
06541 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06542 ast_setstate(ast, AST_STATE_DOWN);
06543 return -1;
06544 }
06545
06546 ch = MISDN_ASTERISK_TECH_PVT(ast);
06547 if (!ch) {
06548 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, chan_list *ch==NULL\n", ast_channel_name(ast));
06549 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06550 ast_setstate(ast, AST_STATE_DOWN);
06551 return -1;
06552 }
06553
06554 newbc = ch->bc;
06555 if (!newbc) {
06556 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, newbc==NULL\n", ast_channel_name(ast));
06557 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06558 ast_setstate(ast, AST_STATE_DOWN);
06559 return -1;
06560 }
06561
06562 port = newbc->port;
06563
06564 #if defined(AST_MISDN_ENHANCEMENTS)
06565 if ((ch->peer = misdn_cc_caller_get(ast))) {
06566 chan_misdn_log(3, port, " --> Found CC caller data, peer:%s\n",
06567 ch->peer->chan ? "available" : "NULL");
06568 }
06569
06570 if (ch->record_id != -1) {
06571 struct misdn_cc_record *cc_record;
06572
06573
06574 AST_LIST_LOCK(&misdn_cc_records_db);
06575 cc_record = misdn_cc_find_by_id(ch->record_id);
06576 if (!cc_record) {
06577 AST_LIST_UNLOCK(&misdn_cc_records_db);
06578 ast_log(LOG_WARNING, " --> ! misdn_call called on %s, cc_record==NULL\n", ast_channel_name(ast));
06579 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06580 ast_setstate(ast, AST_STATE_DOWN);
06581 return -1;
06582 }
06583
06584
06585 newbc->dialed = cc_record->redial.dialed;
06586 newbc->caller = cc_record->redial.caller;
06587 memset(&newbc->redirecting, 0, sizeof(newbc->redirecting));
06588 newbc->capability = cc_record->redial.capability;
06589 newbc->hdlc = cc_record->redial.hdlc;
06590 newbc->sending_complete = 1;
06591
06592 if (cc_record->ptp) {
06593 newbc->fac_out.Function = Fac_CCBS_T_Call;
06594 newbc->fac_out.u.CCBS_T_Call.InvokeID = ++misdn_invoke_id;
06595 } else {
06596 newbc->fac_out.Function = Fac_CCBSCall;
06597 newbc->fac_out.u.CCBSCall.InvokeID = ++misdn_invoke_id;
06598 newbc->fac_out.u.CCBSCall.CCBSReference = cc_record->mode.ptmp.reference_id;
06599 }
06600 AST_LIST_UNLOCK(&misdn_cc_records_db);
06601
06602 ast_channel_exten_set(ast, newbc->dialed.number);
06603
06604 chan_misdn_log(1, port, "* Call completion to: %s\n", newbc->dialed.number);
06605 chan_misdn_log(2, port, " --> * tech:%s context:%s\n", ast_channel_name(ast), ast_channel_context(ast));
06606 } else
06607 #endif
06608 {
06609 struct ast_party_id connected_id = ast_channel_connected_effective_id(ast);
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619 dest_cp = ast_strdupa(dest);
06620 AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
06621 if (!args.ext) {
06622 args.ext = "";
06623 }
06624
06625 chan_misdn_log(1, port, "* CALL: %s\n", dest);
06626 chan_misdn_log(2, port, " --> * dialed:%s tech:%s context:%s\n", args.ext, ast_channel_name(ast), ast_channel_context(ast));
06627
06628 ast_channel_exten_set(ast, args.ext);
06629 ast_copy_string(newbc->dialed.number, args.ext, sizeof(newbc->dialed.number));
06630
06631 if (ast_strlen_zero(newbc->caller.name)
06632 && connected_id.name.valid
06633 && !ast_strlen_zero(connected_id.name.str)) {
06634 ast_copy_string(newbc->caller.name, connected_id.name.str, sizeof(newbc->caller.name));
06635 chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06636 }
06637 if (ast_strlen_zero(newbc->caller.number)
06638 && connected_id.number.valid
06639 && !ast_strlen_zero(connected_id.number.str)) {
06640 ast_copy_string(newbc->caller.number, connected_id.number.str, sizeof(newbc->caller.number));
06641 chan_misdn_log(3, port, " --> * set caller:\"%s\" <%s>\n", newbc->caller.name, newbc->caller.number);
06642 }
06643
06644 misdn_cfg_get(port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
06645 if (append_msn) {
06646 strncat(newbc->incoming_cid_tag, "_", sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06647 strncat(newbc->incoming_cid_tag, newbc->caller.number, sizeof(newbc->incoming_cid_tag) - strlen(newbc->incoming_cid_tag) - 1);
06648 }
06649
06650 ast_channel_caller(ast)->id.tag = ast_strdup(newbc->incoming_cid_tag);
06651
06652 misdn_cfg_get(port, MISDN_CFG_LOCALDIALPLAN, &number_type, sizeof(number_type));
06653 if (number_type < 0) {
06654 if (connected_id.number.valid) {
06655 newbc->caller.number_type = ast_to_misdn_ton(connected_id.number.plan);
06656 newbc->caller.number_plan = ast_to_misdn_plan(connected_id.number.plan);
06657 } else {
06658 newbc->caller.number_type = NUMTYPE_UNKNOWN;
06659 newbc->caller.number_plan = NUMPLAN_ISDN;
06660 }
06661 } else {
06662
06663 newbc->caller.number_type = number_type;
06664 newbc->caller.number_plan = NUMPLAN_ISDN;
06665 }
06666 debug_numtype(port, newbc->caller.number_type, "LTON");
06667
06668 newbc->capability = ast_channel_transfercapability(ast);
06669 pbx_builtin_setvar_helper(ast, "TRANSFERCAPABILITY", ast_transfercapability2str(newbc->capability));
06670 if (ast_channel_transfercapability(ast) == INFO_CAPABILITY_DIGITAL_UNRESTRICTED) {
06671 chan_misdn_log(2, port, " --> * Call with flag Digital\n");
06672 }
06673
06674
06675 update_config(ch);
06676
06677
06678 import_ch(ast, newbc, ch);
06679
06680
06681 if (!ast_strlen_zero(args.opts)) {
06682 misdn_set_opt_exec(ast, args.opts);
06683 } else {
06684 chan_misdn_log(2, port, "NO OPTS GIVEN\n");
06685 }
06686 if (newbc->set_presentation) {
06687 newbc->caller.presentation = newbc->presentation;
06688 }
06689
06690 misdn_copy_redirecting_from_ast(newbc, ast);
06691 switch (newbc->outgoing_colp) {
06692 case 1:
06693 case 2:
06694 newbc->redirecting.from.presentation = 1;
06695 break;
06696 default:
06697 break;
06698 }
06699 #if defined(AST_MISDN_ENHANCEMENTS)
06700 if (newbc->redirecting.from.number[0] && misdn_lib_is_ptp(port)) {
06701 if (newbc->redirecting.count < 1) {
06702 newbc->redirecting.count = 1;
06703 }
06704
06705
06706 newbc->fac_out.Function = Fac_DivertingLegInformation2;
06707 newbc->fac_out.u.DivertingLegInformation2.InvokeID = ++misdn_invoke_id;
06708 newbc->fac_out.u.DivertingLegInformation2.DivertingPresent = 1;
06709 misdn_PresentedNumberUnscreened_fill(
06710 &newbc->fac_out.u.DivertingLegInformation2.Diverting,
06711 &newbc->redirecting.from);
06712 switch (newbc->outgoing_colp) {
06713 case 2:
06714
06715 newbc->fac_out.u.DivertingLegInformation2.Diverting.Type = 1;
06716
06717
06718 newbc->fac_out.u.DivertingLegInformation2.DiversionCounter = 1;
06719 newbc->fac_out.u.DivertingLegInformation2.DiversionReason = 0;
06720 break;
06721 default:
06722 newbc->fac_out.u.DivertingLegInformation2.DiversionCounter =
06723 newbc->redirecting.count;
06724 newbc->fac_out.u.DivertingLegInformation2.DiversionReason =
06725 misdn_to_diversion_reason(newbc->redirecting.reason);
06726 break;
06727 }
06728 newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 0;
06729 if (1 < newbc->fac_out.u.DivertingLegInformation2.DiversionCounter) {
06730 newbc->fac_out.u.DivertingLegInformation2.OriginalCalledPresent = 1;
06731 newbc->fac_out.u.DivertingLegInformation2.OriginalCalled.Type = 2;
06732 }
06733
06734
06735
06736
06737
06738 newbc->div_leg_3_rx_wanted = 1;
06739 }
06740 #endif
06741 }
06742
06743 exceed = add_out_calls(port);
06744 if (exceed != 0) {
06745 char tmp[16];
06746
06747 snprintf(tmp, sizeof(tmp), "%d", exceed);
06748 pbx_builtin_setvar_helper(ast, "MAX_OVERFLOW", tmp);
06749 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_TEMPORARY_FAILURE);
06750 ast_setstate(ast, AST_STATE_DOWN);
06751 return -1;
06752 }
06753
06754 #if defined(AST_MISDN_ENHANCEMENTS)
06755 if (newbc->fac_out.Function != Fac_None) {
06756 print_facility(&newbc->fac_out, newbc);
06757 }
06758 #endif
06759 r = misdn_lib_send_event(newbc, EVENT_SETUP);
06760
06761
06762 ch->l3id = newbc->l3_id;
06763
06764 if (r == -ENOCHAN) {
06765 chan_misdn_log(0, port, " --> * Theres no Channel at the moment .. !\n");
06766 chan_misdn_log(1, port, " --> * SEND: State Down pid:%d\n", newbc ? newbc->pid : -1);
06767 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CIRCUIT_CONGESTION);
06768 ast_setstate(ast, AST_STATE_DOWN);
06769 return -1;
06770 }
06771
06772 chan_misdn_log(2, port, " --> * SEND: State Dialing pid:%d\n", newbc ? newbc->pid : 1);
06773
06774 ast_setstate(ast, AST_STATE_DIALING);
06775 ast_channel_hangupcause_set(ast, AST_CAUSE_NORMAL_CLEARING);
06776
06777 if (newbc->nt) {
06778 stop_bc_tones(ch);
06779 }
06780
06781 ch->state = MISDN_CALLING;
06782
06783 return 0;
06784 }
06785
06786
06787 static int misdn_answer(struct ast_channel *ast)
06788 {
06789 struct chan_list *p;
06790 const char *tmp;
06791
06792 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06793 return -1;
06794 }
06795
06796 chan_misdn_log(1, p ? (p->bc ? p->bc->port : 0) : 0, "* ANSWER:\n");
06797
06798 if (!p) {
06799 ast_log(LOG_WARNING, " --> Channel not connected ??\n");
06800 ast_queue_hangup_with_cause(ast, AST_CAUSE_NETWORK_OUT_OF_ORDER);
06801 }
06802
06803 if (!p->bc) {
06804 chan_misdn_log(1, 0, " --> Got Answer, but there is no bc obj ??\n");
06805
06806 ast_queue_hangup_with_cause(ast, AST_CAUSE_PROTOCOL_ERROR);
06807 }
06808
06809 ast_channel_lock(ast);
06810 tmp = pbx_builtin_getvar_helper(ast, "CRYPT_KEY");
06811 if (!ast_strlen_zero(tmp)) {
06812 chan_misdn_log(1, p->bc->port, " --> Connection will be BF crypted\n");
06813 ast_copy_string(p->bc->crypt_key, tmp, sizeof(p->bc->crypt_key));
06814 } else {
06815 chan_misdn_log(3, p->bc->port, " --> Connection is without BF encryption\n");
06816 }
06817
06818 tmp = pbx_builtin_getvar_helper(ast, "MISDN_DIGITAL_TRANS");
06819 if (!ast_strlen_zero(tmp) && ast_true(tmp)) {
06820 chan_misdn_log(1, p->bc->port, " --> Connection is transparent digital\n");
06821 p->bc->nodsp = 1;
06822 p->bc->hdlc = 0;
06823 p->bc->nojitter = 1;
06824 }
06825 ast_channel_unlock(ast);
06826
06827 p->state = MISDN_CONNECTED;
06828 stop_indicate(p);
06829
06830 if (ast_strlen_zero(p->bc->connected.number)) {
06831 chan_misdn_log(2,p->bc->port," --> empty connected number using dialed number\n");
06832 ast_copy_string(p->bc->connected.number, p->bc->dialed.number, sizeof(p->bc->connected.number));
06833
06834
06835
06836
06837
06838
06839 p->bc->connected.presentation = p->bc->presentation;
06840 p->bc->connected.screening = 0;
06841 p->bc->connected.number_type = p->bc->dialed.number_type;
06842 p->bc->connected.number_plan = p->bc->dialed.number_plan;
06843 }
06844
06845 switch (p->bc->outgoing_colp) {
06846 case 1:
06847 case 2:
06848 p->bc->connected.presentation = 1;
06849 break;
06850 default:
06851 break;
06852 }
06853
06854 #if defined(AST_MISDN_ENHANCEMENTS)
06855 if (p->bc->div_leg_3_tx_pending) {
06856 p->bc->div_leg_3_tx_pending = 0;
06857
06858
06859 p->bc->fac_out.Function = Fac_DivertingLegInformation3;
06860 p->bc->fac_out.u.DivertingLegInformation3.InvokeID = ++misdn_invoke_id;
06861 p->bc->fac_out.u.DivertingLegInformation3.PresentationAllowedIndicator =
06862 (p->bc->connected.presentation == 0) ? 1 : 0;
06863 print_facility(&p->bc->fac_out, p->bc);
06864 }
06865 #endif
06866 misdn_lib_send_event(p->bc, EVENT_CONNECT);
06867 start_bc_tones(p);
06868
06869 return 0;
06870 }
06871
06872 static int misdn_digit_begin(struct ast_channel *chan, char digit)
06873 {
06874
06875 return 0;
06876 }
06877
06878 static int misdn_digit_end(struct ast_channel *ast, char digit, unsigned int duration)
06879 {
06880 struct chan_list *p;
06881 struct misdn_bchannel *bc;
06882 char buf[2] = { digit, 0 };
06883
06884 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06885 return -1;
06886 }
06887
06888 bc = p->bc;
06889 chan_misdn_log(1, bc ? bc->port : 0, "* IND : Digit %c\n", digit);
06890
06891 if (!bc) {
06892 ast_log(LOG_WARNING, " --> !! Got Digit Event without having bchannel Object\n");
06893 return -1;
06894 }
06895
06896 switch (p->state) {
06897 case MISDN_CALLING:
06898 if (strlen(bc->infos_pending) < sizeof(bc->infos_pending) - 1) {
06899 strncat(bc->infos_pending, buf, sizeof(bc->infos_pending) - strlen(bc->infos_pending) - 1);
06900 }
06901 break;
06902 case MISDN_CALLING_ACKNOWLEDGE:
06903 ast_copy_string(bc->info_dad, buf, sizeof(bc->info_dad));
06904 if (strlen(bc->dialed.number) < sizeof(bc->dialed.number) - 1) {
06905 strncat(bc->dialed.number, buf, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
06906 }
06907 ast_channel_exten_set(p->ast, bc->dialed.number);
06908 misdn_lib_send_event(bc, EVENT_INFORMATION);
06909 break;
06910 default:
06911 if (bc->send_dtmf) {
06912 send_digit_to_chan(p, digit);
06913 }
06914 break;
06915 }
06916
06917 return 0;
06918 }
06919
06920
06921 static int misdn_fixup(struct ast_channel *oldast, struct ast_channel *ast)
06922 {
06923 struct chan_list *p;
06924
06925 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06926 return -1;
06927 }
06928
06929 chan_misdn_log(1, p->bc ? p->bc->port : 0, "* IND: Got Fixup State:%s L3id:%x\n", misdn_get_ch_state(p), p->l3id);
06930
06931 p->ast = ast;
06932
06933 return 0;
06934 }
06935
06936
06937
06938 static int misdn_indication(struct ast_channel *ast, int cond, const void *data, size_t datalen)
06939 {
06940 struct chan_list *p;
06941
06942 if (!ast || !(p = MISDN_ASTERISK_TECH_PVT(ast))) {
06943 ast_log(LOG_WARNING, "Returned -1 in misdn_indication\n");
06944 return -1;
06945 }
06946
06947 if (!p->bc) {
06948 if (p->hold.state == MISDN_HOLD_IDLE) {
06949 chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on %s\n", cond,
06950 ast_channel_name(ast));
06951 ast_log(LOG_WARNING, "Private Pointer but no bc ?\n");
06952 } else {
06953 chan_misdn_log(1, 0, "* IND : Indication [%d] ignored on hold %s\n",
06954 cond, ast_channel_name(ast));
06955 }
06956 return -1;
06957 }
06958
06959 chan_misdn_log(5, p->bc->port, "* IND : Indication [%d] on %s\n", cond, ast_channel_name(ast));
06960
06961 switch (cond) {
06962 case AST_CONTROL_BUSY:
06963 chan_misdn_log(1, p->bc->port, "* IND :\tbusy pid:%d\n", p->bc->pid);
06964 ast_setstate(ast, AST_STATE_BUSY);
06965
06966 p->bc->out_cause = AST_CAUSE_USER_BUSY;
06967 if (p->state != MISDN_CONNECTED) {
06968 start_bc_tones(p);
06969 misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
06970 }
06971 return -1;
06972 case AST_CONTROL_RING:
06973 chan_misdn_log(1, p->bc->port, "* IND :\tring pid:%d\n", p->bc->pid);
06974 return -1;
06975 case AST_CONTROL_RINGING:
06976 chan_misdn_log(1, p->bc->port, "* IND :\tringing pid:%d\n", p->bc->pid);
06977 switch (p->state) {
06978 case MISDN_ALERTING:
06979 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but I was Ringing before, so ignoring it\n", p->bc->pid);
06980 break;
06981 case MISDN_CONNECTED:
06982 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d but Connected, so just send TONE_ALERTING without state changes \n", p->bc->pid);
06983 return -1;
06984 default:
06985 p->state = MISDN_ALERTING;
06986 chan_misdn_log(2, p->bc->port, " --> * IND :\tringing pid:%d\n", p->bc->pid);
06987 misdn_lib_send_event(p->bc, EVENT_ALERTING);
06988
06989 chan_misdn_log(3, p->bc->port, " --> * SEND: State Ring pid:%d\n", p->bc->pid);
06990 ast_setstate(ast, AST_STATE_RING);
06991
06992 if (!p->bc->nt && (p->originator == ORG_MISDN) && !p->incoming_early_audio) {
06993 chan_misdn_log(2, p->bc->port, " --> incoming_early_audio off\n");
06994 } else {
06995 return -1;
06996 }
06997 }
06998 break;
06999 case AST_CONTROL_ANSWER:
07000 chan_misdn_log(1, p->bc->port, " --> * IND :\tanswer pid:%d\n", p->bc->pid);
07001 start_bc_tones(p);
07002 break;
07003 case AST_CONTROL_TAKEOFFHOOK:
07004 chan_misdn_log(1, p->bc->port, " --> *\ttakeoffhook pid:%d\n", p->bc->pid);
07005 return -1;
07006 case AST_CONTROL_OFFHOOK:
07007 chan_misdn_log(1, p->bc->port, " --> *\toffhook pid:%d\n", p->bc->pid);
07008 return -1;
07009 case AST_CONTROL_FLASH:
07010 chan_misdn_log(1, p->bc->port, " --> *\tflash pid:%d\n", p->bc->pid);
07011 break;
07012 case AST_CONTROL_PROGRESS:
07013 chan_misdn_log(1, p->bc->port, " --> * IND :\tprogress pid:%d\n", p->bc->pid);
07014 misdn_lib_send_event(p->bc, EVENT_PROGRESS);
07015 break;
07016 case AST_CONTROL_PROCEEDING:
07017 chan_misdn_log(1, p->bc->port, " --> * IND :\tproceeding pid:%d\n", p->bc->pid);
07018 misdn_lib_send_event(p->bc, EVENT_PROCEEDING);
07019 break;
07020 case AST_CONTROL_INCOMPLETE:
07021 chan_misdn_log(1, p->bc->port, " --> *\tincomplete pid:%d\n", p->bc->pid);
07022 if (!p->overlap_dial) {
07023
07024 p->bc->out_cause = AST_CAUSE_INVALID_NUMBER_FORMAT;
07025 start_bc_tones(p);
07026 misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
07027
07028 if (p->bc->nt) {
07029 hanguptone_indicate(p);
07030 }
07031 }
07032 break;
07033 case AST_CONTROL_CONGESTION:
07034 chan_misdn_log(1, p->bc->port, " --> * IND :\tcongestion pid:%d\n", p->bc->pid);
07035
07036 p->bc->out_cause = AST_CAUSE_SWITCH_CONGESTION;
07037 start_bc_tones(p);
07038 misdn_lib_send_event(p->bc, EVENT_DISCONNECT);
07039
07040 if (p->bc->nt) {
07041 hanguptone_indicate(p);
07042 }
07043 break;
07044 case -1 :
07045 chan_misdn_log(1, p->bc->port, " --> * IND :\t-1! (stop indication) pid:%d\n", p->bc->pid);
07046
07047 stop_indicate(p);
07048
07049 if (p->state == MISDN_CONNECTED) {
07050 start_bc_tones(p);
07051 }
07052 break;
07053 case AST_CONTROL_HOLD:
07054 ast_moh_start(ast, data, p->mohinterpret);
07055 chan_misdn_log(1, p->bc->port, " --> *\tHOLD pid:%d\n", p->bc->pid);
07056 break;
07057 case AST_CONTROL_UNHOLD:
07058 ast_moh_stop(ast);
07059 chan_misdn_log(1, p->bc->port, " --> *\tUNHOLD pid:%d\n", p->bc->pid);
07060 break;
07061 case AST_CONTROL_CONNECTED_LINE:
07062 chan_misdn_log(1, p->bc->port, "* IND :\tconnected line update pid:%d\n", p->bc->pid);
07063 misdn_update_connected_line(ast, p->bc, p->originator);
07064 break;
07065 case AST_CONTROL_REDIRECTING:
07066 chan_misdn_log(1, p->bc->port, "* IND :\tredirecting info update pid:%d\n", p->bc->pid);
07067 misdn_update_redirecting(ast, p->bc, p->originator);
07068 break;
07069 default:
07070 chan_misdn_log(1, p->bc->port, " --> * Unknown Indication:%d pid:%d\n", cond, p->bc->pid);
07071
07072 case AST_CONTROL_PVT_CAUSE_CODE:
07073 return -1;
07074 }
07075
07076 return 0;
07077 }
07078
07079 static int misdn_hangup(struct ast_channel *ast)
07080 {
07081 struct chan_list *p;
07082 struct misdn_bchannel *bc;
07083 const char *var;
07084
07085 if (!ast) {
07086 return -1;
07087 }
07088
07089 ast_debug(1, "misdn_hangup(%s)\n", ast_channel_name(ast));
07090
07091
07092 ast_mutex_lock(&release_lock);
07093 p = MISDN_ASTERISK_TECH_PVT(ast);
07094 if (!p) {
07095 ast_mutex_unlock(&release_lock);
07096 return -1;
07097 }
07098 MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
07099
07100 if (!misdn_chan_is_valid(p)) {
07101 ast_mutex_unlock(&release_lock);
07102 chan_list_unref(p, "Release ast_channel reference. Was not active?");
07103 return 0;
07104 }
07105
07106 if (p->hold.state == MISDN_HOLD_IDLE) {
07107 bc = p->bc;
07108 } else {
07109 p->hold.state = MISDN_HOLD_DISCONNECT;
07110 bc = misdn_lib_find_held_bc(p->hold.port, p->l3id);
07111 if (!bc) {
07112 chan_misdn_log(4, p->hold.port,
07113 "misdn_hangup: Could not find held bc for (%s)\n", ast_channel_name(ast));
07114 release_chan_early(p);
07115 ast_mutex_unlock(&release_lock);
07116 chan_list_unref(p, "Release ast_channel reference");
07117 return 0;
07118 }
07119 }
07120
07121 if (ast_channel_state(ast) == AST_STATE_RESERVED || p->state == MISDN_NOTHING) {
07122
07123 ast_debug(1, "State Reserved (or nothing) => chanIsAvail\n");
07124 release_chan_early(p);
07125 if (bc) {
07126 misdn_lib_release(bc);
07127 }
07128 ast_mutex_unlock(&release_lock);
07129 chan_list_unref(p, "Release ast_channel reference");
07130 return 0;
07131 }
07132 if (!bc) {
07133 ast_log(LOG_WARNING, "Hangup with private but no bc ? state:%s l3id:%x\n",
07134 misdn_get_ch_state(p), p->l3id);
07135 release_chan_early(p);
07136 ast_mutex_unlock(&release_lock);
07137 chan_list_unref(p, "Release ast_channel reference");
07138 return 0;
07139 }
07140
07141 p->ast = NULL;
07142 p->need_hangup = 0;
07143 p->need_queue_hangup = 0;
07144 p->need_busy = 0;
07145
07146 if (!bc->nt) {
07147 stop_bc_tones(p);
07148 }
07149
07150 bc->out_cause = ast_channel_hangupcause(ast) ? ast_channel_hangupcause(ast) : AST_CAUSE_NORMAL_CLEARING;
07151
07152
07153
07154 var = pbx_builtin_getvar_helper(ast, "HANGUPCAUSE");
07155 if (!var) {
07156 var = pbx_builtin_getvar_helper(ast, "PRI_CAUSE");
07157 }
07158 if (var) {
07159 int tmpcause;
07160
07161 tmpcause = atoi(var);
07162 bc->out_cause = tmpcause ? tmpcause : AST_CAUSE_NORMAL_CLEARING;
07163 }
07164
07165 var = pbx_builtin_getvar_helper(ast, "MISDN_USERUSER");
07166 if (var) {
07167 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", var);
07168 ast_copy_string(bc->uu, var, sizeof(bc->uu));
07169 bc->uulen = strlen(bc->uu);
07170 }
07171
07172
07173 chan_misdn_log(1, bc->port,
07174 "* IND : HANGUP\tpid:%d context:%s dialed:%s caller:\"%s\" <%s> State:%s\n",
07175 bc->pid,
07176 ast_channel_context(ast),
07177 ast_channel_exten(ast),
07178 (ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
07179 ? ast_channel_caller(ast)->id.name.str : "",
07180 (ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
07181 ? ast_channel_caller(ast)->id.number.str : "",
07182 misdn_get_ch_state(p));
07183 chan_misdn_log(3, bc->port, " --> l3id:%x\n", p->l3id);
07184 chan_misdn_log(3, bc->port, " --> cause:%d\n", bc->cause);
07185 chan_misdn_log(2, bc->port, " --> out_cause:%d\n", bc->out_cause);
07186
07187 switch (p->state) {
07188 case MISDN_INCOMING_SETUP:
07189
07190
07191
07192
07193 ast_log(LOG_NOTICE, "release channel, in INCOMING_SETUP state.. no other events happened\n");
07194 release_chan(p, bc);
07195 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
07196 ast_mutex_unlock(&release_lock);
07197 chan_list_unref(p, "Release ast_channel reference");
07198 return 0;
07199 case MISDN_DIALING:
07200 if (p->hold.state == MISDN_HOLD_IDLE) {
07201 start_bc_tones(p);
07202 hanguptone_indicate(p);
07203 }
07204
07205 if (bc->need_disconnect) {
07206 misdn_lib_send_event(bc, EVENT_DISCONNECT);
07207 }
07208 break;
07209 case MISDN_CALLING_ACKNOWLEDGE:
07210 if (p->hold.state == MISDN_HOLD_IDLE) {
07211 start_bc_tones(p);
07212 hanguptone_indicate(p);
07213 }
07214
07215 if (bc->need_disconnect) {
07216 misdn_lib_send_event(bc, EVENT_DISCONNECT);
07217 }
07218 break;
07219
07220 case MISDN_CALLING:
07221 case MISDN_ALERTING:
07222 case MISDN_PROGRESS:
07223 case MISDN_PROCEEDING:
07224 if (p->originator != ORG_AST && p->hold.state == MISDN_HOLD_IDLE) {
07225 hanguptone_indicate(p);
07226 }
07227
07228 if (bc->need_disconnect) {
07229 misdn_lib_send_event(bc, EVENT_DISCONNECT);
07230 }
07231 break;
07232 case MISDN_CONNECTED:
07233
07234 if (bc->nt && p->hold.state == MISDN_HOLD_IDLE) {
07235 start_bc_tones(p);
07236 hanguptone_indicate(p);
07237 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
07238 }
07239 if (bc->need_disconnect) {
07240 misdn_lib_send_event(bc, EVENT_DISCONNECT);
07241 }
07242 break;
07243 case MISDN_DISCONNECTED:
07244 if (bc->need_release) {
07245 misdn_lib_send_event(bc, EVENT_RELEASE);
07246 }
07247 break;
07248
07249 case MISDN_CLEANING:
07250 ast_mutex_unlock(&release_lock);
07251 chan_list_unref(p, "Release ast_channel reference");
07252 return 0;
07253
07254 case MISDN_BUSY:
07255 break;
07256 default:
07257 if (bc->nt) {
07258 bc->out_cause = -1;
07259 if (bc->need_release) {
07260 misdn_lib_send_event(bc, EVENT_RELEASE);
07261 }
07262 } else {
07263 if (bc->need_disconnect) {
07264 misdn_lib_send_event(bc, EVENT_DISCONNECT);
07265 }
07266 }
07267 break;
07268 }
07269
07270 p->state = MISDN_CLEANING;
07271 chan_misdn_log(3, bc->port, " --> Channel: %s hungup new state:%s\n", ast_channel_name(ast),
07272 misdn_get_ch_state(p));
07273
07274 ast_mutex_unlock(&release_lock);
07275 chan_list_unref(p, "Release ast_channel reference");
07276 return 0;
07277 }
07278
07279
07280 static struct ast_frame *process_ast_dsp(struct chan_list *tmp, struct ast_frame *frame)
07281 {
07282 struct ast_frame *f;
07283
07284 if (tmp->dsp) {
07285 f = ast_dsp_process(tmp->ast, tmp->dsp, frame);
07286 } else {
07287 chan_misdn_log(0, tmp->bc->port, "No DSP-Path found\n");
07288 return NULL;
07289 }
07290
07291 if (!f || (f->frametype != AST_FRAME_DTMF)) {
07292 return f;
07293 }
07294
07295 ast_debug(1, "Detected inband DTMF digit: %c\n", f->subclass.integer);
07296
07297 if (tmp->faxdetect && (f->subclass.integer == 'f')) {
07298
07299 if (!tmp->faxhandled) {
07300 struct ast_channel *ast = tmp->ast;
07301 tmp->faxhandled++;
07302 chan_misdn_log(0, tmp->bc->port, "Fax detected, preparing %s for fax transfer.\n", ast_channel_name(ast));
07303 tmp->bc->rxgain = 0;
07304 isdn_lib_update_rxgain(tmp->bc);
07305 tmp->bc->txgain = 0;
07306 isdn_lib_update_txgain(tmp->bc);
07307 #ifdef MISDN_1_2
07308 *tmp->bc->pipeline = 0;
07309 #else
07310 tmp->bc->ec_enable = 0;
07311 #endif
07312 isdn_lib_update_ec(tmp->bc);
07313 isdn_lib_stop_dtmf(tmp->bc);
07314 switch (tmp->faxdetect) {
07315 case 1:
07316 if (strcmp(ast_channel_exten(ast), "fax")) {
07317 const char *context;
07318 char context_tmp[BUFFERSIZE];
07319 misdn_cfg_get(tmp->bc->port, MISDN_CFG_FAXDETECT_CONTEXT, &context_tmp, sizeof(context_tmp));
07320 context = S_OR(context_tmp, S_OR(ast_channel_macrocontext(ast), ast_channel_context(ast)));
07321 if (ast_exists_extension(ast, context, "fax", 1,
07322 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, NULL))) {
07323 ast_verb(3, "Redirecting %s to fax extension (context:%s)\n", ast_channel_name(ast), context);
07324
07325 pbx_builtin_setvar_helper(ast,"FAXEXTEN",ast_channel_exten(ast));
07326 if (ast_async_goto(ast, context, "fax", 1)) {
07327 ast_log(LOG_WARNING, "Failed to async goto '%s' into fax of '%s'\n", ast_channel_name(ast), context);
07328 }
07329 } else {
07330 ast_log(LOG_NOTICE, "Fax detected but no fax extension, context:%s exten:%s\n", context, ast_channel_exten(ast));
07331 }
07332 } else {
07333 ast_debug(1, "Already in a fax extension, not redirecting\n");
07334 }
07335 break;
07336 case 2:
07337 ast_verb(3, "Not redirecting %s to fax extension, nojump is set.\n", ast_channel_name(ast));
07338 break;
07339 default:
07340 break;
07341 }
07342 } else {
07343 ast_debug(1, "Fax already handled\n");
07344 }
07345 }
07346
07347 if (tmp->ast_dsp && (f->subclass.integer != 'f')) {
07348 chan_misdn_log(2, tmp->bc->port, " --> * SEND: DTMF (AST_DSP) :%c\n", f->subclass.integer);
07349 }
07350
07351 return f;
07352 }
07353
07354
07355 static struct ast_frame *misdn_read(struct ast_channel *ast)
07356 {
07357 struct chan_list *tmp;
07358 int len, t;
07359 struct pollfd pfd = { .fd = -1, .events = POLLIN };
07360
07361 if (!ast) {
07362 chan_misdn_log(1, 0, "misdn_read called without ast\n");
07363 return NULL;
07364 }
07365 if (!(tmp = MISDN_ASTERISK_TECH_PVT(ast))) {
07366 chan_misdn_log(1, 0, "misdn_read called without ast->pvt\n");
07367 return NULL;
07368 }
07369
07370 if (!tmp->bc && tmp->hold.state == MISDN_HOLD_IDLE) {
07371 chan_misdn_log(1, 0, "misdn_read called without bc\n");
07372 return NULL;
07373 }
07374
07375 pfd.fd = tmp->pipe[0];
07376 t = ast_poll(&pfd, 1, 20);
07377
07378 if (t < 0) {
07379 chan_misdn_log(-1, tmp->bc->port, "poll() error (err=%s)\n", strerror(errno));
07380 return NULL;
07381 }
07382
07383 if (!t) {
07384 chan_misdn_log(3, tmp->bc->port, "poll() timed out\n");
07385 len = 160;
07386 } else if (pfd.revents & POLLIN) {
07387 len = read(tmp->pipe[0], tmp->ast_rd_buf, sizeof(tmp->ast_rd_buf));
07388
07389 if (len <= 0) {
07390
07391 chan_misdn_log(2, tmp->bc->port, "misdn_read: Pipe closed, hanging up\n");
07392 return NULL;
07393 }
07394 } else {
07395 return NULL;
07396 }
07397
07398 tmp->frame.frametype = AST_FRAME_VOICE;
07399 ast_format_set(&tmp->frame.subclass.format, AST_FORMAT_ALAW, 0);
07400 tmp->frame.datalen = len;
07401 tmp->frame.samples = len;
07402 tmp->frame.mallocd = 0;
07403 tmp->frame.offset = 0;
07404 tmp->frame.delivery = ast_tv(0, 0);
07405 tmp->frame.src = NULL;
07406 tmp->frame.data.ptr = tmp->ast_rd_buf;
07407
07408 if (tmp->faxdetect && !tmp->faxhandled) {
07409 if (tmp->faxdetect_timeout) {
07410 if (ast_tvzero(tmp->faxdetect_tv)) {
07411 tmp->faxdetect_tv = ast_tvnow();
07412 chan_misdn_log(2, tmp->bc->port, "faxdetect: starting detection with timeout: %ds ...\n", tmp->faxdetect_timeout);
07413 return process_ast_dsp(tmp, &tmp->frame);
07414 } else {
07415 struct timeval tv_now = ast_tvnow();
07416 int diff = ast_tvdiff_ms(tv_now, tmp->faxdetect_tv);
07417 if (diff <= (tmp->faxdetect_timeout * 1000)) {
07418 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ...\n");
07419 return process_ast_dsp(tmp, &tmp->frame);
07420 } else {
07421 chan_misdn_log(2, tmp->bc->port, "faxdetect: stopping detection (time ran out) ...\n");
07422 tmp->faxdetect = 0;
07423 return &tmp->frame;
07424 }
07425 }
07426 } else {
07427 chan_misdn_log(5, tmp->bc->port, "faxdetect: detecting ... (no timeout)\n");
07428 return process_ast_dsp(tmp, &tmp->frame);
07429 }
07430 } else {
07431 if (tmp->ast_dsp) {
07432 return process_ast_dsp(tmp, &tmp->frame);
07433 } else {
07434 return &tmp->frame;
07435 }
07436 }
07437 }
07438
07439
07440 static int misdn_write(struct ast_channel *ast, struct ast_frame *frame)
07441 {
07442 struct chan_list *ch;
07443
07444 if (!ast || !(ch = MISDN_ASTERISK_TECH_PVT(ast))) {
07445 return -1;
07446 }
07447
07448 if (ch->hold.state != MISDN_HOLD_IDLE) {
07449 chan_misdn_log(7, 0, "misdn_write: Returning because hold active\n");
07450 return 0;
07451 }
07452
07453 if (!ch->bc) {
07454 ast_log(LOG_WARNING, "private but no bc\n");
07455 return -1;
07456 }
07457
07458 if (ch->notxtone) {
07459 chan_misdn_log(7, ch->bc->port, "misdn_write: Returning because notxtone\n");
07460 return 0;
07461 }
07462
07463
07464 if (!frame->subclass.format.id) {
07465 chan_misdn_log(4, ch->bc->port, "misdn_write: * prods us\n");
07466 return 0;
07467 }
07468
07469 if (ast_format_cmp(&frame->subclass.format, &prefformat) == AST_FORMAT_CMP_NOT_EQUAL) {
07470 chan_misdn_log(-1, ch->bc->port, "Got Unsupported Frame with Format:%s\n", ast_getformatname(&frame->subclass.format));
07471 return 0;
07472 }
07473
07474
07475 if (!frame->samples) {
07476 chan_misdn_log(4, ch->bc->port, "misdn_write: zero write\n");
07477
07478 if (!strcmp(frame->src,"ast_prod")) {
07479 chan_misdn_log(1, ch->bc->port, "misdn_write: state (%s) prodded.\n", misdn_get_ch_state(ch));
07480
07481 if (ch->ts) {
07482 chan_misdn_log(4, ch->bc->port, "Starting Playtones\n");
07483 misdn_lib_tone_generator_start(ch->bc);
07484 }
07485 return 0;
07486 }
07487
07488 return -1;
07489 }
07490
07491 if (!ch->bc->addr) {
07492 chan_misdn_log(8, ch->bc->port, "misdn_write: no addr for bc dropping:%d\n", frame->samples);
07493 return 0;
07494 }
07495
07496 #ifdef MISDN_DEBUG
07497 {
07498 int i;
07499 int max = 5 > frame->samples ? frame->samples : 5;
07500
07501 ast_debug(1, "write2mISDN %p %d bytes: ", p, frame->samples);
07502
07503 for (i = 0; i < max; i++) {
07504 ast_debug(1, "%2.2x ", ((char *) frame->data.ptr)[i]);
07505 }
07506 }
07507 #endif
07508
07509 switch (ch->bc->bc_state) {
07510 case BCHAN_ACTIVATED:
07511 case BCHAN_BRIDGED:
07512 break;
07513 default:
07514 if (!ch->dropped_frame_cnt) {
07515 chan_misdn_log(5, ch->bc->port,
07516 "BC not active (nor bridged) dropping: %d frames addr:%x exten:%s cid:%s ch->state:%s bc_state:%d l3id:%x\n",
07517 frame->samples, ch->bc->addr, ast_channel_exten(ast),
07518 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""),
07519 misdn_get_ch_state(ch), ch->bc->bc_state, ch->bc->l3_id);
07520 }
07521
07522 if (++ch->dropped_frame_cnt > 100) {
07523 ch->dropped_frame_cnt = 0;
07524 chan_misdn_log(5, ch->bc->port, "BC not active (nor bridged) dropping: %d frames addr:%x dropped > 100 frames!\n", frame->samples, ch->bc->addr);
07525 }
07526
07527 return 0;
07528 }
07529
07530 chan_misdn_log(9, ch->bc->port, "Sending :%d bytes to MISDN\n", frame->samples);
07531 if (!ch->bc->nojitter && misdn_cap_is_speech(ch->bc->capability)) {
07532
07533 if (misdn_jb_fill(ch->jb, frame->data.ptr, frame->samples) < 0) {
07534 if (ch->bc->active) {
07535 cb_log(0, ch->bc->port, "Misdn Jitterbuffer Overflow.\n");
07536 }
07537 }
07538
07539 } else {
07540
07541 misdn_lib_tx2misdn_frm(ch->bc, frame->data.ptr, frame->samples);
07542 }
07543
07544 return 0;
07545 }
07546
07547 static enum ast_bridge_result misdn_bridge(struct ast_channel *c0,
07548 struct ast_channel *c1, int flags,
07549 struct ast_frame **fo,
07550 struct ast_channel **rc,
07551 int timeoutms)
07552 {
07553 struct chan_list *ch1, *ch2;
07554 struct ast_channel *carr[2], *who;
07555 int to = -1;
07556 struct ast_frame *f;
07557 int p1_b, p2_b;
07558 int bridging;
07559
07560 ch1 = get_chan_by_ast(c0);
07561 if (!ch1) {
07562 return -1;
07563 }
07564 ch2 = get_chan_by_ast(c1);
07565 if (!ch2) {
07566 chan_list_unref(ch1, "Failed to find ch2");
07567 return -1;
07568 }
07569
07570 carr[0] = c0;
07571 carr[1] = c1;
07572
07573 misdn_cfg_get(ch1->bc->port, MISDN_CFG_BRIDGING, &p1_b, sizeof(p1_b));
07574 misdn_cfg_get(ch2->bc->port, MISDN_CFG_BRIDGING, &p2_b, sizeof(p2_b));
07575
07576 if (! p1_b || ! p2_b) {
07577 ast_log(LOG_NOTICE, "Falling back to Asterisk bridging\n");
07578 chan_list_unref(ch1, "Bridge fallback ch1");
07579 chan_list_unref(ch2, "Bridge fallback ch2");
07580 return AST_BRIDGE_FAILED;
07581 }
07582
07583 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
07584 if (bridging) {
07585
07586 chan_misdn_log(1, ch1->bc->port, "I SEND: Making conference with Number:%d\n", ch1->bc->pid + 1);
07587 misdn_lib_bridge(ch1->bc, ch2->bc);
07588 }
07589
07590 ast_verb(3, "Native bridging %s and %s\n", ast_channel_name(c0), ast_channel_name(c1));
07591
07592 chan_misdn_log(1, ch1->bc->port, "* Making Native Bridge between \"%s\" <%s> and \"%s\" <%s>\n",
07593 ch1->bc->caller.name,
07594 ch1->bc->caller.number,
07595 ch2->bc->caller.name,
07596 ch2->bc->caller.number);
07597
07598 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
07599 ch1->ignore_dtmf = 1;
07600 }
07601
07602 if (!(flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
07603 ch2->ignore_dtmf = 1;
07604 }
07605
07606 for (;;) {
07607 to = -1;
07608 who = ast_waitfor_n(carr, 2, &to);
07609
07610 if (!who) {
07611 ast_log(LOG_NOTICE, "misdn_bridge: empty read, breaking out\n");
07612 break;
07613 }
07614 f = ast_read(who);
07615
07616 if (!f || (f->frametype == AST_FRAME_CONTROL && f->subclass.integer != AST_CONTROL_PVT_CAUSE_CODE)) {
07617
07618
07619 if (!f) {
07620 chan_misdn_log(4, ch1->bc->port, "Read Null Frame\n");
07621 } else {
07622 chan_misdn_log(4, ch1->bc->port, "Read Frame Control class:%d\n", f->subclass.integer);
07623 }
07624
07625 *fo = f;
07626 *rc = who;
07627 break;
07628 }
07629
07630 if (f->frametype == AST_FRAME_DTMF) {
07631 chan_misdn_log(1, 0, "Read DTMF %d from %s\n", f->subclass.integer, ast_channel_exten(who));
07632
07633 *fo = f;
07634 *rc = who;
07635 break;
07636 }
07637
07638 #if 0
07639 if (f->frametype == AST_FRAME_VOICE) {
07640 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid +1);
07641
07642 continue;
07643 }
07644 #endif
07645
07646 if (f->frametype == AST_FRAME_CONTROL && f->subclass.integer == AST_CONTROL_PVT_CAUSE_CODE) {
07647 ast_channel_hangupcause_hash_set((who == c0) ? c1 : c0, f->data.ptr, f->datalen);
07648 } else {
07649 ast_write((who == c0) ? c1 : c0, f);
07650 }
07651 }
07652
07653 chan_misdn_log(1, ch1->bc->port, "I SEND: Splitting conference with Number:%d\n", ch1->bc->pid + 1);
07654
07655 misdn_lib_split_bridge(ch1->bc, ch2->bc);
07656
07657 chan_list_unref(ch1, "Bridge complete ch1");
07658 chan_list_unref(ch2, "Bridge complete ch2");
07659 return AST_BRIDGE_COMPLETE;
07660 }
07661
07662
07663
07664 static int dialtone_indicate(struct chan_list *cl)
07665 {
07666 struct ast_channel *ast = cl->ast;
07667 int nd = 0;
07668
07669 if (!ast) {
07670 chan_misdn_log(0, cl->bc->port, "No Ast in dialtone_indicate\n");
07671 return -1;
07672 }
07673
07674 misdn_cfg_get(cl->bc->port, MISDN_CFG_NODIALTONE, &nd, sizeof(nd));
07675
07676 if (nd) {
07677 chan_misdn_log(1, cl->bc->port, "Not sending Dialtone, because config wants it\n");
07678 return 0;
07679 }
07680
07681 chan_misdn_log(3, cl->bc->port, " --> Dial\n");
07682
07683 cl->ts = ast_get_indication_tone(ast_channel_zone(ast), "dial");
07684
07685 if (cl->ts) {
07686 cl->notxtone = 0;
07687 cl->norxtone = 0;
07688
07689 ast_playtones_start(ast, 0, cl->ts->data, 0);
07690 }
07691
07692 return 0;
07693 }
07694
07695 static void hanguptone_indicate(struct chan_list *cl)
07696 {
07697 misdn_lib_send_tone(cl->bc, TONE_HANGUP);
07698 }
07699
07700 static int stop_indicate(struct chan_list *cl)
07701 {
07702 struct ast_channel *ast = cl->ast;
07703
07704 if (!ast) {
07705 chan_misdn_log(0, cl->bc->port, "No Ast in stop_indicate\n");
07706 return -1;
07707 }
07708
07709 chan_misdn_log(3, cl->bc->port, " --> None\n");
07710 misdn_lib_tone_generator_stop(cl->bc);
07711 ast_playtones_stop(ast);
07712
07713 if (cl->ts) {
07714 cl->ts = ast_tone_zone_sound_unref(cl->ts);
07715 }
07716
07717 return 0;
07718 }
07719
07720
07721 static int start_bc_tones(struct chan_list* cl)
07722 {
07723 misdn_lib_tone_generator_stop(cl->bc);
07724 cl->notxtone = 0;
07725 cl->norxtone = 0;
07726 return 0;
07727 }
07728
07729 static int stop_bc_tones(struct chan_list *cl)
07730 {
07731 if (!cl) {
07732 return -1;
07733 }
07734
07735 cl->notxtone = 1;
07736 cl->norxtone = 1;
07737
07738 return 0;
07739 }
07740
07741
07742
07743
07744
07745
07746
07747
07748
07749 static void chan_list_destructor(void *obj)
07750 {
07751 struct chan_list *ch = obj;
07752
07753 #if defined(AST_MISDN_ENHANCEMENTS)
07754 if (ch->peer) {
07755 ao2_ref(ch->peer, -1);
07756 ch->peer = NULL;
07757 }
07758 #endif
07759
07760 if (ch->dsp) {
07761 ast_dsp_free(ch->dsp);
07762 ch->dsp = NULL;
07763 }
07764
07765
07766 if (ch->jb) {
07767 misdn_jb_destroy(ch->jb);
07768 ch->jb = NULL;
07769 }
07770
07771 if (ch->overlap_dial) {
07772 if (ch->overlap_dial_task != -1) {
07773 misdn_tasks_remove(ch->overlap_dial_task);
07774 ch->overlap_dial_task = -1;
07775 }
07776 ast_mutex_destroy(&ch->overlap_tv_lock);
07777 }
07778
07779 if (-1 < ch->pipe[0]) {
07780 close(ch->pipe[0]);
07781 }
07782 if (-1 < ch->pipe[1]) {
07783 close(ch->pipe[1]);
07784 }
07785 }
07786
07787
07788 static struct chan_list *chan_list_init(int orig)
07789 {
07790 struct chan_list *cl;
07791
07792 cl = ao2_alloc(sizeof(*cl), chan_list_destructor);
07793 if (!cl) {
07794 chan_misdn_log(-1, 0, "misdn_request: malloc failed!");
07795 return NULL;
07796 }
07797
07798 cl->originator = orig;
07799 cl->need_queue_hangup = 1;
07800 cl->need_hangup = 1;
07801 cl->need_busy = 1;
07802 cl->overlap_dial_task = -1;
07803 #if defined(AST_MISDN_ENHANCEMENTS)
07804 cl->record_id = -1;
07805 #endif
07806 cl->pipe[0] = -1;
07807 cl->pipe[1] = -1;
07808
07809 return cl;
07810 }
07811
07812 static struct ast_channel *misdn_request(const char *type, struct ast_format_cap *cap, const struct ast_channel *requestor, const char *data, int *cause)
07813 {
07814 struct ast_channel *ast;
07815 char group[BUFFERSIZE + 1] = "";
07816 char dial_str[128];
07817 char *dest_cp;
07818 char *p = NULL;
07819 int channel = 0;
07820 int port = 0;
07821 struct misdn_bchannel *newbc = NULL;
07822 int dec = 0;
07823 #if defined(AST_MISDN_ENHANCEMENTS)
07824 int cc_retry_call = 0;
07825 long record_id = -1;
07826 struct misdn_cc_record *cc_record;
07827 const char *err_msg;
07828 #endif
07829 struct chan_list *cl;
07830
07831 AST_DECLARE_APP_ARGS(args,
07832 AST_APP_ARG(intf);
07833 AST_APP_ARG(ext);
07834 AST_APP_ARG(opts);
07835 );
07836
07837 snprintf(dial_str, sizeof(dial_str), "%s/%s", misdn_type, data);
07838
07839
07840
07841
07842
07843
07844
07845
07846
07847
07848 dest_cp = ast_strdupa(data);
07849 AST_NONSTANDARD_APP_ARGS(args, dest_cp, '/');
07850 if (!args.ext) {
07851 args.ext = "";
07852 }
07853
07854 if (!ast_strlen_zero(args.intf)) {
07855 if (args.intf[0] == 'g' && args.intf[1] == ':') {
07856
07857 args.intf += 2;
07858 ast_copy_string(group, args.intf, sizeof(group));
07859 chan_misdn_log(2, 0, " --> Group Call group: %s\n", group);
07860 #if defined(AST_MISDN_ENHANCEMENTS)
07861 } else if (strcmp(args.intf, "cc") == 0) {
07862 cc_retry_call = 1;
07863 #endif
07864 } else if ((p = strchr(args.intf, ':'))) {
07865
07866 *p++ = 0;
07867 channel = atoi(p);
07868 port = atoi(args.intf);
07869 chan_misdn_log(2, port, " --> Call on preselected Channel (%d).\n", channel);
07870 } else {
07871 port = atoi(args.intf);
07872 }
07873 } else {
07874 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT Port or Group, check extensions.conf\n", dial_str);
07875 return NULL;
07876 }
07877
07878 #if defined(AST_MISDN_ENHANCEMENTS)
07879 if (cc_retry_call) {
07880 if (ast_strlen_zero(args.ext)) {
07881 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) WITHOUT cc-record-id, check extensions.conf\n", dial_str);
07882 return NULL;
07883 }
07884 if (!isdigit(*args.ext)) {
07885 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) cc-record-id must be a number.\n", dial_str);
07886 return NULL;
07887 }
07888 record_id = atol(args.ext);
07889
07890 AST_LIST_LOCK(&misdn_cc_records_db);
07891 cc_record = misdn_cc_find_by_id(record_id);
07892 if (!cc_record) {
07893 AST_LIST_UNLOCK(&misdn_cc_records_db);
07894 err_msg = misdn_cc_record_not_found;
07895 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
07896 return NULL;
07897 }
07898 if (!cc_record->activated) {
07899 AST_LIST_UNLOCK(&misdn_cc_records_db);
07900 err_msg = "Call completion has not been activated";
07901 ast_log(LOG_WARNING, " --> ! IND : Dial(%s) %s.\n", dial_str, err_msg);
07902 return NULL;
07903 }
07904 port = cc_record->port;
07905 AST_LIST_UNLOCK(&misdn_cc_records_db);
07906 }
07907 #endif
07908
07909 if (misdn_cfg_is_group_method(group, METHOD_STANDARD_DEC)) {
07910 chan_misdn_log(4, port, " --> STARTING STANDARD DEC...\n");
07911 dec = 1;
07912 }
07913
07914 if (!ast_strlen_zero(group)) {
07915 char cfg_group[BUFFERSIZE + 1];
07916 struct robin_list *rr = NULL;
07917
07918
07919
07920 if (misdn_cfg_is_group_method(group, METHOD_ROUND_ROBIN)) {
07921 chan_misdn_log(4, port, " --> STARTING ROUND ROBIN...\n");
07922 rr = get_robin_position(group);
07923 }
07924
07925 if (rr) {
07926 int port_start;
07927 int bchan_start;
07928 int port_up;
07929 int check;
07930 int maxbchans;
07931 int wraped = 0;
07932
07933 if (!rr->port) {
07934 rr->port = misdn_cfg_get_next_port_spin(0);
07935 }
07936
07937 if (!rr->channel) {
07938 rr->channel = 1;
07939 }
07940
07941 bchan_start = rr->channel;
07942 port_start = rr->port;
07943 do {
07944 misdn_cfg_get(rr->port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
07945 if (strcasecmp(cfg_group, group)) {
07946 wraped = 1;
07947 rr->port = misdn_cfg_get_next_port_spin(rr->port);
07948 rr->channel = 1;
07949 continue;
07950 }
07951
07952 misdn_cfg_get(rr->port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
07953 port_up = misdn_lib_port_up(rr->port, check);
07954
07955 if (!port_up) {
07956 chan_misdn_log(1, rr->port, "L1 is not Up on this Port\n");
07957 rr->port = misdn_cfg_get_next_port_spin(rr->port);
07958 rr->channel = 1;
07959 } else if (port_up < 0) {
07960 ast_log(LOG_WARNING, "This port (%d) is blocked\n", rr->port);
07961 rr->port = misdn_cfg_get_next_port_spin(rr->port);
07962 rr->channel = 1;
07963 } else {
07964 chan_misdn_log(4, rr->port, "portup\n");
07965 maxbchans = misdn_lib_get_maxchans(rr->port);
07966
07967 for (;rr->channel <= maxbchans;rr->channel++) {
07968
07969 if (wraped && (rr->port == port_start) && (rr->channel == bchan_start)) {
07970 break;
07971 }
07972
07973 chan_misdn_log(4, rr->port, "Checking channel %d\n", rr->channel);
07974
07975 if ((newbc = misdn_lib_get_free_bc(rr->port, rr->channel, 0, 0))) {
07976 chan_misdn_log(4, rr->port, " Success! Found port:%d channel:%d\n", newbc->port, newbc->channel);
07977 rr->channel++;
07978 break;
07979 }
07980 }
07981 if (wraped && (rr->port == port_start) && (rr->channel <= bchan_start)) {
07982 break;
07983 } else if (!newbc || (rr->channel == maxbchans)) {
07984 rr->port = misdn_cfg_get_next_port_spin(rr->port);
07985 rr->channel = 1;
07986 }
07987
07988 }
07989 wraped = 1;
07990 } while (!newbc && (rr->port > 0));
07991 } else {
07992 for (port = misdn_cfg_get_next_port(0); port > 0;
07993 port = misdn_cfg_get_next_port(port)) {
07994 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
07995
07996 chan_misdn_log(3, port, "Group [%s] Port [%d]\n", group, port);
07997 if (!strcasecmp(cfg_group, group)) {
07998 int port_up;
07999 int check;
08000
08001 misdn_cfg_get(port, MISDN_CFG_PMP_L1_CHECK, &check, sizeof(check));
08002 port_up = misdn_lib_port_up(port, check);
08003
08004 chan_misdn_log(4, port, "portup:%d\n", port_up);
08005
08006 if (port_up > 0) {
08007 newbc = misdn_lib_get_free_bc(port, 0, 0, dec);
08008 if (newbc) {
08009 break;
08010 }
08011 }
08012 }
08013 }
08014 }
08015
08016
08017 if (!newbc) {
08018 ast_log(LOG_WARNING,
08019 "Could not Dial out on group '%s'.\n"
08020 "\tEither the L2 and L1 on all of these ports where DOWN (see 'show application misdn_check_l2l1')\n"
08021 "\tOr there was no free channel on none of the ports\n\n",
08022 group);
08023 return NULL;
08024 }
08025 } else {
08026
08027 if (channel) {
08028 chan_misdn_log(1, port, " --> preselected_channel: %d\n", channel);
08029 }
08030 newbc = misdn_lib_get_free_bc(port, channel, 0, dec);
08031 if (!newbc) {
08032 ast_log(LOG_WARNING, "Could not create channel on port:%d for Dial(%s)\n", port, dial_str);
08033 return NULL;
08034 }
08035 }
08036
08037
08038 cl = chan_list_init(ORG_AST);
08039 if (!cl) {
08040 misdn_lib_release(newbc);
08041 ast_log(LOG_ERROR, "Could not create call record for Dial(%s)\n", dial_str);
08042 return NULL;
08043 }
08044 cl->bc = newbc;
08045
08046 ast = misdn_new(cl, AST_STATE_RESERVED, args.ext, NULL, cap, requestor ? ast_channel_linkedid(requestor) : NULL, port, channel);
08047 if (!ast) {
08048 chan_list_unref(cl, "Failed to create a new channel");
08049 misdn_lib_release(newbc);
08050 ast_log(LOG_ERROR, "Could not create Asterisk channel for Dial(%s)\n", dial_str);
08051 return NULL;
08052 }
08053
08054 #if defined(AST_MISDN_ENHANCEMENTS)
08055 cl->record_id = record_id;
08056 #endif
08057
08058
08059 cl_queue_chan(cl);
08060
08061
08062 read_config(cl);
08063
08064
08065 cl->need_hangup = 0;
08066
08067 chan_list_unref(cl, "Successful misdn_request()");
08068 return ast;
08069 }
08070
08071
08072 static int misdn_send_text(struct ast_channel *chan, const char *text)
08073 {
08074 struct chan_list *tmp = MISDN_ASTERISK_TECH_PVT(chan);
08075
08076 if (tmp && tmp->bc) {
08077 ast_copy_string(tmp->bc->display, text, sizeof(tmp->bc->display));
08078 misdn_lib_send_event(tmp->bc, EVENT_INFORMATION);
08079 } else {
08080 ast_log(LOG_WARNING, "No chan_list but send_text request?\n");
08081 return -1;
08082 }
08083
08084 return 0;
08085 }
08086
08087 static struct ast_channel_tech misdn_tech = {
08088 .type = misdn_type,
08089 .description = "Channel driver for mISDN Support (Bri/Pri)",
08090 .requester = misdn_request,
08091 .send_digit_begin = misdn_digit_begin,
08092 .send_digit_end = misdn_digit_end,
08093 .call = misdn_call,
08094 .bridge = misdn_bridge,
08095 .hangup = misdn_hangup,
08096 .answer = misdn_answer,
08097 .read = misdn_read,
08098 .write = misdn_write,
08099 .indicate = misdn_indication,
08100 .fixup = misdn_fixup,
08101 .send_text = misdn_send_text,
08102 .properties = 0,
08103 };
08104
08105 static struct ast_channel_tech misdn_tech_wo_bridge = {
08106 .type = misdn_type,
08107 .description = "Channel driver for mISDN Support (Bri/Pri)",
08108 .requester = misdn_request,
08109 .send_digit_begin = misdn_digit_begin,
08110 .send_digit_end = misdn_digit_end,
08111 .call = misdn_call,
08112 .hangup = misdn_hangup,
08113 .answer = misdn_answer,
08114 .read = misdn_read,
08115 .write = misdn_write,
08116 .indicate = misdn_indication,
08117 .fixup = misdn_fixup,
08118 .send_text = misdn_send_text,
08119 .properties = 0,
08120 };
08121
08122
08123 static int glob_channel = 0;
08124
08125 static void update_name(struct ast_channel *tmp, int port, int c)
08126 {
08127 int chan_offset = 0;
08128 int tmp_port = misdn_cfg_get_next_port(0);
08129 char newname[255];
08130
08131 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
08132 if (tmp_port == port) {
08133 break;
08134 }
08135 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
08136 }
08137 if (c < 0) {
08138 c = 0;
08139 }
08140
08141 snprintf(newname, sizeof(newname), "%s/%d-", misdn_type, chan_offset + c);
08142 if (strncmp(ast_channel_name(tmp), newname, strlen(newname))) {
08143 snprintf(newname, sizeof(newname), "%s/%d-u%d", misdn_type, chan_offset + c, glob_channel++);
08144 ast_change_name(tmp, newname);
08145 chan_misdn_log(3, port, " --> updating channel name to [%s]\n", ast_channel_name(tmp));
08146 }
08147 }
08148
08149 static struct ast_channel *misdn_new(struct chan_list *chlist, int state, char *exten, char *callerid, struct ast_format_cap *cap, const char *linkedid, int port, int c)
08150 {
08151 struct ast_channel *tmp;
08152 char *cid_name = NULL;
08153 char *cid_num = NULL;
08154 int chan_offset = 0;
08155 int tmp_port = misdn_cfg_get_next_port(0);
08156 int bridging;
08157 struct ast_format tmpfmt;
08158
08159 for (; tmp_port > 0; tmp_port = misdn_cfg_get_next_port(tmp_port)) {
08160 if (tmp_port == port) {
08161 break;
08162 }
08163 chan_offset += misdn_lib_port_is_pri(tmp_port) ? 30 : 2;
08164 }
08165 if (c < 0) {
08166 c = 0;
08167 }
08168
08169 if (callerid) {
08170 ast_callerid_parse(callerid, &cid_name, &cid_num);
08171 }
08172
08173 tmp = ast_channel_alloc(1, state, cid_num, cid_name, "", exten, "", linkedid, 0, "%s/%s%d-u%d", misdn_type, c ? "" : "tmp", chan_offset + c, glob_channel++);
08174 if (tmp) {
08175 chan_misdn_log(2, port, " --> * NEW CHANNEL dialed:%s caller:%s\n", exten, callerid);
08176
08177 ast_best_codec(cap, &tmpfmt);
08178 ast_format_cap_add(ast_channel_nativeformats(tmp), &prefformat);
08179 ast_format_copy(ast_channel_writeformat(tmp), &tmpfmt);
08180 ast_format_copy(ast_channel_rawwriteformat(tmp), &tmpfmt);
08181 ast_format_copy(ast_channel_readformat(tmp), &tmpfmt);
08182 ast_format_copy(ast_channel_rawreadformat(tmp), &tmpfmt);
08183
08184
08185 chan_list_ref(chlist, "Give a reference to ast_channel");
08186 MISDN_ASTERISK_TECH_PVT_SET(tmp, chlist);
08187 chlist->ast = tmp;
08188
08189 misdn_cfg_get(0, MISDN_GEN_BRIDGING, &bridging, sizeof(bridging));
08190 ast_channel_tech_set(tmp, bridging ? &misdn_tech : &misdn_tech_wo_bridge);
08191
08192 ast_channel_priority_set(tmp, 1);
08193
08194 if (exten) {
08195 ast_channel_exten_set(tmp, exten);
08196 } else {
08197 chan_misdn_log(1, 0, "misdn_new: no exten given.\n");
08198 }
08199
08200 if (!ast_strlen_zero(cid_num)) {
08201
08202
08203 ast_channel_caller(tmp)->ani.number.valid = 1;
08204 ast_channel_caller(tmp)->ani.number.str = ast_strdup(cid_num);
08205 }
08206
08207 if (pipe(chlist->pipe) < 0) {
08208 ast_log(LOG_ERROR, "Pipe failed\n");
08209 }
08210 ast_channel_set_fd(tmp, 0, chlist->pipe[0]);
08211
08212 ast_channel_rings_set(tmp, (state == AST_STATE_RING) ? 1 : 0);
08213
08214 ast_jb_configure(tmp, misdn_get_global_jbconf());
08215 } else {
08216 chan_misdn_log(-1, 0, "Unable to allocate channel structure\n");
08217 }
08218
08219 return tmp;
08220 }
08221
08222
08223 static struct chan_list *find_chan_by_bc(struct misdn_bchannel *bc)
08224 {
08225 struct chan_list *help;
08226
08227 ast_mutex_lock(&cl_te_lock);
08228 for (help = cl_te; help; help = help->next) {
08229 if (help->bc == bc) {
08230 chan_list_ref(help, "Found chan_list by bc");
08231 ast_mutex_unlock(&cl_te_lock);
08232 return help;
08233 }
08234 }
08235 ast_mutex_unlock(&cl_te_lock);
08236
08237 chan_misdn_log(6, bc->port,
08238 "$$$ find_chan_by_bc: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08239 bc->dialed.number,
08240 bc->caller.name,
08241 bc->caller.number);
08242
08243 return NULL;
08244 }
08245
08246
08247 static struct chan_list *find_hold_call(struct misdn_bchannel *bc)
08248 {
08249 struct chan_list *help;
08250
08251 if (bc->pri) {
08252 return NULL;
08253 }
08254
08255 chan_misdn_log(6, bc->port, "$$$ find_hold_call: channel:%d dialed:%s caller:\"%s\" <%s>\n",
08256 bc->channel,
08257 bc->dialed.number,
08258 bc->caller.name,
08259 bc->caller.number);
08260 ast_mutex_lock(&cl_te_lock);
08261 for (help = cl_te; help; help = help->next) {
08262 chan_misdn_log(4, bc->port, "$$$ find_hold_call: --> hold:%d channel:%d\n", help->hold.state, help->hold.channel);
08263 if (help->hold.state == MISDN_HOLD_ACTIVE && help->hold.port == bc->port) {
08264 chan_list_ref(help, "Found chan_list hold call");
08265 ast_mutex_unlock(&cl_te_lock);
08266 return help;
08267 }
08268 }
08269 ast_mutex_unlock(&cl_te_lock);
08270 chan_misdn_log(6, bc->port,
08271 "$$$ find_hold_call: No channel found for dialed:%s caller:\"%s\" <%s>\n",
08272 bc->dialed.number,
08273 bc->caller.name,
08274 bc->caller.number);
08275
08276 return NULL;
08277 }
08278
08279
08280
08281 static struct chan_list *find_hold_call_l3(unsigned long l3_id)
08282 {
08283 struct chan_list *help;
08284
08285 ast_mutex_lock(&cl_te_lock);
08286 for (help = cl_te; help; help = help->next) {
08287 if (help->hold.state != MISDN_HOLD_IDLE && help->l3id == l3_id) {
08288 chan_list_ref(help, "Found chan_list hold call l3");
08289 ast_mutex_unlock(&cl_te_lock);
08290 return help;
08291 }
08292 }
08293 ast_mutex_unlock(&cl_te_lock);
08294
08295 return NULL;
08296 }
08297
08298 #define TRANSFER_ON_HELD_CALL_HANGUP 1
08299 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
08300
08301
08302
08303
08304
08305
08306
08307
08308
08309
08310
08311
08312
08313
08314
08315 static struct chan_list *find_hold_active_call(struct misdn_bchannel *bc)
08316 {
08317 struct chan_list *list;
08318
08319 ast_mutex_lock(&cl_te_lock);
08320 for (list = cl_te; list; list = list->next) {
08321 if (list->hold.state == MISDN_HOLD_IDLE && list->bc && list->bc->port == bc->port
08322 && list->ast) {
08323 switch (list->state) {
08324 case MISDN_PROCEEDING:
08325 case MISDN_PROGRESS:
08326 case MISDN_ALERTING:
08327 case MISDN_CONNECTED:
08328 chan_list_ref(list, "Found chan_list hold active call");
08329 ast_mutex_unlock(&cl_te_lock);
08330 return list;
08331 default:
08332 break;
08333 }
08334 }
08335 }
08336 ast_mutex_unlock(&cl_te_lock);
08337 return NULL;
08338 }
08339 #endif
08340
08341 static void cl_queue_chan(struct chan_list *chan)
08342 {
08343 chan_misdn_log(4, chan->bc ? chan->bc->port : 0, "* Queuing chan %p\n", chan);
08344
08345 chan_list_ref(chan, "Adding chan_list to list");
08346 ast_mutex_lock(&cl_te_lock);
08347 chan->next = NULL;
08348 if (!cl_te) {
08349
08350 cl_te = chan;
08351 } else {
08352 struct chan_list *help;
08353
08354
08355 for (help = cl_te; help->next; help = help->next) {
08356 }
08357 help->next = chan;
08358 }
08359 ast_mutex_unlock(&cl_te_lock);
08360 }
08361
08362 static int cl_dequeue_chan(struct chan_list *chan)
08363 {
08364 int found_it;
08365 struct chan_list *help;
08366
08367 ast_mutex_lock(&cl_te_lock);
08368 if (!cl_te) {
08369
08370 ast_mutex_unlock(&cl_te_lock);
08371 return 0;
08372 }
08373
08374 if (cl_te == chan) {
08375
08376 cl_te = cl_te->next;
08377 ast_mutex_unlock(&cl_te_lock);
08378 chan_list_unref(chan, "Removed chan_list from list head");
08379 return 1;
08380 }
08381
08382 found_it = 0;
08383 for (help = cl_te; help->next; help = help->next) {
08384 if (help->next == chan) {
08385
08386 help->next = help->next->next;
08387 found_it = 1;
08388 break;
08389 }
08390 }
08391
08392 ast_mutex_unlock(&cl_te_lock);
08393 if (found_it) {
08394 chan_list_unref(chan, "Removed chan_list from list");
08395 }
08396 return found_it;
08397 }
08398
08399
08400
08401
08402 static int pbx_start_chan(struct chan_list *ch)
08403 {
08404 int ret = ast_pbx_start(ch->ast);
08405
08406 ch->need_hangup = (ret >= 0) ? 0 : 1;
08407
08408 return ret;
08409 }
08410
08411 static void hangup_chan(struct chan_list *ch, struct misdn_bchannel *bc)
08412 {
08413 int port = bc->port;
08414
08415 if (!ch) {
08416 cb_log(1, port, "Cannot hangup chan, no ch\n");
08417 return;
08418 }
08419
08420 cb_log(5, port, "hangup_chan called\n");
08421
08422 if (ch->need_hangup) {
08423 cb_log(2, port, " --> hangup\n");
08424 ch->need_hangup = 0;
08425 ch->need_queue_hangup = 0;
08426 if (ch->ast && send_cause2ast(ch->ast, bc, ch)) {
08427 ast_hangup(ch->ast);
08428 }
08429 return;
08430 }
08431
08432 if (!ch->need_queue_hangup) {
08433 cb_log(2, port, " --> No need to queue hangup\n");
08434 return;
08435 }
08436
08437 ch->need_queue_hangup = 0;
08438 if (ch->ast) {
08439 if (send_cause2ast(ch->ast, bc, ch)) {
08440 ast_queue_hangup_with_cause(ch->ast, bc->cause);
08441 cb_log(2, port, " --> queue_hangup\n");
08442 }
08443 } else {
08444 cb_log(1, port, "Cannot hangup chan, no ast\n");
08445 }
08446 }
08447
08448
08449
08450
08451
08452
08453
08454
08455
08456
08457
08458
08459 static void release_chan(struct chan_list *ch, struct misdn_bchannel *bc)
08460 {
08461 struct ast_channel *ast;
08462
08463 chan_misdn_log(5, bc->port, "release_chan: bc with pid:%d l3id: %x\n", bc->pid, bc->l3_id);
08464
08465 ast_mutex_lock(&release_lock);
08466 for (;;) {
08467 ast = ch->ast;
08468 if (!ast || !ast_channel_trylock(ast)) {
08469 break;
08470 }
08471 DEADLOCK_AVOIDANCE(&release_lock);
08472 }
08473 if (!cl_dequeue_chan(ch)) {
08474
08475 if (ast) {
08476 ast_channel_unlock(ast);
08477 }
08478 ast_mutex_unlock(&release_lock);
08479 return;
08480 }
08481 ch->state = MISDN_CLEANING;
08482 ch->ast = NULL;
08483 if (ast) {
08484 struct chan_list *ast_ch;
08485
08486 ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08487 MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
08488 chan_misdn_log(1, bc->port,
08489 "* RELEASING CHANNEL pid:%d context:%s dialed:%s caller:\"%s\" <%s>\n",
08490 bc->pid,
08491 ast_channel_context(ast),
08492 ast_channel_exten(ast),
08493 S_COR(ast_channel_caller(ast)->id.name.valid, ast_channel_caller(ast)->id.name.str, ""),
08494 S_COR(ast_channel_caller(ast)->id.number.valid, ast_channel_caller(ast)->id.number.str, ""));
08495
08496 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
08497 chan_misdn_log(3, bc->port, " --> Setting AST State to down\n");
08498 ast_setstate(ast, AST_STATE_DOWN);
08499 }
08500 ast_channel_unlock(ast);
08501 if (ast_ch) {
08502 chan_list_unref(ast_ch, "Release ast_channel reference.");
08503 }
08504 }
08505
08506 if (ch->originator == ORG_AST) {
08507 --misdn_out_calls[bc->port];
08508 } else {
08509 --misdn_in_calls[bc->port];
08510 }
08511
08512 ast_mutex_unlock(&release_lock);
08513 }
08514
08515
08516
08517
08518
08519
08520
08521
08522
08523
08524
08525 static void release_chan_early(struct chan_list *ch)
08526 {
08527 struct ast_channel *ast;
08528
08529 ast_mutex_lock(&release_lock);
08530 for (;;) {
08531 ast = ch->ast;
08532 if (!ast || !ast_channel_trylock(ast)) {
08533 break;
08534 }
08535 DEADLOCK_AVOIDANCE(&release_lock);
08536 }
08537 if (!cl_dequeue_chan(ch)) {
08538
08539 if (ast) {
08540 ast_channel_unlock(ast);
08541 }
08542 ast_mutex_unlock(&release_lock);
08543 return;
08544 }
08545 ch->state = MISDN_CLEANING;
08546 ch->ast = NULL;
08547 if (ast) {
08548 struct chan_list *ast_ch;
08549
08550 ast_ch = MISDN_ASTERISK_TECH_PVT(ast);
08551 MISDN_ASTERISK_TECH_PVT_SET(ast, NULL);
08552
08553 if (ast_channel_state(ast) != AST_STATE_RESERVED) {
08554 ast_setstate(ast, AST_STATE_DOWN);
08555 }
08556 ast_channel_unlock(ast);
08557 if (ast_ch) {
08558 chan_list_unref(ast_ch, "Release ast_channel reference.");
08559 }
08560 }
08561
08562 if (ch->hold.state != MISDN_HOLD_IDLE) {
08563 if (ch->originator == ORG_AST) {
08564 --misdn_out_calls[ch->hold.port];
08565 } else {
08566 --misdn_in_calls[ch->hold.port];
08567 }
08568 }
08569
08570 ast_mutex_unlock(&release_lock);
08571 }
08572
08573
08574
08575
08576
08577
08578
08579
08580
08581
08582
08583 static int misdn_attempt_transfer(struct chan_list *active_ch, struct chan_list *held_ch)
08584 {
08585 int retval;
08586 struct ast_channel *target;
08587 struct ast_channel *transferee;
08588 struct ast_party_connected_line target_colp;
08589 struct ast_party_connected_line transferee_colp;
08590
08591 switch (active_ch->state) {
08592 case MISDN_PROCEEDING:
08593 case MISDN_PROGRESS:
08594 case MISDN_ALERTING:
08595 case MISDN_CONNECTED:
08596 break;
08597 default:
08598 return -1;
08599 }
08600
08601 ast_channel_lock_both(held_ch->ast, active_ch->ast);
08602
08603 transferee = ast_bridged_channel(held_ch->ast);
08604 if (!transferee) {
08605
08606
08607
08608
08609 ast_channel_unlock(held_ch->ast);
08610 ast_channel_unlock(active_ch->ast);
08611 return -1;
08612 }
08613
08614 target = active_ch->ast;
08615 chan_misdn_log(1, held_ch->hold.port, "TRANSFERRING %s to %s\n",
08616 ast_channel_name(held_ch->ast), ast_channel_name(target));
08617
08618 ast_party_connected_line_init(&target_colp);
08619 ast_party_connected_line_copy(&target_colp, ast_channel_connected(target));
08620
08621
08622 ast_party_id_reset(&target_colp.priv);
08623
08624 ast_party_connected_line_init(&transferee_colp);
08625 ast_party_connected_line_copy(&transferee_colp, ast_channel_connected(held_ch->ast));
08626
08627
08628 ast_party_id_reset(&transferee_colp.priv);
08629
08630 held_ch->hold.state = MISDN_HOLD_TRANSFER;
08631
08632
08633
08634
08635
08636
08637
08638
08639
08640
08641
08642 ao2_ref(target, +1);
08643 ao2_ref(transferee, +1);
08644 ast_channel_unlock(held_ch->ast);
08645 ast_channel_unlock(active_ch->ast);
08646
08647
08648 retval = ast_channel_transfer_masquerade(target, &target_colp, 0,
08649 transferee, &transferee_colp, 1);
08650
08651 ast_party_connected_line_free(&target_colp);
08652 ast_party_connected_line_free(&transferee_colp);
08653 ao2_ref(target, -1);
08654 ao2_ref(transferee, -1);
08655 return retval;
08656 }
08657
08658
08659 static void do_immediate_setup(struct misdn_bchannel *bc, struct chan_list *ch, struct ast_channel *ast)
08660 {
08661 char *predial;
08662 struct ast_frame fr;
08663
08664 predial = ast_strdupa(ast_channel_exten(ast));
08665
08666 ch->state = MISDN_DIALING;
08667
08668 if (!ch->noautorespond_on_setup) {
08669 if (bc->nt) {
08670 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08671 } else {
08672 if (misdn_lib_is_ptp(bc->port)) {
08673 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08674 } else {
08675 misdn_lib_send_event(bc, EVENT_PROCEEDING);
08676 }
08677 }
08678 } else {
08679 ch->state = MISDN_INCOMING_SETUP;
08680 }
08681
08682 chan_misdn_log(1, bc->port,
08683 "* Starting Ast context:%s dialed:%s caller:\"%s\" <%s> with 's' extension\n",
08684 ast_channel_context(ast),
08685 ast_channel_exten(ast),
08686 (ast_channel_caller(ast)->id.name.valid && ast_channel_caller(ast)->id.name.str)
08687 ? ast_channel_caller(ast)->id.name.str : "",
08688 (ast_channel_caller(ast)->id.number.valid && ast_channel_caller(ast)->id.number.str)
08689 ? ast_channel_caller(ast)->id.number.str : "");
08690
08691 ast_channel_exten_set(ast, "s");
08692
08693 if (!ast_canmatch_extension(ast, ast_channel_context(ast), ast_channel_exten(ast), 1, bc->caller.number) || pbx_start_chan(ch) < 0) {
08694 ast = NULL;
08695 bc->out_cause = AST_CAUSE_UNALLOCATED;
08696 hangup_chan(ch, bc);
08697 hanguptone_indicate(ch);
08698
08699 misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_DISCONNECT);
08700 }
08701
08702
08703 while (!ast_strlen_zero(predial)) {
08704 fr.frametype = AST_FRAME_DTMF;
08705 fr.subclass.integer = *predial;
08706 fr.src = NULL;
08707 fr.data.ptr = NULL;
08708 fr.datalen = 0;
08709 fr.samples = 0;
08710 fr.mallocd = 0;
08711 fr.offset = 0;
08712 fr.delivery = ast_tv(0,0);
08713
08714 if (ch->ast && MISDN_ASTERISK_TECH_PVT(ch->ast)) {
08715 ast_queue_frame(ch->ast, &fr);
08716 }
08717 predial++;
08718 }
08719 }
08720
08721
08722
08723
08724
08725 static int send_cause2ast(struct ast_channel *ast, struct misdn_bchannel *bc, struct chan_list *ch)
08726 {
08727 int can_hangup;
08728
08729 if (!ast) {
08730 chan_misdn_log(1, 0, "send_cause2ast: No Ast\n");
08731 return 0;
08732 }
08733 if (!bc) {
08734 chan_misdn_log(1, 0, "send_cause2ast: No BC\n");
08735 return 0;
08736 }
08737 if (!ch) {
08738 chan_misdn_log(1, 0, "send_cause2ast: No Ch\n");
08739 return 0;
08740 }
08741
08742 ast_channel_hangupcause_set(ast, bc->cause);
08743
08744 can_hangup = -1;
08745 switch (bc->cause) {
08746 case AST_CAUSE_UNALLOCATED:
08747 case AST_CAUSE_NO_ROUTE_TRANSIT_NET:
08748 case AST_CAUSE_NO_ROUTE_DESTINATION:
08749 case 4:
08750 case AST_CAUSE_NUMBER_CHANGED:
08751 case AST_CAUSE_DESTINATION_OUT_OF_ORDER:
08752
08753
08754
08755
08756
08757
08758
08759
08760
08761
08762 break;
08763
08764 case AST_CAUSE_CALL_REJECTED:
08765 case AST_CAUSE_USER_BUSY:
08766 ch->state = MISDN_BUSY;
08767
08768 if (!ch->need_busy) {
08769 chan_misdn_log(1, bc ? bc->port : 0, "Queued busy already\n");
08770 break;
08771 }
08772 ch->need_busy = 0;
08773
08774 chan_misdn_log(1, bc ? bc->port : 0, " --> * SEND: Queue Busy pid:%d\n", bc ? bc->pid : -1);
08775 ast_queue_control(ast, AST_CONTROL_BUSY);
08776
08777
08778 can_hangup = 0;
08779 break;
08780 }
08781 return can_hangup;
08782 }
08783
08784
08785
08786 void import_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
08787 {
08788 const char *tmp;
08789
08790 ast_channel_lock(chan);
08791 tmp = pbx_builtin_getvar_helper(chan, "MISDN_ADDRESS_COMPLETE");
08792 if (tmp && (atoi(tmp) == 1)) {
08793 bc->sending_complete = 1;
08794 }
08795
08796 tmp = pbx_builtin_getvar_helper(chan, "MISDN_USERUSER");
08797 if (tmp) {
08798 ast_log(LOG_NOTICE, "MISDN_USERUSER: %s\n", tmp);
08799 ast_copy_string(bc->uu, tmp, sizeof(bc->uu));
08800 bc->uulen = strlen(bc->uu);
08801 }
08802
08803 tmp = pbx_builtin_getvar_helper(chan, "MISDN_KEYPAD");
08804 if (tmp) {
08805 ast_copy_string(bc->keypad, tmp, sizeof(bc->keypad));
08806 }
08807 ast_channel_unlock(chan);
08808 }
08809
08810
08811 void export_ch(struct ast_channel *chan, struct misdn_bchannel *bc, struct chan_list *ch)
08812 {
08813 char tmp[32];
08814
08815
08816
08817
08818
08819
08820
08821 chan_misdn_log(3, bc->port, " --> EXPORT_PID: pid:%d\n", bc->pid);
08822 snprintf(tmp, sizeof(tmp), "%d", bc->pid);
08823 pbx_builtin_setvar_helper(chan, "_MISDN_PID", tmp);
08824
08825 if (bc->sending_complete) {
08826 snprintf(tmp, sizeof(tmp), "%d", bc->sending_complete);
08827 pbx_builtin_setvar_helper(chan, "MISDN_ADDRESS_COMPLETE", tmp);
08828 }
08829
08830 if (bc->urate) {
08831 snprintf(tmp, sizeof(tmp), "%d", bc->urate);
08832 pbx_builtin_setvar_helper(chan, "MISDN_URATE", tmp);
08833 }
08834
08835 if (bc->uulen) {
08836 pbx_builtin_setvar_helper(chan, "MISDN_USERUSER", bc->uu);
08837 }
08838
08839 if (!ast_strlen_zero(bc->keypad)) {
08840 pbx_builtin_setvar_helper(chan, "MISDN_KEYPAD", bc->keypad);
08841 }
08842 }
08843
08844 int add_in_calls(int port)
08845 {
08846 int max_in_calls;
08847
08848 misdn_cfg_get(port, MISDN_CFG_MAX_IN, &max_in_calls, sizeof(max_in_calls));
08849 misdn_in_calls[port]++;
08850
08851 if (max_in_calls >= 0 && max_in_calls < misdn_in_calls[port]) {
08852 ast_log(LOG_NOTICE, "Marking Incoming Call on port[%d]\n", port);
08853 return misdn_in_calls[port] - max_in_calls;
08854 }
08855
08856 return 0;
08857 }
08858
08859 int add_out_calls(int port)
08860 {
08861 int max_out_calls;
08862
08863 misdn_cfg_get(port, MISDN_CFG_MAX_OUT, &max_out_calls, sizeof(max_out_calls));
08864
08865 if (max_out_calls >= 0 && max_out_calls <= misdn_out_calls[port]) {
08866 ast_log(LOG_NOTICE, "Rejecting Outgoing Call on port[%d]\n", port);
08867 return (misdn_out_calls[port] + 1) - max_out_calls;
08868 }
08869
08870 misdn_out_calls[port]++;
08871
08872 return 0;
08873 }
08874
08875 static void start_pbx(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
08876 {
08877 if (pbx_start_chan(ch) < 0) {
08878 hangup_chan(ch, bc);
08879 chan_misdn_log(-1, bc->port, "ast_pbx_start returned <0 in SETUP\n");
08880 if (bc->nt) {
08881 hanguptone_indicate(ch);
08882 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
08883 } else {
08884 misdn_lib_send_event(bc, EVENT_RELEASE);
08885 }
08886 }
08887 }
08888
08889 static void wait_for_digits(struct chan_list *ch, struct misdn_bchannel *bc, struct ast_channel *chan)
08890 {
08891 ch->state = MISDN_WAITING4DIGS;
08892 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
08893 if (bc->nt && !bc->dialed.number[0]) {
08894 dialtone_indicate(ch);
08895 }
08896 }
08897
08898 #if defined(AST_MISDN_ENHANCEMENTS)
08899
08900
08901
08902
08903
08904
08905
08906
08907
08908 static void misdn_cc_handle_ccbs_status_request(int port, const struct FacParm *facility)
08909 {
08910 struct misdn_cc_record *cc_record;
08911 struct misdn_bchannel dummy;
08912
08913 switch (facility->u.CCBSStatusRequest.ComponentType) {
08914 case FacComponent_Invoke:
08915
08916 misdn_make_dummy(&dummy, port, 0, misdn_lib_port_is_nt(port), 0);
08917 dummy.fac_out.Function = Fac_CCBSStatusRequest;
08918 dummy.fac_out.u.CCBSStatusRequest.InvokeID = facility->u.CCBSStatusRequest.InvokeID;
08919 dummy.fac_out.u.CCBSStatusRequest.ComponentType = FacComponent_Result;
08920
08921
08922 AST_LIST_LOCK(&misdn_cc_records_db);
08923 cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSStatusRequest.Component.Invoke.CCBSReference);
08924 if (cc_record) {
08925 dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = cc_record->party_a_free;
08926 } else {
08927
08928 dummy.fac_out.u.CCBSStatusRequest.Component.Result.Free = 1;
08929 }
08930 AST_LIST_UNLOCK(&misdn_cc_records_db);
08931
08932
08933 print_facility(&dummy.fac_out, &dummy);
08934 misdn_lib_send_event(&dummy, EVENT_FACILITY);
08935 break;
08936
08937 default:
08938 chan_misdn_log(0, port, " --> not yet handled: facility type:0x%04X\n", facility->Function);
08939 break;
08940 }
08941 }
08942 #endif
08943
08944 #if defined(AST_MISDN_ENHANCEMENTS)
08945
08946
08947
08948
08949
08950
08951
08952
08953
08954 static void misdn_cc_pbx_notify(long record_id, const struct misdn_cc_notify *notify)
08955 {
08956 struct ast_channel *chan;
08957 char id_str[32];
08958
08959 static unsigned short sequence = 0;
08960
08961
08962 snprintf(id_str, sizeof(id_str), "%ld", record_id);
08963 chan = ast_channel_alloc(0, AST_STATE_DOWN, id_str, NULL, NULL,
08964 notify->exten, notify->context, NULL, 0,
08965 "mISDN-CC/%ld-%X", record_id, (unsigned) ++sequence);
08966 if (!chan) {
08967 ast_log(LOG_ERROR, "Unable to allocate channel!\n");
08968 return;
08969 }
08970 ast_channel_priority_set(chan, notify->priority);
08971 ast_free(ast_channel_dialed(chan)->number.str);
08972 ast_channel_dialed(chan)->number.str = ast_strdup(notify->exten);
08973
08974 if (ast_pbx_start(chan)) {
08975 ast_log(LOG_WARNING, "Unable to start pbx channel %s!\n", ast_channel_name(chan));
08976 ast_channel_release(chan);
08977 } else {
08978 ast_verb(1, "Started pbx for call completion notify channel %s\n", ast_channel_name(chan));
08979 }
08980 }
08981 #endif
08982
08983 #if defined(AST_MISDN_ENHANCEMENTS)
08984
08985
08986
08987
08988
08989
08990
08991
08992 static void misdn_cc_handle_T_remote_user_free(struct misdn_bchannel *bc)
08993 {
08994 struct misdn_cc_record *cc_record;
08995 struct misdn_cc_notify notify;
08996 long record_id;
08997
08998 AST_LIST_LOCK(&misdn_cc_records_db);
08999 cc_record = misdn_cc_find_by_bc(bc);
09000 if (cc_record) {
09001 if (cc_record->party_a_free) {
09002 notify = cc_record->remote_user_free;
09003 } else {
09004
09005 bc->fac_out.Function = Fac_CCBS_T_Suspend;
09006 bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
09007 print_facility(&bc->fac_out, bc);
09008 misdn_lib_send_event(bc, EVENT_FACILITY);
09009
09010 notify = cc_record->b_free;
09011 }
09012 record_id = cc_record->record_id;
09013 AST_LIST_UNLOCK(&misdn_cc_records_db);
09014 if (notify.context[0]) {
09015
09016 misdn_cc_pbx_notify(record_id, ¬ify);
09017 }
09018 } else {
09019 AST_LIST_UNLOCK(&misdn_cc_records_db);
09020 }
09021 }
09022 #endif
09023
09024 #if defined(AST_MISDN_ENHANCEMENTS)
09025
09026
09027
09028
09029
09030
09031
09032
09033
09034 static void misdn_cc_handle_remote_user_free(int port, const struct FacParm *facility)
09035 {
09036 struct misdn_cc_record *cc_record;
09037 struct misdn_cc_notify notify;
09038 long record_id;
09039
09040 AST_LIST_LOCK(&misdn_cc_records_db);
09041 cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSRemoteUserFree.CCBSReference);
09042 if (cc_record) {
09043 notify = cc_record->remote_user_free;
09044 record_id = cc_record->record_id;
09045 AST_LIST_UNLOCK(&misdn_cc_records_db);
09046 misdn_cc_pbx_notify(record_id, ¬ify);
09047 } else {
09048 AST_LIST_UNLOCK(&misdn_cc_records_db);
09049 }
09050 }
09051 #endif
09052
09053 #if defined(AST_MISDN_ENHANCEMENTS)
09054
09055
09056
09057
09058
09059
09060
09061
09062
09063 static void misdn_cc_handle_b_free(int port, const struct FacParm *facility)
09064 {
09065 struct misdn_cc_record *cc_record;
09066 struct misdn_cc_notify notify;
09067 long record_id;
09068
09069 AST_LIST_LOCK(&misdn_cc_records_db);
09070 cc_record = misdn_cc_find_by_reference(port, facility->u.CCBSBFree.CCBSReference);
09071 if (cc_record && cc_record->b_free.context[0]) {
09072
09073 notify = cc_record->b_free;
09074 record_id = cc_record->record_id;
09075 AST_LIST_UNLOCK(&misdn_cc_records_db);
09076 misdn_cc_pbx_notify(record_id, ¬ify);
09077 } else {
09078 AST_LIST_UNLOCK(&misdn_cc_records_db);
09079 }
09080 }
09081 #endif
09082
09083
09084
09085
09086
09087
09088
09089
09090
09091
09092
09093 static void misdn_facility_ie_handler(enum event_e event, struct misdn_bchannel *bc, struct chan_list *ch)
09094 {
09095 #if defined(AST_MISDN_ENHANCEMENTS)
09096 const char *diagnostic_msg;
09097 struct misdn_cc_record *cc_record;
09098 char buf[32];
09099 struct misdn_party_id party_id;
09100 long new_record_id;
09101 #endif
09102
09103 print_facility(&bc->fac_in, bc);
09104 switch (bc->fac_in.Function) {
09105 #if defined(AST_MISDN_ENHANCEMENTS)
09106 case Fac_ActivationDiversion:
09107 switch (bc->fac_in.u.ActivationDiversion.ComponentType) {
09108 case FacComponent_Result:
09109
09110
09111 break;
09112 default:
09113 chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
09114 bc->fac_in.Function);
09115 break;
09116 }
09117 break;
09118 case Fac_DeactivationDiversion:
09119 switch (bc->fac_in.u.DeactivationDiversion.ComponentType) {
09120 case FacComponent_Result:
09121
09122
09123 break;
09124 default:
09125 chan_misdn_log(0, bc->port," --> not yet handled: facility type:0x%04X\n",
09126 bc->fac_in.Function);
09127 break;
09128 }
09129 break;
09130 case Fac_ActivationStatusNotificationDiv:
09131
09132
09133
09134 break;
09135 case Fac_DeactivationStatusNotificationDiv:
09136
09137
09138 break;
09139 #if 0
09140 case Fac_InterrogationDiversion:
09141
09142 break;
09143 case Fac_InterrogateServedUserNumbers:
09144
09145 break;
09146 #endif
09147 case Fac_DiversionInformation:
09148
09149
09150 break;
09151 case Fac_CallDeflection:
09152 if (ch && ch->ast) {
09153 switch (bc->fac_in.u.CallDeflection.ComponentType) {
09154 case FacComponent_Invoke:
09155 ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
09156 sizeof(bc->redirecting.from.number));
09157 bc->redirecting.from.name[0] = 0;
09158 bc->redirecting.from.number_plan = bc->dialed.number_plan;
09159 bc->redirecting.from.number_type = bc->dialed.number_type;
09160 bc->redirecting.from.screening = 0;
09161 if (bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent) {
09162 bc->redirecting.from.presentation =
09163 bc->fac_in.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser
09164 ? 0 : 1 ;
09165 } else {
09166 bc->redirecting.from.presentation = 0;
09167 }
09168
09169
09170 memset(&party_id, 0, sizeof(party_id));
09171 misdn_PartyNumber_extract(&party_id,
09172 &bc->fac_in.u.CallDeflection.Component.Invoke.Deflection.Party);
09173 misdn_add_number_prefix(bc->port, party_id.number_type,
09174 party_id.number, sizeof(party_id.number));
09175
09176
09177 bc->redirecting.to = party_id;
09178
09179 ++bc->redirecting.count;
09180 bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
09181
09182 misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09183 ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
09184
09185
09186 #if 1
09187
09188
09189
09190
09191 bc->fac_out.Function = Fac_RESULT;
09192 bc->fac_out.u.RESULT.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
09193 #else
09194 bc->fac_out.Function = Fac_CallDeflection;
09195 bc->fac_out.u.CallDeflection.InvokeID = bc->fac_in.u.CallDeflection.InvokeID;
09196 bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Result;
09197 #endif
09198 print_facility(&bc->fac_out, bc);
09199 misdn_lib_send_event(bc, EVENT_DISCONNECT);
09200
09201
09202 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
09203 break;
09204
09205 case FacComponent_Result:
09206
09207
09208
09209
09210
09211
09212
09213 break;
09214
09215 default:
09216 break;
09217 }
09218 }
09219 break;
09220 #if 0
09221 case Fac_CallRerouteing:
09222
09223
09224 break;
09225 #endif
09226 case Fac_DivertingLegInformation1:
09227
09228 bc->div_leg_3_rx_wanted = 0;
09229 if (ch && ch->ast) {
09230 bc->redirecting.reason =
09231 diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation1.DiversionReason);
09232 if (bc->fac_in.u.DivertingLegInformation1.DivertedToPresent) {
09233 misdn_PresentedNumberUnscreened_extract(&bc->redirecting.to,
09234 &bc->fac_in.u.DivertingLegInformation1.DivertedTo);
09235
09236
09237 misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
09238 bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
09239 } else {
09240 bc->redirecting.to.number[0] = '\0';
09241 bc->redirecting.to.number_plan = NUMPLAN_ISDN;
09242 bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
09243 bc->redirecting.to.presentation = 1;
09244 bc->redirecting.to.screening = 0;
09245 }
09246 misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09247 bc->div_leg_3_rx_wanted = 1;
09248 }
09249 break;
09250 case Fac_DivertingLegInformation2:
09251
09252 switch (event) {
09253 case EVENT_SETUP:
09254
09255 bc->div_leg_3_tx_pending = 1;
09256 if (ch && ch->ast) {
09257
09258
09259
09260
09261
09262
09263
09264
09265
09266
09267 ast_copy_string(bc->redirecting.to.number, bc->dialed.number,
09268 sizeof(bc->redirecting.to.number));
09269 bc->redirecting.to.number_plan = bc->dialed.number_plan;
09270 bc->redirecting.to.number_type = bc->dialed.number_type;
09271 bc->redirecting.to.presentation = 1;
09272 bc->redirecting.to.screening = 0;
09273
09274 bc->redirecting.reason =
09275 diversion_reason_to_misdn(bc->fac_in.u.DivertingLegInformation2.DiversionReason);
09276 bc->redirecting.count = bc->fac_in.u.DivertingLegInformation2.DiversionCounter;
09277 if (bc->fac_in.u.DivertingLegInformation2.DivertingPresent) {
09278
09279 misdn_PresentedNumberUnscreened_extract(&bc->redirecting.from,
09280 &bc->fac_in.u.DivertingLegInformation2.Diverting);
09281
09282
09283 misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type,
09284 bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
09285 }
09286 #if 0
09287 if (bc->fac_in.u.DivertingLegInformation2.OriginalCalledPresent) {
09288
09289 }
09290 #endif
09291 misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09292 }
09293 break;
09294 default:
09295 chan_misdn_log(0, bc->port," --> Expected in a SETUP message: facility type:0x%04X\n",
09296 bc->fac_in.Function);
09297 break;
09298 }
09299 break;
09300 case Fac_DivertingLegInformation3:
09301
09302 if (bc->div_leg_3_rx_wanted) {
09303 bc->div_leg_3_rx_wanted = 0;
09304
09305 if (ch && ch->ast) {
09306 struct ast_party_redirecting redirecting;
09307
09308 ast_channel_redirecting(ch->ast)->to.number.presentation =
09309 bc->fac_in.u.DivertingLegInformation3.PresentationAllowedIndicator
09310 ? AST_PRES_ALLOWED | AST_PRES_USER_NUMBER_UNSCREENED
09311 : AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
09312 ast_party_redirecting_init(&redirecting);
09313 ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
09314
09315
09316
09317
09318
09319 ast_party_id_reset(&redirecting.priv_orig);
09320 ast_party_id_reset(&redirecting.priv_from);
09321 ast_party_id_reset(&redirecting.priv_to);
09322
09323 ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
09324 ast_party_redirecting_free(&redirecting);
09325 }
09326 }
09327 break;
09328
09329 #else
09330
09331 case Fac_CD:
09332 if (ch && ch->ast) {
09333 ast_copy_string(bc->redirecting.from.number, bc->dialed.number,
09334 sizeof(bc->redirecting.from.number));
09335 bc->redirecting.from.name[0] = 0;
09336 bc->redirecting.from.number_plan = bc->dialed.number_plan;
09337 bc->redirecting.from.number_type = bc->dialed.number_type;
09338 bc->redirecting.from.screening = 0;
09339 bc->redirecting.from.presentation =
09340 bc->fac_in.u.CDeflection.PresentationAllowed
09341 ? 0 : 1 ;
09342
09343 ast_copy_string(bc->redirecting.to.number,
09344 (char *) bc->fac_in.u.CDeflection.DeflectedToNumber,
09345 sizeof(bc->redirecting.to.number));
09346 bc->redirecting.to.name[0] = 0;
09347 bc->redirecting.to.number_plan = NUMPLAN_UNKNOWN;
09348 bc->redirecting.to.number_type = NUMTYPE_UNKNOWN;
09349 bc->redirecting.to.presentation = 0;
09350 bc->redirecting.to.screening = 0;
09351
09352 ++bc->redirecting.count;
09353 bc->redirecting.reason = mISDN_REDIRECTING_REASON_DEFLECTION;
09354
09355 misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
09356 ast_channel_call_forward_set(ch->ast, bc->redirecting.to.number);
09357
09358 misdn_lib_send_event(bc, EVENT_DISCONNECT);
09359
09360
09361 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
09362 }
09363 break;
09364 #endif
09365 case Fac_AOCDCurrency:
09366 if (ch && ch->ast) {
09367 bc->AOCDtype = Fac_AOCDCurrency;
09368 memcpy(&bc->AOCD.currency, &bc->fac_in.u.AOCDcur, sizeof(bc->AOCD.currency));
09369 bc->AOCD_need_export = 1;
09370 export_aoc_vars(ch->originator, ch->ast, bc);
09371 }
09372 break;
09373 case Fac_AOCDChargingUnit:
09374 if (ch && ch->ast) {
09375 bc->AOCDtype = Fac_AOCDChargingUnit;
09376 memcpy(&bc->AOCD.chargingUnit, &bc->fac_in.u.AOCDchu, sizeof(bc->AOCD.chargingUnit));
09377 bc->AOCD_need_export = 1;
09378 export_aoc_vars(ch->originator, ch->ast, bc);
09379 }
09380 break;
09381 #if defined(AST_MISDN_ENHANCEMENTS)
09382 case Fac_ERROR:
09383 diagnostic_msg = misdn_to_str_error_code(bc->fac_in.u.ERROR.errorValue);
09384 chan_misdn_log(1, bc->port, " --> Facility error code: %s\n", diagnostic_msg);
09385 switch (event) {
09386 case EVENT_DISCONNECT:
09387 case EVENT_RELEASE:
09388 case EVENT_RELEASE_COMPLETE:
09389
09390 if (ch && ch->peer) {
09391 misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
09392 }
09393 break;
09394 default:
09395 break;
09396 }
09397 AST_LIST_LOCK(&misdn_cc_records_db);
09398 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.ERROR.invokeId);
09399 if (cc_record) {
09400 cc_record->outstanding_message = 0;
09401 cc_record->error_code = bc->fac_in.u.ERROR.errorValue;
09402 }
09403 AST_LIST_UNLOCK(&misdn_cc_records_db);
09404 break;
09405 case Fac_REJECT:
09406 diagnostic_msg = misdn_to_str_reject_code(bc->fac_in.u.REJECT.Code);
09407 chan_misdn_log(1, bc->port, " --> Facility reject code: %s\n", diagnostic_msg);
09408 switch (event) {
09409 case EVENT_DISCONNECT:
09410 case EVENT_RELEASE:
09411 case EVENT_RELEASE_COMPLETE:
09412
09413 if (ch && ch->peer) {
09414 misdn_cc_set_peer_var(ch->peer, MISDN_ERROR_MSG, diagnostic_msg);
09415 }
09416 break;
09417 default:
09418 break;
09419 }
09420 if (bc->fac_in.u.REJECT.InvokeIDPresent) {
09421 AST_LIST_LOCK(&misdn_cc_records_db);
09422 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.REJECT.InvokeID);
09423 if (cc_record) {
09424 cc_record->outstanding_message = 0;
09425 cc_record->reject_code = bc->fac_in.u.REJECT.Code;
09426 }
09427 AST_LIST_UNLOCK(&misdn_cc_records_db);
09428 }
09429 break;
09430 case Fac_RESULT:
09431 AST_LIST_LOCK(&misdn_cc_records_db);
09432 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.RESULT.InvokeID);
09433 if (cc_record) {
09434 cc_record->outstanding_message = 0;
09435 }
09436 AST_LIST_UNLOCK(&misdn_cc_records_db);
09437 break;
09438 #if 0
09439 case Fac_EctExecute:
09440
09441 break;
09442 case Fac_ExplicitEctExecute:
09443
09444 break;
09445 case Fac_EctLinkIdRequest:
09446
09447 break;
09448 #endif
09449 case Fac_SubaddressTransfer:
09450
09451 break;
09452 case Fac_RequestSubaddress:
09453
09454
09455
09456
09457 if (bc->redirecting.to_changed) {
09458
09459 misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
09460 bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
09461 }
09462 switch (bc->notify_description_code) {
09463 case mISDN_NOTIFY_CODE_INVALID:
09464
09465 bc->redirecting.to_changed = 0;
09466 break;
09467 case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
09468
09469
09470
09471
09472
09473
09474
09475
09476
09477 if (!bc->redirecting.to_changed) {
09478 break;
09479 }
09480 bc->redirecting.to_changed = 0;
09481 if (!ch || !ch->ast) {
09482 break;
09483 }
09484 misdn_update_remote_party(ch->ast, &bc->redirecting.to,
09485 AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
09486 bc->incoming_cid_tag);
09487 break;
09488 case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
09489 if (!bc->redirecting.to_changed) {
09490 break;
09491 }
09492 bc->redirecting.to_changed = 0;
09493 if (!ch || !ch->ast) {
09494 break;
09495 }
09496 misdn_update_remote_party(ch->ast, &bc->redirecting.to,
09497 AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
09498 break;
09499 default:
09500 bc->redirecting.to_changed = 0;
09501 chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
09502 bc->notify_description_code);
09503 break;
09504 }
09505 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
09506 break;
09507 case Fac_EctInform:
09508
09509 if (ch && ch->ast && bc->fac_in.u.EctInform.RedirectionPresent) {
09510
09511 memset(&party_id, 0, sizeof(party_id));
09512 misdn_PresentedNumberUnscreened_extract(&party_id,
09513 &bc->fac_in.u.EctInform.Redirection);
09514 misdn_add_number_prefix(bc->port, party_id.number_type,
09515 party_id.number, sizeof(party_id.number));
09516
09517
09518
09519
09520
09521
09522
09523
09524
09525
09526 misdn_update_remote_party(ch->ast, &party_id,
09527 (bc->fac_in.u.EctInform.Status == 0 )
09528 ? AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING
09529 : AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER,
09530 bc->incoming_cid_tag);
09531 }
09532 break;
09533 #if 0
09534 case Fac_EctLoopTest:
09535
09536
09537 break;
09538 #endif
09539 case Fac_CallInfoRetain:
09540 switch (event) {
09541 case EVENT_ALERTING:
09542 case EVENT_DISCONNECT:
09543
09544 if (ch && ch->peer) {
09545 AST_LIST_LOCK(&misdn_cc_records_db);
09546 if (ch->record_id == -1) {
09547 cc_record = misdn_cc_new();
09548 } else {
09549
09550
09551
09552
09553
09554
09555
09556
09557
09558 cc_record = misdn_cc_find_by_id(ch->record_id);
09559 if (cc_record) {
09560 if (cc_record->ptp && cc_record->mode.ptp.bc) {
09561
09562
09563
09564
09565
09566
09567
09568
09569 cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
09570 cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
09571 misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
09572 }
09573
09574
09575
09576
09577
09578 new_record_id = misdn_cc_record_id_new();
09579 if (new_record_id < 0) {
09580
09581 } else {
09582 cc_record->record_id = new_record_id;
09583 ch->record_id = new_record_id;
09584 }
09585 cc_record->ptp = 0;
09586 cc_record->port = bc->port;
09587 memset(&cc_record->mode, 0, sizeof(cc_record->mode));
09588 cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
09589 cc_record->invoke_id = ++misdn_invoke_id;
09590 cc_record->activated = 0;
09591 cc_record->outstanding_message = 0;
09592 cc_record->activation_requested = 0;
09593 cc_record->error_code = FacError_None;
09594 cc_record->reject_code = FacReject_None;
09595 memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
09596 memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
09597 cc_record->time_created = time(NULL);
09598
09599 cc_record = NULL;
09600 } else {
09601
09602
09603
09604
09605
09606 ch->record_id = -1;
09607 cc_record = misdn_cc_new();
09608 }
09609 }
09610 if (cc_record) {
09611 ch->record_id = cc_record->record_id;
09612 cc_record->ptp = 0;
09613 cc_record->port = bc->port;
09614 cc_record->mode.ptmp.linkage_id = bc->fac_in.u.CallInfoRetain.CallLinkageID;
09615
09616
09617 cc_record->redial.caller = bc->caller;
09618 cc_record->redial.dialed = bc->dialed;
09619 cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
09620 cc_record->redial.capability = bc->capability;
09621 cc_record->redial.hdlc = bc->hdlc;
09622 }
09623 AST_LIST_UNLOCK(&misdn_cc_records_db);
09624
09625
09626 if (ch->record_id != -1) {
09627 snprintf(buf, sizeof(buf), "%ld", ch->record_id);
09628 } else {
09629 buf[0] = 0;
09630 }
09631 misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
09632 }
09633 break;
09634 default:
09635 chan_misdn_log(0, bc->port,
09636 " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
09637 bc->fac_in.Function);
09638 break;
09639 }
09640 break;
09641 case Fac_CCBS_T_Call:
09642 case Fac_CCBSCall:
09643 switch (event) {
09644 case EVENT_SETUP:
09645
09646
09647
09648
09649 break;
09650 default:
09651 chan_misdn_log(0, bc->port, " --> Expected in a SETUP message: facility type:0x%04X\n",
09652 bc->fac_in.Function);
09653 break;
09654 }
09655 break;
09656 case Fac_CCBSDeactivate:
09657 switch (bc->fac_in.u.CCBSDeactivate.ComponentType) {
09658 case FacComponent_Result:
09659 AST_LIST_LOCK(&misdn_cc_records_db);
09660 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSDeactivate.InvokeID);
09661 if (cc_record) {
09662 cc_record->outstanding_message = 0;
09663 }
09664 AST_LIST_UNLOCK(&misdn_cc_records_db);
09665 break;
09666
09667 default:
09668 chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09669 bc->fac_in.Function);
09670 break;
09671 }
09672 break;
09673 case Fac_CCBSErase:
09674 AST_LIST_LOCK(&misdn_cc_records_db);
09675 cc_record = misdn_cc_find_by_reference(bc->port, bc->fac_in.u.CCBSErase.CCBSReference);
09676 if (cc_record) {
09677 misdn_cc_delete(cc_record);
09678 }
09679 AST_LIST_UNLOCK(&misdn_cc_records_db);
09680 break;
09681 case Fac_CCBSRemoteUserFree:
09682 misdn_cc_handle_remote_user_free(bc->port, &bc->fac_in);
09683 break;
09684 case Fac_CCBSBFree:
09685 misdn_cc_handle_b_free(bc->port, &bc->fac_in);
09686 break;
09687 case Fac_CCBSStatusRequest:
09688 misdn_cc_handle_ccbs_status_request(bc->port, &bc->fac_in);
09689 break;
09690 case Fac_EraseCallLinkageID:
09691 AST_LIST_LOCK(&misdn_cc_records_db);
09692 cc_record = misdn_cc_find_by_linkage(bc->port,
09693 bc->fac_in.u.EraseCallLinkageID.CallLinkageID);
09694 if (cc_record && !cc_record->activation_requested) {
09695
09696
09697
09698
09699
09700 misdn_cc_delete(cc_record);
09701 }
09702 AST_LIST_UNLOCK(&misdn_cc_records_db);
09703 break;
09704 case Fac_CCBSStopAlerting:
09705
09706 break;
09707 case Fac_CCBSRequest:
09708 case Fac_CCNRRequest:
09709 switch (bc->fac_in.u.CCBSRequest.ComponentType) {
09710 case FacComponent_Result:
09711 AST_LIST_LOCK(&misdn_cc_records_db);
09712 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBSRequest.InvokeID);
09713 if (cc_record && !cc_record->ptp) {
09714 cc_record->outstanding_message = 0;
09715 cc_record->activated = 1;
09716 cc_record->mode.ptmp.recall_mode = bc->fac_in.u.CCBSRequest.Component.Result.RecallMode;
09717 cc_record->mode.ptmp.reference_id = bc->fac_in.u.CCBSRequest.Component.Result.CCBSReference;
09718 }
09719 AST_LIST_UNLOCK(&misdn_cc_records_db);
09720 break;
09721
09722 default:
09723 chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09724 bc->fac_in.Function);
09725 break;
09726 }
09727 break;
09728 #if 0
09729 case Fac_CCBSInterrogate:
09730 case Fac_CCNRInterrogate:
09731
09732 break;
09733 case Fac_StatusRequest:
09734
09735 break;
09736 #endif
09737 #if 0
09738 case Fac_CCBS_T_Suspend:
09739 case Fac_CCBS_T_Resume:
09740
09741 break;
09742 #endif
09743 case Fac_CCBS_T_RemoteUserFree:
09744 misdn_cc_handle_T_remote_user_free(bc);
09745 break;
09746 case Fac_CCBS_T_Available:
09747 switch (event) {
09748 case EVENT_ALERTING:
09749 case EVENT_DISCONNECT:
09750
09751 if (ch && ch->peer) {
09752 int set_id = 1;
09753
09754 AST_LIST_LOCK(&misdn_cc_records_db);
09755 if (ch->record_id == -1) {
09756 cc_record = misdn_cc_new();
09757 } else {
09758
09759
09760
09761
09762
09763 cc_record = misdn_cc_find_by_id(ch->record_id);
09764 if (cc_record) {
09765 if (cc_record->ptp && cc_record->mode.ptp.retention_enabled) {
09766
09767
09768
09769
09770 chan_misdn_log(1, bc->port, " --> Call-completion request retention option is enabled\n");
09771
09772 set_id = 0;
09773 } else {
09774 if (cc_record->ptp && cc_record->mode.ptp.bc) {
09775
09776
09777
09778
09779
09780
09781
09782
09783
09784 cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
09785 cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
09786 misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
09787 }
09788
09789
09790
09791
09792
09793 new_record_id = misdn_cc_record_id_new();
09794 if (new_record_id < 0) {
09795
09796 } else {
09797 cc_record->record_id = new_record_id;
09798 ch->record_id = new_record_id;
09799 }
09800 cc_record->ptp = 1;
09801 cc_record->port = bc->port;
09802 memset(&cc_record->mode, 0, sizeof(cc_record->mode));
09803 cc_record->invoke_id = ++misdn_invoke_id;
09804 cc_record->activated = 0;
09805 cc_record->outstanding_message = 0;
09806 cc_record->activation_requested = 0;
09807 cc_record->error_code = FacError_None;
09808 cc_record->reject_code = FacReject_None;
09809 memset(&cc_record->remote_user_free, 0, sizeof(cc_record->remote_user_free));
09810 memset(&cc_record->b_free, 0, sizeof(cc_record->b_free));
09811 cc_record->time_created = time(NULL);
09812 }
09813 cc_record = NULL;
09814 } else {
09815
09816
09817
09818
09819
09820 ch->record_id = -1;
09821 cc_record = misdn_cc_new();
09822 }
09823 }
09824 if (cc_record) {
09825 ch->record_id = cc_record->record_id;
09826 cc_record->ptp = 1;
09827 cc_record->port = bc->port;
09828
09829
09830 cc_record->redial.caller = bc->caller;
09831 cc_record->redial.dialed = bc->dialed;
09832 cc_record->redial.setup_bc_hlc_llc = bc->setup_bc_hlc_llc;
09833 cc_record->redial.capability = bc->capability;
09834 cc_record->redial.hdlc = bc->hdlc;
09835 }
09836 AST_LIST_UNLOCK(&misdn_cc_records_db);
09837
09838
09839 if (ch->record_id != -1 && set_id) {
09840 snprintf(buf, sizeof(buf), "%ld", ch->record_id);
09841 } else {
09842 buf[0] = 0;
09843 }
09844 misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, buf);
09845 }
09846 break;
09847 default:
09848 chan_misdn_log(0, bc->port,
09849 " --> Expected in a DISCONNECT or ALERTING message: facility type:0x%04X\n",
09850 bc->fac_in.Function);
09851 break;
09852 }
09853 break;
09854 case Fac_CCBS_T_Request:
09855 case Fac_CCNR_T_Request:
09856 switch (bc->fac_in.u.CCBS_T_Request.ComponentType) {
09857 case FacComponent_Result:
09858 AST_LIST_LOCK(&misdn_cc_records_db);
09859 cc_record = misdn_cc_find_by_invoke(bc->port, bc->fac_in.u.CCBS_T_Request.InvokeID);
09860 if (cc_record && cc_record->ptp) {
09861 cc_record->outstanding_message = 0;
09862 cc_record->activated = 1;
09863 cc_record->mode.ptp.retention_enabled =
09864 cc_record->mode.ptp.requested_retention
09865 ? bc->fac_in.u.CCBS_T_Request.Component.Result.RetentionSupported
09866 ? 1 : 0
09867 : 0;
09868 }
09869 AST_LIST_UNLOCK(&misdn_cc_records_db);
09870 break;
09871
09872 case FacComponent_Invoke:
09873
09874 default:
09875 chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09876 bc->fac_in.Function);
09877 break;
09878 }
09879 break;
09880
09881 #endif
09882 case Fac_None:
09883 break;
09884 default:
09885 chan_misdn_log(0, bc->port, " --> not yet handled: facility type:0x%04X\n",
09886 bc->fac_in.Function);
09887 break;
09888 }
09889 }
09890
09891
09892
09893
09894
09895
09896
09897
09898
09899
09900
09901
09902 static int misdn_is_msn_valid(int port, const struct misdn_party_dialing *dialed)
09903 {
09904 char number[sizeof(dialed->number)];
09905
09906 ast_copy_string(number, dialed->number, sizeof(number));
09907 misdn_add_number_prefix(port, dialed->number_type, number, sizeof(number));
09908 return misdn_cfg_is_msn_valid(port, number);
09909 }
09910
09911
09912
09913
09914 static enum event_response_e
09915 cb_events(enum event_e event, struct misdn_bchannel *bc, void *user_data)
09916 {
09917 #if defined(AST_MISDN_ENHANCEMENTS)
09918 struct misdn_cc_record *cc_record;
09919 #endif
09920 struct chan_list *held_ch;
09921 struct chan_list *ch = find_chan_by_bc(bc);
09922
09923 if (event != EVENT_BCHAN_DATA && event != EVENT_TONE_GENERATE) {
09924 int debuglevel = 1;
09925
09926
09927 if (event == EVENT_CLEANUP && !user_data) {
09928 debuglevel = 5;
09929 }
09930
09931 chan_misdn_log(debuglevel, bc->port,
09932 "I IND :%s caller:\"%s\" <%s> dialed:%s pid:%d state:%s\n",
09933 manager_isdn_get_info(event),
09934 bc->caller.name,
09935 bc->caller.number,
09936 bc->dialed.number,
09937 bc->pid,
09938 ch ? misdn_get_ch_state(ch) : "none");
09939 if (debuglevel == 1) {
09940 misdn_lib_log_ies(bc);
09941 chan_misdn_log(4, bc->port, " --> bc_state:%s\n", bc_state2str(bc->bc_state));
09942 }
09943 }
09944
09945 if (!ch) {
09946 switch(event) {
09947 case EVENT_SETUP:
09948 case EVENT_DISCONNECT:
09949 case EVENT_RELEASE:
09950 case EVENT_RELEASE_COMPLETE:
09951 case EVENT_PORT_ALARM:
09952 case EVENT_RETRIEVE:
09953 case EVENT_NEW_BC:
09954 case EVENT_FACILITY:
09955 case EVENT_REGISTER:
09956 break;
09957 case EVENT_CLEANUP:
09958 case EVENT_TONE_GENERATE:
09959 case EVENT_BCHAN_DATA:
09960 return -1;
09961 default:
09962 chan_misdn_log(1, bc->port, "Chan not existing at the moment bc->l3id:%x bc:%p event:%s port:%d channel:%d\n", bc->l3_id, bc, manager_isdn_get_info(event), bc->port, bc->channel);
09963 return -1;
09964 }
09965 } else {
09966 switch (event) {
09967 case EVENT_TONE_GENERATE:
09968 break;
09969 case EVENT_DISCONNECT:
09970 case EVENT_RELEASE:
09971 case EVENT_RELEASE_COMPLETE:
09972 case EVENT_CLEANUP:
09973 case EVENT_TIMEOUT:
09974 if (!ch->ast) {
09975 chan_misdn_log(3, bc->port, "ast_hangup already called, so we have no ast ptr anymore in event(%s)\n", manager_isdn_get_info(event));
09976 }
09977 break;
09978 default:
09979 if (!ch->ast || !MISDN_ASTERISK_TECH_PVT(ch->ast)) {
09980 if (event != EVENT_BCHAN_DATA) {
09981 ast_log(LOG_NOTICE, "No Ast or No private Pointer in Event (%d:%s)\n", event, manager_isdn_get_info(event));
09982 }
09983 chan_list_unref(ch, "No Ast or Ast private pointer");
09984 return -1;
09985 }
09986 break;
09987 }
09988 }
09989
09990
09991 switch (event) {
09992 case EVENT_PORT_ALARM:
09993 {
09994 int boa = 0;
09995 misdn_cfg_get(bc->port, MISDN_CFG_ALARM_BLOCK, &boa, sizeof(boa));
09996 if (boa) {
09997 cb_log(1, bc->port, " --> blocking\n");
09998 misdn_lib_port_block(bc->port);
09999 }
10000 }
10001 break;
10002 case EVENT_BCHAN_ACTIVATED:
10003 break;
10004
10005 case EVENT_NEW_CHANNEL:
10006 update_name(ch->ast,bc->port,bc->channel);
10007 break;
10008
10009 case EVENT_NEW_L3ID:
10010 ch->l3id=bc->l3_id;
10011 ch->addr=bc->addr;
10012 break;
10013
10014 case EVENT_NEW_BC:
10015 if (!ch) {
10016 ch = find_hold_call(bc);
10017 }
10018
10019 if (!ch) {
10020 ast_log(LOG_WARNING, "NEW_BC without chan_list?\n");
10021 break;
10022 }
10023
10024 if (bc) {
10025 ch->bc = (struct misdn_bchannel *) user_data;
10026 }
10027 break;
10028
10029 case EVENT_DTMF_TONE:
10030 {
10031
10032 struct ast_frame fr;
10033
10034 memset(&fr, 0, sizeof(fr));
10035 fr.frametype = AST_FRAME_DTMF;
10036 fr.subclass.integer = bc->dtmf ;
10037 fr.src = NULL;
10038 fr.data.ptr = NULL;
10039 fr.datalen = 0;
10040 fr.samples = 0;
10041 fr.mallocd = 0;
10042 fr.offset = 0;
10043 fr.delivery = ast_tv(0,0);
10044
10045 if (!ch->ignore_dtmf) {
10046 chan_misdn_log(2, bc->port, " --> DTMF:%c\n", bc->dtmf);
10047 ast_queue_frame(ch->ast, &fr);
10048 } else {
10049 chan_misdn_log(2, bc->port, " --> Ignoring DTMF:%c due to bridge flags\n", bc->dtmf);
10050 }
10051 break;
10052 }
10053 case EVENT_STATUS:
10054 break;
10055
10056 case EVENT_INFORMATION:
10057 if (ch->state != MISDN_CONNECTED) {
10058 stop_indicate(ch);
10059 }
10060
10061 if (!ch->ast) {
10062 break;
10063 }
10064
10065 if (ch->state == MISDN_WAITING4DIGS) {
10066
10067 if (ast_strlen_zero(bc->info_dad) && ! ast_strlen_zero(bc->keypad)) {
10068 chan_misdn_log(1, bc->port, " --> using keypad as info\n");
10069 ast_copy_string(bc->info_dad, bc->keypad, sizeof(bc->info_dad));
10070 }
10071
10072 strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10073 ast_channel_exten_set(ch->ast, bc->dialed.number);
10074
10075
10076 if (!strcmp(ast_channel_exten(ch->ast), ast_pickup_ext())) {
10077 if (ast_pickup_call(ch->ast)) {
10078 hangup_chan(ch, bc);
10079 } else {
10080 ch->state = MISDN_CALLING_ACKNOWLEDGE;
10081 hangup_chan(ch, bc);
10082 ch->ast = NULL;
10083 break;
10084 }
10085 }
10086
10087 if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10088 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10089 ast_log(LOG_WARNING,
10090 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10091 bc->dialed.number, ch->context, bc->port);
10092 pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10093 ast_channel_exten_set(ch->ast, "i");
10094 ch->state = MISDN_DIALING;
10095 start_pbx(ch, bc, ch->ast);
10096 break;
10097 }
10098
10099 ast_log(LOG_WARNING,
10100 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10101 "\tMaybe you want to add an 'i' extension to catch this case.\n",
10102 bc->dialed.number, ch->context, bc->port);
10103
10104 if (bc->nt) {
10105 hanguptone_indicate(ch);
10106 }
10107 ch->state = MISDN_EXTCANTMATCH;
10108 bc->out_cause = AST_CAUSE_UNALLOCATED;
10109
10110 misdn_lib_send_event(bc, EVENT_DISCONNECT);
10111 break;
10112 }
10113
10114 if (ch->overlap_dial) {
10115 ast_mutex_lock(&ch->overlap_tv_lock);
10116 ch->overlap_tv = ast_tvnow();
10117 ast_mutex_unlock(&ch->overlap_tv_lock);
10118 if (ch->overlap_dial_task == -1) {
10119 ch->overlap_dial_task =
10120 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10121 }
10122 break;
10123 }
10124
10125 if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10126 ch->state = MISDN_DIALING;
10127 start_pbx(ch, bc, ch->ast);
10128 }
10129 } else {
10130
10131 struct ast_frame fr;
10132 int digits;
10133
10134 memset(&fr, 0, sizeof(fr));
10135 fr.frametype = AST_FRAME_DTMF;
10136 fr.subclass.integer = bc->info_dad[0] ;
10137 fr.src = NULL;
10138 fr.data.ptr = NULL;
10139 fr.datalen = 0;
10140 fr.samples = 0;
10141 fr.mallocd = 0;
10142 fr.offset = 0;
10143 fr.delivery = ast_tv(0,0);
10144
10145 misdn_cfg_get(0, MISDN_GEN_APPEND_DIGITS2EXTEN, &digits, sizeof(digits));
10146 if (ch->state != MISDN_CONNECTED) {
10147 if (digits) {
10148 strncat(bc->dialed.number, bc->info_dad, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10149 ast_channel_exten_set(ch->ast, bc->dialed.number);
10150 ast_cdr_update(ch->ast);
10151 }
10152
10153 ast_queue_frame(ch->ast, &fr);
10154 }
10155 }
10156 break;
10157 case EVENT_SETUP:
10158 {
10159 struct ast_channel *chan;
10160 int exceed;
10161 int ai;
10162 int im;
10163 int append_msn = 0;
10164
10165 if (ch) {
10166 switch (ch->state) {
10167 case MISDN_NOTHING:
10168 chan_list_unref(ch, "Ignore found ch. Is it for an outgoing call?");
10169 ch = NULL;
10170 break;
10171 default:
10172 chan_list_unref(ch, "Already have a call.");
10173 chan_misdn_log(1, bc->port, " --> Ignoring Call we have already one\n");
10174 return RESPONSE_IGNORE_SETUP_WITHOUT_CLOSE;
10175 }
10176 }
10177
10178 if (!bc->nt && !misdn_is_msn_valid(bc->port, &bc->dialed)) {
10179 chan_misdn_log(1, bc->port, " --> Ignoring Call, its not in our MSN List\n");
10180 return RESPONSE_IGNORE_SETUP;
10181 }
10182
10183 if (bc->cw) {
10184 int cause;
10185 chan_misdn_log(0, bc->port, " --> Call Waiting on PMP sending RELEASE_COMPLETE\n");
10186 misdn_cfg_get(bc->port, MISDN_CFG_REJECT_CAUSE, &cause, sizeof(cause));
10187 bc->out_cause = cause ? cause : AST_CAUSE_NORMAL_CLEARING;
10188 return RESPONSE_RELEASE_SETUP;
10189 }
10190
10191 print_bearer(bc);
10192
10193 ch = chan_list_init(ORG_MISDN);
10194 if (!ch) {
10195 chan_misdn_log(-1, bc->port, "cb_events: malloc for chan_list failed!\n");
10196 return RESPONSE_RELEASE_SETUP;
10197 }
10198
10199 ch->bc = bc;
10200 ch->l3id = bc->l3_id;
10201 ch->addr = bc->addr;
10202
10203 {
10204 struct ast_format_cap *cap = ast_format_cap_alloc_nolock();
10205 struct ast_format tmpfmt;
10206 if (!(cap)) {
10207 return RESPONSE_ERR;
10208 }
10209 ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_ALAW, 0));
10210 chan = misdn_new(ch, AST_STATE_RESERVED, bc->dialed.number, bc->caller.number, cap, NULL, bc->port, bc->channel);
10211 cap = ast_format_cap_destroy(cap);
10212 }
10213 if (!chan) {
10214 chan_list_unref(ch, "Failed to create a new channel");
10215 ast_log(LOG_ERROR, "cb_events: misdn_new failed!\n");
10216 return RESPONSE_RELEASE_SETUP;
10217 }
10218
10219 if ((exceed = add_in_calls(bc->port))) {
10220 char tmp[16];
10221 snprintf(tmp, sizeof(tmp), "%d", exceed);
10222 pbx_builtin_setvar_helper(chan, "MAX_OVERFLOW", tmp);
10223 }
10224
10225 read_config(ch);
10226
10227 export_ch(chan, bc, ch);
10228
10229 ast_channel_rings_set(ch->ast, 1);
10230 ast_setstate(ch->ast, AST_STATE_RINGING);
10231
10232
10233 chan_misdn_log(2, bc->port, " --> TON: %s(%d)\n", misdn_to_str_ton(bc->caller.number_type), bc->caller.number_type);
10234 chan_misdn_log(2, bc->port, " --> PLAN: %s(%d)\n", misdn_to_str_plan(bc->caller.number_plan), bc->caller.number_plan);
10235 ast_channel_caller(chan)->id.number.plan = misdn_to_ast_ton(bc->caller.number_type)
10236 | misdn_to_ast_plan(bc->caller.number_plan);
10237
10238 chan_misdn_log(2, bc->port, " --> PRES: %s(%d)\n", misdn_to_str_pres(bc->caller.presentation), bc->caller.presentation);
10239 chan_misdn_log(2, bc->port, " --> SCREEN: %s(%d)\n", misdn_to_str_screen(bc->caller.screening), bc->caller.screening);
10240 ast_channel_caller(chan)->id.number.presentation = misdn_to_ast_pres(bc->caller.presentation)
10241 | misdn_to_ast_screen(bc->caller.screening);
10242
10243 ast_set_callerid(chan, bc->caller.number, NULL, bc->caller.number);
10244
10245 misdn_cfg_get(bc->port, MISDN_CFG_APPEND_MSN_TO_CALLERID_TAG, &append_msn, sizeof(append_msn));
10246 if (append_msn) {
10247 strncat(bc->incoming_cid_tag, "_", sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10248 strncat(bc->incoming_cid_tag, bc->dialed.number, sizeof(bc->incoming_cid_tag) - strlen(bc->incoming_cid_tag) - 1);
10249 }
10250
10251 ast_channel_lock(chan);
10252 ast_channel_caller(chan)->id.tag = ast_strdup(bc->incoming_cid_tag);
10253 ast_channel_unlock(chan);
10254
10255 if (!ast_strlen_zero(bc->redirecting.from.number)) {
10256
10257 misdn_add_number_prefix(bc->port, bc->redirecting.from.number_type, bc->redirecting.from.number, sizeof(bc->redirecting.from.number));
10258
10259
10260 misdn_copy_redirecting_to_ast(chan, &bc->redirecting, bc->incoming_cid_tag);
10261 }
10262
10263 pbx_builtin_setvar_helper(chan, "TRANSFERCAPABILITY", ast_transfercapability2str(bc->capability));
10264 ast_channel_transfercapability_set(chan, bc->capability);
10265
10266 switch (bc->capability) {
10267 case INFO_CAPABILITY_DIGITAL_UNRESTRICTED:
10268 pbx_builtin_setvar_helper(chan, "CALLTYPE", "DIGITAL");
10269 break;
10270 default:
10271 pbx_builtin_setvar_helper(chan, "CALLTYPE", "SPEECH");
10272 break;
10273 }
10274
10275 if (!strstr(ch->allowed_bearers, "all")) {
10276 int i;
10277
10278 for (i = 0; i < ARRAY_LEN(allowed_bearers_array); ++i) {
10279 if (allowed_bearers_array[i].cap == bc->capability) {
10280 if (strstr(ch->allowed_bearers, allowed_bearers_array[i].name)) {
10281
10282 if (allowed_bearers_array[i].deprecated) {
10283 chan_misdn_log(0, bc->port, "%s in allowed_bearers list is deprecated\n",
10284 allowed_bearers_array[i].name);
10285 }
10286 break;
10287 }
10288 }
10289 }
10290 if (i == ARRAY_LEN(allowed_bearers_array)) {
10291
10292 chan_misdn_log(0, bc->port, "Bearer capability not allowed: %s(%d)\n",
10293 bearer2str(bc->capability), bc->capability);
10294
10295 ch->state = MISDN_EXTCANTMATCH;
10296 chan_list_unref(ch, "BC not allowed, releasing call");
10297 bc->out_cause = AST_CAUSE_INCOMPATIBLE_DESTINATION;
10298 return RESPONSE_RELEASE_SETUP;
10299 }
10300 }
10301
10302
10303 cl_queue_chan(ch);
10304
10305 if (bc->fac_in.Function != Fac_None) {
10306 misdn_facility_ie_handler(event, bc, ch);
10307 }
10308
10309
10310 if (!strcmp(ast_channel_exten(chan), ast_pickup_ext())) {
10311 if (!ch->noautorespond_on_setup) {
10312
10313 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10314 } else {
10315 ch->state = MISDN_INCOMING_SETUP;
10316 }
10317 if (ast_pickup_call(chan)) {
10318 hangup_chan(ch, bc);
10319 } else {
10320 ch->state = MISDN_CALLING_ACKNOWLEDGE;
10321 hangup_chan(ch, bc);
10322 ch->ast = NULL;
10323 break;
10324 }
10325 }
10326
10327
10328
10329
10330
10331 misdn_cfg_get(bc->port, MISDN_CFG_ALWAYS_IMMEDIATE, &ai, sizeof(ai));
10332 if (ai) {
10333 do_immediate_setup(bc, ch, chan);
10334 break;
10335 }
10336
10337
10338 misdn_cfg_get(bc->port, MISDN_CFG_IMMEDIATE, &im, sizeof(im));
10339 if (im && ast_strlen_zero(bc->dialed.number)) {
10340 do_immediate_setup(bc, ch, chan);
10341 break;
10342 }
10343
10344 chan_misdn_log(5, bc->port, "CONTEXT:%s\n", ch->context);
10345 if (!ast_canmatch_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10346 if (ast_exists_extension(ch->ast, ch->context, "i", 1, bc->caller.number)) {
10347 ast_log(LOG_WARNING,
10348 "Extension '%s@%s' can never match. Jumping to 'i' extension. port:%d\n",
10349 bc->dialed.number, ch->context, bc->port);
10350 pbx_builtin_setvar_helper(ch->ast, "INVALID_EXTEN", bc->dialed.number);
10351 ast_channel_exten_set(ch->ast, "i");
10352 misdn_lib_send_event(bc, EVENT_SETUP_ACKNOWLEDGE);
10353 ch->state = MISDN_DIALING;
10354 start_pbx(ch, bc, chan);
10355 break;
10356 }
10357
10358 ast_log(LOG_WARNING,
10359 "Extension '%s@%s' can never match. Disconnecting. port:%d\n"
10360 "\tMaybe you want to add an 'i' extension to catch this case.\n",
10361 bc->dialed.number, ch->context, bc->port);
10362 if (bc->nt) {
10363 hanguptone_indicate(ch);
10364 }
10365
10366 ch->state = MISDN_EXTCANTMATCH;
10367 bc->out_cause = AST_CAUSE_UNALLOCATED;
10368
10369 misdn_lib_send_event(bc, bc->nt ? EVENT_RELEASE_COMPLETE : EVENT_RELEASE);
10370 break;
10371 }
10372
10373
10374
10375
10376 if (bc->sending_complete || (!bc->nt && !misdn_lib_is_ptp(bc->port))) {
10377 if (!ch->noautorespond_on_setup) {
10378 ch->state=MISDN_DIALING;
10379 misdn_lib_send_event(bc, EVENT_PROCEEDING);
10380 } else {
10381 ch->state = MISDN_INCOMING_SETUP;
10382 }
10383 start_pbx(ch, bc, chan);
10384 break;
10385 }
10386
10387
10388
10389
10390
10391
10392
10393 if (ch->overlap_dial && bc->nt && !bc->dialed.number[0]) {
10394 wait_for_digits(ch, bc, chan);
10395 break;
10396 }
10397
10398
10399
10400
10401
10402 if (ch->overlap_dial) {
10403 ast_mutex_lock(&ch->overlap_tv_lock);
10404 ch->overlap_tv = ast_tvnow();
10405 ast_mutex_unlock(&ch->overlap_tv_lock);
10406
10407 wait_for_digits(ch, bc, chan);
10408 if (ch->overlap_dial_task == -1) {
10409 ch->overlap_dial_task =
10410 misdn_tasks_add_variable(ch->overlap_dial, misdn_overlap_dial_task, ch);
10411 }
10412 break;
10413 }
10414
10415
10416
10417
10418 if (!ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10419 wait_for_digits(ch, bc, chan);
10420 break;
10421 }
10422
10423
10424
10425
10426 if (ast_exists_extension(ch->ast, ch->context, bc->dialed.number, 1, bc->caller.number)) {
10427 misdn_lib_send_event(bc, bc->need_more_infos ? EVENT_SETUP_ACKNOWLEDGE : EVENT_PROCEEDING);
10428 ch->state = MISDN_DIALING;
10429 start_pbx(ch, bc, chan);
10430 break;
10431 }
10432 break;
10433 }
10434 #if defined(AST_MISDN_ENHANCEMENTS)
10435 case EVENT_REGISTER:
10436 if (bc->fac_in.Function != Fac_None) {
10437 misdn_facility_ie_handler(event, bc, ch);
10438 }
10439
10440
10441
10442
10443
10444
10445
10446 bc->fac_out.Function = Fac_None;
10447 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10448 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10449 break;
10450 #endif
10451 case EVENT_SETUP_ACKNOWLEDGE:
10452 ch->state = MISDN_CALLING_ACKNOWLEDGE;
10453
10454 if (bc->channel) {
10455 update_name(ch->ast,bc->port,bc->channel);
10456 }
10457
10458 if (bc->fac_in.Function != Fac_None) {
10459 misdn_facility_ie_handler(event, bc, ch);
10460 }
10461
10462 if (!ast_strlen_zero(bc->infos_pending)) {
10463
10464 strncat(bc->dialed.number, bc->infos_pending, sizeof(bc->dialed.number) - strlen(bc->dialed.number) - 1);
10465
10466 if (!ch->ast) {
10467 break;
10468 }
10469 ast_channel_exten_set(ch->ast, bc->dialed.number);
10470 ast_copy_string(bc->info_dad, bc->infos_pending, sizeof(bc->info_dad));
10471 ast_copy_string(bc->infos_pending, "", sizeof(bc->infos_pending));
10472
10473 misdn_lib_send_event(bc, EVENT_INFORMATION);
10474 }
10475 break;
10476 case EVENT_PROCEEDING:
10477 if (misdn_cap_is_speech(bc->capability) &&
10478 misdn_inband_avail(bc)) {
10479 start_bc_tones(ch);
10480 }
10481
10482 ch->state = MISDN_PROCEEDING;
10483
10484 if (bc->fac_in.Function != Fac_None) {
10485 misdn_facility_ie_handler(event, bc, ch);
10486 }
10487
10488 if (!ch->ast) {
10489 break;
10490 }
10491
10492 ast_queue_control(ch->ast, AST_CONTROL_PROCEEDING);
10493 break;
10494 case EVENT_PROGRESS:
10495 if (bc->channel) {
10496 update_name(ch->ast, bc->port, bc->channel);
10497 }
10498
10499 if (bc->fac_in.Function != Fac_None) {
10500 misdn_facility_ie_handler(event, bc, ch);
10501 }
10502
10503 if (!bc->nt) {
10504 if (misdn_cap_is_speech(bc->capability) &&
10505 misdn_inband_avail(bc)) {
10506 start_bc_tones(ch);
10507 }
10508
10509 ch->state = MISDN_PROGRESS;
10510
10511 if (!ch->ast) {
10512 break;
10513 }
10514 ast_queue_control(ch->ast, AST_CONTROL_PROGRESS);
10515 }
10516 break;
10517 case EVENT_ALERTING:
10518 ch->state = MISDN_ALERTING;
10519
10520 if (!ch->ast) {
10521 break;
10522 }
10523
10524 if (bc->fac_in.Function != Fac_None) {
10525 misdn_facility_ie_handler(event, bc, ch);
10526 }
10527
10528 ast_queue_control(ch->ast, AST_CONTROL_RINGING);
10529 ast_setstate(ch->ast, AST_STATE_RINGING);
10530
10531 cb_log(7, bc->port, " --> Set State Ringing\n");
10532
10533 if (misdn_cap_is_speech(bc->capability) && misdn_inband_avail(bc)) {
10534 cb_log(1, bc->port, "Starting Tones, we have inband Data\n");
10535 start_bc_tones(ch);
10536 } else {
10537 cb_log(3, bc->port, " --> We have no inband Data, the other end must create ringing\n");
10538 if (ch->far_alerting) {
10539 cb_log(1, bc->port, " --> The other end can not do ringing eh ?.. we must do all ourself..");
10540 start_bc_tones(ch);
10541
10542 }
10543 }
10544 break;
10545 case EVENT_CONNECT:
10546 if (bc->fac_in.Function != Fac_None) {
10547 misdn_facility_ie_handler(event, bc, ch);
10548 }
10549 #if defined(AST_MISDN_ENHANCEMENTS)
10550 if (bc->div_leg_3_rx_wanted) {
10551 bc->div_leg_3_rx_wanted = 0;
10552
10553 if (ch->ast) {
10554 struct ast_party_redirecting redirecting;
10555
10556 ast_channel_redirecting(ch->ast)->to.number.presentation =
10557 AST_PRES_RESTRICTED | AST_PRES_USER_NUMBER_UNSCREENED;
10558 ast_party_redirecting_init(&redirecting);
10559 ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
10560
10561
10562
10563
10564
10565 ast_party_id_reset(&redirecting.priv_orig);
10566 ast_party_id_reset(&redirecting.priv_from);
10567 ast_party_id_reset(&redirecting.priv_to);
10568
10569 ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
10570 ast_party_redirecting_free(&redirecting);
10571 }
10572 }
10573 #endif
10574
10575
10576 misdn_lib_send_event(bc, EVENT_CONNECT_ACKNOWLEDGE);
10577
10578 if (!ch->ast) {
10579 break;
10580 }
10581
10582 stop_indicate(ch);
10583
10584 #if defined(AST_MISDN_ENHANCEMENTS)
10585 if (ch->record_id != -1) {
10586
10587
10588
10589
10590
10591
10592 AST_LIST_LOCK(&misdn_cc_records_db);
10593 cc_record = misdn_cc_find_by_id(ch->record_id);
10594 if (cc_record) {
10595 if (cc_record->ptp && cc_record->mode.ptp.bc) {
10596
10597 cc_record->mode.ptp.bc->fac_out.Function = Fac_None;
10598 cc_record->mode.ptp.bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10599 misdn_lib_send_event(cc_record->mode.ptp.bc, EVENT_RELEASE_COMPLETE);
10600 }
10601 misdn_cc_delete(cc_record);
10602 }
10603 AST_LIST_UNLOCK(&misdn_cc_records_db);
10604 ch->record_id = -1;
10605 if (ch->peer) {
10606 misdn_cc_set_peer_var(ch->peer, MISDN_CC_RECORD_ID, "");
10607
10608 ao2_ref(ch->peer, -1);
10609 ch->peer = NULL;
10610 }
10611 }
10612 #endif
10613
10614 if (!ast_strlen_zero(bc->connected.number)) {
10615
10616 misdn_add_number_prefix(bc->port, bc->connected.number_type, bc->connected.number, sizeof(bc->connected.number));
10617
10618
10619 misdn_update_remote_party(ch->ast, &bc->connected, AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER, bc->incoming_cid_tag);
10620 }
10621
10622 ch->l3id = bc->l3_id;
10623 ch->addr = bc->addr;
10624
10625 start_bc_tones(ch);
10626
10627 ch->state = MISDN_CONNECTED;
10628
10629 ast_queue_control(ch->ast, AST_CONTROL_ANSWER);
10630 break;
10631 case EVENT_CONNECT_ACKNOWLEDGE:
10632 ch->l3id = bc->l3_id;
10633 ch->addr = bc->addr;
10634
10635 start_bc_tones(ch);
10636
10637 ch->state = MISDN_CONNECTED;
10638 break;
10639 case EVENT_DISCONNECT:
10640
10641 if (ch) {
10642 if (bc->fac_in.Function != Fac_None) {
10643 misdn_facility_ie_handler(event, bc, ch);
10644 }
10645
10646 chan_misdn_log(3, bc->port, " --> org:%d nt:%d, inbandavail:%d state:%d\n", ch->originator, bc->nt, misdn_inband_avail(bc), ch->state);
10647 if (ch->originator == ORG_AST && !bc->nt && misdn_inband_avail(bc) && ch->state != MISDN_CONNECTED) {
10648
10649
10650
10651
10652
10653 chan_misdn_log(1, bc->port, " --> Inband Info Avail, not sending RELEASE\n");
10654
10655 ch->state = MISDN_DISCONNECTED;
10656 start_bc_tones(ch);
10657
10658 if (ch->ast) {
10659 ast_channel_hangupcause_set(ch->ast, bc->cause);
10660 if (bc->cause == AST_CAUSE_USER_BUSY) {
10661 ast_queue_control(ch->ast, AST_CONTROL_BUSY);
10662 }
10663 }
10664 ch->need_busy = 0;
10665 break;
10666 }
10667
10668 bc->need_disconnect = 0;
10669 stop_bc_tones(ch);
10670
10671
10672 held_ch = find_hold_call(bc);
10673 if (!held_ch || !ch->ast || misdn_attempt_transfer(ch, held_ch)) {
10674 hangup_chan(ch, bc);
10675 }
10676 } else {
10677 held_ch = find_hold_call_l3(bc->l3_id);
10678 if (held_ch) {
10679 if (bc->fac_in.Function != Fac_None) {
10680 misdn_facility_ie_handler(event, bc, held_ch);
10681 }
10682
10683 if (held_ch->hold.state == MISDN_HOLD_ACTIVE) {
10684 bc->need_disconnect = 0;
10685
10686 #if defined(TRANSFER_ON_HELD_CALL_HANGUP)
10687
10688
10689
10690
10691
10692 ch = find_hold_active_call(bc);
10693 if (!ch || misdn_attempt_transfer(ch, held_ch)) {
10694 held_ch->hold.state = MISDN_HOLD_DISCONNECT;
10695 hangup_chan(held_ch, bc);
10696 }
10697 #else
10698 hangup_chan(held_ch, bc);
10699 #endif
10700 }
10701 }
10702 }
10703 if (held_ch) {
10704 chan_list_unref(held_ch, "Done with held call");
10705 }
10706 bc->out_cause = -1;
10707 if (bc->need_release) {
10708 misdn_lib_send_event(bc, EVENT_RELEASE);
10709 }
10710 break;
10711 case EVENT_RELEASE:
10712 if (!ch) {
10713 ch = find_hold_call_l3(bc->l3_id);
10714 if (!ch) {
10715 chan_misdn_log(1, bc->port,
10716 " --> no Ch, so we've already released. (%s)\n",
10717 manager_isdn_get_info(event));
10718 return -1;
10719 }
10720 }
10721 if (bc->fac_in.Function != Fac_None) {
10722 misdn_facility_ie_handler(event, bc, ch);
10723 }
10724
10725 bc->need_disconnect = 0;
10726 bc->need_release = 0;
10727
10728 hangup_chan(ch, bc);
10729 release_chan(ch, bc);
10730 break;
10731 case EVENT_RELEASE_COMPLETE:
10732 if (!ch) {
10733 ch = find_hold_call_l3(bc->l3_id);
10734 }
10735
10736 bc->need_disconnect = 0;
10737 bc->need_release = 0;
10738 bc->need_release_complete = 0;
10739
10740 if (ch) {
10741 if (bc->fac_in.Function != Fac_None) {
10742 misdn_facility_ie_handler(event, bc, ch);
10743 }
10744
10745 stop_bc_tones(ch);
10746 hangup_chan(ch, bc);
10747 release_chan(ch, bc);
10748 } else {
10749 #if defined(AST_MISDN_ENHANCEMENTS)
10750
10751
10752
10753
10754
10755 AST_LIST_LOCK(&misdn_cc_records_db);
10756 cc_record = misdn_cc_find_by_bc(bc);
10757 if (cc_record) {
10758
10759 misdn_cc_delete(cc_record);
10760 }
10761 AST_LIST_UNLOCK(&misdn_cc_records_db);
10762 #endif
10763
10764 chan_misdn_log(1, bc->port,
10765 " --> no Ch, so we've already released. (%s)\n",
10766 manager_isdn_get_info(event));
10767 }
10768 break;
10769 case EVENT_BCHAN_ERROR:
10770 case EVENT_CLEANUP:
10771 stop_bc_tones(ch);
10772
10773 switch (ch->state) {
10774 case MISDN_CALLING:
10775 bc->cause = AST_CAUSE_DESTINATION_OUT_OF_ORDER;
10776 break;
10777 default:
10778 break;
10779 }
10780
10781 hangup_chan(ch, bc);
10782 release_chan(ch, bc);
10783 break;
10784 case EVENT_TONE_GENERATE:
10785 {
10786 int tone_len = bc->tone_cnt;
10787 struct ast_channel *ast = ch->ast;
10788 void *tmp;
10789 int res;
10790 int (*generate)(struct ast_channel *chan, void *tmp, int datalen, int samples);
10791
10792 chan_misdn_log(9, bc->port, "TONE_GEN: len:%d\n", tone_len);
10793
10794 if (!ast) {
10795 break;
10796 }
10797
10798 if (!ast_channel_generator(ast)) {
10799 break;
10800 }
10801
10802 tmp = ast_channel_generatordata(ast);
10803 ast_channel_generatordata_set(ast, NULL);
10804 generate = ast_channel_generator(ast)->generate;
10805
10806 if (tone_len < 0 || tone_len > 512) {
10807 ast_log(LOG_NOTICE, "TONE_GEN: len was %d, set to 128\n", tone_len);
10808 tone_len = 128;
10809 }
10810
10811 res = generate(ast, tmp, tone_len, tone_len);
10812 ast_channel_generatordata_set(ast, tmp);
10813
10814 if (res) {
10815 ast_log(LOG_WARNING, "Auto-deactivating generator\n");
10816 ast_deactivate_generator(ast);
10817 } else {
10818 bc->tone_cnt = 0;
10819 }
10820 break;
10821 }
10822 case EVENT_BCHAN_DATA:
10823 if (ch->bc->AOCD_need_export) {
10824 export_aoc_vars(ch->originator, ch->ast, ch->bc);
10825 }
10826 if (!misdn_cap_is_speech(ch->bc->capability)) {
10827 struct ast_frame frame;
10828
10829
10830 memset(&frame, 0, sizeof(frame));
10831 frame.frametype = AST_FRAME_VOICE;
10832 ast_format_set(&frame.subclass.format, AST_FORMAT_ALAW, 0);
10833 frame.datalen = bc->bframe_len;
10834 frame.samples = bc->bframe_len;
10835 frame.mallocd = 0;
10836 frame.offset = 0;
10837 frame.delivery = ast_tv(0, 0);
10838 frame.src = NULL;
10839 frame.data.ptr = bc->bframe;
10840
10841 if (ch->ast) {
10842 ast_queue_frame(ch->ast, &frame);
10843 }
10844 } else {
10845 struct pollfd pfd = { .fd = ch->pipe[1], .events = POLLOUT };
10846 int t;
10847
10848 t = ast_poll(&pfd, 1, 0);
10849
10850 if (t < 0) {
10851 chan_misdn_log(-1, bc->port, "poll() error (err=%s)\n", strerror(errno));
10852 break;
10853 }
10854 if (!t) {
10855 chan_misdn_log(9, bc->port, "poll() timed out\n");
10856 break;
10857 }
10858
10859 if (pfd.revents & POLLOUT) {
10860 chan_misdn_log(9, bc->port, "writing %d bytes to asterisk\n", bc->bframe_len);
10861 if (write(ch->pipe[1], bc->bframe, bc->bframe_len) <= 0) {
10862 chan_misdn_log(0, bc->port, "Write returned <=0 (err=%s) --> hanging up channel\n", strerror(errno));
10863
10864 stop_bc_tones(ch);
10865 hangup_chan(ch, bc);
10866 release_chan(ch, bc);
10867 }
10868 } else {
10869 chan_misdn_log(1, bc->port, "Write Pipe full!\n");
10870 }
10871 }
10872 break;
10873 case EVENT_TIMEOUT:
10874 if (ch && bc) {
10875 chan_misdn_log(1, bc->port, "--> state: %s\n", misdn_get_ch_state(ch));
10876 }
10877
10878 switch (ch->state) {
10879 case MISDN_DIALING:
10880 case MISDN_PROGRESS:
10881 if (bc->nt && !ch->nttimeout) {
10882 break;
10883 }
10884
10885 case MISDN_CALLING:
10886 case MISDN_ALERTING:
10887 case MISDN_PROCEEDING:
10888 case MISDN_CALLING_ACKNOWLEDGE:
10889 if (bc->nt) {
10890 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10891 hanguptone_indicate(ch);
10892 }
10893
10894 bc->out_cause = AST_CAUSE_UNALLOCATED;
10895 misdn_lib_send_event(bc, EVENT_DISCONNECT);
10896 break;
10897 case MISDN_WAITING4DIGS:
10898 if (bc->nt) {
10899 bc->progress_indicator = INFO_PI_INBAND_AVAILABLE;
10900 bc->out_cause = AST_CAUSE_UNALLOCATED;
10901 hanguptone_indicate(ch);
10902 misdn_lib_send_event(bc, EVENT_DISCONNECT);
10903 } else {
10904 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
10905 misdn_lib_send_event(bc, EVENT_RELEASE);
10906 }
10907 break;
10908 case MISDN_CLEANING:
10909 chan_misdn_log(1, bc->port, " --> in state cleaning .. so ignoring, the stack should clean it for us\n");
10910 break;
10911 default:
10912 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
10913 break;
10914 }
10915 break;
10916
10917
10918
10919
10920 case EVENT_RETRIEVE:
10921 if (!ch) {
10922 chan_misdn_log(4, bc->port, " --> no CH, searching for held call\n");
10923 ch = find_hold_call_l3(bc->l3_id);
10924 if (!ch || ch->hold.state != MISDN_HOLD_ACTIVE) {
10925 ast_log(LOG_WARNING, "No held call found, cannot Retrieve\n");
10926 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10927 break;
10928 }
10929 }
10930
10931
10932 ch->bc = bc;
10933
10934 ch->hold.state = MISDN_HOLD_IDLE;
10935 ch->hold.port = 0;
10936 ch->hold.channel = 0;
10937
10938 ast_queue_control(ch->ast, AST_CONTROL_UNHOLD);
10939
10940 if (misdn_lib_send_event(bc, EVENT_RETRIEVE_ACKNOWLEDGE) < 0) {
10941 chan_misdn_log(4, bc->port, " --> RETRIEVE_ACK failed\n");
10942 misdn_lib_send_event(bc, EVENT_RETRIEVE_REJECT);
10943 }
10944 break;
10945 case EVENT_HOLD:
10946 {
10947 int hold_allowed;
10948 struct ast_channel *bridged;
10949
10950 misdn_cfg_get(bc->port, MISDN_CFG_HOLD_ALLOWED, &hold_allowed, sizeof(hold_allowed));
10951 if (!hold_allowed) {
10952 chan_misdn_log(-1, bc->port, "Hold not allowed this port.\n");
10953 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
10954 break;
10955 }
10956
10957 bridged = ast_bridged_channel(ch->ast);
10958 if (bridged) {
10959 chan_misdn_log(2, bc->port, "Bridge Partner is of type: %s\n", ast_channel_tech(bridged)->type);
10960 ch->l3id = bc->l3_id;
10961
10962
10963 ch->bc = NULL;
10964 ch->hold.state = MISDN_HOLD_ACTIVE;
10965 ch->hold.port = bc->port;
10966 ch->hold.channel = bc->channel;
10967
10968 ast_queue_control(ch->ast, AST_CONTROL_HOLD);
10969
10970 misdn_lib_send_event(bc, EVENT_HOLD_ACKNOWLEDGE);
10971 } else {
10972 misdn_lib_send_event(bc, EVENT_HOLD_REJECT);
10973 chan_misdn_log(0, bc->port, "We aren't bridged to anybody\n");
10974 }
10975 break;
10976 }
10977 case EVENT_NOTIFY:
10978 if (bc->redirecting.to_changed) {
10979
10980 misdn_add_number_prefix(bc->port, bc->redirecting.to.number_type,
10981 bc->redirecting.to.number, sizeof(bc->redirecting.to.number));
10982 }
10983 switch (bc->notify_description_code) {
10984 case mISDN_NOTIFY_CODE_DIVERSION_ACTIVATED:
10985
10986 bc->redirecting.to_changed = 0;
10987 break;
10988 case mISDN_NOTIFY_CODE_CALL_IS_DIVERTING:
10989 {
10990 struct ast_party_redirecting redirecting;
10991
10992 if (!bc->redirecting.to_changed) {
10993 break;
10994 }
10995 bc->redirecting.to_changed = 0;
10996 if (!ch || !ch->ast) {
10997 break;
10998 }
10999 switch (ch->state) {
11000 case MISDN_ALERTING:
11001
11002 bc->redirecting.reason = mISDN_REDIRECTING_REASON_NO_REPLY;
11003 break;
11004 default:
11005
11006 bc->redirecting.reason = mISDN_REDIRECTING_REASON_UNKNOWN;
11007 break;
11008 }
11009 misdn_copy_redirecting_to_ast(ch->ast, &bc->redirecting, bc->incoming_cid_tag);
11010 ast_party_redirecting_init(&redirecting);
11011 ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(ch->ast));
11012
11013
11014
11015
11016
11017 ast_party_id_reset(&redirecting.priv_orig);
11018 ast_party_id_reset(&redirecting.priv_from);
11019 ast_party_id_reset(&redirecting.priv_to);
11020
11021 ast_channel_queue_redirecting_update(ch->ast, &redirecting, NULL);
11022 ast_party_redirecting_free(&redirecting);
11023 break;
11024 }
11025 case mISDN_NOTIFY_CODE_CALL_TRANSFER_ALERTING:
11026
11027
11028
11029
11030
11031
11032
11033
11034
11035 if (!bc->redirecting.to_changed) {
11036 break;
11037 }
11038 bc->redirecting.to_changed = 0;
11039 if (!ch || !ch->ast) {
11040 break;
11041 }
11042 misdn_update_remote_party(ch->ast, &bc->redirecting.to,
11043 AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER_ALERTING,
11044 bc->incoming_cid_tag);
11045 break;
11046 case mISDN_NOTIFY_CODE_CALL_TRANSFER_ACTIVE:
11047 if (!bc->redirecting.to_changed) {
11048 break;
11049 }
11050 bc->redirecting.to_changed = 0;
11051 if (!ch || !ch->ast) {
11052 break;
11053 }
11054 misdn_update_remote_party(ch->ast, &bc->redirecting.to,
11055 AST_CONNECTED_LINE_UPDATE_SOURCE_TRANSFER, bc->incoming_cid_tag);
11056 break;
11057 default:
11058 bc->redirecting.to_changed = 0;
11059 chan_misdn_log(0, bc->port," --> not yet handled: notify code:0x%02X\n",
11060 bc->notify_description_code);
11061 break;
11062 }
11063 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
11064 break;
11065 case EVENT_FACILITY:
11066 if (bc->fac_in.Function == Fac_None) {
11067
11068 chan_misdn_log(0, bc->port," --> Missing facility ie or unknown facility ie contents.\n");
11069 } else {
11070 misdn_facility_ie_handler(event, bc, ch);
11071 }
11072
11073
11074 bc->redirecting.to_changed = 0;
11075 bc->notify_description_code = mISDN_NOTIFY_CODE_INVALID;
11076 break;
11077 case EVENT_RESTART:
11078 if (!bc->dummy) {
11079 stop_bc_tones(ch);
11080 release_chan(ch, bc);
11081 }
11082 break;
11083 default:
11084 chan_misdn_log(1, 0, "Got Unknown Event\n");
11085 break;
11086 }
11087
11088 if (ch) {
11089 chan_list_unref(ch, "cb_event complete OK");
11090 }
11091 return RESPONSE_OK;
11092 }
11093
11094
11095
11096 #if defined(AST_MISDN_ENHANCEMENTS)
11097
11098
11099
11100
11101
11102
11103
11104
11105
11106
11107
11108
11109
11110 static int misdn_cc_read(struct ast_channel *chan, const char *function_name,
11111 char *function_args, char *buf, size_t size)
11112 {
11113 char *parse;
11114 struct misdn_cc_record *cc_record;
11115
11116 AST_DECLARE_APP_ARGS(args,
11117 AST_APP_ARG(cc_id);
11118 AST_APP_ARG(get_name);
11119 AST_APP_ARG(other);
11120 );
11121
11122
11123 *buf = 0;
11124
11125 if (ast_strlen_zero(function_args)) {
11126 ast_log(LOG_ERROR, "Function '%s' requires arguments.\n", function_name);
11127 return -1;
11128 }
11129
11130 parse = ast_strdupa(function_args);
11131 AST_STANDARD_APP_ARGS(args, parse);
11132
11133 if (!args.argc || ast_strlen_zero(args.cc_id)) {
11134 ast_log(LOG_ERROR, "Function '%s' missing call completion record ID.\n",
11135 function_name);
11136 return -1;
11137 }
11138 if (!isdigit(*args.cc_id)) {
11139 ast_log(LOG_ERROR, "Function '%s' call completion record ID must be numeric.\n",
11140 function_name);
11141 return -1;
11142 }
11143
11144 if (ast_strlen_zero(args.get_name)) {
11145 ast_log(LOG_ERROR, "Function '%s' missing what-to-get parameter.\n",
11146 function_name);
11147 return -1;
11148 }
11149
11150 AST_LIST_LOCK(&misdn_cc_records_db);
11151 cc_record = misdn_cc_find_by_id(atoi(args.cc_id));
11152 if (cc_record) {
11153 if (!strcasecmp("a-all", args.get_name)) {
11154 snprintf(buf, size, "\"%s\" <%s>", cc_record->redial.caller.name,
11155 cc_record->redial.caller.number);
11156 } else if (!strcasecmp("a-name", args.get_name)) {
11157 ast_copy_string(buf, cc_record->redial.caller.name, size);
11158 } else if (!strncasecmp("a-num", args.get_name, 5)) {
11159 ast_copy_string(buf, cc_record->redial.caller.number, size);
11160 } else if (!strcasecmp("a-ton", args.get_name)) {
11161 snprintf(buf, size, "%d",
11162 misdn_to_ast_plan(cc_record->redial.caller.number_plan)
11163 | misdn_to_ast_ton(cc_record->redial.caller.number_type));
11164 } else if (!strncasecmp("a-pres", args.get_name, 6)) {
11165 ast_copy_string(buf, ast_named_caller_presentation(
11166 misdn_to_ast_pres(cc_record->redial.caller.presentation)
11167 | misdn_to_ast_screen(cc_record->redial.caller.screening)), size);
11168 } else if (!strcasecmp("a-busy", args.get_name)) {
11169 ast_copy_string(buf, cc_record->party_a_free ? "no" : "yes", size);
11170 } else if (!strncasecmp("b-num", args.get_name, 5)) {
11171 ast_copy_string(buf, cc_record->redial.dialed.number, size);
11172 } else if (!strcasecmp("b-ton", args.get_name)) {
11173 snprintf(buf, size, "%d",
11174 misdn_to_ast_plan(cc_record->redial.dialed.number_plan)
11175 | misdn_to_ast_ton(cc_record->redial.dialed.number_type));
11176 } else if (!strcasecmp("port", args.get_name)) {
11177 snprintf(buf, size, "%d", cc_record->port);
11178 } else if (!strcasecmp("available-notify-priority", args.get_name)) {
11179 snprintf(buf, size, "%d", cc_record->remote_user_free.priority);
11180 } else if (!strcasecmp("available-notify-exten", args.get_name)) {
11181 ast_copy_string(buf, cc_record->remote_user_free.exten, size);
11182 } else if (!strcasecmp("available-notify-context", args.get_name)) {
11183 ast_copy_string(buf, cc_record->remote_user_free.context, size);
11184 } else if (!strcasecmp("busy-notify-priority", args.get_name)) {
11185 snprintf(buf, size, "%d", cc_record->b_free.priority);
11186 } else if (!strcasecmp("busy-notify-exten", args.get_name)) {
11187 ast_copy_string(buf, cc_record->b_free.exten, size);
11188 } else if (!strcasecmp("busy-notify-context", args.get_name)) {
11189 ast_copy_string(buf, cc_record->b_free.context, size);
11190 } else {
11191 AST_LIST_UNLOCK(&misdn_cc_records_db);
11192 ast_log(LOG_ERROR, "Function '%s': Unknown what-to-get '%s'.\n", function_name, args.get_name);
11193 return -1;
11194 }
11195 }
11196 AST_LIST_UNLOCK(&misdn_cc_records_db);
11197
11198 return 0;
11199 }
11200 #endif
11201
11202 #if defined(AST_MISDN_ENHANCEMENTS)
11203 static struct ast_custom_function misdn_cc_function = {
11204 .name = "mISDN_CC",
11205 .synopsis = "Get call completion record information.",
11206 .syntax = "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)",
11207 .desc =
11208 "mISDN_CC(${MISDN_CC_RECORD_ID},<what-to-get>)\n"
11209 "The following can be retrieved:\n"
11210 "\"a-num\", \"a-name\", \"a-all\", \"a-ton\", \"a-pres\", \"a-busy\",\n"
11211 "\"b-num\", \"b-ton\", \"port\",\n"
11212 " User-A is available for call completion:\n"
11213 " \"available-notify-priority\",\n"
11214 " \"available-notify-exten\",\n"
11215 " \"available-notify-context\",\n"
11216 " User-A is busy:\n"
11217 " \"busy-notify-priority\",\n"
11218 " \"busy-notify-exten\",\n"
11219 " \"busy-notify-context\"\n",
11220 .read = misdn_cc_read,
11221 };
11222 #endif
11223
11224
11225
11226
11227
11228
11229
11230
11231
11232
11233 static int unload_module(void)
11234 {
11235
11236 ast_verb(0, "-- Unregistering mISDN Channel Driver --\n");
11237
11238 misdn_tasks_destroy();
11239
11240 if (!g_config_initialized) {
11241 return 0;
11242 }
11243
11244 ast_cli_unregister_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11245
11246
11247 ast_unregister_application("misdn_set_opt");
11248 ast_unregister_application("misdn_facility");
11249 ast_unregister_application("misdn_check_l2l1");
11250 #if defined(AST_MISDN_ENHANCEMENTS)
11251 ast_unregister_application(misdn_command_name);
11252 ast_custom_function_unregister(&misdn_cc_function);
11253 #endif
11254
11255 ast_channel_unregister(&misdn_tech);
11256
11257 free_robin_list();
11258 misdn_cfg_destroy();
11259 misdn_lib_destroy();
11260
11261 ast_free(misdn_out_calls);
11262 ast_free(misdn_in_calls);
11263 ast_free(misdn_debug_only);
11264 ast_free(misdn_ports);
11265 ast_free(misdn_debug);
11266
11267 #if defined(AST_MISDN_ENHANCEMENTS)
11268 misdn_cc_destroy();
11269 #endif
11270 misdn_tech.capabilities = ast_format_cap_destroy(misdn_tech.capabilities);
11271 misdn_tech_wo_bridge.capabilities = ast_format_cap_destroy(misdn_tech_wo_bridge.capabilities);
11272
11273 return 0;
11274 }
11275
11276 static int load_module(void)
11277 {
11278 int i, port;
11279 int ntflags = 0, ntkc = 0;
11280 char ports[256] = "";
11281 char tempbuf[BUFFERSIZE + 1];
11282 char ntfile[BUFFERSIZE + 1];
11283 struct misdn_lib_iface iface = {
11284 .cb_event = cb_events,
11285 .cb_log = chan_misdn_log,
11286 .cb_jb_empty = chan_misdn_jb_empty,
11287 };
11288
11289
11290 if (!(misdn_tech.capabilities = ast_format_cap_alloc())) {
11291 return AST_MODULE_LOAD_DECLINE;
11292 }
11293 if (!(misdn_tech_wo_bridge.capabilities = ast_format_cap_alloc())) {
11294 return AST_MODULE_LOAD_DECLINE;
11295 }
11296 ast_format_set(&prefformat, AST_FORMAT_ALAW, 0);
11297 ast_format_cap_add(misdn_tech.capabilities, &prefformat);
11298 ast_format_cap_add(misdn_tech_wo_bridge.capabilities, &prefformat);
11299
11300 max_ports = misdn_lib_maxports_get();
11301
11302 if (max_ports <= 0) {
11303 ast_log(LOG_ERROR, "Unable to initialize mISDN\n");
11304 return AST_MODULE_LOAD_DECLINE;
11305 }
11306
11307 if (misdn_cfg_init(max_ports, 0)) {
11308 ast_log(LOG_ERROR, "Unable to initialize misdn_config.\n");
11309 return AST_MODULE_LOAD_DECLINE;
11310 }
11311 g_config_initialized = 1;
11312
11313 #if defined(AST_MISDN_ENHANCEMENTS)
11314 misdn_cc_init();
11315 #endif
11316
11317 misdn_debug = ast_malloc(sizeof(int) * (max_ports + 1));
11318 if (!misdn_debug) {
11319 ast_log(LOG_ERROR, "Out of memory for misdn_debug\n");
11320 return AST_MODULE_LOAD_DECLINE;
11321 }
11322 misdn_ports = ast_malloc(sizeof(int) * (max_ports + 1));
11323 if (!misdn_ports) {
11324 ast_free(misdn_debug);
11325 ast_log(LOG_ERROR, "Out of memory for misdn_ports\n");
11326 return AST_MODULE_LOAD_DECLINE;
11327 }
11328 misdn_cfg_get(0, MISDN_GEN_DEBUG, &misdn_debug[0], sizeof(misdn_debug[0]));
11329 for (i = 1; i <= max_ports; i++) {
11330 misdn_debug[i] = misdn_debug[0];
11331 misdn_ports[i] = i;
11332 }
11333 *misdn_ports = 0;
11334 misdn_debug_only = ast_calloc(max_ports + 1, sizeof(int));
11335 if (!misdn_debug_only) {
11336 ast_free(misdn_ports);
11337 ast_free(misdn_debug);
11338 ast_log(LOG_ERROR, "Out of memory for misdn_debug_only\n");
11339 return AST_MODULE_LOAD_DECLINE;
11340 }
11341
11342 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, tempbuf, sizeof(tempbuf));
11343 if (!ast_strlen_zero(tempbuf)) {
11344 tracing = 1;
11345 }
11346
11347 misdn_in_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11348 if (!misdn_in_calls) {
11349 ast_free(misdn_debug_only);
11350 ast_free(misdn_ports);
11351 ast_free(misdn_debug);
11352 ast_log(LOG_ERROR, "Out of memory for misdn_in_calls\n");
11353 return AST_MODULE_LOAD_DECLINE;
11354 }
11355 misdn_out_calls = ast_malloc(sizeof(int) * (max_ports + 1));
11356 if (!misdn_out_calls) {
11357 ast_free(misdn_in_calls);
11358 ast_free(misdn_debug_only);
11359 ast_free(misdn_ports);
11360 ast_free(misdn_debug);
11361 ast_log(LOG_ERROR, "Out of memory for misdn_out_calls\n");
11362 return AST_MODULE_LOAD_DECLINE;
11363 }
11364
11365 for (i = 1; i <= max_ports; i++) {
11366 misdn_in_calls[i] = 0;
11367 misdn_out_calls[i] = 0;
11368 }
11369
11370 ast_mutex_init(&cl_te_lock);
11371 ast_mutex_init(&release_lock);
11372
11373 misdn_cfg_update_ptp();
11374 misdn_cfg_get_ports_string(ports);
11375
11376 if (!ast_strlen_zero(ports)) {
11377 chan_misdn_log(0, 0, "Got: %s from get_ports\n", ports);
11378 }
11379 if (misdn_lib_init(ports, &iface, NULL)) {
11380 chan_misdn_log(0, 0, "No te ports initialized\n");
11381 }
11382
11383 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFLAGS, &ntflags, sizeof(ntflags));
11384 misdn_cfg_get(0, MISDN_GEN_NTDEBUGFILE, &ntfile, sizeof(ntfile));
11385 misdn_cfg_get(0, MISDN_GEN_NTKEEPCALLS, &ntkc, sizeof(ntkc));
11386
11387 misdn_lib_nt_keepcalls(ntkc);
11388 misdn_lib_nt_debug_init(ntflags, ntfile);
11389
11390 if (ast_channel_register(&misdn_tech)) {
11391 ast_log(LOG_ERROR, "Unable to register channel class %s\n", misdn_type);
11392 unload_module();
11393 return AST_MODULE_LOAD_DECLINE;
11394 }
11395
11396 ast_cli_register_multiple(chan_misdn_clis, sizeof(chan_misdn_clis) / sizeof(struct ast_cli_entry));
11397
11398 ast_register_application("misdn_set_opt", misdn_set_opt_exec, "misdn_set_opt",
11399 "misdn_set_opt(:<opt><optarg>:<opt><optarg>...):\n"
11400 "Sets mISDN opts. and optargs\n"
11401 "\n"
11402 "The available options are:\n"
11403 " a - Have Asterisk detect DTMF tones on called channel\n"
11404 " c - Make crypted outgoing call, optarg is keyindex\n"
11405 " d - Send display text to called phone, text is the optarg\n"
11406 " e - Perform echo cancellation on this channel,\n"
11407 " takes taps as optarg (32,64,128,256)\n"
11408 " e! - Disable echo cancellation on this channel\n"
11409 " f - Enable fax detection\n"
11410 " h - Make digital outgoing call\n"
11411 " h1 - Make HDLC mode digital outgoing call\n"
11412 " i - Ignore detected DTMF tones, don't signal them to Asterisk,\n"
11413 " they will be transported inband.\n"
11414 " jb - Set jitter buffer length, optarg is length\n"
11415 " jt - Set jitter buffer upper threshold, optarg is threshold\n"
11416 " jn - Disable jitter buffer\n"
11417 " n - Disable mISDN DSP on channel.\n"
11418 " Disables: echo cancel, DTMF detection, and volume control.\n"
11419 " p - Caller ID presentation,\n"
11420 " optarg is either 'allowed' or 'restricted'\n"
11421 " s - Send Non-inband DTMF as inband\n"
11422 " vr - Rx gain control, optarg is gain\n"
11423 " vt - Tx gain control, optarg is gain\n"
11424 );
11425
11426
11427 ast_register_application("misdn_facility", misdn_facility_exec, "misdn_facility",
11428 "misdn_facility(<FACILITY_TYPE>|<ARG1>|..)\n"
11429 "Sends the Facility Message FACILITY_TYPE with \n"
11430 "the given Arguments to the current ISDN Channel\n"
11431 "Supported Facilities are:\n"
11432 "\n"
11433 "type=calldeflect args=Nr where to deflect\n"
11434 #if defined(AST_MISDN_ENHANCEMENTS)
11435 "type=callrerouting args=Nr where to deflect\n"
11436 #endif
11437 );
11438
11439
11440 ast_register_application("misdn_check_l2l1", misdn_check_l2l1, "misdn_check_l2l1",
11441 "misdn_check_l2l1(<port>||g:<groupname>,timeout)\n"
11442 "Checks if the L2 and L1 are up on either the given <port> or\n"
11443 "on the ports in the group with <groupname>\n"
11444 "If the L1/L2 are down, check_l2l1 gets up the L1/L2 and waits\n"
11445 "for <timeout> seconds that this happens. Otherwise, nothing happens\n"
11446 "\n"
11447 "This application, ensures the L1/L2 state of the Ports in a group\n"
11448 "it is intended to make the pmp_l1_check option redundant and to\n"
11449 "fix a buggy switch config from your provider\n"
11450 "\n"
11451 "a sample dialplan would look like:\n\n"
11452 "exten => _X.,1,misdn_check_l2l1(g:out|2)\n"
11453 "exten => _X.,n,dial(mISDN/g:out/${EXTEN})\n"
11454 );
11455
11456 #if defined(AST_MISDN_ENHANCEMENTS)
11457 ast_register_application(misdn_command_name, misdn_command_exec, misdn_command_name,
11458 "misdn_command(<command>[,<options>])\n"
11459 "The following commands are defined:\n"
11460 "cc-initialize\n"
11461 " Setup mISDN support for call completion\n"
11462 " Must call before doing any Dial() involving call completion.\n"
11463 "ccnr-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11464 " Request Call Completion No Reply activation\n"
11465 "ccbs-request,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11466 " Request Call Completion Busy Subscriber activation\n"
11467 "cc-b-free,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>\n"
11468 " Set the dialplan location to notify when User-B is available but User-A is busy.\n"
11469 " Setting this dialplan location is optional.\n"
11470 "cc-a-busy,${MISDN_CC_RECORD_ID},<yes/no>\n"
11471 " Set the busy status of call completion User-A\n"
11472 "cc-deactivate,${MISDN_CC_RECORD_ID}\n"
11473 " Deactivate the identified call completion request\n"
11474 "\n"
11475 "MISDN_CC_RECORD_ID is set when Dial() returns and call completion is possible\n"
11476 "MISDN_CC_STATUS is set to ACTIVATED or ERROR after the call completion\n"
11477 "activation request.\n"
11478 "MISDN_ERROR_MSG is set to a descriptive message on error.\n"
11479 );
11480
11481 ast_custom_function_register(&misdn_cc_function);
11482 #endif
11483
11484 misdn_cfg_get(0, MISDN_GEN_TRACEFILE, global_tracefile, sizeof(global_tracefile));
11485
11486
11487
11488 for (port = misdn_cfg_get_next_port(0); port >= 0; port = misdn_cfg_get_next_port(port)) {
11489 int l1timeout;
11490 misdn_cfg_get(port, MISDN_CFG_L1_TIMEOUT, &l1timeout, sizeof(l1timeout));
11491 if (l1timeout) {
11492 chan_misdn_log(4, 0, "Adding L1watcher task: port:%d timeout:%ds\n", port, l1timeout);
11493 misdn_tasks_add(l1timeout * 1000, misdn_l1_task, &misdn_ports[port]);
11494 }
11495 }
11496
11497 chan_misdn_log(0, 0, "-- mISDN Channel Driver Registered --\n");
11498
11499 return 0;
11500 }
11501
11502
11503
11504 static int reload(void)
11505 {
11506 reload_config();
11507
11508 return 0;
11509 }
11510
11511
11512
11513 #if defined(AST_MISDN_ENHANCEMENTS)
11514
11515
11516
11517 AST_DEFINE_APP_ARGS_TYPE(misdn_command_args,
11518 AST_APP_ARG(name);
11519 AST_APP_ARG(arg)[10 + 1];
11520 );
11521 #endif
11522
11523 #if defined(AST_MISDN_ENHANCEMENTS)
11524 static void misdn_cc_caller_destroy(void *obj)
11525 {
11526
11527 }
11528 #endif
11529
11530 #if defined(AST_MISDN_ENHANCEMENTS)
11531 static struct misdn_cc_caller *misdn_cc_caller_alloc(struct ast_channel *chan)
11532 {
11533 struct misdn_cc_caller *cc_caller;
11534
11535 if (!(cc_caller = ao2_alloc(sizeof(*cc_caller), misdn_cc_caller_destroy))) {
11536 return NULL;
11537 }
11538
11539 cc_caller->chan = chan;
11540
11541 return cc_caller;
11542 }
11543 #endif
11544
11545 #if defined(AST_MISDN_ENHANCEMENTS)
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556 static int misdn_command_cc_initialize(struct ast_channel *chan, struct misdn_command_args *subcommand)
11557 {
11558 struct misdn_cc_caller *cc_caller;
11559 struct ast_datastore *datastore;
11560
11561 if (!(cc_caller = misdn_cc_caller_alloc(chan))) {
11562 return -1;
11563 }
11564
11565 if (!(datastore = ast_datastore_alloc(&misdn_cc_ds_info, NULL))) {
11566 ao2_ref(cc_caller, -1);
11567 return -1;
11568 }
11569
11570 ast_channel_lock(chan);
11571
11572
11573 datastore->data = cc_caller;
11574 cc_caller = NULL;
11575
11576 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
11577
11578 ast_channel_datastore_add(chan, datastore);
11579
11580 ast_channel_unlock(chan);
11581
11582 return 0;
11583 }
11584 #endif
11585
11586 #if defined(AST_MISDN_ENHANCEMENTS)
11587
11588
11589
11590
11591
11592
11593
11594
11595
11596
11597
11598
11599
11600
11601 static int misdn_command_cc_deactivate(struct ast_channel *chan, struct misdn_command_args *subcommand)
11602 {
11603 long record_id;
11604 const char *error_str;
11605 struct misdn_cc_record *cc_record;
11606 struct misdn_bchannel *bc;
11607 struct misdn_bchannel dummy;
11608
11609 static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID})\n";
11610
11611 if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11612 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11613 return -1;
11614 }
11615 record_id = atol(subcommand->arg[0]);
11616
11617 AST_LIST_LOCK(&misdn_cc_records_db);
11618 cc_record = misdn_cc_find_by_id(record_id);
11619 if (cc_record && 0 <= cc_record->port) {
11620 if (cc_record->ptp) {
11621 if (cc_record->mode.ptp.bc) {
11622
11623 bc = cc_record->mode.ptp.bc;
11624 bc->fac_out.Function = Fac_None;
11625 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
11626 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
11627 }
11628 misdn_cc_delete(cc_record);
11629 } else if (cc_record->activated) {
11630 cc_record->error_code = FacError_None;
11631 cc_record->reject_code = FacReject_None;
11632 cc_record->invoke_id = ++misdn_invoke_id;
11633 cc_record->outstanding_message = 1;
11634
11635
11636 misdn_make_dummy(&dummy, cc_record->port, 0, misdn_lib_port_is_nt(cc_record->port), 0);
11637 dummy.fac_out.Function = Fac_CCBSDeactivate;
11638 dummy.fac_out.u.CCBSDeactivate.InvokeID = cc_record->invoke_id;
11639 dummy.fac_out.u.CCBSDeactivate.ComponentType = FacComponent_Invoke;
11640 dummy.fac_out.u.CCBSDeactivate.Component.Invoke.CCBSReference = cc_record->mode.ptmp.reference_id;
11641
11642
11643 print_facility(&dummy.fac_out, &dummy);
11644 misdn_lib_send_event(&dummy, EVENT_FACILITY);
11645 }
11646 }
11647 AST_LIST_UNLOCK(&misdn_cc_records_db);
11648
11649
11650 misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11651
11652 AST_LIST_LOCK(&misdn_cc_records_db);
11653 cc_record = misdn_cc_find_by_id(record_id);
11654 if (cc_record) {
11655 if (cc_record->port < 0) {
11656
11657 error_str = NULL;
11658 } else if (cc_record->outstanding_message) {
11659 cc_record->outstanding_message = 0;
11660 error_str = misdn_no_response_from_network;
11661 } else if (cc_record->reject_code != FacReject_None) {
11662 error_str = misdn_to_str_reject_code(cc_record->reject_code);
11663 } else if (cc_record->error_code != FacError_None) {
11664 error_str = misdn_to_str_error_code(cc_record->error_code);
11665 } else {
11666 error_str = NULL;
11667 }
11668
11669 misdn_cc_delete(cc_record);
11670 } else {
11671 error_str = NULL;
11672 }
11673 AST_LIST_UNLOCK(&misdn_cc_records_db);
11674 if (error_str) {
11675 ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
11676 misdn_command_name, subcommand->name, error_str, ast_channel_name(chan));
11677 pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
11678 }
11679
11680 return 0;
11681 }
11682 #endif
11683
11684 #if defined(AST_MISDN_ENHANCEMENTS)
11685
11686
11687
11688
11689
11690
11691
11692
11693
11694
11695
11696
11697
11698
11699 static int misdn_command_cc_a_busy(struct ast_channel *chan, struct misdn_command_args *subcommand)
11700 {
11701 long record_id;
11702 int party_a_free;
11703 struct misdn_cc_record *cc_record;
11704 struct misdn_bchannel *bc;
11705
11706 static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<yes/no>)\n";
11707
11708 if (ast_strlen_zero(subcommand->arg[0]) || !isdigit(*subcommand->arg[0])) {
11709 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11710 return -1;
11711 }
11712 record_id = atol(subcommand->arg[0]);
11713
11714 if (ast_true(subcommand->arg[1])) {
11715 party_a_free = 0;
11716 } else if (ast_false(subcommand->arg[1])) {
11717 party_a_free = 1;
11718 } else {
11719 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11720 return -1;
11721 }
11722
11723 AST_LIST_LOCK(&misdn_cc_records_db);
11724 cc_record = misdn_cc_find_by_id(record_id);
11725 if (cc_record && cc_record->party_a_free != party_a_free) {
11726
11727 cc_record->party_a_free = party_a_free;
11728
11729 if (cc_record->ptp && cc_record->mode.ptp.bc) {
11730 cc_record->error_code = FacError_None;
11731 cc_record->reject_code = FacReject_None;
11732
11733
11734 bc = cc_record->mode.ptp.bc;
11735 if (cc_record->party_a_free) {
11736 bc->fac_out.Function = Fac_CCBS_T_Resume;
11737 bc->fac_out.u.CCBS_T_Resume.InvokeID = ++misdn_invoke_id;
11738 } else {
11739 bc->fac_out.Function = Fac_CCBS_T_Suspend;
11740 bc->fac_out.u.CCBS_T_Suspend.InvokeID = ++misdn_invoke_id;
11741 }
11742
11743
11744 print_facility(&bc->fac_out, bc);
11745 misdn_lib_send_event(bc, EVENT_FACILITY);
11746 }
11747 }
11748 AST_LIST_UNLOCK(&misdn_cc_records_db);
11749
11750 return 0;
11751 }
11752 #endif
11753
11754 #if defined(AST_MISDN_ENHANCEMENTS)
11755
11756
11757
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769 static int misdn_command_cc_b_free(struct ast_channel *chan, struct misdn_command_args *subcommand)
11770 {
11771 unsigned index;
11772 long record_id;
11773 int priority;
11774 char *context;
11775 char *exten;
11776 struct misdn_cc_record *cc_record;
11777
11778 static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11779
11780
11781 for (index = 0; index < 4; ++index) {
11782 if (ast_strlen_zero(subcommand->arg[index])) {
11783 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11784 return -1;
11785 }
11786 }
11787
11788
11789 if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11790 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11791 return -1;
11792 }
11793
11794 record_id = atol(subcommand->arg[0]);
11795 context = subcommand->arg[1];
11796 exten = subcommand->arg[2];
11797 priority = atoi(subcommand->arg[3]);
11798
11799 AST_LIST_LOCK(&misdn_cc_records_db);
11800 cc_record = misdn_cc_find_by_id(record_id);
11801 if (cc_record) {
11802
11803 ast_copy_string(cc_record->b_free.context, context, sizeof(cc_record->b_free.context));
11804 ast_copy_string(cc_record->b_free.exten, exten, sizeof(cc_record->b_free.exten));
11805 cc_record->b_free.priority = priority;
11806 }
11807 AST_LIST_UNLOCK(&misdn_cc_records_db);
11808
11809 return 0;
11810 }
11811 #endif
11812
11813 #if defined(AST_MISDN_ENHANCEMENTS)
11814 struct misdn_cc_request {
11815 enum FacFunction ptmp;
11816 enum FacFunction ptp;
11817 };
11818 #endif
11819
11820 #if defined(AST_MISDN_ENHANCEMENTS)
11821
11822
11823
11824
11825
11826
11827
11828
11829
11830
11831
11832
11833
11834
11835
11836
11837 static int misdn_command_cc_request(struct ast_channel *chan, struct misdn_command_args *subcommand, const struct misdn_cc_request *request)
11838 {
11839 unsigned index;
11840 int request_retention;
11841 long record_id;
11842 int priority;
11843 char *context;
11844 char *exten;
11845 const char *error_str;
11846 struct misdn_cc_record *cc_record;
11847 struct misdn_bchannel *bc;
11848 struct misdn_bchannel dummy;
11849 struct misdn_party_id id;
11850
11851 static const char cmd_help[] = "%s(%s,${MISDN_CC_RECORD_ID},<notify-context>,<user-a-extension>,<priority>)\n";
11852
11853
11854 for (index = 0; index < 4; ++index) {
11855 if (ast_strlen_zero(subcommand->arg[index])) {
11856 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11857 return -1;
11858 }
11859 }
11860
11861
11862 if (!isdigit(*subcommand->arg[0]) || !isdigit(*subcommand->arg[3])) {
11863 ast_log(LOG_WARNING, cmd_help, misdn_command_name, subcommand->name);
11864 return -1;
11865 }
11866
11867 record_id = atol(subcommand->arg[0]);
11868 context = subcommand->arg[1];
11869 exten = subcommand->arg[2];
11870 priority = atoi(subcommand->arg[3]);
11871
11872 AST_LIST_LOCK(&misdn_cc_records_db);
11873 cc_record = misdn_cc_find_by_id(record_id);
11874 if (cc_record) {
11875
11876 ast_copy_string(cc_record->remote_user_free.context, context,
11877 sizeof(cc_record->remote_user_free.context));
11878 ast_copy_string(cc_record->remote_user_free.exten, exten,
11879 sizeof(cc_record->remote_user_free.exten));
11880 cc_record->remote_user_free.priority = priority;
11881
11882 if (0 <= cc_record->port) {
11883 if (cc_record->ptp) {
11884 if (!cc_record->mode.ptp.bc) {
11885 bc = misdn_lib_get_register_bc(cc_record->port);
11886 if (bc) {
11887 cc_record->mode.ptp.bc = bc;
11888 cc_record->error_code = FacError_None;
11889 cc_record->reject_code = FacReject_None;
11890 cc_record->invoke_id = ++misdn_invoke_id;
11891 cc_record->outstanding_message = 1;
11892 cc_record->activation_requested = 1;
11893
11894 misdn_cfg_get(bc->port, MISDN_CFG_CC_REQUEST_RETENTION,
11895 &request_retention, sizeof(request_retention));
11896 cc_record->mode.ptp.requested_retention = request_retention ? 1 : 0;
11897
11898
11899 bc->fac_out.Function = request->ptp;
11900 bc->fac_out.u.CCBS_T_Request.InvokeID = cc_record->invoke_id;
11901 bc->fac_out.u.CCBS_T_Request.ComponentType = FacComponent_Invoke;
11902 bc->fac_out.u.CCBS_T_Request.Component.Invoke.Q931ie =
11903 cc_record->redial.setup_bc_hlc_llc;
11904 memset(&id, 0, sizeof(id));
11905 id.number_plan = cc_record->redial.dialed.number_plan;
11906 id.number_type = cc_record->redial.dialed.number_type;
11907 ast_copy_string(id.number, cc_record->redial.dialed.number,
11908 sizeof(id.number));
11909 misdn_Address_fill(
11910 &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Destination,
11911 &id);
11912 misdn_Address_fill(
11913 &bc->fac_out.u.CCBS_T_Request.Component.Invoke.Originating,
11914 &cc_record->redial.caller);
11915 bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicatorPresent = 1;
11916 bc->fac_out.u.CCBS_T_Request.Component.Invoke.PresentationAllowedIndicator =
11917 (cc_record->redial.caller.presentation != 0) ? 0 : 1;
11918 bc->fac_out.u.CCBS_T_Request.Component.Invoke.RetentionSupported =
11919 request_retention ? 1 : 0;
11920
11921
11922 print_facility(&bc->fac_out, bc);
11923 misdn_lib_send_event(bc, EVENT_REGISTER);
11924 }
11925 }
11926 } else {
11927 cc_record->error_code = FacError_None;
11928 cc_record->reject_code = FacReject_None;
11929 cc_record->invoke_id = ++misdn_invoke_id;
11930 cc_record->outstanding_message = 1;
11931 cc_record->activation_requested = 1;
11932
11933
11934 misdn_make_dummy(&dummy, cc_record->port, 0,
11935 misdn_lib_port_is_nt(cc_record->port), 0);
11936 dummy.fac_out.Function = request->ptmp;
11937 dummy.fac_out.u.CCBSRequest.InvokeID = cc_record->invoke_id;
11938 dummy.fac_out.u.CCBSRequest.ComponentType = FacComponent_Invoke;
11939 dummy.fac_out.u.CCBSRequest.Component.Invoke.CallLinkageID =
11940 cc_record->mode.ptmp.linkage_id;
11941
11942
11943 print_facility(&dummy.fac_out, &dummy);
11944 misdn_lib_send_event(&dummy, EVENT_FACILITY);
11945 }
11946 }
11947 }
11948 AST_LIST_UNLOCK(&misdn_cc_records_db);
11949
11950
11951 misdn_cc_response_wait(chan, MISDN_CC_REQUEST_WAIT_MAX, record_id);
11952
11953 AST_LIST_LOCK(&misdn_cc_records_db);
11954 cc_record = misdn_cc_find_by_id(record_id);
11955 if (cc_record) {
11956 if (!cc_record->activated) {
11957 if (cc_record->port < 0) {
11958
11959 error_str = "No port number";
11960 } else if (cc_record->outstanding_message) {
11961 cc_record->outstanding_message = 0;
11962 error_str = misdn_no_response_from_network;
11963 } else if (cc_record->reject_code != FacReject_None) {
11964 error_str = misdn_to_str_reject_code(cc_record->reject_code);
11965 } else if (cc_record->error_code != FacError_None) {
11966 error_str = misdn_to_str_error_code(cc_record->error_code);
11967 } else if (cc_record->ptp) {
11968 if (cc_record->mode.ptp.bc) {
11969 error_str = "Call-completion already requested";
11970 } else {
11971 error_str = "Could not allocate call-completion signaling link";
11972 }
11973 } else {
11974
11975 error_str = "Unexpected error";
11976 }
11977
11978
11979 if (cc_record->ptp && cc_record->mode.ptp.bc) {
11980
11981 bc = cc_record->mode.ptp.bc;
11982 bc->fac_out.Function = Fac_None;
11983 bc->out_cause = AST_CAUSE_NORMAL_CLEARING;
11984 misdn_lib_send_event(bc, EVENT_RELEASE_COMPLETE);
11985 }
11986 misdn_cc_delete(cc_record);
11987 } else {
11988 error_str = NULL;
11989 }
11990 } else {
11991 error_str = misdn_cc_record_not_found;
11992 }
11993 AST_LIST_UNLOCK(&misdn_cc_records_db);
11994 if (error_str) {
11995 ast_verb(1, "%s(%s) diagnostic '%s' on channel %s\n",
11996 misdn_command_name, subcommand->name, error_str, ast_channel_name(chan));
11997 pbx_builtin_setvar_helper(chan, MISDN_ERROR_MSG, error_str);
11998 pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ERROR");
11999 } else {
12000 pbx_builtin_setvar_helper(chan, MISDN_CC_STATUS, "ACTIVATED");
12001 }
12002
12003 return 0;
12004 }
12005 #endif
12006
12007 #if defined(AST_MISDN_ENHANCEMENTS)
12008
12009
12010
12011
12012
12013
12014
12015
12016
12017
12018
12019
12020
12021
12022 static int misdn_command_ccbs_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
12023 {
12024 static const struct misdn_cc_request request = {
12025 .ptmp = Fac_CCBSRequest,
12026 .ptp = Fac_CCBS_T_Request
12027 };
12028
12029 return misdn_command_cc_request(chan, subcommand, &request);
12030 }
12031 #endif
12032
12033 #if defined(AST_MISDN_ENHANCEMENTS)
12034
12035
12036
12037
12038
12039
12040
12041
12042
12043
12044
12045
12046
12047
12048 static int misdn_command_ccnr_request(struct ast_channel *chan, struct misdn_command_args *subcommand)
12049 {
12050 static const struct misdn_cc_request request = {
12051 .ptmp = Fac_CCNRRequest,
12052 .ptp = Fac_CCNR_T_Request
12053 };
12054
12055 return misdn_command_cc_request(chan, subcommand, &request);
12056 }
12057 #endif
12058
12059 #if defined(AST_MISDN_ENHANCEMENTS)
12060 struct misdn_command_table {
12061
12062 const char *name;
12063
12064
12065 int (*func)(struct ast_channel *chan, struct misdn_command_args *subcommand);
12066
12067
12068 int misdn_only;
12069 };
12070 static const struct misdn_command_table misdn_commands[] = {
12071
12072
12073 { "cc-initialize", misdn_command_cc_initialize, 0 },
12074 { "cc-deactivate", misdn_command_cc_deactivate, 0 },
12075 { "cc-a-busy", misdn_command_cc_a_busy, 0 },
12076 { "cc-b-free", misdn_command_cc_b_free, 0 },
12077 { "ccbs-request", misdn_command_ccbs_request, 0 },
12078 { "ccnr-request", misdn_command_ccnr_request, 0 },
12079
12080 };
12081 #endif
12082
12083 #if defined(AST_MISDN_ENHANCEMENTS)
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094 static int misdn_command_exec(struct ast_channel *chan, const char *data)
12095 {
12096 char *parse;
12097 unsigned index;
12098 struct misdn_command_args subcommand;
12099
12100 if (ast_strlen_zero((char *) data)) {
12101 ast_log(LOG_ERROR, "%s requires arguments\n", misdn_command_name);
12102 return -1;
12103 }
12104
12105 ast_debug(1, "%s(%s)\n", misdn_command_name, (char *) data);
12106
12107 parse = ast_strdupa(data);
12108 AST_STANDARD_APP_ARGS(subcommand, parse);
12109 if (!subcommand.argc || ast_strlen_zero(subcommand.name)) {
12110 ast_log(LOG_ERROR, "%s requires a subcommand\n", misdn_command_name);
12111 return -1;
12112 }
12113
12114 for (index = 0; index < ARRAY_LEN(misdn_commands); ++index) {
12115 if (strcasecmp(misdn_commands[index].name, subcommand.name) == 0) {
12116 strcpy(subcommand.name, misdn_commands[index].name);
12117 if (misdn_commands[index].misdn_only
12118 && strcasecmp(ast_channel_tech(chan)->type, misdn_type) != 0) {
12119 ast_log(LOG_WARNING,
12120 "%s(%s) only makes sense with %s channels!\n",
12121 misdn_command_name, subcommand.name, misdn_type);
12122 return -1;
12123 }
12124 return misdn_commands[index].func(chan, &subcommand);
12125 }
12126 }
12127
12128 ast_log(LOG_WARNING, "%s(%s) subcommand is unknown\n", misdn_command_name,
12129 subcommand.name);
12130 return -1;
12131 }
12132 #endif
12133
12134 static int misdn_facility_exec(struct ast_channel *chan, const char *data)
12135 {
12136 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12137 char *parse;
12138 unsigned max_len;
12139
12140 AST_DECLARE_APP_ARGS(args,
12141 AST_APP_ARG(facility_type);
12142 AST_APP_ARG(arg)[99];
12143 );
12144
12145 chan_misdn_log(0, 0, "TYPE: %s\n", ast_channel_tech(chan)->type);
12146
12147 if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
12148 ast_log(LOG_WARNING, "misdn_facility only makes sense with %s channels!\n", misdn_type);
12149 return -1;
12150 }
12151
12152 if (ast_strlen_zero((char *) data)) {
12153 ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12154 return -1;
12155 }
12156
12157 parse = ast_strdupa(data);
12158 AST_STANDARD_APP_ARGS(args, parse);
12159
12160 if (ast_strlen_zero(args.facility_type)) {
12161 ast_log(LOG_WARNING, "misdn_facility requires arguments: facility_type[,<args>]\n");
12162 return -1;
12163 }
12164
12165 if (!strcasecmp(args.facility_type, "calldeflect")) {
12166 if (ast_strlen_zero(args.arg[0])) {
12167 ast_log(LOG_WARNING, "Facility: Call Deflection requires an argument: Number\n");
12168 }
12169
12170 #if defined(AST_MISDN_ENHANCEMENTS)
12171 max_len = sizeof(ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number) - 1;
12172 if (max_len < strlen(args.arg[0])) {
12173 ast_log(LOG_WARNING,
12174 "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12175 max_len);
12176 return 0;
12177 }
12178 ch->bc->fac_out.Function = Fac_CallDeflection;
12179 ch->bc->fac_out.u.CallDeflection.InvokeID = ++misdn_invoke_id;
12180 ch->bc->fac_out.u.CallDeflection.ComponentType = FacComponent_Invoke;
12181 ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUserPresent = 1;
12182 ch->bc->fac_out.u.CallDeflection.Component.Invoke.PresentationAllowedToDivertedToUser = 0;
12183 ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Type = 0;
12184 ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.LengthOfNumber = strlen(args.arg[0]);
12185 strcpy((char *) ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Party.Number, args.arg[0]);
12186 ch->bc->fac_out.u.CallDeflection.Component.Invoke.Deflection.Subaddress.Length = 0;
12187
12188 #else
12189
12190 max_len = sizeof(ch->bc->fac_out.u.CDeflection.DeflectedToNumber) - 1;
12191 if (max_len < strlen(args.arg[0])) {
12192 ast_log(LOG_WARNING,
12193 "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12194 max_len);
12195 return 0;
12196 }
12197 ch->bc->fac_out.Function = Fac_CD;
12198 ch->bc->fac_out.u.CDeflection.PresentationAllowed = 0;
12199
12200 strcpy((char *) ch->bc->fac_out.u.CDeflection.DeflectedToNumber, args.arg[0]);
12201 #endif
12202
12203
12204 print_facility(&ch->bc->fac_out, ch->bc);
12205 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
12206 #if defined(AST_MISDN_ENHANCEMENTS)
12207 } else if (!strcasecmp(args.facility_type, "callrerouteing")
12208 || !strcasecmp(args.facility_type, "callrerouting")) {
12209 if (ast_strlen_zero(args.arg[0])) {
12210 ast_log(LOG_WARNING, "Facility: Call rerouting requires an argument: Number\n");
12211 }
12212
12213 max_len = sizeof(ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number) - 1;
12214 if (max_len < strlen(args.arg[0])) {
12215 ast_log(LOG_WARNING,
12216 "Facility: Number argument too long (up to %u digits are allowed). Ignoring.\n",
12217 max_len);
12218 return 0;
12219 }
12220 ch->bc->fac_out.Function = Fac_CallRerouteing;
12221 ch->bc->fac_out.u.CallRerouteing.InvokeID = ++misdn_invoke_id;
12222 ch->bc->fac_out.u.CallRerouteing.ComponentType = FacComponent_Invoke;
12223
12224 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingReason = 0;
12225 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.ReroutingCounter = 1;
12226
12227 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Type = 0;
12228 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.LengthOfNumber = strlen(args.arg[0]);
12229 strcpy((char *) ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Party.Number, args.arg[0]);
12230 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CalledAddress.Subaddress.Length = 0;
12231
12232 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.CallingPartySubaddress.Length = 0;
12233
12234
12235 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Length = 3;
12236 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[0] = 0x90;
12237 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[1] = 0x90;
12238 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Bc.Contents[2] = 0xa3;
12239 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Hlc.Length = 0;
12240 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.Llc.Length = 0;
12241 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.Q931ie.UserInfo.Length = 0;
12242
12243 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.LastRerouting.Type = 1;
12244 ch->bc->fac_out.u.CallRerouteing.Component.Invoke.SubscriptionOption = 0;
12245
12246
12247 print_facility(&ch->bc->fac_out, ch->bc);
12248 misdn_lib_send_event(ch->bc, EVENT_FACILITY);
12249 #endif
12250 } else {
12251 chan_misdn_log(1, ch->bc->port, "Unknown Facility: %s\n", args.facility_type);
12252 }
12253
12254 return 0;
12255 }
12256
12257 static int misdn_check_l2l1(struct ast_channel *chan, const char *data)
12258 {
12259 char *parse;
12260 char group[BUFFERSIZE + 1];
12261 char *port_str;
12262 int port = 0;
12263 int timeout;
12264 int dowait = 0;
12265 int port_up;
12266
12267 AST_DECLARE_APP_ARGS(args,
12268 AST_APP_ARG(grouppar);
12269 AST_APP_ARG(timeout);
12270 );
12271
12272 if (ast_strlen_zero((char *) data)) {
12273 ast_log(LOG_WARNING, "misdn_check_l2l1 Requires arguments\n");
12274 return -1;
12275 }
12276
12277 parse = ast_strdupa(data);
12278 AST_STANDARD_APP_ARGS(args, parse);
12279
12280 if (args.argc != 2) {
12281 ast_log(LOG_WARNING, "Wrong argument count\n");
12282 return 0;
12283 }
12284
12285
12286 timeout = atoi(args.timeout);
12287 port_str = args.grouppar;
12288
12289 if (port_str[0] == 'g' && port_str[1] == ':') {
12290
12291 port_str += 2;
12292 ast_copy_string(group, port_str, sizeof(group));
12293 chan_misdn_log(2, 0, "Checking Ports in group: %s\n", group);
12294
12295 for (port = misdn_cfg_get_next_port(port);
12296 port > 0;
12297 port = misdn_cfg_get_next_port(port)) {
12298 char cfg_group[BUFFERSIZE + 1];
12299
12300 chan_misdn_log(2, 0, "trying port %d\n", port);
12301
12302 misdn_cfg_get(port, MISDN_CFG_GROUPNAME, cfg_group, sizeof(cfg_group));
12303
12304 if (!strcasecmp(cfg_group, group)) {
12305 port_up = misdn_lib_port_up(port, 1);
12306 if (!port_up) {
12307 chan_misdn_log(2, 0, " --> port '%d'\n", port);
12308 misdn_lib_get_port_up(port);
12309 dowait = 1;
12310 }
12311 }
12312 }
12313 } else {
12314 port = atoi(port_str);
12315 chan_misdn_log(2, 0, "Checking Port: %d\n", port);
12316 port_up = misdn_lib_port_up(port, 1);
12317 if (!port_up) {
12318 misdn_lib_get_port_up(port);
12319 dowait = 1;
12320 }
12321 }
12322
12323 if (dowait) {
12324 chan_misdn_log(2, 0, "Waiting for '%d' seconds\n", timeout);
12325 ast_safe_sleep(chan, timeout * 1000);
12326 }
12327
12328 return 0;
12329 }
12330
12331 static int misdn_set_opt_exec(struct ast_channel *chan, const char *data)
12332 {
12333 struct chan_list *ch = MISDN_ASTERISK_TECH_PVT(chan);
12334 char *tok;
12335 char *tokb;
12336 char *parse;
12337 int keyidx = 0;
12338 int rxgain = 0;
12339 int txgain = 0;
12340 int change_jitter = 0;
12341
12342 if (strcasecmp(ast_channel_tech(chan)->type, misdn_type)) {
12343 ast_log(LOG_WARNING, "misdn_set_opt makes sense only with %s channels!\n", misdn_type);
12344 return -1;
12345 }
12346
12347 if (ast_strlen_zero((char *) data)) {
12348 ast_log(LOG_WARNING, "misdn_set_opt Requires arguments\n");
12349 return -1;
12350 }
12351
12352 parse = ast_strdupa(data);
12353 for (tok = strtok_r(parse, ":", &tokb);
12354 tok;
12355 tok = strtok_r(NULL, ":", &tokb)) {
12356 int neglect = 0;
12357
12358 if (tok[0] == '!') {
12359 neglect = 1;
12360 tok++;
12361 }
12362
12363 switch(tok[0]) {
12364 case 'd' :
12365 ast_copy_string(ch->bc->display, ++tok, sizeof(ch->bc->display));
12366 chan_misdn_log(1, ch->bc->port, "SETOPT: Display:%s\n", ch->bc->display);
12367 break;
12368 case 'n':
12369 chan_misdn_log(1, ch->bc->port, "SETOPT: No DSP\n");
12370 ch->bc->nodsp = 1;
12371 break;
12372 case 'j':
12373 chan_misdn_log(1, ch->bc->port, "SETOPT: jitter\n");
12374 tok++;
12375 change_jitter = 1;
12376
12377 switch (tok[0]) {
12378 case 'b':
12379 ch->jb_len = atoi(++tok);
12380 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d\n", ch->jb_len);
12381 break;
12382 case 't' :
12383 ch->jb_upper_threshold = atoi(++tok);
12384 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d\n", ch->jb_upper_threshold);
12385 break;
12386 case 'n':
12387 ch->bc->nojitter = 1;
12388 chan_misdn_log(1, ch->bc->port, " --> nojitter\n");
12389 break;
12390 default:
12391 ch->jb_len = 4000;
12392 ch->jb_upper_threshold = 0;
12393 chan_misdn_log(1, ch->bc->port, " --> buffer_len:%d (default)\n", ch->jb_len);
12394 chan_misdn_log(1, ch->bc->port, " --> upper_threshold:%d (default)\n", ch->jb_upper_threshold);
12395 break;
12396 }
12397 break;
12398 case 'v':
12399 tok++;
12400
12401 switch (tok[0]) {
12402 case 'r' :
12403 rxgain = atoi(++tok);
12404 if (rxgain < -8) {
12405 rxgain = -8;
12406 }
12407 if (rxgain > 8) {
12408 rxgain = 8;
12409 }
12410 ch->bc->rxgain = rxgain;
12411 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", rxgain);
12412 break;
12413 case 't':
12414 txgain = atoi(++tok);
12415 if (txgain < -8) {
12416 txgain = -8;
12417 }
12418 if (txgain > 8) {
12419 txgain = 8;
12420 }
12421 ch->bc->txgain = txgain;
12422 chan_misdn_log(1, ch->bc->port, "SETOPT: Volume:%d\n", txgain);
12423 break;
12424 }
12425 break;
12426 case 'c':
12427 keyidx = atoi(++tok);
12428 {
12429 char keys[4096];
12430 char *key = NULL;
12431 char *tmp = keys;
12432 int i;
12433
12434 misdn_cfg_get(0, MISDN_GEN_CRYPT_KEYS, keys, sizeof(keys));
12435
12436 for (i = 0; i < keyidx; i++) {
12437 key = strsep(&tmp, ",");
12438 }
12439
12440 if (key) {
12441 ast_copy_string(ch->bc->crypt_key, key, sizeof(ch->bc->crypt_key));
12442 }
12443
12444 chan_misdn_log(0, ch->bc->port, "SETOPT: crypt with key:%s\n", ch->bc->crypt_key);
12445 break;
12446 }
12447 case 'e':
12448 chan_misdn_log(1, ch->bc->port, "SETOPT: EchoCancel\n");
12449
12450 if (neglect) {
12451 chan_misdn_log(1, ch->bc->port, " --> disabled\n");
12452 #ifdef MISDN_1_2
12453 *ch->bc->pipeline = 0;
12454 #else
12455 ch->bc->ec_enable = 0;
12456 #endif
12457 } else {
12458 #ifdef MISDN_1_2
12459 update_pipeline_config(ch->bc);
12460 #else
12461 ch->bc->ec_enable = 1;
12462 ch->bc->orig = ch->originator;
12463 tok++;
12464 if (*tok) {
12465 ch->bc->ec_deftaps = atoi(tok);
12466 }
12467 #endif
12468 }
12469 break;
12470 case 'h':
12471 chan_misdn_log(1, ch->bc->port, "SETOPT: Digital\n");
12472
12473 if (strlen(tok) > 1 && tok[1] == '1') {
12474 chan_misdn_log(1, ch->bc->port, "SETOPT: HDLC \n");
12475 if (!ch->bc->hdlc) {
12476 ch->bc->hdlc = 1;
12477 }
12478 }
12479 ch->bc->capability = INFO_CAPABILITY_DIGITAL_UNRESTRICTED;
12480 break;
12481 case 's':
12482 chan_misdn_log(1, ch->bc->port, "SETOPT: Send DTMF\n");
12483 ch->bc->send_dtmf = 1;
12484 break;
12485 case 'f':
12486 chan_misdn_log(1, ch->bc->port, "SETOPT: Faxdetect\n");
12487 ch->faxdetect = 1;
12488 misdn_cfg_get(ch->bc->port, MISDN_CFG_FAXDETECT_TIMEOUT, &ch->faxdetect_timeout, sizeof(ch->faxdetect_timeout));
12489 break;
12490 case 'a':
12491 chan_misdn_log(1, ch->bc->port, "SETOPT: AST_DSP (for DTMF)\n");
12492 ch->ast_dsp = 1;
12493 break;
12494 case 'p':
12495 chan_misdn_log(1, ch->bc->port, "SETOPT: callerpres: %s\n", &tok[1]);
12496
12497 if (strstr(tok, "allowed")) {
12498 ch->bc->presentation = 0;
12499 ch->bc->set_presentation = 1;
12500 } else if (strstr(tok, "restricted")) {
12501 ch->bc->presentation = 1;
12502 ch->bc->set_presentation = 1;
12503 } else if (strstr(tok, "not_screened")) {
12504 chan_misdn_log(0, ch->bc->port, "SETOPT: callerpres: not_screened is deprecated\n");
12505 ch->bc->presentation = 1;
12506 ch->bc->set_presentation = 1;
12507 }
12508 break;
12509 case 'i' :
12510 chan_misdn_log(1, ch->bc->port, "Ignoring dtmf tones, just use them inband\n");
12511 ch->ignore_dtmf = 1;
12512 break;
12513 default:
12514 break;
12515 }
12516 }
12517
12518 if (change_jitter) {
12519 config_jitterbuffer(ch);
12520 }
12521
12522 if (ch->faxdetect || ch->ast_dsp) {
12523 if (!ch->dsp) {
12524 ch->dsp = ast_dsp_new();
12525 }
12526 if (ch->dsp) {
12527 ast_dsp_set_features(ch->dsp, DSP_FEATURE_DIGIT_DETECT | DSP_FEATURE_FAX_DETECT);
12528 }
12529 }
12530
12531 if (ch->ast_dsp) {
12532 chan_misdn_log(1, ch->bc->port, "SETOPT: with AST_DSP we deactivate mISDN_dsp\n");
12533 ch->bc->nodsp = 1;
12534 }
12535
12536 return 0;
12537 }
12538
12539
12540 int chan_misdn_jb_empty(struct misdn_bchannel *bc, char *buf, int len)
12541 {
12542 struct chan_list *ch;
12543 int res;
12544
12545 ch = find_chan_by_bc(bc);
12546 if (!ch) {
12547 return 0;
12548 }
12549
12550 if (ch->jb) {
12551 res = misdn_jb_empty(ch->jb, buf, len);
12552 } else {
12553 res = 0;
12554 }
12555 chan_list_unref(ch, "Done emptying jb");
12556
12557 return res;
12558 }
12559
12560
12561
12562
12563
12564
12565
12566
12567
12568 struct misdn_jb *misdn_jb_init(int size, int upper_threshold)
12569 {
12570 struct misdn_jb *jb;
12571
12572 jb = ast_calloc(1, sizeof(*jb));
12573 if (!jb) {
12574 chan_misdn_log(-1, 0, "No free Mem for jb\n");
12575 return NULL;
12576 }
12577 jb->size = size;
12578 jb->upper_threshold = upper_threshold;
12579
12580
12581
12582
12583
12584 jb->samples = ast_calloc(size, sizeof(*jb->samples));
12585 if (!jb->samples) {
12586 ast_free(jb);
12587 chan_misdn_log(-1, 0, "No free Mem for jb->samples\n");
12588 return NULL;
12589 }
12590
12591 jb->ok = ast_calloc(size, sizeof(*jb->ok));
12592 if (!jb->ok) {
12593 ast_free(jb->samples);
12594 ast_free(jb);
12595 chan_misdn_log(-1, 0, "No free Mem for jb->ok\n");
12596 return NULL;
12597 }
12598
12599 ast_mutex_init(&jb->mutexjb);
12600
12601 return jb;
12602 }
12603
12604
12605 void misdn_jb_destroy(struct misdn_jb *jb)
12606 {
12607 ast_mutex_destroy(&jb->mutexjb);
12608
12609 ast_free(jb->ok);
12610 ast_free(jb->samples);
12611 ast_free(jb);
12612 }
12613
12614
12615
12616 int misdn_jb_fill(struct misdn_jb *jb, const char *data, int len)
12617 {
12618 int i;
12619 int j;
12620 int rp;
12621 int wp;
12622
12623 if (!jb || ! data) {
12624 return 0;
12625 }
12626
12627 ast_mutex_lock(&jb->mutexjb);
12628
12629 wp = jb->wp;
12630 rp = jb->rp;
12631
12632 for (i = 0; i < len; i++) {
12633 jb->samples[wp] = data[i];
12634 jb->ok[wp] = 1;
12635 wp = (wp != jb->size - 1) ? wp + 1 : 0;
12636
12637 if (wp == jb->rp) {
12638 jb->state_full = 1;
12639 }
12640 }
12641
12642 if (wp >= rp) {
12643 jb->state_buffer = wp - rp;
12644 } else {
12645 jb->state_buffer = jb->size - rp + wp;
12646 }
12647 chan_misdn_log(9, 0, "misdn_jb_fill: written:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12648
12649 if (jb->state_full) {
12650 jb->wp = wp;
12651
12652 rp = wp;
12653 for (j = 0; j < jb->upper_threshold; j++) {
12654 rp = (rp != 0) ? rp - 1 : jb->size - 1;
12655 }
12656 jb->rp = rp;
12657 jb->state_full = 0;
12658 jb->state_empty = 1;
12659
12660 ast_mutex_unlock(&jb->mutexjb);
12661
12662 return -1;
12663 }
12664
12665 if (!jb->state_empty) {
12666 jb->bytes_wrote += len;
12667 if (jb->bytes_wrote >= jb->upper_threshold) {
12668 jb->state_empty = 1;
12669 jb->bytes_wrote = 0;
12670 }
12671 }
12672 jb->wp = wp;
12673
12674 ast_mutex_unlock(&jb->mutexjb);
12675
12676 return 0;
12677 }
12678
12679
12680
12681
12682 int misdn_jb_empty(struct misdn_jb *jb, char *data, int len)
12683 {
12684 int i;
12685 int wp;
12686 int rp;
12687 int read = 0;
12688
12689 ast_mutex_lock(&jb->mutexjb);
12690
12691 rp = jb->rp;
12692 wp = jb->wp;
12693
12694 if (jb->state_empty) {
12695 for (i = 0; i < len; i++) {
12696 if (wp == rp) {
12697 jb->rp = rp;
12698 jb->state_empty = 0;
12699
12700 ast_mutex_unlock(&jb->mutexjb);
12701
12702 return read;
12703 } else {
12704 if (jb->ok[rp] == 1) {
12705 data[i] = jb->samples[rp];
12706 jb->ok[rp] = 0;
12707 rp = (rp != jb->size - 1) ? rp + 1 : 0;
12708 read += 1;
12709 }
12710 }
12711 }
12712
12713 if (wp >= rp) {
12714 jb->state_buffer = wp - rp;
12715 } else {
12716 jb->state_buffer = jb->size - rp + wp;
12717 }
12718 chan_misdn_log(9, 0, "misdn_jb_empty: read:%d | Buffer status:%d p:%p\n", len, jb->state_buffer, jb);
12719
12720 jb->rp = rp;
12721 } else {
12722 chan_misdn_log(9, 0, "misdn_jb_empty: Wait...requested:%d p:%p\n", len, jb);
12723 }
12724
12725 ast_mutex_unlock(&jb->mutexjb);
12726
12727 return read;
12728 }
12729
12730
12731
12732
12733
12734 static void chan_misdn_log(int level, int port, char *tmpl, ...)
12735 {
12736 va_list ap;
12737 char buf[1024];
12738 char port_buf[8];
12739
12740 if (!(0 <= port && port <= max_ports)) {
12741 ast_log(LOG_WARNING, "chan_misdn_log called with out-of-range port number! (%d)\n", port);
12742 port = 0;
12743 level = -1;
12744 } else if (!(level == -1
12745 || (misdn_debug_only[port]
12746 ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12747 : level <= misdn_debug[port])
12748 || (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)))) {
12749
12750
12751
12752
12753 return;
12754 }
12755
12756 snprintf(port_buf, sizeof(port_buf), "P[%2d] ", port);
12757 va_start(ap, tmpl);
12758 vsnprintf(buf, sizeof(buf), tmpl, ap);
12759 va_end(ap);
12760
12761 if (level == -1) {
12762 ast_log(LOG_WARNING, "%s", buf);
12763 } else if (misdn_debug_only[port]
12764 ? (level == 1 && misdn_debug[port]) || level == misdn_debug[port]
12765 : level <= misdn_debug[port]) {
12766 ast_verbose("%s%s", port_buf, buf);
12767 }
12768
12769 if (level <= misdn_debug[0] && !ast_strlen_zero(global_tracefile)) {
12770 char ctimebuf[30];
12771 time_t tm;
12772 char *tmp;
12773 char *p;
12774 FILE *fp;
12775
12776 fp = fopen(global_tracefile, "a+");
12777 if (!fp) {
12778 ast_verbose("Error opening Tracefile: [ %s ] %s\n", global_tracefile, strerror(errno));
12779 return;
12780 }
12781
12782 tm = time(NULL);
12783 tmp = ctime_r(&tm, ctimebuf);
12784 p = strchr(tmp, '\n');
12785 if (p) {
12786 *p = ':';
12787 }
12788 fputs(tmp, fp);
12789 fputs(" ", fp);
12790 fputs(port_buf, fp);
12791 fputs(" ", fp);
12792 fputs(buf, fp);
12793
12794 fclose(fp);
12795 }
12796 }
12797
12798 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_LOAD_ORDER, "Channel driver for mISDN Support (BRI/PRI)",
12799 .load = load_module,
12800 .unload = unload_module,
12801 .reload = reload,
12802 .load_pri = AST_MODPRI_CHANNEL_DRIVER,
12803 );