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