00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071 #include "asterisk.h"
00072
00073 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 374805 $")
00074
00075 #include <sys/time.h>
00076 #include <sys/signal.h>
00077 #include <netinet/in.h>
00078 #include <ctype.h>
00079
00080 #include "asterisk/lock.h"
00081 #include "asterisk/file.h"
00082 #include "asterisk/channel.h"
00083 #include "asterisk/pbx.h"
00084 #include "asterisk/app.h"
00085 #include "asterisk/linkedlists.h"
00086 #include "asterisk/module.h"
00087 #include "asterisk/translate.h"
00088 #include "asterisk/say.h"
00089 #include "asterisk/features.h"
00090 #include "asterisk/musiconhold.h"
00091 #include "asterisk/cli.h"
00092 #include "asterisk/manager.h"
00093 #include "asterisk/config.h"
00094 #include "asterisk/monitor.h"
00095 #include "asterisk/utils.h"
00096 #include "asterisk/causes.h"
00097 #include "asterisk/astdb.h"
00098 #include "asterisk/devicestate.h"
00099 #include "asterisk/stringfields.h"
00100 #include "asterisk/event.h"
00101 #include "asterisk/astobj2.h"
00102 #include "asterisk/strings.h"
00103 #include "asterisk/global_datastores.h"
00104 #include "asterisk/taskprocessor.h"
00105 #include "asterisk/aoc.h"
00106 #include "asterisk/callerid.h"
00107 #include "asterisk/cel.h"
00108 #include "asterisk/data.h"
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895 enum {
00896 OPT_MARK_AS_ANSWERED = (1 << 0),
00897 OPT_GO_ON = (1 << 1),
00898 OPT_DATA_QUALITY = (1 << 2),
00899 OPT_CALLEE_GO_ON = (1 << 3),
00900 OPT_CALLEE_HANGUP = (1 << 4),
00901 OPT_CALLER_HANGUP = (1 << 5),
00902 OPT_IGNORE_CALL_FW = (1 << 6),
00903 OPT_IGNORE_CONNECTEDLINE = (1 << 7),
00904 OPT_CALLEE_PARK = (1 << 8),
00905 OPT_CALLER_PARK = (1 << 9),
00906 OPT_NO_RETRY = (1 << 10),
00907 OPT_RINGING = (1 << 11),
00908 OPT_RING_WHEN_RINGING = (1 << 12),
00909 OPT_CALLEE_TRANSFER = (1 << 13),
00910 OPT_CALLER_TRANSFER = (1 << 14),
00911 OPT_CALLEE_AUTOMIXMON = (1 << 15),
00912 OPT_CALLER_AUTOMIXMON = (1 << 16),
00913 OPT_CALLEE_AUTOMON = (1 << 17),
00914 OPT_CALLER_AUTOMON = (1 << 18),
00915 };
00916
00917 enum {
00918 OPT_ARG_CALLEE_GO_ON = 0,
00919
00920 OPT_ARG_ARRAY_SIZE
00921 };
00922
00923 AST_APP_OPTIONS(queue_exec_options, BEGIN_OPTIONS
00924 AST_APP_OPTION('C', OPT_MARK_AS_ANSWERED),
00925 AST_APP_OPTION('c', OPT_GO_ON),
00926 AST_APP_OPTION('d', OPT_DATA_QUALITY),
00927 AST_APP_OPTION_ARG('F', OPT_CALLEE_GO_ON, OPT_ARG_CALLEE_GO_ON),
00928 AST_APP_OPTION('h', OPT_CALLEE_HANGUP),
00929 AST_APP_OPTION('H', OPT_CALLER_HANGUP),
00930 AST_APP_OPTION('i', OPT_IGNORE_CALL_FW),
00931 AST_APP_OPTION('I', OPT_IGNORE_CONNECTEDLINE),
00932 AST_APP_OPTION('k', OPT_CALLEE_PARK),
00933 AST_APP_OPTION('K', OPT_CALLER_PARK),
00934 AST_APP_OPTION('n', OPT_NO_RETRY),
00935 AST_APP_OPTION('r', OPT_RINGING),
00936 AST_APP_OPTION('R', OPT_RING_WHEN_RINGING),
00937 AST_APP_OPTION('t', OPT_CALLEE_TRANSFER),
00938 AST_APP_OPTION('T', OPT_CALLER_TRANSFER),
00939 AST_APP_OPTION('x', OPT_CALLEE_AUTOMIXMON),
00940 AST_APP_OPTION('X', OPT_CALLER_AUTOMIXMON),
00941 AST_APP_OPTION('w', OPT_CALLEE_AUTOMON),
00942 AST_APP_OPTION('W', OPT_CALLER_AUTOMON),
00943 END_OPTIONS);
00944
00945 enum {
00946 QUEUE_STRATEGY_RINGALL = 0,
00947 QUEUE_STRATEGY_LEASTRECENT,
00948 QUEUE_STRATEGY_FEWESTCALLS,
00949 QUEUE_STRATEGY_RANDOM,
00950 QUEUE_STRATEGY_RRMEMORY,
00951 QUEUE_STRATEGY_LINEAR,
00952 QUEUE_STRATEGY_WRANDOM,
00953 QUEUE_STRATEGY_RRORDERED,
00954 };
00955
00956 enum {
00957 QUEUE_AUTOPAUSE_OFF = 0,
00958 QUEUE_AUTOPAUSE_ON,
00959 QUEUE_AUTOPAUSE_ALL
00960 };
00961
00962 enum queue_reload_mask {
00963 QUEUE_RELOAD_PARAMETERS = (1 << 0),
00964 QUEUE_RELOAD_MEMBER = (1 << 1),
00965 QUEUE_RELOAD_RULES = (1 << 2),
00966 QUEUE_RESET_STATS = (1 << 3),
00967 };
00968
00969 static const struct strategy {
00970 int strategy;
00971 const char *name;
00972 } strategies[] = {
00973 { QUEUE_STRATEGY_RINGALL, "ringall" },
00974 { QUEUE_STRATEGY_LEASTRECENT, "leastrecent" },
00975 { QUEUE_STRATEGY_FEWESTCALLS, "fewestcalls" },
00976 { QUEUE_STRATEGY_RANDOM, "random" },
00977 { QUEUE_STRATEGY_RRMEMORY, "rrmemory" },
00978 { QUEUE_STRATEGY_RRMEMORY, "roundrobin" },
00979 { QUEUE_STRATEGY_LINEAR, "linear" },
00980 { QUEUE_STRATEGY_WRANDOM, "wrandom"},
00981 { QUEUE_STRATEGY_RRORDERED, "rrordered"},
00982 };
00983
00984 static const struct autopause {
00985 int autopause;
00986 const char *name;
00987 } autopausesmodes [] = {
00988 { QUEUE_AUTOPAUSE_OFF,"no" },
00989 { QUEUE_AUTOPAUSE_ON, "yes" },
00990 { QUEUE_AUTOPAUSE_ALL,"all" },
00991 };
00992
00993
00994 static struct ast_taskprocessor *devicestate_tps;
00995
00996 #define DEFAULT_RETRY 5
00997 #define DEFAULT_TIMEOUT 15
00998 #define RECHECK 1
00999 #define MAX_PERIODIC_ANNOUNCEMENTS 10
01000 #define DEFAULT_MIN_ANNOUNCE_FREQUENCY 15
01001
01002 #define MAX_QUEUE_BUCKETS 53
01003
01004 #define RES_OKAY 0
01005 #define RES_EXISTS (-1)
01006 #define RES_OUTOFMEMORY (-2)
01007 #define RES_NOSUCHQUEUE (-3)
01008 #define RES_NOT_DYNAMIC (-4)
01009
01010 static char *app = "Queue";
01011
01012 static char *app_aqm = "AddQueueMember" ;
01013
01014 static char *app_rqm = "RemoveQueueMember" ;
01015
01016 static char *app_pqm = "PauseQueueMember" ;
01017
01018 static char *app_upqm = "UnpauseQueueMember" ;
01019
01020 static char *app_ql = "QueueLog" ;
01021
01022
01023 static const char * const pm_family = "Queue/PersistentMembers";
01024
01025
01026 static int queue_persistent_members = 0;
01027
01028
01029 static int use_weight = 0;
01030
01031
01032 static int autofill_default = 1;
01033
01034
01035 static int montype_default = 0;
01036
01037
01038 static int shared_lastcall = 1;
01039
01040
01041 static struct ast_event_sub *device_state_sub;
01042
01043
01044 static int update_cdr = 0;
01045
01046
01047 static int negative_penalty_invalid = 0;
01048
01049
01050 static int log_membername_as_agent = 0;
01051
01052
01053 static int check_state_unknown = 0;
01054
01055
01056 static char *realtime_ringinuse_field;
01057
01058 enum queue_result {
01059 QUEUE_UNKNOWN = 0,
01060 QUEUE_TIMEOUT = 1,
01061 QUEUE_JOINEMPTY = 2,
01062 QUEUE_LEAVEEMPTY = 3,
01063 QUEUE_JOINUNAVAIL = 4,
01064 QUEUE_LEAVEUNAVAIL = 5,
01065 QUEUE_FULL = 6,
01066 QUEUE_CONTINUE = 7,
01067 };
01068
01069 static const struct {
01070 enum queue_result id;
01071 char *text;
01072 } queue_results[] = {
01073 { QUEUE_UNKNOWN, "UNKNOWN" },
01074 { QUEUE_TIMEOUT, "TIMEOUT" },
01075 { QUEUE_JOINEMPTY,"JOINEMPTY" },
01076 { QUEUE_LEAVEEMPTY, "LEAVEEMPTY" },
01077 { QUEUE_JOINUNAVAIL, "JOINUNAVAIL" },
01078 { QUEUE_LEAVEUNAVAIL, "LEAVEUNAVAIL" },
01079 { QUEUE_FULL, "FULL" },
01080 { QUEUE_CONTINUE, "CONTINUE" },
01081 };
01082
01083 enum queue_timeout_priority {
01084 TIMEOUT_PRIORITY_APP,
01085 TIMEOUT_PRIORITY_CONF,
01086 };
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100 struct callattempt {
01101 struct callattempt *q_next;
01102 struct callattempt *call_next;
01103 struct ast_channel *chan;
01104 char interface[256];
01105 int metric;
01106 time_t lastcall;
01107 struct call_queue *lastqueue;
01108 struct member *member;
01109
01110 struct ast_party_connected_line connected;
01111
01112 unsigned int pending_connected_update:1;
01113
01114 unsigned int block_connected_update:1;
01115
01116 unsigned int dial_callerid_absent:1;
01117
01118 unsigned int stillgoing:1;
01119 struct ast_aoc_decoded *aoc_s_rate_list;
01120 };
01121
01122
01123 struct queue_ent {
01124 struct call_queue *parent;
01125 char moh[MAX_MUSICCLASS];
01126 char announce[PATH_MAX];
01127 char context[AST_MAX_CONTEXT];
01128 char digits[AST_MAX_EXTENSION];
01129 int valid_digits;
01130 int pos;
01131 int prio;
01132 int last_pos_said;
01133 int ring_when_ringing;
01134 time_t last_periodic_announce_time;
01135 int last_periodic_announce_sound;
01136 time_t last_pos;
01137 int opos;
01138 int handled;
01139 int pending;
01140 int max_penalty;
01141 int min_penalty;
01142 int linpos;
01143 int linwrapped;
01144 time_t start;
01145 time_t expire;
01146 int cancel_answered_elsewhere;
01147 struct ast_channel *chan;
01148 AST_LIST_HEAD_NOLOCK(,penalty_rule) qe_rules;
01149 struct penalty_rule *pr;
01150 struct queue_ent *next;
01151 };
01152
01153 struct member {
01154 char interface[AST_CHANNEL_NAME];
01155 char state_exten[AST_MAX_EXTENSION];
01156 char state_context[AST_MAX_CONTEXT];
01157 char state_interface[AST_CHANNEL_NAME];
01158 char membername[80];
01159 int penalty;
01160 int calls;
01161 int dynamic;
01162 int realtime;
01163 int status;
01164 int paused;
01165 time_t lastcall;
01166 struct call_queue *lastqueue;
01167 unsigned int dead:1;
01168 unsigned int delme:1;
01169 char rt_uniqueid[80];
01170 unsigned int ringinuse:1;
01171 };
01172
01173 enum empty_conditions {
01174 QUEUE_EMPTY_PENALTY = (1 << 0),
01175 QUEUE_EMPTY_PAUSED = (1 << 1),
01176 QUEUE_EMPTY_INUSE = (1 << 2),
01177 QUEUE_EMPTY_RINGING = (1 << 3),
01178 QUEUE_EMPTY_UNAVAILABLE = (1 << 4),
01179 QUEUE_EMPTY_INVALID = (1 << 5),
01180 QUEUE_EMPTY_UNKNOWN = (1 << 6),
01181 QUEUE_EMPTY_WRAPUP = (1 << 7),
01182 };
01183
01184 enum member_properties {
01185 MEMBER_PENALTY = 0,
01186 MEMBER_RINGINUSE = 1,
01187 };
01188
01189
01190 #define ANNOUNCEHOLDTIME_ALWAYS 1
01191 #define ANNOUNCEHOLDTIME_ONCE 2
01192 #define QUEUE_EVENT_VARIABLES 3
01193
01194 struct penalty_rule {
01195 int time;
01196 int max_value;
01197 int min_value;
01198 int max_relative;
01199 int min_relative;
01200 AST_LIST_ENTRY(penalty_rule) list;
01201 };
01202
01203 #define ANNOUNCEPOSITION_YES 1
01204 #define ANNOUNCEPOSITION_NO 2
01205 #define ANNOUNCEPOSITION_MORE_THAN 3
01206 #define ANNOUNCEPOSITION_LIMIT 4
01207
01208 struct call_queue {
01209 AST_DECLARE_STRING_FIELDS(
01210
01211 AST_STRING_FIELD(name);
01212
01213 AST_STRING_FIELD(moh);
01214
01215 AST_STRING_FIELD(announce);
01216
01217 AST_STRING_FIELD(context);
01218
01219 AST_STRING_FIELD(membermacro);
01220
01221 AST_STRING_FIELD(membergosub);
01222
01223 AST_STRING_FIELD(defaultrule);
01224
01225 AST_STRING_FIELD(sound_next);
01226
01227 AST_STRING_FIELD(sound_thereare);
01228
01229 AST_STRING_FIELD(sound_calls);
01230
01231 AST_STRING_FIELD(queue_quantity1);
01232
01233 AST_STRING_FIELD(queue_quantity2);
01234
01235 AST_STRING_FIELD(sound_holdtime);
01236
01237 AST_STRING_FIELD(sound_minutes);
01238
01239 AST_STRING_FIELD(sound_minute);
01240
01241 AST_STRING_FIELD(sound_seconds);
01242
01243 AST_STRING_FIELD(sound_thanks);
01244
01245 AST_STRING_FIELD(sound_callerannounce);
01246
01247 AST_STRING_FIELD(sound_reporthold);
01248 );
01249
01250 struct ast_str *sound_periodicannounce[MAX_PERIODIC_ANNOUNCEMENTS];
01251 unsigned int dead:1;
01252 unsigned int eventwhencalled:2;
01253 unsigned int ringinuse:1;
01254 unsigned int setinterfacevar:1;
01255 unsigned int setqueuevar:1;
01256 unsigned int setqueueentryvar:1;
01257 unsigned int reportholdtime:1;
01258 unsigned int wrapped:1;
01259 unsigned int timeoutrestart:1;
01260 unsigned int announceholdtime:2;
01261 unsigned int announceposition:3;
01262 int strategy:4;
01263 unsigned int maskmemberstatus:1;
01264 unsigned int realtime:1;
01265 unsigned int found:1;
01266 unsigned int relativeperiodicannounce:1;
01267 unsigned int autopausebusy:1;
01268 unsigned int autopauseunavail:1;
01269 enum empty_conditions joinempty;
01270 enum empty_conditions leavewhenempty;
01271 int announcepositionlimit;
01272 int announcefrequency;
01273 int minannouncefrequency;
01274 int periodicannouncefrequency;
01275 int numperiodicannounce;
01276 int randomperiodicannounce;
01277 int roundingseconds;
01278 int holdtime;
01279 int talktime;
01280 int callscompleted;
01281 int callsabandoned;
01282 int servicelevel;
01283 int callscompletedinsl;
01284 char monfmt[8];
01285 int montype;
01286 int count;
01287 int maxlen;
01288 int wrapuptime;
01289 int penaltymemberslimit;
01290
01291 int retry;
01292 int timeout;
01293 int weight;
01294 int autopause;
01295 int autopausedelay;
01296 int timeoutpriority;
01297
01298
01299 int rrpos;
01300 int memberdelay;
01301 int autofill;
01302
01303 struct ao2_container *members;
01304 struct queue_ent *head;
01305 AST_LIST_ENTRY(call_queue) list;
01306 AST_LIST_HEAD_NOLOCK(, penalty_rule) rules;
01307 };
01308
01309 struct rule_list {
01310 char name[80];
01311 AST_LIST_HEAD_NOLOCK(,penalty_rule) rules;
01312 AST_LIST_ENTRY(rule_list) list;
01313 };
01314
01315 static AST_LIST_HEAD_STATIC(rule_lists, rule_list);
01316
01317 static struct ao2_container *queues;
01318
01319 static void update_realtime_members(struct call_queue *q);
01320 static struct member *interface_exists(struct call_queue *q, const char *interface);
01321 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused);
01322
01323 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan);
01324
01325 static struct member *find_member_by_queuename_and_interface(const char *queuename, const char *interface);
01326
01327 static void set_queue_result(struct ast_channel *chan, enum queue_result res)
01328 {
01329 int i;
01330
01331 for (i = 0; i < ARRAY_LEN(queue_results); i++) {
01332 if (queue_results[i].id == res) {
01333 pbx_builtin_setvar_helper(chan, "QUEUESTATUS", queue_results[i].text);
01334 return;
01335 }
01336 }
01337 }
01338
01339 static const char *int2strat(int strategy)
01340 {
01341 int x;
01342
01343 for (x = 0; x < ARRAY_LEN(strategies); x++) {
01344 if (strategy == strategies[x].strategy) {
01345 return strategies[x].name;
01346 }
01347 }
01348
01349 return "<unknown>";
01350 }
01351
01352 static int strat2int(const char *strategy)
01353 {
01354 int x;
01355
01356 for (x = 0; x < ARRAY_LEN(strategies); x++) {
01357 if (!strcasecmp(strategy, strategies[x].name)) {
01358 return strategies[x].strategy;
01359 }
01360 }
01361
01362 return -1;
01363 }
01364
01365 static int autopause2int(const char *autopause)
01366 {
01367 int x;
01368
01369 if (ast_strlen_zero(autopause)) {
01370 return QUEUE_AUTOPAUSE_OFF;
01371 }
01372
01373
01374 if(ast_true(autopause)) {
01375 return QUEUE_AUTOPAUSE_ON;
01376 }
01377
01378 for (x = 0; x < ARRAY_LEN(autopausesmodes); x++) {
01379 if (!strcasecmp(autopause, autopausesmodes[x].name)) {
01380 return autopausesmodes[x].autopause;
01381 }
01382 }
01383
01384
01385 return QUEUE_AUTOPAUSE_OFF;
01386 }
01387
01388 static int queue_hash_cb(const void *obj, const int flags)
01389 {
01390 const struct call_queue *q = obj;
01391
01392 return ast_str_case_hash(q->name);
01393 }
01394
01395 static int queue_cmp_cb(void *obj, void *arg, int flags)
01396 {
01397 struct call_queue *q = obj, *q2 = arg;
01398 return !strcasecmp(q->name, q2->name) ? CMP_MATCH | CMP_STOP : 0;
01399 }
01400
01401 #ifdef REF_DEBUG_ONLY_QUEUES
01402 #define queue_ref(q) _queue_ref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01403 #define queue_unref(q) _queue_unref(q, "", __FILE__, __LINE__, __PRETTY_FUNCTION__)
01404 #define queue_t_ref(q, tag) _queue_ref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01405 #define queue_t_unref(q, tag) _queue_unref(q, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01406 #define queues_t_link(c, q, tag) __ao2_link_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01407 #define queues_t_unlink(c, q, tag) __ao2_unlink_debug(c, q, 0, tag, __FILE__, __LINE__, __PRETTY_FUNCTION__)
01408
01409 static inline struct call_queue *_queue_ref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01410 {
01411 __ao2_ref_debug(q, 1, tag, file, line, filename);
01412 return q;
01413 }
01414
01415 static inline struct call_queue *_queue_unref(struct call_queue *q, const char *tag, const char *file, int line, const char *filename)
01416 {
01417 __ao2_ref_debug(q, -1, tag, file, line, filename);
01418 return NULL;
01419 }
01420
01421 #else
01422
01423 #define queue_t_ref(q, tag) queue_ref(q)
01424 #define queue_t_unref(q, tag) queue_unref(q)
01425 #define queues_t_link(c, q, tag) ao2_t_link(c, q, tag)
01426 #define queues_t_unlink(c, q, tag) ao2_t_unlink(c, q, tag)
01427
01428 static inline struct call_queue *queue_ref(struct call_queue *q)
01429 {
01430 ao2_ref(q, 1);
01431 return q;
01432 }
01433
01434 static inline struct call_queue *queue_unref(struct call_queue *q)
01435 {
01436 ao2_ref(q, -1);
01437 return NULL;
01438 }
01439 #endif
01440
01441
01442 static void set_queue_variables(struct call_queue *q, struct ast_channel *chan)
01443 {
01444 char interfacevar[256]="";
01445 float sl = 0;
01446
01447 ao2_lock(q);
01448
01449 if (q->setqueuevar) {
01450 sl = 0;
01451 if (q->callscompleted > 0) {
01452 sl = 100 * ((float) q->callscompletedinsl / (float) q->callscompleted);
01453 }
01454
01455 snprintf(interfacevar, sizeof(interfacevar),
01456 "QUEUENAME=%s,QUEUEMAX=%d,QUEUESTRATEGY=%s,QUEUECALLS=%d,QUEUEHOLDTIME=%d,QUEUETALKTIME=%d,QUEUECOMPLETED=%d,QUEUEABANDONED=%d,QUEUESRVLEVEL=%d,QUEUESRVLEVELPERF=%2.1f",
01457 q->name, q->maxlen, int2strat(q->strategy), q->count, q->holdtime, q->talktime, q->callscompleted, q->callsabandoned, q->servicelevel, sl);
01458
01459 ao2_unlock(q);
01460
01461 pbx_builtin_setvar_multiple(chan, interfacevar);
01462 } else {
01463 ao2_unlock(q);
01464 }
01465 }
01466
01467
01468 static inline void insert_entry(struct call_queue *q, struct queue_ent *prev, struct queue_ent *new, int *pos)
01469 {
01470 struct queue_ent *cur;
01471
01472 if (!q || !new)
01473 return;
01474 if (prev) {
01475 cur = prev->next;
01476 prev->next = new;
01477 } else {
01478 cur = q->head;
01479 q->head = new;
01480 }
01481 new->next = cur;
01482
01483
01484
01485
01486 queue_ref(q);
01487 new->parent = q;
01488 new->pos = ++(*pos);
01489 new->opos = *pos;
01490 }
01491
01492
01493
01494
01495
01496
01497
01498 static int get_member_status(struct call_queue *q, int max_penalty, int min_penalty, enum empty_conditions conditions)
01499 {
01500 struct member *member;
01501 struct ao2_iterator mem_iter;
01502
01503 ao2_lock(q);
01504 mem_iter = ao2_iterator_init(q->members, 0);
01505 for (; (member = ao2_iterator_next(&mem_iter)); ao2_ref(member, -1)) {
01506 if ((max_penalty && (member->penalty > max_penalty)) || (min_penalty && (member->penalty < min_penalty))) {
01507 if (conditions & QUEUE_EMPTY_PENALTY) {
01508 ast_debug(4, "%s is unavailable because his penalty is not between %d and %d\n", member->membername, min_penalty, max_penalty);
01509 continue;
01510 }
01511 }
01512
01513 switch (member->status) {
01514 case AST_DEVICE_INVALID:
01515 if (conditions & QUEUE_EMPTY_INVALID) {
01516 ast_debug(4, "%s is unavailable because his device state is 'invalid'\n", member->membername);
01517 break;
01518 }
01519 goto default_case;
01520 case AST_DEVICE_UNAVAILABLE:
01521 if (conditions & QUEUE_EMPTY_UNAVAILABLE) {
01522 ast_debug(4, "%s is unavailable because his device state is 'unavailable'\n", member->membername);
01523 break;
01524 }
01525 goto default_case;
01526 case AST_DEVICE_INUSE:
01527 if (conditions & QUEUE_EMPTY_INUSE) {
01528 ast_debug(4, "%s is unavailable because his device state is 'inuse'\n", member->membername);
01529 break;
01530 }
01531 goto default_case;
01532 case AST_DEVICE_RINGING:
01533 if (conditions & QUEUE_EMPTY_RINGING) {
01534 ast_debug(4, "%s is unavailable because his device state is 'ringing'\n", member->membername);
01535 break;
01536 }
01537 goto default_case;
01538 case AST_DEVICE_UNKNOWN:
01539 if (conditions & QUEUE_EMPTY_UNKNOWN) {
01540 ast_debug(4, "%s is unavailable because his device state is 'unknown'\n", member->membername);
01541 break;
01542 }
01543
01544 default:
01545 default_case:
01546 if (member->paused && (conditions & QUEUE_EMPTY_PAUSED)) {
01547 ast_debug(4, "%s is unavailable because he is paused'\n", member->membername);
01548 break;
01549 } else if ((conditions & QUEUE_EMPTY_WRAPUP) && member->lastcall && q->wrapuptime && (time(NULL) - q->wrapuptime < member->lastcall)) {
01550 ast_debug(4, "%s is unavailable because it has only been %d seconds since his last call (wrapup time is %d)\n", member->membername, (int) (time(NULL) - member->lastcall), q->wrapuptime);
01551 break;
01552 } else {
01553 ao2_ref(member, -1);
01554 ao2_iterator_destroy(&mem_iter);
01555 ao2_unlock(q);
01556 ast_debug(4, "%s is available.\n", member->membername);
01557 return 0;
01558 }
01559 break;
01560 }
01561 }
01562 ao2_iterator_destroy(&mem_iter);
01563
01564 ao2_unlock(q);
01565 return -1;
01566 }
01567
01568 struct statechange {
01569 AST_LIST_ENTRY(statechange) entry;
01570 int state;
01571 char dev[0];
01572 };
01573
01574
01575
01576
01577
01578
01579 static int update_status(struct call_queue *q, struct member *m, const int status)
01580 {
01581 m->status = status;
01582
01583 if (q->maskmemberstatus) {
01584 return 0;
01585 }
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642 manager_event(EVENT_FLAG_AGENT, "QueueMemberStatus",
01643 "Queue: %s\r\n"
01644 "Location: %s\r\n"
01645 "MemberName: %s\r\n"
01646 "StateInterface: %s\r\n"
01647 "Membership: %s\r\n"
01648 "Penalty: %d\r\n"
01649 "CallsTaken: %d\r\n"
01650 "LastCall: %d\r\n"
01651 "Status: %d\r\n"
01652 "Paused: %d\r\n",
01653 q->name, m->interface, m->membername, m->state_interface, m->dynamic ? "dynamic" : m->realtime ? "realtime" : "static",
01654 m->penalty, m->calls, (int)m->lastcall, m->status, m->paused
01655 );
01656
01657 return 0;
01658 }
01659
01660
01661
01662
01663
01664
01665 static int is_member_available(struct member *mem)
01666 {
01667 int available = 0;
01668
01669 switch (mem->status) {
01670 case AST_DEVICE_INVALID:
01671 case AST_DEVICE_UNAVAILABLE:
01672 break;
01673 case AST_DEVICE_INUSE:
01674 case AST_DEVICE_BUSY:
01675 case AST_DEVICE_RINGING:
01676 case AST_DEVICE_RINGINUSE:
01677 case AST_DEVICE_ONHOLD:
01678 if (!mem->ringinuse) {
01679 break;
01680 }
01681
01682 case AST_DEVICE_NOT_INUSE:
01683 case AST_DEVICE_UNKNOWN:
01684 if (!mem->paused) {
01685 available = 1;
01686 }
01687 break;
01688 }
01689
01690 return available;
01691 }
01692
01693
01694 static int handle_statechange(void *datap)
01695 {
01696 struct statechange *sc = datap;
01697 struct ao2_iterator miter, qiter;
01698 struct member *m;
01699 struct call_queue *q;
01700 char interface[80], *slash_pos;
01701 int found = 0;
01702 int found_member;
01703 int avail = 0;
01704
01705 qiter = ao2_iterator_init(queues, 0);
01706 while ((q = ao2_t_iterator_next(&qiter, "Iterate over queues"))) {
01707 ao2_lock(q);
01708
01709 avail = 0;
01710 found_member = 0;
01711 miter = ao2_iterator_init(q->members, 0);
01712 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
01713 if (!found_member) {
01714 ast_copy_string(interface, m->state_interface, sizeof(interface));
01715
01716 if ((slash_pos = strchr(interface, '/'))) {
01717 if (!strncasecmp(interface, "Local/", 6) && (slash_pos = strchr(slash_pos + 1, '/'))) {
01718 *slash_pos = '\0';
01719 }
01720 }
01721
01722 if (!strcasecmp(interface, sc->dev)) {
01723 found_member = 1;
01724 update_status(q, m, sc->state);
01725 }
01726 }
01727
01728
01729 if (!avail) {
01730 avail = is_member_available(m);
01731 }
01732 if (avail && found_member) {
01733
01734 ao2_ref(m, -1);
01735 break;
01736 }
01737 }
01738
01739 if (found_member) {
01740 found = 1;
01741 if (avail) {
01742 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s_avail", q->name);
01743 } else {
01744 ast_devstate_changed(AST_DEVICE_INUSE, "Queue:%s_avail", q->name);
01745 }
01746 }
01747
01748 ao2_iterator_destroy(&miter);
01749
01750 ao2_unlock(q);
01751 queue_t_unref(q, "Done with iterator");
01752 }
01753 ao2_iterator_destroy(&qiter);
01754
01755 if (found) {
01756 ast_debug(1, "Device '%s' changed to state '%d' (%s)\n", sc->dev, sc->state, ast_devstate2str(sc->state));
01757 } else {
01758 ast_debug(3, "Device '%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n", sc->dev, sc->state, ast_devstate2str(sc->state));
01759 }
01760
01761 ast_free(sc);
01762 return 0;
01763 }
01764
01765 static void device_state_cb(const struct ast_event *event, void *unused)
01766 {
01767 enum ast_device_state state;
01768 const char *device;
01769 struct statechange *sc;
01770 size_t datapsize;
01771
01772 state = ast_event_get_ie_uint(event, AST_EVENT_IE_STATE);
01773 device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
01774
01775 if (ast_strlen_zero(device)) {
01776 ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
01777 return;
01778 }
01779 datapsize = sizeof(*sc) + strlen(device) + 1;
01780 if (!(sc = ast_calloc(1, datapsize))) {
01781 ast_log(LOG_ERROR, "failed to calloc a state change struct\n");
01782 return;
01783 }
01784 sc->state = state;
01785 strcpy(sc->dev, device);
01786 if (ast_taskprocessor_push(devicestate_tps, handle_statechange, sc) < 0) {
01787 ast_free(sc);
01788 }
01789 }
01790
01791
01792 static int extensionstate2devicestate(int state)
01793 {
01794 switch (state) {
01795 case AST_EXTENSION_NOT_INUSE:
01796 state = AST_DEVICE_NOT_INUSE;
01797 break;
01798 case AST_EXTENSION_INUSE:
01799 state = AST_DEVICE_INUSE;
01800 break;
01801 case AST_EXTENSION_BUSY:
01802 state = AST_DEVICE_BUSY;
01803 break;
01804 case AST_EXTENSION_RINGING:
01805 state = AST_DEVICE_RINGING;
01806 break;
01807 case AST_EXTENSION_ONHOLD:
01808 state = AST_DEVICE_ONHOLD;
01809 break;
01810 case AST_EXTENSION_UNAVAILABLE:
01811 state = AST_DEVICE_UNAVAILABLE;
01812 break;
01813 case AST_EXTENSION_REMOVED:
01814 case AST_EXTENSION_DEACTIVATED:
01815 default:
01816 state = AST_DEVICE_INVALID;
01817 break;
01818 }
01819
01820 return state;
01821 }
01822
01823 static int extension_state_cb(char *context, char *exten, struct ast_state_cb_info *info, void *data)
01824 {
01825 struct ao2_iterator miter, qiter;
01826 struct member *m;
01827 struct call_queue *q;
01828 int state = info->exten_state;
01829 int found = 0, device_state = extensionstate2devicestate(state);
01830
01831
01832 if (info->reason != AST_HINT_UPDATE_DEVICE) {
01833 return 0;
01834 }
01835
01836 qiter = ao2_iterator_init(queues, 0);
01837 while ((q = ao2_t_iterator_next(&qiter, "Iterate through queues"))) {
01838 ao2_lock(q);
01839
01840 miter = ao2_iterator_init(q->members, 0);
01841 for (; (m = ao2_iterator_next(&miter)); ao2_ref(m, -1)) {
01842 if (!strcmp(m->state_context, context) && !strcmp(m->state_exten, exten)) {
01843 update_status(q, m, device_state);
01844 ao2_ref(m, -1);
01845 found = 1;
01846 break;
01847 }
01848 }
01849 ao2_iterator_destroy(&miter);
01850
01851 ao2_unlock(q);
01852 queue_t_unref(q, "Done with iterator");
01853 }
01854 ao2_iterator_destroy(&qiter);
01855
01856 if (found) {
01857 ast_debug(1, "Extension '%s@%s' changed to state '%d' (%s)\n", exten, context, device_state, ast_devstate2str(device_state));
01858 } else {
01859 ast_debug(3, "Extension '%s@%s' changed to state '%d' (%s) but we don't care because they're not a member of any queue.\n",
01860 exten, context, device_state, ast_devstate2str(device_state));
01861 }
01862
01863 return 0;
01864 }
01865
01866
01867 static int get_queue_member_status(struct member *cur)
01868 {
01869 return ast_strlen_zero(cur->state_exten) ? ast_device_state(cur->state_interface) : extensionstate2devicestate(ast_extension_state(NULL, cur->state_context, cur->state_exten));
01870 }
01871
01872
01873 static struct member *create_queue_member(const char *interface, const char *membername, int penalty, int paused, const char *state_interface, int ringinuse)
01874 {
01875 struct member *cur;
01876
01877 if ((cur = ao2_alloc(sizeof(*cur), NULL))) {
01878 cur->ringinuse = ringinuse;
01879 cur->penalty = penalty;
01880 cur->paused = paused;
01881 ast_copy_string(cur->interface, interface, sizeof(cur->interface));
01882 if (!ast_strlen_zero(state_interface)) {
01883 ast_copy_string(cur->state_interface, state_interface, sizeof(cur->state_interface));
01884 } else {
01885 ast_copy_string(cur->state_interface, interface, sizeof(cur->state_interface));
01886 }
01887 if (!ast_strlen_zero(membername)) {
01888 ast_copy_string(cur->membername, membername, sizeof(cur->membername));
01889 } else {
01890 ast_copy_string(cur->membername, interface, sizeof(cur->membername));
01891 }
01892 if (!strchr(cur->interface, '/')) {
01893 ast_log(LOG_WARNING, "No location at interface '%s'\n", interface);
01894 }
01895 if (!strncmp(cur->state_interface, "hint:", 5)) {
01896 char *tmp = ast_strdupa(cur->state_interface), *context = tmp;
01897 char *exten = strsep(&context, "@") + 5;
01898
01899 ast_copy_string(cur->state_exten, exten, sizeof(cur->state_exten));
01900 ast_copy_string(cur->state_context, S_OR(context, "default"), sizeof(cur->state_context));
01901 }
01902 cur->status = get_queue_member_status(cur);
01903 }
01904
01905 return cur;
01906 }
01907
01908
01909 static int compress_char(const char c)
01910 {
01911 if (c < 32) {
01912 return 0;
01913 } else if (c > 96) {
01914 return c - 64;
01915 }
01916 return c - 32;
01917 }
01918
01919 static int member_hash_fn(const void *obj, const int flags)
01920 {
01921 const struct member *mem = obj;
01922 const char *interface = (flags & OBJ_KEY) ? obj : mem->interface;
01923 const char *chname = strchr(interface, '/');
01924 int ret = 0, i;
01925
01926 if (!chname) {
01927 chname = interface;
01928 }
01929 for (i = 0; i < 5 && chname[i]; i++) {
01930 ret += compress_char(chname[i]) << (i * 6);
01931 }
01932 return ret;
01933 }
01934
01935 static int member_cmp_fn(void *obj1, void *obj2, int flags)
01936 {
01937 struct member *mem1 = obj1;
01938 struct member *mem2 = obj2;
01939 const char *interface = (flags & OBJ_KEY) ? obj2 : mem2->interface;
01940
01941 return strcasecmp(mem1->interface, interface) ? 0 : CMP_MATCH | CMP_STOP;
01942 }
01943
01944
01945
01946
01947
01948 static void init_queue(struct call_queue *q)
01949 {
01950 int i;
01951 struct penalty_rule *pr_iter;
01952
01953 q->dead = 0;
01954 q->retry = DEFAULT_RETRY;
01955 q->timeout = DEFAULT_TIMEOUT;
01956 q->maxlen = 0;
01957 q->announcefrequency = 0;
01958 q->minannouncefrequency = DEFAULT_MIN_ANNOUNCE_FREQUENCY;
01959 q->announceholdtime = 1;
01960 q->announcepositionlimit = 10;
01961 q->announceposition = ANNOUNCEPOSITION_YES;
01962 q->roundingseconds = 0;
01963 q->servicelevel = 0;
01964 q->ringinuse = 1;
01965 q->setinterfacevar = 0;
01966 q->setqueuevar = 0;
01967 q->setqueueentryvar = 0;
01968 q->autofill = autofill_default;
01969 q->montype = montype_default;
01970 q->monfmt[0] = '\0';
01971 q->reportholdtime = 0;
01972 q->wrapuptime = 0;
01973 q->penaltymemberslimit = 0;
01974 q->joinempty = 0;
01975 q->leavewhenempty = 0;
01976 q->memberdelay = 0;
01977 q->maskmemberstatus = 0;
01978 q->eventwhencalled = 0;
01979 q->weight = 0;
01980 q->timeoutrestart = 0;
01981 q->periodicannouncefrequency = 0;
01982 q->randomperiodicannounce = 0;
01983 q->numperiodicannounce = 0;
01984 q->autopause = QUEUE_AUTOPAUSE_OFF;
01985 q->timeoutpriority = TIMEOUT_PRIORITY_APP;
01986 q->autopausedelay = 0;
01987 if (!q->members) {
01988 if (q->strategy == QUEUE_STRATEGY_LINEAR || q->strategy == QUEUE_STRATEGY_RRORDERED) {
01989
01990 q->members = ao2_container_alloc(1, member_hash_fn, member_cmp_fn);
01991 } else {
01992 q->members = ao2_container_alloc(37, member_hash_fn, member_cmp_fn);
01993 }
01994 }
01995 q->found = 1;
01996
01997 ast_string_field_set(q, sound_next, "queue-youarenext");
01998 ast_string_field_set(q, sound_thereare, "queue-thereare");
01999 ast_string_field_set(q, sound_calls, "queue-callswaiting");
02000 ast_string_field_set(q, queue_quantity1, "queue-quantity1");
02001 ast_string_field_set(q, queue_quantity2, "queue-quantity2");
02002 ast_string_field_set(q, sound_holdtime, "queue-holdtime");
02003 ast_string_field_set(q, sound_minutes, "queue-minutes");
02004 ast_string_field_set(q, sound_minute, "queue-minute");
02005 ast_string_field_set(q, sound_seconds, "queue-seconds");
02006 ast_string_field_set(q, sound_thanks, "queue-thankyou");
02007 ast_string_field_set(q, sound_reporthold, "queue-reporthold");
02008
02009 if (!q->sound_periodicannounce[0]) {
02010 q->sound_periodicannounce[0] = ast_str_create(32);
02011 }
02012
02013 if (q->sound_periodicannounce[0]) {
02014 ast_str_set(&q->sound_periodicannounce[0], 0, "queue-periodic-announce");
02015 }
02016
02017 for (i = 1; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
02018 if (q->sound_periodicannounce[i]) {
02019 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", "");
02020 }
02021 }
02022
02023 while ((pr_iter = AST_LIST_REMOVE_HEAD(&q->rules,list))) {
02024 ast_free(pr_iter);
02025 }
02026
02027
02028
02029
02030
02031
02032
02033
02034 ast_devstate_changed(AST_DEVICE_INUSE, "Queue:%s_avail", q->name);
02035 }
02036
02037 static void clear_queue(struct call_queue *q)
02038 {
02039 q->holdtime = 0;
02040 q->callscompleted = 0;
02041 q->callsabandoned = 0;
02042 q->callscompletedinsl = 0;
02043 q->talktime = 0;
02044
02045 if (q->members) {
02046 struct member *mem;
02047 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
02048 while ((mem = ao2_iterator_next(&mem_iter))) {
02049 mem->calls = 0;
02050 mem->lastcall = 0;
02051 ao2_ref(mem, -1);
02052 }
02053 ao2_iterator_destroy(&mem_iter);
02054 }
02055 }
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066 static int insert_penaltychange(const char *list_name, const char *content, const int linenum)
02067 {
02068 char *timestr, *maxstr, *minstr, *contentdup;
02069 struct penalty_rule *rule = NULL, *rule_iter;
02070 struct rule_list *rl_iter;
02071 int penaltychangetime, inserted = 0;
02072
02073 if (!(rule = ast_calloc(1, sizeof(*rule)))) {
02074 return -1;
02075 }
02076
02077 contentdup = ast_strdupa(content);
02078
02079 if (!(maxstr = strchr(contentdup, ','))) {
02080 ast_log(LOG_WARNING, "Improperly formatted penaltychange rule at line %d. Ignoring.\n", linenum);
02081 ast_free(rule);
02082 return -1;
02083 }
02084
02085 *maxstr++ = '\0';
02086 timestr = contentdup;
02087
02088 if ((penaltychangetime = atoi(timestr)) < 0) {
02089 ast_log(LOG_WARNING, "Improper time parameter specified for penaltychange rule at line %d. Ignoring.\n", linenum);
02090 ast_free(rule);
02091 return -1;
02092 }
02093
02094 rule->time = penaltychangetime;
02095
02096 if ((minstr = strchr(maxstr,','))) {
02097 *minstr++ = '\0';
02098 }
02099
02100
02101
02102 if (*maxstr == '+' || *maxstr == '-' || *maxstr == '\0') {
02103 rule->max_relative = 1;
02104 }
02105
02106 rule->max_value = atoi(maxstr);
02107
02108 if (!ast_strlen_zero(minstr)) {
02109 if (*minstr == '+' || *minstr == '-') {
02110 rule->min_relative = 1;
02111 }
02112 rule->min_value = atoi(minstr);
02113 } else {
02114 rule->min_relative = 1;
02115 }
02116
02117
02118 AST_LIST_TRAVERSE(&rule_lists, rl_iter, list){
02119 if (strcasecmp(rl_iter->name, list_name)) {
02120 continue;
02121 }
02122
02123 AST_LIST_TRAVERSE_SAFE_BEGIN(&rl_iter->rules, rule_iter, list) {
02124 if (rule->time < rule_iter->time) {
02125 AST_LIST_INSERT_BEFORE_CURRENT(rule, list);
02126 inserted = 1;
02127 break;
02128 }
02129 }
02130 AST_LIST_TRAVERSE_SAFE_END;
02131
02132 if (!inserted) {
02133 AST_LIST_INSERT_TAIL(&rl_iter->rules, rule, list);
02134 inserted = 1;
02135 }
02136
02137 break;
02138 }
02139
02140 if (!inserted) {
02141 ast_log(LOG_WARNING, "Unknown rule list name %s; ignoring.\n", list_name);
02142 ast_free(rule);
02143 return -1;
02144 }
02145 return 0;
02146 }
02147
02148 static void parse_empty_options(const char *value, enum empty_conditions *empty, int joinempty)
02149 {
02150 char *value_copy = ast_strdupa(value);
02151 char *option = NULL;
02152 while ((option = strsep(&value_copy, ","))) {
02153 if (!strcasecmp(option, "paused")) {
02154 *empty |= QUEUE_EMPTY_PAUSED;
02155 } else if (!strcasecmp(option, "penalty")) {
02156 *empty |= QUEUE_EMPTY_PENALTY;
02157 } else if (!strcasecmp(option, "inuse")) {
02158 *empty |= QUEUE_EMPTY_INUSE;
02159 } else if (!strcasecmp(option, "ringing")) {
02160 *empty |= QUEUE_EMPTY_RINGING;
02161 } else if (!strcasecmp(option, "invalid")) {
02162 *empty |= QUEUE_EMPTY_INVALID;
02163 } else if (!strcasecmp(option, "wrapup")) {
02164 *empty |= QUEUE_EMPTY_WRAPUP;
02165 } else if (!strcasecmp(option, "unavailable")) {
02166 *empty |= QUEUE_EMPTY_UNAVAILABLE;
02167 } else if (!strcasecmp(option, "unknown")) {
02168 *empty |= QUEUE_EMPTY_UNKNOWN;
02169 } else if (!strcasecmp(option, "loose")) {
02170 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID);
02171 } else if (!strcasecmp(option, "strict")) {
02172 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED | QUEUE_EMPTY_UNAVAILABLE);
02173 } else if ((ast_false(option) && joinempty) || (ast_true(option) && !joinempty)) {
02174 *empty = (QUEUE_EMPTY_PENALTY | QUEUE_EMPTY_INVALID | QUEUE_EMPTY_PAUSED);
02175 } else if ((ast_false(option) && !joinempty) || (ast_true(option) && joinempty)) {
02176 *empty = 0;
02177 } else {
02178 ast_log(LOG_WARNING, "Unknown option %s for '%s'\n", option, joinempty ? "joinempty" : "leavewhenempty");
02179 }
02180 }
02181 }
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191 static void queue_set_param(struct call_queue *q, const char *param, const char *val, int linenum, int failunknown)
02192 {
02193 if (!strcasecmp(param, "musicclass") ||
02194 !strcasecmp(param, "music") || !strcasecmp(param, "musiconhold")) {
02195 ast_string_field_set(q, moh, val);
02196 } else if (!strcasecmp(param, "announce")) {
02197 ast_string_field_set(q, announce, val);
02198 } else if (!strcasecmp(param, "context")) {
02199 ast_string_field_set(q, context, val);
02200 } else if (!strcasecmp(param, "timeout")) {
02201 q->timeout = atoi(val);
02202 if (q->timeout < 0) {
02203 q->timeout = DEFAULT_TIMEOUT;
02204 }
02205 } else if (!strcasecmp(param, "ringinuse")) {
02206 q->ringinuse = ast_true(val);
02207 } else if (!strcasecmp(param, "setinterfacevar")) {
02208 q->setinterfacevar = ast_true(val);
02209 } else if (!strcasecmp(param, "setqueuevar")) {
02210 q->setqueuevar = ast_true(val);
02211 } else if (!strcasecmp(param, "setqueueentryvar")) {
02212 q->setqueueentryvar = ast_true(val);
02213 } else if (!strcasecmp(param, "monitor-format")) {
02214 ast_copy_string(q->monfmt, val, sizeof(q->monfmt));
02215 } else if (!strcasecmp(param, "membermacro")) {
02216 ast_string_field_set(q, membermacro, val);
02217 } else if (!strcasecmp(param, "membergosub")) {
02218 ast_string_field_set(q, membergosub, val);
02219 } else if (!strcasecmp(param, "queue-youarenext")) {
02220 ast_string_field_set(q, sound_next, val);
02221 } else if (!strcasecmp(param, "queue-thereare")) {
02222 ast_string_field_set(q, sound_thereare, val);
02223 } else if (!strcasecmp(param, "queue-callswaiting")) {
02224 ast_string_field_set(q, sound_calls, val);
02225 } else if (!strcasecmp(param, "queue-quantity1")) {
02226 ast_string_field_set(q, queue_quantity1, val);
02227 } else if (!strcasecmp(param, "queue-quantity2")) {
02228 ast_string_field_set(q, queue_quantity2, val);
02229 } else if (!strcasecmp(param, "queue-holdtime")) {
02230 ast_string_field_set(q, sound_holdtime, val);
02231 } else if (!strcasecmp(param, "queue-minutes")) {
02232 ast_string_field_set(q, sound_minutes, val);
02233 } else if (!strcasecmp(param, "queue-minute")) {
02234 ast_string_field_set(q, sound_minute, val);
02235 } else if (!strcasecmp(param, "queue-seconds")) {
02236 ast_string_field_set(q, sound_seconds, val);
02237 } else if (!strcasecmp(param, "queue-thankyou")) {
02238 ast_string_field_set(q, sound_thanks, val);
02239 } else if (!strcasecmp(param, "queue-callerannounce")) {
02240 ast_string_field_set(q, sound_callerannounce, val);
02241 } else if (!strcasecmp(param, "queue-reporthold")) {
02242 ast_string_field_set(q, sound_reporthold, val);
02243 } else if (!strcasecmp(param, "announce-frequency")) {
02244 q->announcefrequency = atoi(val);
02245 } else if (!strcasecmp(param, "min-announce-frequency")) {
02246 q->minannouncefrequency = atoi(val);
02247 ast_debug(1, "%s=%s for queue '%s'\n", param, val, q->name);
02248 } else if (!strcasecmp(param, "announce-round-seconds")) {
02249 q->roundingseconds = atoi(val);
02250
02251 if (!(q->roundingseconds == 0 || q->roundingseconds == 5 || q->roundingseconds == 10
02252 || q->roundingseconds == 15 || q->roundingseconds == 20 || q->roundingseconds == 30)) {
02253 if (linenum >= 0) {
02254 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02255 "using 0 instead for queue '%s' at line %d of queues.conf\n",
02256 val, param, q->name, linenum);
02257 } else {
02258 ast_log(LOG_WARNING, "'%s' isn't a valid value for %s "
02259 "using 0 instead for queue '%s'\n", val, param, q->name);
02260 }
02261 q->roundingseconds=0;
02262 }
02263 } else if (!strcasecmp(param, "announce-holdtime")) {
02264 if (!strcasecmp(val, "once")) {
02265 q->announceholdtime = ANNOUNCEHOLDTIME_ONCE;
02266 } else if (ast_true(val)) {
02267 q->announceholdtime = ANNOUNCEHOLDTIME_ALWAYS;
02268 } else {
02269 q->announceholdtime = 0;
02270 }
02271 } else if (!strcasecmp(param, "announce-position")) {
02272 if (!strcasecmp(val, "limit")) {
02273 q->announceposition = ANNOUNCEPOSITION_LIMIT;
02274 } else if (!strcasecmp(val, "more")) {
02275 q->announceposition = ANNOUNCEPOSITION_MORE_THAN;
02276 } else if (ast_true(val)) {
02277 q->announceposition = ANNOUNCEPOSITION_YES;
02278 } else {
02279 q->announceposition = ANNOUNCEPOSITION_NO;
02280 }
02281 } else if (!strcasecmp(param, "announce-position-limit")) {
02282 q->announcepositionlimit = atoi(val);
02283 } else if (!strcasecmp(param, "periodic-announce")) {
02284 if (strchr(val, ',')) {
02285 char *s, *buf = ast_strdupa(val);
02286 unsigned int i = 0;
02287
02288 while ((s = strsep(&buf, ",|"))) {
02289 if (!q->sound_periodicannounce[i]) {
02290 q->sound_periodicannounce[i] = ast_str_create(16);
02291 }
02292 ast_str_set(&q->sound_periodicannounce[i], 0, "%s", s);
02293 i++;
02294 if (i == MAX_PERIODIC_ANNOUNCEMENTS) {
02295 break;
02296 }
02297 }
02298 q->numperiodicannounce = i;
02299 } else {
02300 ast_str_set(&q->sound_periodicannounce[0], 0, "%s", val);
02301 q->numperiodicannounce = 1;
02302 }
02303 } else if (!strcasecmp(param, "periodic-announce-frequency")) {
02304 q->periodicannouncefrequency = atoi(val);
02305 } else if (!strcasecmp(param, "relative-periodic-announce")) {
02306 q->relativeperiodicannounce = ast_true(val);
02307 } else if (!strcasecmp(param, "random-periodic-announce")) {
02308 q->randomperiodicannounce = ast_true(val);
02309 } else if (!strcasecmp(param, "retry")) {
02310 q->retry = atoi(val);
02311 if (q->retry <= 0) {
02312 q->retry = DEFAULT_RETRY;
02313 }
02314 } else if (!strcasecmp(param, "wrapuptime")) {
02315 q->wrapuptime = atoi(val);
02316 } else if (!strcasecmp(param, "penaltymemberslimit")) {
02317 if ((sscanf(val, "%10d", &q->penaltymemberslimit) != 1)) {
02318 q->penaltymemberslimit = 0;
02319 }
02320 } else if (!strcasecmp(param, "autofill")) {
02321 q->autofill = ast_true(val);
02322 } else if (!strcasecmp(param, "monitor-type")) {
02323 if (!strcasecmp(val, "mixmonitor")) {
02324 q->montype = 1;
02325 }
02326 } else if (!strcasecmp(param, "autopause")) {
02327 q->autopause = autopause2int(val);
02328 } else if (!strcasecmp(param, "autopausedelay")) {
02329 q->autopausedelay = atoi(val);
02330 } else if (!strcasecmp(param, "autopausebusy")) {
02331 q->autopausebusy = ast_true(val);
02332 } else if (!strcasecmp(param, "autopauseunavail")) {
02333 q->autopauseunavail = ast_true(val);
02334 } else if (!strcasecmp(param, "maxlen")) {
02335 q->maxlen = atoi(val);
02336 if (q->maxlen < 0) {
02337 q->maxlen = 0;
02338 }
02339 } else if (!strcasecmp(param, "servicelevel")) {
02340 q->servicelevel= atoi(val);
02341 } else if (!strcasecmp(param, "strategy")) {
02342 int strategy;
02343
02344
02345 if (failunknown) {
02346 return;
02347 }
02348 strategy = strat2int(val);
02349 if (strategy < 0) {
02350 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
02351 val, q->name);
02352 q->strategy = QUEUE_STRATEGY_RINGALL;
02353 }
02354 if (strategy == q->strategy) {
02355 return;
02356 }
02357 if (strategy == QUEUE_STRATEGY_LINEAR) {
02358 ast_log(LOG_WARNING, "Changing to the linear strategy currently requires asterisk to be restarted.\n");
02359 return;
02360 }
02361 q->strategy = strategy;
02362 } else if (!strcasecmp(param, "joinempty")) {
02363 parse_empty_options(val, &q->joinempty, 1);
02364 } else if (!strcasecmp(param, "leavewhenempty")) {
02365 parse_empty_options(val, &q->leavewhenempty, 0);
02366 } else if (!strcasecmp(param, "eventmemberstatus")) {
02367 q->maskmemberstatus = !ast_true(val);
02368 } else if (!strcasecmp(param, "eventwhencalled")) {
02369 if (!strcasecmp(val, "vars")) {
02370 q->eventwhencalled = QUEUE_EVENT_VARIABLES;
02371 } else {
02372 q->eventwhencalled = ast_true(val) ? 1 : 0;
02373 }
02374 } else if (!strcasecmp(param, "reportholdtime")) {
02375 q->reportholdtime = ast_true(val);
02376 } else if (!strcasecmp(param, "memberdelay")) {
02377 q->memberdelay = atoi(val);
02378 } else if (!strcasecmp(param, "weight")) {
02379 q->weight = atoi(val);
02380 } else if (!strcasecmp(param, "timeoutrestart")) {
02381 q->timeoutrestart = ast_true(val);
02382 } else if (!strcasecmp(param, "defaultrule")) {
02383 ast_string_field_set(q, defaultrule, val);
02384 } else if (!strcasecmp(param, "timeoutpriority")) {
02385 if (!strcasecmp(val, "conf")) {
02386 q->timeoutpriority = TIMEOUT_PRIORITY_CONF;
02387 } else {
02388 q->timeoutpriority = TIMEOUT_PRIORITY_APP;
02389 }
02390 } else if (failunknown) {
02391 if (linenum >= 0) {
02392 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s at line %d of queues.conf\n",
02393 q->name, param, linenum);
02394 } else {
02395 ast_log(LOG_WARNING, "Unknown keyword in queue '%s': %s\n", q->name, param);
02396 }
02397 }
02398 }
02399
02400
02401
02402
02403
02404
02405
02406 static void rt_handle_member_record(struct call_queue *q, char *interface, struct ast_config *member_config)
02407 {
02408 struct member *m;
02409 struct ao2_iterator mem_iter;
02410 int penalty = 0;
02411 int paused = 0;
02412 int found = 0;
02413 int ringinuse = q->ringinuse;
02414
02415 const char *config_val;
02416 const char *rt_uniqueid = ast_variable_retrieve(member_config, interface, "uniqueid");
02417 const char *membername = S_OR(ast_variable_retrieve(member_config, interface, "membername"), interface);
02418 const char *state_interface = S_OR(ast_variable_retrieve(member_config, interface, "state_interface"), interface);
02419 const char *penalty_str = ast_variable_retrieve(member_config, interface, "penalty");
02420 const char *paused_str = ast_variable_retrieve(member_config, interface, "paused");
02421
02422 if (ast_strlen_zero(rt_uniqueid)) {
02423 ast_log(LOG_WARNING, "Realtime field uniqueid is empty for member %s\n", S_OR(membername, "NULL"));
02424 return;
02425 }
02426
02427 if (penalty_str) {
02428 penalty = atoi(penalty_str);
02429 if ((penalty < 0) && negative_penalty_invalid) {
02430 return;
02431 } else if (penalty < 0) {
02432 penalty = 0;
02433 }
02434 }
02435
02436 if (paused_str) {
02437 paused = atoi(paused_str);
02438 if (paused < 0) {
02439 paused = 0;
02440 }
02441 }
02442
02443 if ((config_val = ast_variable_retrieve(member_config, interface, realtime_ringinuse_field))) {
02444 if (ast_true(config_val)) {
02445 ringinuse = 1;
02446 } else if (ast_false(config_val)) {
02447 ringinuse = 0;
02448 } else {
02449 ast_log(LOG_WARNING, "Invalid value of '%s' field for %s in queue '%s'\n", realtime_ringinuse_field, interface, q->name);
02450 }
02451 }
02452
02453
02454 mem_iter = ao2_iterator_init(q->members, 0);
02455 while ((m = ao2_iterator_next(&mem_iter))) {
02456 if (!strcasecmp(m->rt_uniqueid, rt_uniqueid)) {
02457 m->dead = 0;
02458 ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
02459 if (paused_str) {
02460 m->paused = paused;
02461 }
02462 if (strcasecmp(state_interface, m->state_interface)) {
02463 ast_copy_string(m->state_interface, state_interface, sizeof(m->state_interface));
02464 }
02465 m->penalty = penalty;
02466 m->ringinuse = ringinuse;
02467 found = 1;
02468 ao2_ref(m, -1);
02469 break;
02470 }
02471 ao2_ref(m, -1);
02472 }
02473 ao2_iterator_destroy(&mem_iter);
02474
02475
02476 if (!found) {
02477 if ((m = create_queue_member(interface, membername, penalty, paused, state_interface, ringinuse))) {
02478 m->dead = 0;
02479 m->realtime = 1;
02480 ast_copy_string(m->rt_uniqueid, rt_uniqueid, sizeof(m->rt_uniqueid));
02481 if (!log_membername_as_agent) {
02482 ast_queue_log(q->name, "REALTIME", m->interface, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
02483 } else {
02484 ast_queue_log(q->name, "REALTIME", m->membername, "ADDMEMBER", "%s", paused ? "PAUSED" : "");
02485 }
02486 ao2_link(q->members, m);
02487 ao2_ref(m, -1);
02488 m = NULL;
02489 }
02490 }
02491 }
02492
02493
02494 static void free_members(struct call_queue *q, int all)
02495 {
02496
02497 struct member *cur;
02498 struct ao2_iterator mem_iter = ao2_iterator_init(q->members, 0);
02499
02500 while ((cur = ao2_iterator_next(&mem_iter))) {
02501 if (all || !cur->dynamic) {
02502 ao2_unlink(q->members, cur);
02503 }
02504 ao2_ref(cur, -1);
02505 }
02506 ao2_iterator_destroy(&mem_iter);
02507 }
02508
02509
02510 static void destroy_queue(void *obj)
02511 {
02512 struct call_queue *q = obj;
02513 int i;
02514
02515 free_members(q, 1);
02516 ast_string_field_free_memory(q);
02517 for (i = 0; i < MAX_PERIODIC_ANNOUNCEMENTS; i++) {
02518 if (q->sound_periodicannounce[i]) {
02519 free(q->sound_periodicannounce[i]);
02520 }
02521 }
02522 ao2_ref(q->members, -1);
02523 }
02524
02525 static struct call_queue *alloc_queue(const char *queuename)
02526 {
02527 struct call_queue *q;
02528
02529 if ((q = ao2_t_alloc(sizeof(*q), destroy_queue, "Allocate queue"))) {
02530 if (ast_string_field_init(q, 64)) {
02531 queue_t_unref(q, "String field allocation failed");
02532 return NULL;
02533 }
02534 ast_string_field_set(q, name, queuename);
02535 }
02536 return q;
02537 }
02538
02539
02540
02541
02542
02543
02544
02545
02546
02547
02548
02549 static struct call_queue *find_queue_by_name_rt(const char *queuename, struct ast_variable *queue_vars, struct ast_config *member_config)
02550 {
02551 struct ast_variable *v;
02552 struct call_queue *q, tmpq = {
02553 .name = queuename,
02554 };
02555 struct member *m;
02556 struct ao2_iterator mem_iter;
02557 char *interface = NULL;
02558 const char *tmp_name;
02559 char *tmp;
02560 char tmpbuf[64];
02561
02562
02563 if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Check if static queue exists"))) {
02564 ao2_lock(q);
02565 if (!q->realtime) {
02566 if (q->dead) {
02567 ao2_unlock(q);
02568 queue_t_unref(q, "Queue is dead; can't return it");
02569 return NULL;
02570 }
02571 ast_log(LOG_WARNING, "Static queue '%s' already exists. Not loading from realtime\n", q->name);
02572 ao2_unlock(q);
02573 return q;
02574 }
02575 } else if (!member_config) {
02576
02577 return NULL;
02578 }
02579
02580 if (!queue_vars) {
02581
02582 if (q) {
02583
02584
02585
02586 ast_debug(1, "Queue %s not found in realtime.\n", queuename);
02587
02588 q->dead = 1;
02589
02590 queues_t_unlink(queues, q, "Unused; removing from container");
02591 ao2_unlock(q);
02592 queue_t_unref(q, "Queue is dead; can't return it");
02593 }
02594 return NULL;
02595 }
02596
02597
02598 if (!q) {
02599 struct ast_variable *tmpvar = NULL;
02600 if (!(q = alloc_queue(queuename))) {
02601 return NULL;
02602 }
02603 ao2_lock(q);
02604 clear_queue(q);
02605 q->realtime = 1;
02606
02607
02608
02609 for (tmpvar = queue_vars; tmpvar; tmpvar = tmpvar->next) {
02610 if (!strcasecmp(tmpvar->name, "strategy")) {
02611 q->strategy = strat2int(tmpvar->value);
02612 if (q->strategy < 0) {
02613 ast_log(LOG_WARNING, "'%s' isn't a valid strategy for queue '%s', using ringall instead\n",
02614 tmpvar->value, q->name);
02615 q->strategy = QUEUE_STRATEGY_RINGALL;
02616 }
02617 break;
02618 }
02619 }
02620
02621 if (!tmpvar) {
02622 q->strategy = QUEUE_STRATEGY_RINGALL;
02623 }
02624 queues_t_link(queues, q, "Add queue to container");
02625 }
02626 init_queue(q);
02627
02628 memset(tmpbuf, 0, sizeof(tmpbuf));
02629 for (v = queue_vars; v; v = v->next) {
02630
02631 if (strchr(v->name, '_')) {
02632 ast_copy_string(tmpbuf, v->name, sizeof(tmpbuf));
02633 tmp_name = tmpbuf;
02634 tmp = tmpbuf;
02635 while ((tmp = strchr(tmp, '_'))) {
02636 *tmp++ = '-';
02637 }
02638 } else {
02639 tmp_name = v->name;
02640 }
02641
02642
02643
02644
02645 queue_set_param(q, tmp_name, v->value, -1, 0);
02646 }
02647
02648
02649 mem_iter = ao2_iterator_init(q->members, 0);
02650 while ((m = ao2_iterator_next(&mem_iter))) {
02651 if (m->realtime) {
02652 m->dead = 1;
02653 }
02654 ao2_ref(m, -1);
02655 }
02656 ao2_iterator_destroy(&mem_iter);
02657
02658 while ((interface = ast_category_browse(member_config, interface))) {
02659 rt_handle_member_record(q, interface, member_config);
02660 }
02661
02662
02663 mem_iter = ao2_iterator_init(q->members, 0);
02664 while ((m = ao2_iterator_next(&mem_iter))) {
02665 if (m->dead) {
02666 if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
02667 ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
02668 } else {
02669 ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
02670 }
02671 ao2_unlink(q->members, m);
02672 }
02673 ao2_ref(m, -1);
02674 }
02675 ao2_iterator_destroy(&mem_iter);
02676
02677 ao2_unlock(q);
02678
02679 return q;
02680 }
02681
02682
02683
02684
02685
02686
02687
02688
02689
02690
02691
02692
02693 static struct call_queue *find_load_queue_rt_friendly(const char *queuename)
02694 {
02695 struct ast_variable *queue_vars;
02696 struct ast_config *member_config = NULL;
02697 struct call_queue *q = NULL, tmpq = {
02698 .name = queuename,
02699 };
02700 int prev_weight = 0;
02701
02702
02703 q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Look for queue in memory first");
02704
02705 if (!q || q->realtime) {
02706
02707
02708
02709
02710
02711
02712
02713
02714
02715 queue_vars = ast_load_realtime("queues", "name", queuename, SENTINEL);
02716 if (queue_vars) {
02717 member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", queuename, SENTINEL);
02718 if (!member_config) {
02719 ast_debug(1, "No queue_members defined in config extconfig.conf\n");
02720 member_config = ast_config_new();
02721 }
02722 }
02723 if (q) {
02724 prev_weight = q->weight ? 1 : 0;
02725 queue_t_unref(q, "Need to find realtime queue");
02726 }
02727
02728 q = find_queue_by_name_rt(queuename, queue_vars, member_config);
02729 ast_config_destroy(member_config);
02730 ast_variables_destroy(queue_vars);
02731
02732
02733 if (q) {
02734 if (!q->weight && prev_weight) {
02735 ast_atomic_fetchadd_int(&use_weight, -1);
02736 }
02737 if (q->weight && !prev_weight) {
02738 ast_atomic_fetchadd_int(&use_weight, +1);
02739 }
02740 }
02741
02742 } else {
02743 update_realtime_members(q);
02744 }
02745 return q;
02746 }
02747
02748 static int update_realtime_member_field(struct member *mem, const char *queue_name, const char *field, const char *value)
02749 {
02750 int ret = -1;
02751
02752 if (ast_strlen_zero(mem->rt_uniqueid)) {
02753 return ret;
02754 }
02755
02756 if ((ast_update_realtime("queue_members", "uniqueid", mem->rt_uniqueid, field, value, SENTINEL)) > 0) {
02757 ret = 0;
02758 }
02759
02760 return ret;
02761 }
02762
02763
02764 static void update_realtime_members(struct call_queue *q)
02765 {
02766 struct ast_config *member_config = NULL;
02767 struct member *m;
02768 char *interface = NULL;
02769 struct ao2_iterator mem_iter;
02770
02771 if (!(member_config = ast_load_realtime_multientry("queue_members", "interface LIKE", "%", "queue_name", q->name , SENTINEL))) {
02772
02773
02774
02775 ao2_lock(q);
02776 mem_iter = ao2_iterator_init(q->members, 0);
02777 while ((m = ao2_iterator_next(&mem_iter))) {
02778 if (m->realtime) {
02779 ao2_unlink(q->members, m);
02780 }
02781 ao2_ref(m, -1);
02782 }
02783 ast_debug(3, "Queue %s has no realtime members defined. No need for update\n", q->name);
02784 ao2_unlock(q);
02785 return;
02786 }
02787
02788 ao2_lock(q);
02789
02790
02791 mem_iter = ao2_iterator_init(q->members, 0);
02792 while ((m = ao2_iterator_next(&mem_iter))) {
02793 if (m->realtime) {
02794 m->dead = 1;
02795 }
02796 ao2_ref(m, -1);
02797 }
02798 ao2_iterator_destroy(&mem_iter);
02799
02800 while ((interface = ast_category_browse(member_config, interface))) {
02801 rt_handle_member_record(q, interface, member_config);
02802 }
02803
02804
02805 mem_iter = ao2_iterator_init(q->members, 0);
02806 while ((m = ao2_iterator_next(&mem_iter))) {
02807 if (m->dead) {
02808 if (ast_strlen_zero(m->membername) || !log_membername_as_agent) {
02809 ast_queue_log(q->name, "REALTIME", m->interface, "REMOVEMEMBER", "%s", "");
02810 } else {
02811 ast_queue_log(q->name, "REALTIME", m->membername, "REMOVEMEMBER", "%s", "");
02812 }
02813 ao2_unlink(q->members, m);
02814 }
02815 ao2_ref(m, -1);
02816 }
02817 ao2_iterator_destroy(&mem_iter);
02818 ao2_unlock(q);
02819 ast_config_destroy(member_config);
02820 }
02821
02822 static int join_queue(char *queuename, struct queue_ent *qe, enum queue_result *reason, int position)
02823 {
02824 struct call_queue *q;
02825 struct queue_ent *cur, *prev = NULL;
02826 int res = -1;
02827 int pos = 0;
02828 int inserted = 0;
02829
02830 if (!(q = find_load_queue_rt_friendly(queuename))) {
02831 return res;
02832 }
02833 ao2_lock(q);
02834
02835
02836 if (q->joinempty) {
02837 int status = 0;
02838 if ((status = get_member_status(q, qe->max_penalty, qe->min_penalty, q->joinempty))) {
02839 *reason = QUEUE_JOINEMPTY;
02840 ao2_unlock(q);
02841 queue_t_unref(q, "Done with realtime queue");
02842 return res;
02843 }
02844 }
02845 if (*reason == QUEUE_UNKNOWN && q->maxlen && (q->count >= q->maxlen)) {
02846 *reason = QUEUE_FULL;
02847 } else if (*reason == QUEUE_UNKNOWN) {
02848
02849
02850
02851 inserted = 0;
02852 prev = NULL;
02853 cur = q->head;
02854 while (cur) {
02855
02856
02857
02858 if ((!inserted) && (qe->prio > cur->prio)) {
02859 insert_entry(q, prev, qe, &pos);
02860 inserted = 1;
02861 }
02862
02863
02864
02865 if (!inserted && (qe->prio >= cur->prio) && position && (position <= pos + 1)) {
02866 insert_entry(q, prev, qe, &pos);
02867 inserted = 1;
02868
02869 if (position < pos) {
02870 ast_log(LOG_NOTICE, "Asked to be inserted at position %d but forced into position %d due to higher priority callers\n", position, pos);
02871 }
02872 }
02873 cur->pos = ++pos;
02874 prev = cur;
02875 cur = cur->next;
02876 }
02877
02878 if (!inserted) {
02879 insert_entry(q, prev, qe, &pos);
02880 }
02881 ast_copy_string(qe->moh, q->moh, sizeof(qe->moh));
02882 ast_copy_string(qe->announce, q->announce, sizeof(qe->announce));
02883 ast_copy_string(qe->context, q->context, sizeof(qe->context));
02884 q->count++;
02885 if (q->count == 1) {
02886 ast_devstate_changed(AST_DEVICE_RINGING, "Queue:%s", q->name);
02887 }
02888
02889 res = 0;
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899
02900
02901
02902
02903
02904
02905
02906
02907
02908 ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Join",
02909 "Channel: %s\r\n"
02910 "CallerIDNum: %s\r\n"
02911 "CallerIDName: %s\r\n"
02912 "ConnectedLineNum: %s\r\n"
02913 "ConnectedLineName: %s\r\n"
02914 "Queue: %s\r\n"
02915 "Position: %d\r\n"
02916 "Count: %d\r\n"
02917 "Uniqueid: %s\r\n",
02918 ast_channel_name(qe->chan),
02919 S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
02920 S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
02921 S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
02922 S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
02923 q->name, qe->pos, q->count, ast_channel_uniqueid(qe->chan));
02924 ast_debug(1, "Queue '%s' Join, Channel '%s', Position '%d'\n", q->name, ast_channel_name(qe->chan), qe->pos );
02925 }
02926 ao2_unlock(q);
02927 queue_t_unref(q, "Done with realtime queue");
02928
02929 return res;
02930 }
02931
02932 static int play_file(struct ast_channel *chan, const char *filename)
02933 {
02934 int res;
02935
02936 if (ast_strlen_zero(filename)) {
02937 return 0;
02938 }
02939
02940 if (!ast_fileexists(filename, NULL, ast_channel_language(chan))) {
02941 return 0;
02942 }
02943
02944 ast_stopstream(chan);
02945
02946 res = ast_streamfile(chan, filename, ast_channel_language(chan));
02947 if (!res) {
02948 res = ast_waitstream(chan, AST_DIGIT_ANY);
02949 }
02950
02951 ast_stopstream(chan);
02952
02953 return res;
02954 }
02955
02956
02957
02958
02959
02960
02961 static int valid_exit(struct queue_ent *qe, char digit)
02962 {
02963 int digitlen = strlen(qe->digits);
02964
02965
02966 if (digitlen < sizeof(qe->digits) - 2) {
02967 qe->digits[digitlen] = digit;
02968 qe->digits[digitlen + 1] = '\0';
02969 } else {
02970 qe->digits[0] = '\0';
02971 return 0;
02972 }
02973
02974
02975 if (ast_strlen_zero(qe->context)) {
02976 return 0;
02977 }
02978
02979
02980 if (!ast_canmatch_extension(qe->chan, qe->context, qe->digits, 1,
02981 S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, NULL))) {
02982 qe->digits[0] = '\0';
02983 return 0;
02984 }
02985
02986
02987 if (!ast_goto_if_exists(qe->chan, qe->context, qe->digits, 1)) {
02988 qe->valid_digits = 1;
02989
02990 return 1;
02991 }
02992
02993 return 0;
02994 }
02995
02996 static int say_position(struct queue_ent *qe, int ringing)
02997 {
02998 int res = 0, avgholdmins, avgholdsecs, announceposition = 0;
02999 int say_thanks = 1;
03000 time_t now;
03001
03002
03003 time(&now);
03004 if ((now - qe->last_pos) < qe->parent->minannouncefrequency) {
03005 return 0;
03006 }
03007
03008
03009 if ((qe->last_pos_said == qe->pos) && ((now - qe->last_pos) < qe->parent->announcefrequency)) {
03010 return 0;
03011 }
03012
03013 if (ringing) {
03014 ast_indicate(qe->chan,-1);
03015 } else {
03016 ast_moh_stop(qe->chan);
03017 }
03018
03019 if (qe->parent->announceposition == ANNOUNCEPOSITION_YES ||
03020 qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN ||
03021 (qe->parent->announceposition == ANNOUNCEPOSITION_LIMIT &&
03022 qe->pos <= qe->parent->announcepositionlimit)) {
03023 announceposition = 1;
03024 }
03025
03026
03027 if (announceposition == 1) {
03028
03029 if (qe->pos == 1) {
03030 res = play_file(qe->chan, qe->parent->sound_next);
03031 if (res) {
03032 goto playout;
03033 }
03034 goto posout;
03035 } else {
03036 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03037
03038 res = play_file(qe->chan, qe->parent->queue_quantity1);
03039 if (res) {
03040 goto playout;
03041 }
03042 res = ast_say_number(qe->chan, qe->parent->announcepositionlimit, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03043 if (res) {
03044 goto playout;
03045 }
03046 } else {
03047
03048 res = play_file(qe->chan, qe->parent->sound_thereare);
03049 if (res) {
03050 goto playout;
03051 }
03052 res = ast_say_number(qe->chan, qe->pos, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03053 if (res) {
03054 goto playout;
03055 }
03056 }
03057 if (qe->parent->announceposition == ANNOUNCEPOSITION_MORE_THAN && qe->pos > qe->parent->announcepositionlimit){
03058
03059 res = play_file(qe->chan, qe->parent->queue_quantity2);
03060 if (res) {
03061 goto playout;
03062 }
03063 } else {
03064 res = play_file(qe->chan, qe->parent->sound_calls);
03065 if (res) {
03066 goto playout;
03067 }
03068 }
03069 }
03070 }
03071
03072 avgholdmins = abs(((qe->parent->holdtime + 30) - (now - qe->start)) / 60);
03073
03074
03075 if (qe->parent->roundingseconds) {
03076 avgholdsecs = (abs(((qe->parent->holdtime + 30) - (now - qe->start))) - 60 * avgholdmins) / qe->parent->roundingseconds;
03077 avgholdsecs *= qe->parent->roundingseconds;
03078 } else {
03079 avgholdsecs = 0;
03080 }
03081
03082 ast_verb(3, "Hold time for %s is %d minute(s) %d seconds\n", qe->parent->name, avgholdmins, avgholdsecs);
03083
03084
03085
03086 if ((avgholdmins+avgholdsecs) > 0 && qe->parent->announceholdtime &&
03087 ((qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE && !qe->last_pos) ||
03088 !(qe->parent->announceholdtime == ANNOUNCEHOLDTIME_ONCE))) {
03089 res = play_file(qe->chan, qe->parent->sound_holdtime);
03090 if (res) {
03091 goto playout;
03092 }
03093
03094 if (avgholdmins >= 1) {
03095 res = ast_say_number(qe->chan, avgholdmins, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03096 if (res) {
03097 goto playout;
03098 }
03099
03100 if (avgholdmins == 1) {
03101 res = play_file(qe->chan, qe->parent->sound_minute);
03102 if (res) {
03103 goto playout;
03104 }
03105 } else {
03106 res = play_file(qe->chan, qe->parent->sound_minutes);
03107 if (res) {
03108 goto playout;
03109 }
03110 }
03111 }
03112 if (avgholdsecs >= 1) {
03113 res = ast_say_number(qe->chan, avgholdsecs, AST_DIGIT_ANY, ast_channel_language(qe->chan), NULL);
03114 if (res) {
03115 goto playout;
03116 }
03117
03118 res = play_file(qe->chan, qe->parent->sound_seconds);
03119 if (res) {
03120 goto playout;
03121 }
03122 }
03123 } else if (qe->parent->announceholdtime && !qe->parent->announceposition) {
03124 say_thanks = 0;
03125 }
03126
03127 posout:
03128 if (qe->parent->announceposition) {
03129 ast_verb(3, "Told %s in %s their queue position (which was %d)\n",
03130 ast_channel_name(qe->chan), qe->parent->name, qe->pos);
03131 }
03132 if (say_thanks) {
03133 res = play_file(qe->chan, qe->parent->sound_thanks);
03134 }
03135 playout:
03136
03137 if ((res > 0 && !valid_exit(qe, res))) {
03138 res = 0;
03139 }
03140
03141
03142 qe->last_pos = now;
03143 qe->last_pos_said = qe->pos;
03144
03145
03146 if (!res) {
03147 if (ringing) {
03148 ast_indicate(qe->chan, AST_CONTROL_RINGING);
03149 } else {
03150 ast_moh_start(qe->chan, qe->moh, NULL);
03151 }
03152 }
03153 return res;
03154 }
03155
03156 static void recalc_holdtime(struct queue_ent *qe, int newholdtime)
03157 {
03158 int oldvalue;
03159
03160
03161
03162
03163
03164 ao2_lock(qe->parent);
03165 oldvalue = qe->parent->holdtime;
03166 qe->parent->holdtime = (((oldvalue << 2) - oldvalue) + newholdtime) >> 2;
03167 ao2_unlock(qe->parent);
03168 }
03169
03170
03171
03172
03173
03174
03175 static void leave_queue(struct queue_ent *qe)
03176 {
03177 struct call_queue *q;
03178 struct queue_ent *current, *prev = NULL;
03179 struct penalty_rule *pr_iter;
03180 int pos = 0;
03181
03182 if (!(q = qe->parent)) {
03183 return;
03184 }
03185 queue_t_ref(q, "Copy queue pointer from queue entry");
03186 ao2_lock(q);
03187
03188 prev = NULL;
03189 for (current = q->head; current; current = current->next) {
03190 if (current == qe) {
03191 char posstr[20];
03192 q->count--;
03193 if (!q->count) {
03194 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s", q->name);
03195 }
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 ast_manager_event(qe->chan, EVENT_FLAG_CALL, "Leave",
03212 "Channel: %s\r\nQueue: %s\r\nCount: %d\r\nPosition: %d\r\nUniqueid: %s\r\n",
03213 ast_channel_name(qe->chan), q->name, q->count, qe->pos, ast_channel_uniqueid(qe->chan));
03214 ast_debug(1, "Queue '%s' Leave, Channel '%s'\n", q->name, ast_channel_name(qe->chan));
03215
03216 if (prev) {
03217 prev->next = current->next;
03218 } else {
03219 q->head = current->next;
03220 }
03221
03222 while ((pr_iter = AST_LIST_REMOVE_HEAD(&qe->qe_rules, list))) {
03223 ast_free(pr_iter);
03224 }
03225 snprintf(posstr, sizeof(posstr), "%d", qe->pos);
03226 pbx_builtin_setvar_helper(qe->chan, "QUEUEPOSITION", posstr);
03227 } else {
03228
03229 current->pos = ++pos;
03230 prev = current;
03231 }
03232 }
03233 ao2_unlock(q);
03234
03235
03236 if (q->realtime) {
03237 struct ast_variable *var;
03238 if (!(var = ast_load_realtime("queues", "name", q->name, SENTINEL))) {
03239 q->dead = 1;
03240 } else {
03241 ast_variables_destroy(var);
03242 }
03243 }
03244
03245 if (q->dead) {
03246
03247 queues_t_unlink(queues, q, "Queue is now dead; remove it from the container");
03248 }
03249
03250 queue_t_unref(q, "Expire copied reference");
03251 }
03252
03253
03254
03255
03256
03257
03258
03259
03260
03261
03262 static void callattempt_free(struct callattempt *doomed)
03263 {
03264 if (doomed->member) {
03265 ao2_ref(doomed->member, -1);
03266 }
03267 ast_party_connected_line_free(&doomed->connected);
03268 ast_free(doomed);
03269 }
03270
03271
03272 static void hangupcalls(struct callattempt *outgoing, struct ast_channel *exception, int cancel_answered_elsewhere)
03273 {
03274 struct callattempt *oo;
03275
03276 while (outgoing) {
03277
03278
03279 if (outgoing->chan && (outgoing->chan != exception)) {
03280 if (exception || cancel_answered_elsewhere) {
03281 ast_channel_hangupcause_set(outgoing->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
03282 }
03283 ast_hangup(outgoing->chan);
03284 }
03285 oo = outgoing;
03286 outgoing = outgoing->q_next;
03287 ast_aoc_destroy_decoded(oo->aoc_s_rate_list);
03288 callattempt_free(oo);
03289 }
03290 }
03291
03292
03293
03294
03295
03296
03297
03298
03299
03300 static int num_available_members(struct call_queue *q)
03301 {
03302 struct member *mem;
03303 int avl = 0;
03304 struct ao2_iterator mem_iter;
03305
03306 mem_iter = ao2_iterator_init(q->members, 0);
03307 while ((mem = ao2_iterator_next(&mem_iter))) {
03308
03309 avl += is_member_available(mem);
03310 ao2_ref(mem, -1);
03311
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322 if ((!q->autofill || q->strategy == QUEUE_STRATEGY_RINGALL) && avl) {
03323 break;
03324 }
03325 }
03326 ao2_iterator_destroy(&mem_iter);
03327
03328 return avl;
03329 }
03330
03331
03332
03333 static int compare_weight(struct call_queue *rq, struct member *member)
03334 {
03335 struct call_queue *q;
03336 struct member *mem;
03337 int found = 0;
03338 struct ao2_iterator queue_iter;
03339
03340 queue_iter = ao2_iterator_init(queues, 0);
03341 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
03342 if (q == rq) {
03343 queue_t_unref(q, "Done with iterator");
03344 continue;
03345 }
03346 ao2_lock(q);
03347 if (q->count && q->members) {
03348 if ((mem = ao2_find(q->members, member, OBJ_POINTER))) {
03349 ast_debug(1, "Found matching member %s in queue '%s'\n", mem->interface, q->name);
03350 if (q->weight > rq->weight && q->count >= num_available_members(q)) {
03351 ast_debug(1, "Queue '%s' (weight %d, calls %d) is preferred over '%s' (weight %d, calls %d)\n", q->name, q->weight, q->count, rq->name, rq->weight, rq->count);
03352 found = 1;
03353 }
03354 ao2_ref(mem, -1);
03355 }
03356 }
03357 ao2_unlock(q);
03358 queue_t_unref(q, "Done with iterator");
03359 if (found) {
03360 break;
03361 }
03362 }
03363 ao2_iterator_destroy(&queue_iter);
03364 return found;
03365 }
03366
03367
03368 static void do_hang(struct callattempt *o)
03369 {
03370 o->stillgoing = 0;
03371 ast_hangup(o->chan);
03372 o->chan = NULL;
03373 }
03374
03375
03376 static char *vars2manager(struct ast_channel *chan, char *vars, size_t len)
03377 {
03378 struct ast_str *buf = ast_str_thread_get(&ast_str_thread_global_buf, len + 1);
03379 const char *tmp;
03380
03381 if (pbx_builtin_serialize_variables(chan, &buf)) {
03382 int i, j;
03383
03384
03385 strcpy(vars, "Variable: ");
03386 tmp = ast_str_buffer(buf);
03387
03388 for (i = 0, j = 10; (i < len - 1) && (j < len - 1); i++, j++) {
03389 vars[j] = tmp[i];
03390
03391 if (tmp[i + 1] == '\0') {
03392 break;
03393 }
03394 if (tmp[i] == '\n') {
03395 vars[j++] = '\r';
03396 vars[j++] = '\n';
03397
03398 ast_copy_string(&(vars[j]), "Variable: ", len - j);
03399 j += 9;
03400 }
03401 }
03402 if (j > len - 3) {
03403 j = len - 3;
03404 }
03405 vars[j++] = '\r';
03406 vars[j++] = '\n';
03407 vars[j] = '\0';
03408 } else {
03409
03410 *vars = '\0';
03411 }
03412 return vars;
03413 }
03414
03415
03416
03417
03418
03419
03420
03421
03422
03423
03424
03425
03426
03427
03428
03429 static int ring_entry(struct queue_ent *qe, struct callattempt *tmp, int *busies)
03430 {
03431 int res;
03432 int status;
03433 char tech[256];
03434 char *location;
03435 const char *macrocontext, *macroexten;
03436 enum ast_device_state newstate;
03437
03438
03439 if (tmp->member->paused) {
03440 ast_debug(1, "%s paused, can't receive call\n", tmp->interface);
03441 if (ast_channel_cdr(qe->chan)) {
03442 ast_cdr_busy(ast_channel_cdr(qe->chan));
03443 }
03444 tmp->stillgoing = 0;
03445 return 0;
03446 }
03447
03448 if ((tmp->lastqueue && tmp->lastqueue->wrapuptime && (time(NULL) - tmp->lastcall < tmp->lastqueue->wrapuptime)) ||
03449 (!tmp->lastqueue && qe->parent->wrapuptime && (time(NULL) - tmp->lastcall < qe->parent->wrapuptime))) {
03450 ast_debug(1, "Wrapuptime not yet expired on queue %s for %s\n",
03451 (tmp->lastqueue ? tmp->lastqueue->name : qe->parent->name), tmp->interface);
03452 if (ast_channel_cdr(qe->chan)) {
03453 ast_cdr_busy(ast_channel_cdr(qe->chan));
03454 }
03455 tmp->stillgoing = 0;
03456 (*busies)++;
03457 return 0;
03458 }
03459
03460 if (!tmp->member->ringinuse) {
03461 if (check_state_unknown && (tmp->member->status == AST_DEVICE_UNKNOWN)) {
03462 newstate = ast_device_state(tmp->member->interface);
03463 if (newstate != tmp->member->status) {
03464 ast_log(LOG_WARNING, "Found a channel matching iterface %s while status was %s changed to %s\n",
03465 tmp->member->interface, ast_devstate2str(tmp->member->status), ast_devstate2str(newstate));
03466 ast_devstate_changed_literal(newstate, tmp->member->interface);
03467 }
03468 }
03469 if ((tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
03470 ast_debug(1, "%s in use, can't receive call\n", tmp->interface);
03471 if (ast_channel_cdr(qe->chan)) {
03472 ast_cdr_busy(ast_channel_cdr(qe->chan));
03473 }
03474 tmp->stillgoing = 0;
03475 return 0;
03476 }
03477 }
03478
03479 if (use_weight && compare_weight(qe->parent,tmp->member)) {
03480 ast_debug(1, "Priority queue delaying call to %s:%s\n", qe->parent->name, tmp->interface);
03481 if (ast_channel_cdr(qe->chan)) {
03482 ast_cdr_busy(ast_channel_cdr(qe->chan));
03483 }
03484 tmp->stillgoing = 0;
03485 (*busies)++;
03486 return 0;
03487 }
03488
03489 ast_copy_string(tech, tmp->interface, sizeof(tech));
03490 if ((location = strchr(tech, '/'))) {
03491 *location++ = '\0';
03492 } else {
03493 location = "";
03494 }
03495
03496
03497 tmp->chan = ast_request(tech, ast_channel_nativeformats(qe->chan), qe->chan, location, &status);
03498 if (!tmp->chan) {
03499 if (ast_channel_cdr(qe->chan)) {
03500 ast_cdr_busy(ast_channel_cdr(qe->chan));
03501 }
03502 tmp->stillgoing = 0;
03503
03504 ao2_lock(qe->parent);
03505 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
03506 qe->parent->rrpos++;
03507 qe->linpos++;
03508 ao2_unlock(qe->parent);
03509
03510 (*busies)++;
03511 return 0;
03512 }
03513
03514 ast_channel_lock_both(tmp->chan, qe->chan);
03515
03516 if (qe->cancel_answered_elsewhere) {
03517 ast_channel_hangupcause_set(tmp->chan, AST_CAUSE_ANSWERED_ELSEWHERE);
03518 }
03519 ast_channel_appl_set(tmp->chan, "AppQueue");
03520 ast_channel_data_set(tmp->chan, "(Outgoing Line)");
03521 memset(ast_channel_whentohangup(tmp->chan), 0, sizeof(*ast_channel_whentohangup(tmp->chan)));
03522
03523
03524 if (!ast_channel_caller(tmp->chan)->id.number.valid) {
03525 if (ast_channel_connected(qe->chan)->id.number.valid) {
03526 struct ast_party_caller caller;
03527
03528 ast_party_caller_set_init(&caller, ast_channel_caller(tmp->chan));
03529 caller.id = ast_channel_connected(qe->chan)->id;
03530 caller.ani = ast_channel_connected(qe->chan)->ani;
03531 ast_channel_set_caller_event(tmp->chan, &caller, NULL);
03532 } else if (!ast_strlen_zero(ast_channel_dialed(qe->chan)->number.str)) {
03533 ast_set_callerid(tmp->chan, ast_channel_dialed(qe->chan)->number.str, NULL, NULL);
03534 } else if (!ast_strlen_zero(S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)))) {
03535 ast_set_callerid(tmp->chan, S_OR(ast_channel_macroexten(qe->chan), ast_channel_exten(qe->chan)), NULL, NULL);
03536 }
03537 tmp->dial_callerid_absent = 1;
03538 }
03539
03540 ast_party_redirecting_copy(ast_channel_redirecting(tmp->chan), ast_channel_redirecting(qe->chan));
03541
03542 ast_channel_dialed(tmp->chan)->transit_network_select = ast_channel_dialed(qe->chan)->transit_network_select;
03543
03544 ast_connected_line_copy_from_caller(ast_channel_connected(tmp->chan), ast_channel_caller(qe->chan));
03545
03546
03547 ast_channel_inherit_variables(qe->chan, tmp->chan);
03548 ast_channel_datastore_inherit(qe->chan, tmp->chan);
03549
03550
03551 ast_channel_adsicpe_set(tmp->chan, ast_channel_adsicpe(qe->chan));
03552
03553
03554 macrocontext = pbx_builtin_getvar_helper(qe->chan, "MACRO_CONTEXT");
03555 ast_channel_dialcontext_set(tmp->chan, ast_strlen_zero(macrocontext) ? ast_channel_context(qe->chan) : macrocontext);
03556 macroexten = pbx_builtin_getvar_helper(qe->chan, "MACRO_EXTEN");
03557 if (!ast_strlen_zero(macroexten)) {
03558 ast_channel_exten_set(tmp->chan, macroexten);
03559 } else {
03560 ast_channel_exten_set(tmp->chan, ast_channel_exten(qe->chan));
03561 }
03562 if (ast_cdr_isset_unanswered()) {
03563
03564
03565 ast_cdr_setdestchan(ast_channel_cdr(tmp->chan), ast_channel_name(tmp->chan));
03566 strcpy(ast_channel_cdr(tmp->chan)->clid, ast_channel_cdr(qe->chan)->clid);
03567 strcpy(ast_channel_cdr(tmp->chan)->channel, ast_channel_cdr(qe->chan)->channel);
03568 strcpy(ast_channel_cdr(tmp->chan)->src, ast_channel_cdr(qe->chan)->src);
03569 strcpy(ast_channel_cdr(tmp->chan)->dst, ast_channel_exten(qe->chan));
03570 strcpy(ast_channel_cdr(tmp->chan)->dcontext, ast_channel_context(qe->chan));
03571 strcpy(ast_channel_cdr(tmp->chan)->lastapp, ast_channel_cdr(qe->chan)->lastapp);
03572 strcpy(ast_channel_cdr(tmp->chan)->lastdata, ast_channel_cdr(qe->chan)->lastdata);
03573 ast_channel_cdr(tmp->chan)->amaflags = ast_channel_cdr(qe->chan)->amaflags;
03574 strcpy(ast_channel_cdr(tmp->chan)->accountcode, ast_channel_cdr(qe->chan)->accountcode);
03575 strcpy(ast_channel_cdr(tmp->chan)->userfield, ast_channel_cdr(qe->chan)->userfield);
03576 }
03577
03578 ast_channel_unlock(tmp->chan);
03579 ast_channel_unlock(qe->chan);
03580
03581 ao2_lock(tmp->member);
03582 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
03583 if (!qe->parent->ringinuse && (tmp->member->status != AST_DEVICE_NOT_INUSE) && (tmp->member->status != AST_DEVICE_UNKNOWN)) {
03584 ast_verb(1, "Member %s is busy, cannot dial", tmp->member->interface);
03585 res = -1;
03586 }
03587 else {
03588
03589 res = ast_call(tmp->chan, location, 0);
03590 }
03591 ao2_unlock(tmp->member);
03592 if (res) {
03593
03594 ast_verb(3, "Couldn't call %s\n", tmp->interface);
03595 do_hang(tmp);
03596 (*busies)++;
03597 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
03598 return 0;
03599 } else if (qe->parent->eventwhencalled) {
03600 char vars[2048];
03601
03602 ast_channel_lock_both(tmp->chan, qe->chan);
03603
03604
03605
03606
03607
03608
03609
03610
03611
03612
03613
03614
03615
03616
03617
03618
03619
03620
03621
03622
03623
03624
03625
03626 manager_event(EVENT_FLAG_AGENT, "AgentCalled",
03627 "Queue: %s\r\n"
03628 "AgentCalled: %s\r\n"
03629 "AgentName: %s\r\n"
03630 "ChannelCalling: %s\r\n"
03631 "DestinationChannel: %s\r\n"
03632 "CallerIDNum: %s\r\n"
03633 "CallerIDName: %s\r\n"
03634 "ConnectedLineNum: %s\r\n"
03635 "ConnectedLineName: %s\r\n"
03636 "Context: %s\r\n"
03637 "Extension: %s\r\n"
03638 "Priority: %d\r\n"
03639 "Uniqueid: %s\r\n"
03640 "%s",
03641 qe->parent->name, tmp->interface, tmp->member->membername, ast_channel_name(qe->chan), ast_channel_name(tmp->chan),
03642 S_COR(ast_channel_caller(qe->chan)->id.number.valid, ast_channel_caller(qe->chan)->id.number.str, "unknown"),
03643 S_COR(ast_channel_caller(qe->chan)->id.name.valid, ast_channel_caller(qe->chan)->id.name.str, "unknown"),
03644 S_COR(ast_channel_connected(qe->chan)->id.number.valid, ast_channel_connected(qe->chan)->id.number.str, "unknown"),
03645 S_COR(ast_channel_connected(qe->chan)->id.name.valid, ast_channel_connected(qe->chan)->id.name.str, "unknown"),
03646 ast_channel_context(qe->chan), ast_channel_exten(qe->chan), ast_channel_priority(qe->chan), ast_channel_uniqueid(qe->chan),
03647 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
03648
03649 ast_channel_unlock(tmp->chan);
03650 ast_channel_unlock(qe->chan);
03651
03652 ast_verb(3, "Called %s\n", tmp->interface);
03653 }
03654
03655 update_status(qe->parent, tmp->member, get_queue_member_status(tmp->member));
03656 return 1;
03657 }
03658
03659
03660 static struct callattempt *find_best(struct callattempt *outgoing)
03661 {
03662 struct callattempt *best = NULL, *cur;
03663
03664 for (cur = outgoing; cur; cur = cur->q_next) {
03665 if (cur->stillgoing &&
03666 !cur->chan &&
03667 (!best || cur->metric < best->metric)) {
03668 best = cur;
03669 }
03670 }
03671
03672 return best;
03673 }
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685 static int ring_one(struct queue_ent *qe, struct callattempt *outgoing, int *busies)
03686 {
03687 int ret = 0;
03688
03689 while (ret == 0) {
03690 struct callattempt *best = find_best(outgoing);
03691 if (!best) {
03692 ast_debug(1, "Nobody left to try ringing in queue\n");
03693 break;
03694 }
03695 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
03696 struct callattempt *cur;
03697
03698 for (cur = outgoing; cur; cur = cur->q_next) {
03699 if (cur->stillgoing && !cur->chan && cur->metric <= best->metric) {
03700 ast_debug(1, "(Parallel) Trying '%s' with metric %d\n", cur->interface, cur->metric);
03701 ret |= ring_entry(qe, cur, busies);
03702 }
03703 }
03704 } else {
03705
03706 ast_debug(1, "Trying '%s' with metric %d\n", best->interface, best->metric);
03707 ret = ring_entry(qe, best, busies);
03708 }
03709
03710
03711 if (qe->expire && (time(NULL) >= qe->expire)) {
03712 ast_debug(1, "Queue timed out while ringing members.\n");
03713 ret = 0;
03714 break;
03715 }
03716 }
03717
03718 return ret;
03719 }
03720
03721
03722 static int store_next_rr(struct queue_ent *qe, struct callattempt *outgoing)
03723 {
03724 struct callattempt *best = find_best(outgoing);
03725
03726 if (best) {
03727
03728 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
03729 qe->parent->rrpos = best->metric % 1000;
03730 } else {
03731
03732 if (qe->parent->wrapped) {
03733
03734 qe->parent->rrpos = 0;
03735 } else {
03736
03737 qe->parent->rrpos++;
03738 }
03739 }
03740 qe->parent->wrapped = 0;
03741
03742 return 0;
03743 }
03744
03745
03746 static int store_next_lin(struct queue_ent *qe, struct callattempt *outgoing)
03747 {
03748 struct callattempt *best = find_best(outgoing);
03749
03750 if (best) {
03751
03752 ast_debug(1, "Next is '%s' with metric %d\n", best->interface, best->metric);
03753 qe->linpos = best->metric % 1000;
03754 } else {
03755
03756 if (qe->linwrapped) {
03757
03758 qe->linpos = 0;
03759 } else {
03760
03761 qe->linpos++;
03762 }
03763 }
03764 qe->linwrapped = 0;
03765
03766 return 0;
03767 }
03768
03769
03770 static int say_periodic_announcement(struct queue_ent *qe, int ringing)
03771 {
03772 int res = 0;
03773 time_t now;
03774
03775
03776 time(&now);
03777
03778
03779 if ((now - qe->last_periodic_announce_time) < qe->parent->periodicannouncefrequency) {
03780 return 0;
03781 }
03782
03783
03784 if (ringing) {
03785 ast_indicate(qe->chan,-1);
03786 } else {
03787 ast_moh_stop(qe->chan);
03788 }
03789
03790 ast_verb(3, "Playing periodic announcement\n");
03791
03792 if (qe->parent->randomperiodicannounce && qe->parent->numperiodicannounce) {
03793 qe->last_periodic_announce_sound = ((unsigned long) ast_random()) % qe->parent->numperiodicannounce;
03794 } else if (qe->last_periodic_announce_sound >= qe->parent->numperiodicannounce ||
03795 ast_str_strlen(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]) == 0) {
03796 qe->last_periodic_announce_sound = 0;
03797 }
03798
03799
03800 res = play_file(qe->chan, ast_str_buffer(qe->parent->sound_periodicannounce[qe->last_periodic_announce_sound]));
03801
03802 if (res > 0 && !valid_exit(qe, res)) {
03803 res = 0;
03804 }
03805
03806
03807 if (!res) {
03808 if (ringing) {
03809 ast_indicate(qe->chan, AST_CONTROL_RINGING);
03810 } else {
03811 ast_moh_start(qe->chan, qe->moh, NULL);
03812 }
03813 }
03814
03815
03816 if (qe->parent->relativeperiodicannounce) {
03817 time(&qe->last_periodic_announce_time);
03818 } else {
03819 qe->last_periodic_announce_time = now;
03820 }
03821
03822
03823 if (!qe->parent->randomperiodicannounce) {
03824 qe->last_periodic_announce_sound++;
03825 }
03826
03827 return res;
03828 }
03829
03830
03831 static void record_abandoned(struct queue_ent *qe)
03832 {
03833 set_queue_variables(qe->parent, qe->chan);
03834 ao2_lock(qe->parent);
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850 manager_event(EVENT_FLAG_AGENT, "QueueCallerAbandon",
03851 "Queue: %s\r\n"
03852 "Uniqueid: %s\r\n"
03853 "Position: %d\r\n"
03854 "OriginalPosition: %d\r\n"
03855 "HoldTime: %d\r\n",
03856 qe->parent->name, ast_channel_uniqueid(qe->chan), qe->pos, qe->opos, (int)(time(NULL) - qe->start));
03857
03858 qe->parent->callsabandoned++;
03859 ao2_unlock(qe->parent);
03860 }
03861
03862
03863 static void rna(int rnatime, struct queue_ent *qe, char *interface, char *membername, int autopause)
03864 {
03865 ast_verb(3, "Nobody picked up in %d ms\n", rnatime);
03866
03867
03868 if (qe->ring_when_ringing) {
03869 ast_indicate(qe->chan, -1);
03870 ast_moh_start(qe->chan, qe->moh, NULL);
03871 }
03872
03873 if (qe->parent->eventwhencalled) {
03874 char vars[2048];
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885
03886
03887
03888
03889
03890
03891
03892
03893
03894 manager_event(EVENT_FLAG_AGENT, "AgentRingNoAnswer",
03895 "Queue: %s\r\n"
03896 "Uniqueid: %s\r\n"
03897 "Channel: %s\r\n"
03898 "Member: %s\r\n"
03899 "MemberName: %s\r\n"
03900 "RingTime: %d\r\n"
03901 "%s",
03902 qe->parent->name,
03903 ast_channel_uniqueid(qe->chan),
03904 ast_channel_name(qe->chan),
03905 interface,
03906 membername,
03907 rnatime,
03908 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
03909 }
03910 ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), membername, "RINGNOANSWER", "%d", rnatime);
03911 if (qe->parent->autopause != QUEUE_AUTOPAUSE_OFF && autopause) {
03912 if (qe->parent->autopausedelay > 0) {
03913 struct member *mem;
03914 ao2_lock(qe->parent);
03915 if ((mem = interface_exists(qe->parent, interface))) {
03916 time_t idletime = time(&idletime)-mem->lastcall;
03917 if ((mem->lastcall != 0) && (qe->parent->autopausedelay > idletime)) {
03918 ao2_unlock(qe->parent);
03919 ao2_ref(mem, -1);
03920 return;
03921 }
03922 ao2_ref(mem, -1);
03923 }
03924 ao2_unlock(qe->parent);
03925 }
03926 if (qe->parent->autopause == QUEUE_AUTOPAUSE_ON) {
03927 if (!set_member_paused(qe->parent->name, interface, "Auto-Pause", 1)) {
03928 ast_verb(3, "Auto-Pausing Queue Member %s in queue %s since they failed to answer.\n",
03929 interface, qe->parent->name);
03930 } else {
03931 ast_verb(3, "Failed to pause Queue Member %s in queue %s!\n", interface, qe->parent->name);
03932 }
03933 } else {
03934
03935
03936 if (!set_member_paused("", interface, "Auto-Pause", 1)) {
03937 ast_verb(3, "Auto-Pausing Queue Member %s in all queues since they failed to answer on queue %s.\n",
03938 interface, qe->parent->name);
03939 } else {
03940 ast_verb(3, "Failed to pause Queue Member %s in all queues!\n", interface);
03941 }
03942 }
03943 }
03944 return;
03945 }
03946
03947 #define AST_MAX_WATCHERS 256
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959
03960
03961 static struct callattempt *wait_for_answer(struct queue_ent *qe, struct callattempt *outgoing, int *to, char *digit, int prebusies, int caller_disconnect, int forwardsallowed)
03962 {
03963 const char *queue = qe->parent->name;
03964 struct callattempt *o, *start = NULL, *prev = NULL;
03965 int status;
03966 int numbusies = prebusies;
03967 int numnochan = 0;
03968 int stillgoing = 0;
03969 int orig = *to;
03970 struct ast_frame *f;
03971 struct callattempt *peer = NULL;
03972 struct ast_channel *winner;
03973 struct ast_channel *in = qe->chan;
03974 char on[80] = "";
03975 char membername[80] = "";
03976 long starttime = 0;
03977 long endtime = 0;
03978 #ifdef HAVE_EPOLL
03979 struct callattempt *epollo;
03980 #endif
03981 struct ast_party_connected_line connected_caller;
03982 char *inchan_name;
03983
03984 ast_party_connected_line_init(&connected_caller);
03985
03986 ast_channel_lock(qe->chan);
03987 inchan_name = ast_strdupa(ast_channel_name(qe->chan));
03988 ast_channel_unlock(qe->chan);
03989
03990 starttime = (long) time(NULL);
03991 #ifdef HAVE_EPOLL
03992 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
03993 if (epollo->chan) {
03994 ast_poll_channel_add(in, epollo->chan);
03995 }
03996 }
03997 #endif
03998
03999 while (*to && !peer) {
04000 int numlines, retry, pos = 1;
04001 struct ast_channel *watchers[AST_MAX_WATCHERS];
04002 watchers[0] = in;
04003 start = NULL;
04004
04005 for (retry = 0; retry < 2; retry++) {
04006 numlines = 0;
04007 for (o = outgoing; o; o = o->q_next) {
04008 if (o->stillgoing) {
04009 stillgoing = 1;
04010 if (o->chan) {
04011 if (pos < AST_MAX_WATCHERS) {
04012 watchers[pos++] = o->chan;
04013 }
04014 if (!start) {
04015 start = o;
04016 } else {
04017 prev->call_next = o;
04018 }
04019 prev = o;
04020 }
04021 }
04022 numlines++;
04023 }
04024 if (pos > 1 || !stillgoing ||
04025 (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) ) {
04026 break;
04027 }
04028
04029
04030 ring_one(qe, outgoing, &numbusies);
04031
04032 }
04033 if (pos == 1 ) {
04034 if (numlines == (numbusies + numnochan)) {
04035 ast_debug(1, "Everyone is busy at this time\n");
04036 } else {
04037 ast_debug(3, "No one is answering queue '%s' (%d numlines / %d busies / %d failed channels)\n", queue, numlines, numbusies, numnochan);
04038 }
04039 *to = 0;
04040 return NULL;
04041 }
04042
04043
04044 winner = ast_waitfor_n(watchers, pos, to);
04045
04046
04047 for (o = start; o; o = o->call_next) {
04048
04049
04050
04051 char ochan_name[AST_CHANNEL_NAME];
04052
04053 if (o->chan) {
04054 ast_channel_lock(o->chan);
04055 ast_copy_string(ochan_name, ast_channel_name(o->chan), sizeof(ochan_name));
04056 ast_channel_unlock(o->chan);
04057 }
04058 if (o->stillgoing && (o->chan) && (ast_channel_state(o->chan) == AST_STATE_UP)) {
04059 if (!peer) {
04060 ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04061 if (!o->block_connected_update) {
04062 if (o->pending_connected_update) {
04063 if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04064 ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04065 ast_channel_update_connected_line(in, &o->connected, NULL);
04066 }
04067 } else if (!o->dial_callerid_absent) {
04068 ast_channel_lock(o->chan);
04069 ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04070 ast_channel_unlock(o->chan);
04071 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04072 if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04073 ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04074 ast_channel_update_connected_line(in, &connected_caller, NULL);
04075 }
04076 ast_party_connected_line_free(&connected_caller);
04077 }
04078 }
04079 if (o->aoc_s_rate_list) {
04080 size_t encoded_size;
04081 struct ast_aoc_encoded *encoded;
04082 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04083 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04084 ast_aoc_destroy_encoded(encoded);
04085 }
04086 }
04087 peer = o;
04088 }
04089 } else if (o->chan && (o->chan == winner)) {
04090
04091 ast_copy_string(on, o->member->interface, sizeof(on));
04092 ast_copy_string(membername, o->member->membername, sizeof(membername));
04093
04094
04095 if (!ast_strlen_zero(ast_channel_call_forward(o->chan)) && !forwardsallowed) {
04096 ast_verb(3, "Forwarding %s to '%s' prevented.\n", inchan_name, ast_channel_call_forward(o->chan));
04097 numnochan++;
04098 do_hang(o);
04099 winner = NULL;
04100 continue;
04101 } else if (!ast_strlen_zero(ast_channel_call_forward(o->chan))) {
04102 struct ast_channel *original = o->chan;
04103 char tmpchan[256];
04104 char *stuff;
04105 char *tech;
04106
04107 ast_copy_string(tmpchan, ast_channel_call_forward(o->chan), sizeof(tmpchan));
04108 if ((stuff = strchr(tmpchan, '/'))) {
04109 *stuff++ = '\0';
04110 tech = tmpchan;
04111 } else {
04112 snprintf(tmpchan, sizeof(tmpchan), "%s@%s", ast_channel_call_forward(o->chan), ast_channel_context(o->chan));
04113 stuff = tmpchan;
04114 tech = "Local";
04115 }
04116 if (!strcasecmp(tech, "Local")) {
04117
04118
04119
04120
04121
04122 o->block_connected_update = 0;
04123 }
04124
04125 ast_cel_report_event(in, AST_CEL_FORWARD, NULL, ast_channel_call_forward(o->chan), NULL);
04126
04127 ast_verb(3, "Now forwarding %s to '%s/%s' (thanks to %s)\n", inchan_name, tech, stuff, ochan_name);
04128
04129 o->chan = ast_request(tech, ast_channel_nativeformats(in), in, stuff, &status);
04130 if (!o->chan) {
04131 ast_log(LOG_NOTICE,
04132 "Forwarding failed to create channel to dial '%s/%s'\n",
04133 tech, stuff);
04134 o->stillgoing = 0;
04135 numnochan++;
04136 } else {
04137 ast_channel_lock_both(o->chan, original);
04138 ast_party_redirecting_copy(ast_channel_redirecting(o->chan),
04139 ast_channel_redirecting(original));
04140 ast_channel_unlock(o->chan);
04141 ast_channel_unlock(original);
04142
04143 ast_channel_lock_both(o->chan, in);
04144 ast_channel_inherit_variables(in, o->chan);
04145 ast_channel_datastore_inherit(in, o->chan);
04146
04147 if (o->pending_connected_update) {
04148
04149
04150
04151
04152
04153
04154 o->pending_connected_update = 0;
04155 ast_party_connected_line_copy(&o->connected, ast_channel_connected(in));
04156 }
04157
04158 ast_channel_accountcode_set(o->chan, ast_channel_accountcode(in));
04159
04160 if (!ast_channel_redirecting(o->chan)->from.number.valid
04161 || ast_strlen_zero(ast_channel_redirecting(o->chan)->from.number.str)) {
04162
04163
04164
04165
04166 ast_party_number_free(&ast_channel_redirecting(o->chan)->from.number);
04167 ast_party_number_init(&ast_channel_redirecting(o->chan)->from.number);
04168 ast_channel_redirecting(o->chan)->from.number.valid = 1;
04169 ast_channel_redirecting(o->chan)->from.number.str =
04170 ast_strdup(S_OR(ast_channel_macroexten(in), ast_channel_exten(in)));
04171 }
04172
04173 ast_channel_dialed(o->chan)->transit_network_select = ast_channel_dialed(in)->transit_network_select;
04174
04175 o->dial_callerid_absent = !ast_channel_caller(o->chan)->id.number.valid
04176 || ast_strlen_zero(ast_channel_caller(o->chan)->id.number.str);
04177 ast_connected_line_copy_from_caller(ast_channel_connected(o->chan),
04178 ast_channel_caller(in));
04179
04180 ast_channel_unlock(in);
04181 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL
04182 && !o->block_connected_update) {
04183 struct ast_party_redirecting redirecting;
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193
04194
04195 ast_party_redirecting_init(&redirecting);
04196 ast_party_redirecting_copy(&redirecting, ast_channel_redirecting(o->chan));
04197 ast_channel_unlock(o->chan);
04198 if (ast_channel_redirecting_sub(o->chan, in, &redirecting, 0) &&
04199 ast_channel_redirecting_macro(o->chan, in, &redirecting, 1, 0)) {
04200 ast_channel_update_redirecting(in, &redirecting, NULL);
04201 }
04202 ast_party_redirecting_free(&redirecting);
04203 } else {
04204 ast_channel_unlock(o->chan);
04205 }
04206
04207 if (ast_call(o->chan, stuff, 0)) {
04208 ast_log(LOG_NOTICE, "Forwarding failed to dial '%s/%s'\n",
04209 tech, stuff);
04210 do_hang(o);
04211 numnochan++;
04212 }
04213 }
04214
04215 ast_hangup(winner);
04216 continue;
04217 }
04218 f = ast_read(winner);
04219 if (f) {
04220 if (f->frametype == AST_FRAME_CONTROL) {
04221 switch (f->subclass.integer) {
04222 case AST_CONTROL_ANSWER:
04223
04224 if (!peer) {
04225 ast_verb(3, "%s answered %s\n", ochan_name, inchan_name);
04226 if (!o->block_connected_update) {
04227 if (o->pending_connected_update) {
04228 if (ast_channel_connected_line_sub(o->chan, in, &o->connected, 0) &&
04229 ast_channel_connected_line_macro(o->chan, in, &o->connected, 1, 0)) {
04230 ast_channel_update_connected_line(in, &o->connected, NULL);
04231 }
04232 } else if (!o->dial_callerid_absent) {
04233 ast_channel_lock(o->chan);
04234 ast_connected_line_copy_from_caller(&connected_caller, ast_channel_caller(o->chan));
04235 ast_channel_unlock(o->chan);
04236 connected_caller.source = AST_CONNECTED_LINE_UPDATE_SOURCE_ANSWER;
04237 if (ast_channel_connected_line_sub(o->chan, in, &connected_caller, 0) &&
04238 ast_channel_connected_line_macro(o->chan, in, &connected_caller, 1, 0)) {
04239 ast_channel_update_connected_line(in, &connected_caller, NULL);
04240 }
04241 ast_party_connected_line_free(&connected_caller);
04242 }
04243 }
04244 if (o->aoc_s_rate_list) {
04245 size_t encoded_size;
04246 struct ast_aoc_encoded *encoded;
04247 if ((encoded = ast_aoc_encode(o->aoc_s_rate_list, &encoded_size, o->chan))) {
04248 ast_indicate_data(in, AST_CONTROL_AOC, encoded, encoded_size);
04249 ast_aoc_destroy_encoded(encoded);
04250 }
04251 }
04252 peer = o;
04253 }
04254 break;
04255 case AST_CONTROL_BUSY:
04256 ast_verb(3, "%s is busy\n", ochan_name);
04257 if (ast_channel_cdr(in)) {
04258 ast_cdr_busy(ast_channel_cdr(in));
04259 }
04260 do_hang(o);
04261 endtime = (long) time(NULL);
04262 endtime -= starttime;
04263 rna(endtime * 1000, qe, on, membername, qe->parent->autopausebusy);
04264 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04265 if (qe->parent->timeoutrestart) {
04266 *to = orig;
04267 }
04268
04269 if (*to > 500) {
04270 ring_one(qe, outgoing, &numbusies);
04271 starttime = (long) time(NULL);
04272 }
04273 }
04274 numbusies++;
04275 break;
04276 case AST_CONTROL_CONGESTION:
04277 ast_verb(3, "%s is circuit-busy\n", ochan_name);
04278 if (ast_channel_cdr(in)) {
04279 ast_cdr_busy(ast_channel_cdr(in));
04280 }
04281 endtime = (long) time(NULL);
04282 endtime -= starttime;
04283 rna(endtime * 1000, qe, on, membername, qe->parent->autopauseunavail);
04284 do_hang(o);
04285 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04286 if (qe->parent->timeoutrestart) {
04287 *to = orig;
04288 }
04289 if (*to > 500) {
04290 ring_one(qe, outgoing, &numbusies);
04291 starttime = (long) time(NULL);
04292 }
04293 }
04294 numbusies++;
04295 break;
04296 case AST_CONTROL_RINGING:
04297 ast_verb(3, "%s is ringing\n", ochan_name);
04298
04299
04300 if (qe->ring_when_ringing) {
04301 ast_moh_stop(qe->chan);
04302 ast_indicate(qe->chan, AST_CONTROL_RINGING);
04303 }
04304 break;
04305 case AST_CONTROL_OFFHOOK:
04306
04307 break;
04308 case AST_CONTROL_CONNECTED_LINE:
04309 if (o->block_connected_update) {
04310 ast_verb(3, "Connected line update to %s prevented.\n", inchan_name);
04311 break;
04312 }
04313 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04314 struct ast_party_connected_line connected;
04315
04316 ast_verb(3, "%s connected line has changed. Saving it until answer for %s\n", ochan_name, inchan_name);
04317 ast_party_connected_line_set_init(&connected, &o->connected);
04318 ast_connected_line_parse_data(f->data.ptr, f->datalen, &connected);
04319 ast_party_connected_line_set(&o->connected, &connected, NULL);
04320 ast_party_connected_line_free(&connected);
04321 o->pending_connected_update = 1;
04322 break;
04323 }
04324
04325
04326
04327
04328
04329 o->dial_callerid_absent = 1;
04330
04331 if (ast_channel_connected_line_sub(o->chan, in, f, 1) &&
04332 ast_channel_connected_line_macro(o->chan, in, f, 1, 1)) {
04333 ast_indicate_data(in, AST_CONTROL_CONNECTED_LINE, f->data.ptr, f->datalen);
04334 }
04335 break;
04336 case AST_CONTROL_AOC:
04337 {
04338 struct ast_aoc_decoded *decoded = ast_aoc_decode(f->data.ptr, f->datalen, o->chan);
04339 if (decoded && (ast_aoc_get_msg_type(decoded) == AST_AOC_S)) {
04340 ast_aoc_destroy_decoded(o->aoc_s_rate_list);
04341 o->aoc_s_rate_list = decoded;
04342 } else {
04343 ast_aoc_destroy_decoded(decoded);
04344 }
04345 }
04346 break;
04347 case AST_CONTROL_REDIRECTING:
04348 if (qe->parent->strategy == QUEUE_STRATEGY_RINGALL) {
04349
04350
04351
04352
04353 break;
04354 }
04355 if (o->block_connected_update) {
04356 ast_verb(3, "Redirecting update to %s prevented\n",
04357 inchan_name);
04358 break;
04359 }
04360 ast_verb(3, "%s redirecting info has changed, passing it to %s\n",
04361 ochan_name, inchan_name);
04362 if (ast_channel_redirecting_sub(o->chan, in, f, 1) &&
04363 ast_channel_redirecting_macro(o->chan, in, f, 1, 1)) {
04364 ast_indicate_data(in, AST_CONTROL_REDIRECTING, f->data.ptr, f->datalen);
04365 }
04366 break;
04367 case AST_CONTROL_PVT_CAUSE_CODE:
04368 ast_indicate_data(in, AST_CONTROL_PVT_CAUSE_CODE, f->data.ptr, f->datalen);
04369 break;
04370 default:
04371 ast_debug(1, "Dunno what to do with control type %d\n", f->subclass.integer);
04372 break;
04373 }
04374 }
04375 ast_frfree(f);
04376 } else {
04377 endtime = (long) time(NULL) - starttime;
04378 rna(endtime * 1000, qe, on, membername, 1);
04379 do_hang(o);
04380 if (qe->parent->strategy != QUEUE_STRATEGY_RINGALL) {
04381 if (qe->parent->timeoutrestart) {
04382 *to = orig;
04383 }
04384 if (*to > 500) {
04385 ring_one(qe, outgoing, &numbusies);
04386 starttime = (long) time(NULL);
04387 }
04388 }
04389 }
04390 }
04391 }
04392
04393
04394 if (winner == in) {
04395 f = ast_read(in);
04396 if (!f || ((f->frametype == AST_FRAME_CONTROL) && (f->subclass.integer == AST_CONTROL_HANGUP))) {
04397
04398 *to = -1;
04399 if (f) {
04400 if (f->data.uint32) {
04401 ast_channel_hangupcause_set(in, f->data.uint32);
04402 }
04403 ast_frfree(f);
04404 }
04405 return NULL;
04406 }
04407
04408 if ((f->frametype == AST_FRAME_DTMF) && caller_disconnect && (f->subclass.integer == '*')) {
04409 ast_verb(3, "User hit %c to disconnect call.\n", f->subclass.integer);
04410 *to = 0;
04411 ast_frfree(f);
04412 return NULL;
04413 }
04414 if ((f->frametype == AST_FRAME_DTMF) && valid_exit(qe, f->subclass.integer)) {
04415 ast_verb(3, "User pressed digit: %c\n", f->subclass.integer);
04416 *to = 0;
04417 *digit = f->subclass.integer;
04418 ast_frfree(f);
04419 return NULL;
04420 }
04421
04422
04423 for (o = start; o; o = o->call_next) {
04424 if (!o->stillgoing || !o->chan) {
04425
04426 continue;
04427 }
04428 switch (f->frametype) {
04429 case AST_FRAME_CONTROL:
04430 switch (f->subclass.integer) {
04431 case AST_CONTROL_CONNECTED_LINE:
04432 if (ast_channel_connected_line_sub(in, o->chan, f, 1) &&
04433 ast_channel_connected_line_macro(in, o->chan, f, 0, 1)) {
04434 ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
04435 }
04436 break;
04437 case AST_CONTROL_REDIRECTING:
04438 if (ast_channel_redirecting_sub(in, o->chan, f, 1) &&
04439 ast_channel_redirecting_macro(in, o->chan, f, 0, 1)) {
04440 ast_indicate_data(o->chan, f->subclass.integer, f->data.ptr, f->datalen);
04441 }
04442 break;
04443 default:
04444
04445 goto skip_frame;
04446 }
04447 break;
04448 default:
04449
04450 goto skip_frame;
04451 }
04452 }
04453 skip_frame:;
04454
04455 ast_frfree(f);
04456 }
04457 if (!*to) {
04458 for (o = start; o; o = o->call_next) {
04459 rna(orig, qe, o->interface, o->member->membername, 1);
04460 }
04461 }
04462 }
04463
04464 #ifdef HAVE_EPOLL
04465 for (epollo = outgoing; epollo; epollo = epollo->q_next) {
04466 if (epollo->chan) {
04467 ast_poll_channel_del(in, epollo->chan);
04468 }
04469 }
04470 #endif
04471
04472 return peer;
04473 }
04474
04475
04476
04477
04478
04479
04480
04481
04482
04483
04484
04485
04486 static int is_our_turn(struct queue_ent *qe)
04487 {
04488 struct queue_ent *ch;
04489 int res;
04490 int avl;
04491 int idx = 0;
04492
04493 ao2_lock(qe->parent);
04494
04495 avl = num_available_members(qe->parent);
04496
04497 ch = qe->parent->head;
04498
04499 ast_debug(1, "There %s %d available %s.\n", avl != 1 ? "are" : "is", avl, avl != 1 ? "members" : "member");
04500
04501 while ((idx < avl) && (ch) && (ch != qe)) {
04502 if (!ch->pending) {
04503 idx++;
04504 }
04505 ch = ch->next;
04506 }
04507
04508 ao2_unlock(qe->parent);
04509
04510
04511
04512
04513 if (ch && idx < avl && (qe->parent->autofill || qe->pos == 1)) {
04514 ast_debug(1, "It's our turn (%s).\n", ast_channel_name(qe->chan));
04515 res = 1;
04516 } else {
04517 ast_debug(1, "It's not our turn (%s).\n", ast_channel_name(qe->chan));
04518 res = 0;
04519 }
04520
04521 return res;
04522 }
04523
04524
04525
04526
04527
04528
04529
04530 static void update_qe_rule(struct queue_ent *qe)
04531 {
04532 int max_penalty = qe->pr->max_relative ? qe->max_penalty + qe->pr->max_value : qe->pr->max_value;
04533 int min_penalty = qe->pr->min_relative ? qe->min_penalty + qe->pr->min_value : qe->pr->min_value;
04534 char max_penalty_str[20], min_penalty_str[20];
04535
04536 if (max_penalty < 0) {
04537 max_penalty = 0;
04538 }
04539 if (min_penalty < 0) {
04540 min_penalty = 0;
04541 }
04542 if (min_penalty > max_penalty) {
04543 min_penalty = max_penalty;
04544 }
04545 snprintf(max_penalty_str, sizeof(max_penalty_str), "%d", max_penalty);
04546 snprintf(min_penalty_str, sizeof(min_penalty_str), "%d", min_penalty);
04547 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MAX_PENALTY", max_penalty_str);
04548 pbx_builtin_setvar_helper(qe->chan, "QUEUE_MIN_PENALTY", min_penalty_str);
04549 qe->max_penalty = max_penalty;
04550 qe->min_penalty = min_penalty;
04551 ast_debug(3, "Setting max penalty to %d and min penalty to %d for caller %s since %d seconds have elapsed\n", qe->max_penalty, qe->min_penalty, ast_channel_name(qe->chan), qe->pr->time);
04552 qe->pr = AST_LIST_NEXT(qe->pr, list);
04553 }
04554
04555
04556
04557
04558
04559
04560
04561
04562
04563
04564
04565 static int wait_our_turn(struct queue_ent *qe, int ringing, enum queue_result *reason)
04566 {
04567 int res = 0;
04568
04569
04570 for (;;) {
04571
04572 if (is_our_turn(qe)) {
04573 break;
04574 }
04575
04576
04577 if (qe->expire && (time(NULL) >= qe->expire)) {
04578 *reason = QUEUE_TIMEOUT;
04579 break;
04580 }
04581
04582 if (qe->parent->leavewhenempty) {
04583 int status = 0;
04584
04585 if ((status = get_member_status(qe->parent, qe->max_penalty, qe->min_penalty, qe->parent->leavewhenempty))) {
04586 *reason = QUEUE_LEAVEEMPTY;
04587 ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), "NONE", "EXITEMPTY", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
04588 leave_queue(qe);
04589 break;
04590 }
04591 }
04592
04593
04594 if (qe->parent->announcefrequency &&
04595 (res = say_position(qe,ringing))) {
04596 break;
04597 }
04598
04599
04600 if (qe->expire && (time(NULL) >= qe->expire)) {
04601 *reason = QUEUE_TIMEOUT;
04602 break;
04603 }
04604
04605
04606 if (qe->parent->periodicannouncefrequency &&
04607 (res = say_periodic_announcement(qe,ringing)))
04608 break;
04609
04610
04611 while (qe->pr && ((time(NULL) - qe->start) >= qe->pr->time)) {
04612 update_qe_rule(qe);
04613 }
04614
04615
04616 if (qe->expire && (time(NULL) >= qe->expire)) {
04617 *reason = QUEUE_TIMEOUT;
04618 break;
04619 }
04620
04621
04622 if ((res = ast_waitfordigit(qe->chan, RECHECK * 1000))) {
04623 if (res > 0 && !valid_exit(qe, res)) {
04624 res = 0;
04625 } else {
04626 break;
04627 }
04628 }
04629
04630
04631 if (qe->expire && (time(NULL) >= qe->expire)) {
04632 *reason = QUEUE_TIMEOUT;
04633 break;
04634 }
04635 }
04636
04637 return res;
04638 }
04639
04640
04641
04642
04643
04644 static int update_queue(struct call_queue *q, struct member *member, int callcompletedinsl, int newtalktime)
04645 {
04646 int oldtalktime;
04647
04648 struct member *mem;
04649 struct call_queue *qtmp;
04650 struct ao2_iterator queue_iter;
04651
04652 if (shared_lastcall) {
04653 queue_iter = ao2_iterator_init(queues, 0);
04654 while ((qtmp = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
04655 ao2_lock(qtmp);
04656 if ((mem = ao2_find(qtmp->members, member, OBJ_POINTER))) {
04657 time(&mem->lastcall);
04658 mem->calls++;
04659 mem->lastqueue = q;
04660 ao2_ref(mem, -1);
04661 }
04662 ao2_unlock(qtmp);
04663 queue_t_unref(qtmp, "Done with iterator");
04664 }
04665 ao2_iterator_destroy(&queue_iter);
04666 } else {
04667 ao2_lock(q);
04668 time(&member->lastcall);
04669 member->calls++;
04670 member->lastqueue = q;
04671 ao2_unlock(q);
04672 }
04673 ao2_lock(q);
04674 q->callscompleted++;
04675 if (callcompletedinsl) {
04676 q->callscompletedinsl++;
04677 }
04678
04679 oldtalktime = q->talktime;
04680 q->talktime = (((oldtalktime << 2) - oldtalktime) + newtalktime) >> 2;
04681 ao2_unlock(q);
04682 return 0;
04683 }
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693 static int calc_metric(struct call_queue *q, struct member *mem, int pos, struct queue_ent *qe, struct callattempt *tmp)
04694 {
04695
04696 int membercount = ao2_container_count(q->members);
04697 unsigned char usepenalty = (membercount <= q->penaltymemberslimit) ? 0 : 1;
04698
04699 if (usepenalty) {
04700 if ((qe->max_penalty && (mem->penalty > qe->max_penalty)) ||
04701 (qe->min_penalty && (mem->penalty < qe->min_penalty))) {
04702 return -1;
04703 }
04704 } else {
04705 ast_debug(1, "Disregarding penalty, %d members and %d in penaltymemberslimit.\n",
04706 membercount, q->penaltymemberslimit);
04707 }
04708
04709 switch (q->strategy) {
04710 case QUEUE_STRATEGY_RINGALL:
04711
04712 tmp->metric = mem->penalty * 1000000 * usepenalty;
04713 break;
04714 case QUEUE_STRATEGY_LINEAR:
04715 if (pos < qe->linpos) {
04716 tmp->metric = 1000 + pos;
04717 } else {
04718 if (pos > qe->linpos) {
04719
04720 qe->linwrapped = 1;
04721 }
04722 tmp->metric = pos;
04723 }
04724 tmp->metric += mem->penalty * 1000000 * usepenalty;
04725 break;
04726 case QUEUE_STRATEGY_RRORDERED:
04727 case QUEUE_STRATEGY_RRMEMORY:
04728 if (pos < q->rrpos) {
04729 tmp->metric = 1000 + pos;
04730 } else {
04731 if (pos > q->rrpos) {
04732
04733 q->wrapped = 1;
04734 }
04735 tmp->metric = pos;
04736 }
04737 tmp->metric += mem->penalty * 1000000 * usepenalty;
04738 break;
04739 case QUEUE_STRATEGY_RANDOM:
04740 tmp->metric = ast_random() % 1000;
04741 tmp->metric += mem->penalty * 1000000 * usepenalty;
04742 break;
04743 case QUEUE_STRATEGY_WRANDOM:
04744 tmp->metric = ast_random() % ((1 + mem->penalty) * 1000);
04745 break;
04746 case QUEUE_STRATEGY_FEWESTCALLS:
04747 tmp->metric = mem->calls;
04748 tmp->metric += mem->penalty * 1000000 * usepenalty;
04749 break;
04750 case QUEUE_STRATEGY_LEASTRECENT:
04751 if (!mem->lastcall) {
04752 tmp->metric = 0;
04753 } else {
04754 tmp->metric = 1000000 - (time(NULL) - mem->lastcall);
04755 }
04756 tmp->metric += mem->penalty * 1000000 * usepenalty;
04757 break;
04758 default:
04759 ast_log(LOG_WARNING, "Can't calculate metric for unknown strategy %d\n", q->strategy);
04760 break;
04761 }
04762 return 0;
04763 }
04764
04765 enum agent_complete_reason {
04766 CALLER,
04767 AGENT,
04768 TRANSFER
04769 };
04770
04771
04772 static void send_agent_complete(const struct queue_ent *qe, const char *queuename,
04773 const struct ast_channel *peer, const struct member *member, time_t callstart,
04774 char *vars, size_t vars_len, enum agent_complete_reason rsn)
04775 {
04776 const char *reason = NULL;
04777
04778 if (!qe->parent->eventwhencalled) {
04779 return;
04780 }
04781
04782 switch (rsn) {
04783 case CALLER:
04784 reason = "caller";
04785 break;
04786 case AGENT:
04787 reason = "agent";
04788 break;
04789 case TRANSFER:
04790 reason = "transfer";
04791 break;
04792 }
04793
04794
04795
04796
04797
04798
04799
04800
04801
04802
04803
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815
04816
04817
04818
04819
04820 manager_event(EVENT_FLAG_AGENT, "AgentComplete",
04821 "Queue: %s\r\n"
04822 "Uniqueid: %s\r\n"
04823 "Channel: %s\r\n"
04824 "Member: %s\r\n"
04825 "MemberName: %s\r\n"
04826 "HoldTime: %ld\r\n"
04827 "TalkTime: %ld\r\n"
04828 "Reason: %s\r\n"
04829 "%s",
04830 queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
04831 (long)(callstart - qe->start), (long)(time(NULL) - callstart), reason,
04832 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, vars_len) : "");
04833 }
04834
04835 struct queue_transfer_ds {
04836 struct queue_ent *qe;
04837 struct member *member;
04838 time_t starttime;
04839 int callcompletedinsl;
04840 };
04841
04842 static void queue_transfer_destroy(void *data)
04843 {
04844 struct queue_transfer_ds *qtds = data;
04845 ast_free(qtds);
04846 }
04847
04848
04849
04850 static const struct ast_datastore_info queue_transfer_info = {
04851 .type = "queue_transfer",
04852 .chan_fixup = queue_transfer_fixup,
04853 .destroy = queue_transfer_destroy,
04854 };
04855
04856
04857
04858
04859
04860
04861
04862
04863
04864
04865 static void queue_transfer_fixup(void *data, struct ast_channel *old_chan, struct ast_channel *new_chan)
04866 {
04867 struct queue_transfer_ds *qtds = data;
04868 struct queue_ent *qe = qtds->qe;
04869 struct member *member = qtds->member;
04870 time_t callstart = qtds->starttime;
04871 int callcompletedinsl = qtds->callcompletedinsl;
04872 struct ast_datastore *datastore;
04873
04874 ast_queue_log(qe->parent->name, ast_channel_uniqueid(qe->chan), member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
04875 ast_channel_exten(new_chan), ast_channel_context(new_chan), (long) (callstart - qe->start),
04876 (long) (time(NULL) - callstart), qe->opos);
04877
04878 update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
04879
04880
04881 if ((datastore = ast_channel_datastore_find(old_chan, &queue_transfer_info, NULL))) {
04882 ast_channel_datastore_remove(old_chan, datastore);
04883 } else {
04884 ast_log(LOG_WARNING, "Can't find the queue_transfer datastore.\n");
04885 }
04886 }
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896 static int attended_transfer_occurred(struct ast_channel *chan)
04897 {
04898 return ast_channel_datastore_find(chan, &queue_transfer_info, NULL) ? 0 : 1;
04899 }
04900
04901
04902
04903 static struct ast_datastore *setup_transfer_datastore(struct queue_ent *qe, struct member *member, time_t starttime, int callcompletedinsl)
04904 {
04905 struct ast_datastore *ds;
04906 struct queue_transfer_ds *qtds = ast_calloc(1, sizeof(*qtds));
04907
04908 if (!qtds) {
04909 ast_log(LOG_WARNING, "Memory allocation error!\n");
04910 return NULL;
04911 }
04912
04913 ast_channel_lock(qe->chan);
04914 if (!(ds = ast_datastore_alloc(&queue_transfer_info, NULL))) {
04915 ast_channel_unlock(qe->chan);
04916 ast_free(qtds);
04917 ast_log(LOG_WARNING, "Unable to create transfer datastore. queue_log will not show attended transfer\n");
04918 return NULL;
04919 }
04920
04921 qtds->qe = qe;
04922
04923 qtds->member = member;
04924 qtds->starttime = starttime;
04925 qtds->callcompletedinsl = callcompletedinsl;
04926 ds->data = qtds;
04927 ast_channel_datastore_add(qe->chan, ds);
04928 ast_channel_unlock(qe->chan);
04929 return ds;
04930 }
04931
04932 struct queue_end_bridge {
04933 struct call_queue *q;
04934 struct ast_channel *chan;
04935 };
04936
04937 static void end_bridge_callback_data_fixup(struct ast_bridge_config *bconfig, struct ast_channel *originator, struct ast_channel *terminator)
04938 {
04939 struct queue_end_bridge *qeb = bconfig->end_bridge_callback_data;
04940 ao2_ref(qeb, +1);
04941 qeb->chan = originator;
04942 }
04943
04944 static void end_bridge_callback(void *data)
04945 {
04946 struct queue_end_bridge *qeb = data;
04947 struct call_queue *q = qeb->q;
04948 struct ast_channel *chan = qeb->chan;
04949
04950 if (ao2_ref(qeb, -1) == 1) {
04951 set_queue_variables(q, chan);
04952
04953 queue_t_unref(q, "Expire bridge_config reference");
04954 }
04955 }
04956
04957
04958
04959
04960
04961
04962
04963
04964
04965
04966
04967
04968
04969
04970
04971
04972
04973
04974
04975
04976
04977
04978
04979
04980
04981
04982
04983
04984
04985
04986
04987 static int try_calling(struct queue_ent *qe, const struct ast_flags opts, char **opt_args, char *announceoverride, const char *url, int *tries, int *noption, const char *agi, const char *macro, const char *gosub, int ringing)
04988 {
04989 struct member *cur;
04990 struct callattempt *outgoing = NULL;
04991 int to, orig;
04992 char oldexten[AST_MAX_EXTENSION]="";
04993 char oldcontext[AST_MAX_CONTEXT]="";
04994 char queuename[256]="";
04995 char interfacevar[256]="";
04996 struct ast_channel *peer;
04997 struct ast_channel *which;
04998 struct callattempt *lpeer;
04999 struct member *member;
05000 struct ast_app *application;
05001 int res = 0, bridge = 0;
05002 int numbusies = 0;
05003 int x=0;
05004 char *announce = NULL;
05005 char digit = 0;
05006 time_t callstart;
05007 time_t now = time(NULL);
05008 struct ast_bridge_config bridge_config;
05009 char nondataquality = 1;
05010 char *agiexec = NULL;
05011 char *macroexec = NULL;
05012 char *gosubexec = NULL;
05013 const char *monitorfilename;
05014 const char *monitor_exec;
05015 const char *monitor_options;
05016 char tmpid[256], tmpid2[256];
05017 char meid[1024], meid2[1024];
05018 char mixmonargs[1512];
05019 struct ast_app *mixmonapp = NULL;
05020 char *p;
05021 char vars[2048];
05022 int forwardsallowed = 1;
05023 int block_connected_line = 0;
05024 int callcompletedinsl;
05025 struct ao2_iterator memi;
05026 struct ast_datastore *datastore, *transfer_ds;
05027 struct queue_end_bridge *queue_end_bridge = NULL;
05028
05029 ast_channel_lock(qe->chan);
05030 datastore = ast_channel_datastore_find(qe->chan, &dialed_interface_info, NULL);
05031 ast_channel_unlock(qe->chan);
05032
05033 memset(&bridge_config, 0, sizeof(bridge_config));
05034 tmpid[0] = 0;
05035 meid[0] = 0;
05036 time(&now);
05037
05038
05039
05040
05041
05042 if (qe->expire && now >= qe->expire) {
05043 res = 0;
05044 goto out;
05045 }
05046
05047 if (ast_test_flag(&opts, OPT_CALLEE_TRANSFER)) {
05048 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_REDIRECT);
05049 }
05050 if (ast_test_flag(&opts, OPT_CALLER_TRANSFER)) {
05051 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_REDIRECT);
05052 }
05053 if (ast_test_flag(&opts, OPT_CALLEE_AUTOMON)) {
05054 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMON);
05055 }
05056 if (ast_test_flag(&opts, OPT_CALLER_AUTOMON)) {
05057 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMON);
05058 }
05059 if (ast_test_flag(&opts, OPT_GO_ON)) {
05060 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_NO_H_EXTEN);
05061 }
05062 if (ast_test_flag(&opts, OPT_DATA_QUALITY)) {
05063 nondataquality = 0;
05064 }
05065 if (ast_test_flag(&opts, OPT_CALLEE_HANGUP)) {
05066 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_DISCONNECT);
05067 }
05068 if (ast_test_flag(&opts, OPT_CALLER_HANGUP)) {
05069 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT);
05070 }
05071 if (ast_test_flag(&opts, OPT_CALLEE_PARK)) {
05072 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_PARKCALL);
05073 }
05074 if (ast_test_flag(&opts, OPT_CALLER_PARK)) {
05075 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_PARKCALL);
05076 }
05077 if (ast_test_flag(&opts, OPT_NO_RETRY)) {
05078 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_LINEAR
05079 || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
05080 (*tries)++;
05081 } else {
05082 *tries = ao2_container_count(qe->parent->members);
05083 }
05084 *noption = 1;
05085 }
05086 if (ast_test_flag(&opts, OPT_IGNORE_CALL_FW)) {
05087 forwardsallowed = 0;
05088 }
05089 if (ast_test_flag(&opts, OPT_IGNORE_CONNECTEDLINE)) {
05090 block_connected_line = 1;
05091 }
05092 if (ast_test_flag(&opts, OPT_CALLEE_AUTOMIXMON)) {
05093 ast_set_flag(&(bridge_config.features_callee), AST_FEATURE_AUTOMIXMON);
05094 }
05095 if (ast_test_flag(&opts, OPT_CALLER_AUTOMIXMON)) {
05096 ast_set_flag(&(bridge_config.features_caller), AST_FEATURE_AUTOMIXMON);
05097 }
05098 if (ast_test_flag(&opts, OPT_MARK_AS_ANSWERED)) {
05099 qe->cancel_answered_elsewhere = 1;
05100 }
05101
05102
05103
05104
05105 if (ast_channel_hangupcause(qe->chan) == AST_CAUSE_ANSWERED_ELSEWHERE) {
05106 qe->cancel_answered_elsewhere = 1;
05107 }
05108
05109 ao2_lock(qe->parent);
05110 ast_debug(1, "%s is trying to call a queue member.\n",
05111 ast_channel_name(qe->chan));
05112 ast_copy_string(queuename, qe->parent->name, sizeof(queuename));
05113 if (!ast_strlen_zero(qe->announce)) {
05114 announce = qe->announce;
05115 }
05116 if (!ast_strlen_zero(announceoverride)) {
05117 announce = announceoverride;
05118 }
05119
05120 memi = ao2_iterator_init(qe->parent->members, 0);
05121 while ((cur = ao2_iterator_next(&memi))) {
05122 struct callattempt *tmp = ast_calloc(1, sizeof(*tmp));
05123 struct ast_dialed_interface *di;
05124 AST_LIST_HEAD(,ast_dialed_interface) *dialed_interfaces;
05125 if (!tmp) {
05126 ao2_ref(cur, -1);
05127 ao2_iterator_destroy(&memi);
05128 ao2_unlock(qe->parent);
05129 goto out;
05130 }
05131 if (!datastore) {
05132 if (!(datastore = ast_datastore_alloc(&dialed_interface_info, NULL))) {
05133 callattempt_free(tmp);
05134 ao2_ref(cur, -1);
05135 ao2_iterator_destroy(&memi);
05136 ao2_unlock(qe->parent);
05137 goto out;
05138 }
05139 datastore->inheritance = DATASTORE_INHERIT_FOREVER;
05140 if (!(dialed_interfaces = ast_calloc(1, sizeof(*dialed_interfaces)))) {
05141 callattempt_free(tmp);
05142 ao2_ref(cur, -1);
05143 ao2_iterator_destroy(&memi);
05144 ao2_unlock(qe->parent);
05145 goto out;
05146 }
05147 datastore->data = dialed_interfaces;
05148 AST_LIST_HEAD_INIT(dialed_interfaces);
05149
05150 ast_channel_lock(qe->chan);
05151 ast_channel_datastore_add(qe->chan, datastore);
05152 ast_channel_unlock(qe->chan);
05153 } else
05154 dialed_interfaces = datastore->data;
05155
05156 AST_LIST_LOCK(dialed_interfaces);
05157 AST_LIST_TRAVERSE(dialed_interfaces, di, list) {
05158 if (!strcasecmp(cur->interface, di->interface)) {
05159 ast_debug(1, "Skipping dialing interface '%s' since it has already been dialed\n",
05160 di->interface);
05161 break;
05162 }
05163 }
05164 AST_LIST_UNLOCK(dialed_interfaces);
05165
05166 if (di) {
05167 callattempt_free(tmp);
05168 ao2_ref(cur, -1);
05169 continue;
05170 }
05171
05172
05173
05174
05175
05176 if (strncasecmp(cur->interface, "Local/", 6)) {
05177 if (!(di = ast_calloc(1, sizeof(*di) + strlen(cur->interface)))) {
05178 callattempt_free(tmp);
05179 ao2_ref(cur, -1);
05180 ao2_iterator_destroy(&memi);
05181 ao2_unlock(qe->parent);
05182 goto out;
05183 }
05184 strcpy(di->interface, cur->interface);
05185
05186 AST_LIST_LOCK(dialed_interfaces);
05187 AST_LIST_INSERT_TAIL(dialed_interfaces, di, list);
05188 AST_LIST_UNLOCK(dialed_interfaces);
05189 }
05190
05191
05192
05193
05194
05195
05196
05197 ast_channel_lock(qe->chan);
05198 ast_party_connected_line_copy(&tmp->connected, ast_channel_connected(qe->chan));
05199 ast_channel_unlock(qe->chan);
05200
05201 tmp->block_connected_update = block_connected_line;
05202 tmp->stillgoing = 1;
05203 tmp->member = cur;
05204 tmp->lastcall = cur->lastcall;
05205 tmp->lastqueue = cur->lastqueue;
05206 ast_copy_string(tmp->interface, cur->interface, sizeof(tmp->interface));
05207
05208
05209 if (!calc_metric(qe->parent, cur, x++, qe, tmp)) {
05210
05211
05212
05213 tmp->q_next = outgoing;
05214 outgoing = tmp;
05215
05216 if (outgoing->chan && (ast_channel_state(outgoing->chan) == AST_STATE_UP))
05217 break;
05218 } else {
05219 callattempt_free(tmp);
05220 }
05221 }
05222 ao2_iterator_destroy(&memi);
05223
05224 if (qe->parent->timeoutpriority == TIMEOUT_PRIORITY_APP) {
05225
05226 if (qe->expire && (!qe->parent->timeout || (qe->expire - now) <= qe->parent->timeout)) {
05227 to = (qe->expire - now) * 1000;
05228 } else {
05229 to = (qe->parent->timeout) ? qe->parent->timeout * 1000 : -1;
05230 }
05231 } else {
05232
05233 if (qe->expire && qe->expire<=now) {
05234 to = 0;
05235 } else if (qe->parent->timeout) {
05236 to = qe->parent->timeout * 1000;
05237 } else {
05238 to = -1;
05239 }
05240 }
05241 orig = to;
05242 ++qe->pending;
05243 ao2_unlock(qe->parent);
05244 ring_one(qe, outgoing, &numbusies);
05245 lpeer = wait_for_answer(qe, outgoing, &to, &digit, numbusies,
05246 ast_test_flag(&(bridge_config.features_caller), AST_FEATURE_DISCONNECT),
05247 forwardsallowed);
05248
05249
05250
05251
05252
05253
05254 ast_channel_lock(qe->chan);
05255 if (datastore && !ast_channel_datastore_remove(qe->chan, datastore)) {
05256 ast_datastore_free(datastore);
05257 }
05258 ast_channel_unlock(qe->chan);
05259 ao2_lock(qe->parent);
05260 if (qe->parent->strategy == QUEUE_STRATEGY_RRMEMORY || qe->parent->strategy == QUEUE_STRATEGY_RRORDERED) {
05261 store_next_rr(qe, outgoing);
05262
05263 }
05264 if (qe->parent->strategy == QUEUE_STRATEGY_LINEAR) {
05265 store_next_lin(qe, outgoing);
05266 }
05267 ao2_unlock(qe->parent);
05268 peer = lpeer ? lpeer->chan : NULL;
05269 if (!peer) {
05270 qe->pending = 0;
05271 if (to) {
05272
05273 res = -1;
05274 } else {
05275
05276 res = digit;
05277 }
05278 if (res == -1) {
05279 ast_debug(1, "%s: Nobody answered.\n", ast_channel_name(qe->chan));
05280 }
05281 if (ast_cdr_isset_unanswered()) {
05282
05283
05284 struct callattempt *o;
05285 for (o = outgoing; o; o = o->q_next) {
05286 if (!o->chan) {
05287 continue;
05288 }
05289 if (strcmp(ast_channel_cdr(o->chan)->dstchannel, ast_channel_cdr(qe->chan)->dstchannel) == 0) {
05290 ast_set_flag(ast_channel_cdr(o->chan), AST_CDR_FLAG_POST_DISABLED);
05291 break;
05292 }
05293 }
05294 }
05295 } else {
05296
05297 char *caller_context;
05298 char *caller_extension;
05299 int caller_priority;
05300
05301
05302
05303
05304 if (!strcmp(ast_channel_tech(qe->chan)->type, "DAHDI")) {
05305 ast_channel_setoption(qe->chan, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
05306 }
05307 if (!strcmp(ast_channel_tech(peer)->type, "DAHDI")) {
05308 ast_channel_setoption(peer, AST_OPTION_TONE_VERIFY, &nondataquality, sizeof(nondataquality), 0);
05309 }
05310
05311 time(&now);
05312 recalc_holdtime(qe, (now - qe->start));
05313 ao2_lock(qe->parent);
05314 callcompletedinsl = ((now - qe->start) <= qe->parent->servicelevel);
05315 ao2_unlock(qe->parent);
05316 member = lpeer->member;
05317
05318 ao2_ref(member, 1);
05319 hangupcalls(outgoing, peer, qe->cancel_answered_elsewhere);
05320 outgoing = NULL;
05321 if (announce || qe->parent->reportholdtime || qe->parent->memberdelay) {
05322 int res2;
05323
05324 res2 = ast_autoservice_start(qe->chan);
05325 if (!res2) {
05326 if (qe->parent->memberdelay) {
05327 ast_log(LOG_NOTICE, "Delaying member connect for %d seconds\n", qe->parent->memberdelay);
05328 res2 = ast_safe_sleep(peer, qe->parent->memberdelay * 1000);
05329 }
05330 if (!res2 && announce) {
05331 if (play_file(peer, announce) < 0) {
05332 ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", announce, ast_channel_name(peer));
05333 }
05334 }
05335 if (!res2 && qe->parent->reportholdtime) {
05336 if (!play_file(peer, qe->parent->sound_reporthold)) {
05337 int holdtime, holdtimesecs;
05338
05339 time(&now);
05340 holdtime = abs((now - qe->start) / 60);
05341 holdtimesecs = abs((now - qe->start) % 60);
05342 if (holdtime > 0) {
05343 ast_say_number(peer, holdtime, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
05344 if (play_file(peer, qe->parent->sound_minutes) < 0) {
05345 ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_minutes, ast_channel_name(peer));
05346 }
05347 }
05348 if (holdtimesecs > 1) {
05349 ast_say_number(peer, holdtimesecs, AST_DIGIT_ANY, ast_channel_language(peer), NULL);
05350 if (play_file(peer, qe->parent->sound_seconds) < 0) {
05351 ast_log(LOG_ERROR, "play_file failed for '%s' on %s\n", qe->parent->sound_seconds, ast_channel_name(peer));
05352 }
05353 }
05354 }
05355 }
05356 ast_autoservice_stop(qe->chan);
05357 }
05358 if (ast_check_hangup(peer)) {
05359
05360 ast_log(LOG_WARNING, "Agent on %s hungup on the customer.\n", ast_channel_name(peer));
05361 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "AGENTDUMP", "%s", "");
05362 if (qe->parent->eventwhencalled)
05363
05364
05365
05366
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377
05378 manager_event(EVENT_FLAG_AGENT, "AgentDump",
05379 "Queue: %s\r\n"
05380 "Uniqueid: %s\r\n"
05381 "Channel: %s\r\n"
05382 "Member: %s\r\n"
05383 "MemberName: %s\r\n"
05384 "%s",
05385 queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
05386 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
05387 ast_autoservice_chan_hangup_peer(qe->chan, peer);
05388 ao2_ref(member, -1);
05389 goto out;
05390 } else if (ast_check_hangup(qe->chan)) {
05391
05392 ast_log(LOG_NOTICE, "Caller was about to talk to agent on %s but the caller hungup.\n", ast_channel_name(peer));
05393 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "ABANDON", "%d|%d|%ld", qe->pos, qe->opos, (long) time(NULL) - qe->start);
05394 record_abandoned(qe);
05395 ast_autoservice_chan_hangup_peer(qe->chan, peer);
05396 ao2_ref(member, -1);
05397 return -1;
05398 }
05399 }
05400
05401 if (ringing) {
05402 ast_indicate(qe->chan,-1);
05403 } else {
05404 ast_moh_stop(qe->chan);
05405 }
05406
05407 if (ast_channel_cdr(qe->chan)) {
05408 ast_cdr_setdestchan(ast_channel_cdr(qe->chan), ast_channel_name(peer));
05409 }
05410
05411 res = ast_channel_make_compatible(qe->chan, peer);
05412 if (res < 0) {
05413 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "SYSCOMPAT", "%s", "");
05414 ast_log(LOG_WARNING, "Had to drop call because I couldn't make %s compatible with %s\n", ast_channel_name(qe->chan), ast_channel_name(peer));
05415 record_abandoned(qe);
05416 ast_cdr_failed(ast_channel_cdr(qe->chan));
05417 ast_autoservice_chan_hangup_peer(qe->chan, peer);
05418 ao2_ref(member, -1);
05419 return -1;
05420 }
05421
05422
05423 if (!ast_strlen_zero(qe->parent->sound_callerannounce)) {
05424 if (play_file(qe->chan, qe->parent->sound_callerannounce)) {
05425 ast_log(LOG_WARNING, "Announcement file '%s' is unavailable, continuing anyway...\n", qe->parent->sound_callerannounce);
05426 }
05427 }
05428
05429 ao2_lock(qe->parent);
05430
05431
05432 if (qe->parent->setinterfacevar) {
05433 snprintf(interfacevar, sizeof(interfacevar), "MEMBERINTERFACE=%s,MEMBERNAME=%s,MEMBERCALLS=%d,MEMBERLASTCALL=%ld,MEMBERPENALTY=%d,MEMBERDYNAMIC=%d,MEMBERREALTIME=%d",
05434 member->interface, member->membername, member->calls, (long)member->lastcall, member->penalty, member->dynamic, member->realtime);
05435 pbx_builtin_setvar_multiple(qe->chan, interfacevar);
05436 pbx_builtin_setvar_multiple(peer, interfacevar);
05437 }
05438
05439
05440
05441 if (qe->parent->setqueueentryvar) {
05442 snprintf(interfacevar, sizeof(interfacevar), "QEHOLDTIME=%ld,QEORIGINALPOS=%d",
05443 (long) time(NULL) - qe->start, qe->opos);
05444 pbx_builtin_setvar_multiple(qe->chan, interfacevar);
05445 pbx_builtin_setvar_multiple(peer, interfacevar);
05446 }
05447
05448 ao2_unlock(qe->parent);
05449
05450
05451 set_queue_variables(qe->parent, qe->chan);
05452 set_queue_variables(qe->parent, peer);
05453
05454 ast_channel_lock(qe->chan);
05455
05456 caller_context = ast_strdupa(ast_channel_context(qe->chan));
05457 caller_extension = ast_strdupa(ast_channel_exten(qe->chan));
05458 caller_priority = ast_channel_priority(qe->chan);
05459 if ((monitorfilename = pbx_builtin_getvar_helper(qe->chan, "MONITOR_FILENAME"))) {
05460 monitorfilename = ast_strdupa(monitorfilename);
05461 }
05462 ast_channel_unlock(qe->chan);
05463
05464
05465 if (qe->parent->monfmt && *qe->parent->monfmt) {
05466 if (!qe->parent->montype) {
05467 const char *monexec;
05468 ast_debug(1, "Starting Monitor as requested.\n");
05469 ast_channel_lock(qe->chan);
05470 if ((monexec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC")) || pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC_ARGS")) {
05471 which = qe->chan;
05472 monexec = monexec ? ast_strdupa(monexec) : NULL;
05473 } else {
05474 which = peer;
05475 }
05476 ast_channel_unlock(qe->chan);
05477 if (monitorfilename) {
05478 ast_monitor_start(which, qe->parent->monfmt, monitorfilename, 1, X_REC_IN | X_REC_OUT);
05479 } else if (ast_channel_cdr(qe->chan)) {
05480 ast_monitor_start(which, qe->parent->monfmt, ast_channel_cdr(qe->chan)->uniqueid, 1, X_REC_IN | X_REC_OUT);
05481 } else {
05482
05483 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
05484 ast_monitor_start(which, qe->parent->monfmt, tmpid, 1, X_REC_IN | X_REC_OUT);
05485 }
05486 if (!ast_strlen_zero(monexec)) {
05487 ast_monitor_setjoinfiles(which, 1);
05488 }
05489 } else {
05490 mixmonapp = pbx_findapp("MixMonitor");
05491
05492 if (mixmonapp) {
05493 ast_debug(1, "Starting MixMonitor as requested.\n");
05494 if (!monitorfilename) {
05495 if (ast_channel_cdr(qe->chan)) {
05496 ast_copy_string(tmpid, ast_channel_cdr(qe->chan)->uniqueid, sizeof(tmpid));
05497 } else {
05498 snprintf(tmpid, sizeof(tmpid), "chan-%lx", ast_random());
05499 }
05500 } else {
05501 const char *m = monitorfilename;
05502 for (p = tmpid2; p < tmpid2 + sizeof(tmpid2) - 1; p++, m++) {
05503 switch (*m) {
05504 case '^':
05505 if (*(m + 1) == '{')
05506 *p = '$';
05507 break;
05508 case ',':
05509 *p++ = '\\';
05510
05511 default:
05512 *p = *m;
05513 }
05514 if (*m == '\0')
05515 break;
05516 }
05517 if (p == tmpid2 + sizeof(tmpid2))
05518 tmpid2[sizeof(tmpid2) - 1] = '\0';
05519
05520 pbx_substitute_variables_helper(qe->chan, tmpid2, tmpid, sizeof(tmpid) - 1);
05521 }
05522
05523 ast_channel_lock(qe->chan);
05524 if ((monitor_exec = pbx_builtin_getvar_helper(qe->chan, "MONITOR_EXEC"))) {
05525 monitor_exec = ast_strdupa(monitor_exec);
05526 }
05527 if ((monitor_options = pbx_builtin_getvar_helper(qe->chan, "MONITOR_OPTIONS"))) {
05528 monitor_options = ast_strdupa(monitor_options);
05529 } else {
05530 monitor_options = "";
05531 }
05532 ast_channel_unlock(qe->chan);
05533
05534 if (monitor_exec) {
05535 const char *m = monitor_exec;
05536 for (p = meid2; p < meid2 + sizeof(meid2) - 1; p++, m++) {
05537 switch (*m) {
05538 case '^':
05539 if (*(m + 1) == '{')
05540 *p = '$';
05541 break;
05542 case ',':
05543 *p++ = '\\';
05544
05545 default:
05546 *p = *m;
05547 }
05548 if (*m == '\0') {
05549 break;
05550 }
05551 }
05552 if (p == meid2 + sizeof(meid2)) {
05553 meid2[sizeof(meid2) - 1] = '\0';
05554 }
05555
05556 pbx_substitute_variables_helper(qe->chan, meid2, meid, sizeof(meid) - 1);
05557 }
05558
05559 snprintf(tmpid2, sizeof(tmpid2), "%s.%s", tmpid, qe->parent->monfmt);
05560
05561 if (!ast_strlen_zero(monitor_exec)) {
05562 snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s,%s", tmpid2, monitor_options, monitor_exec);
05563 } else {
05564 snprintf(mixmonargs, sizeof(mixmonargs), "%s,b%s", tmpid2, monitor_options);
05565 }
05566
05567 ast_debug(1, "Arguments being passed to MixMonitor: %s\n", mixmonargs);
05568
05569 if (ast_channel_cdr(qe->chan)) {
05570 ast_set_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED);
05571 }
05572 pbx_exec(qe->chan, mixmonapp, mixmonargs);
05573 if (ast_channel_cdr(qe->chan)) {
05574 ast_clear_flag(ast_channel_cdr(qe->chan), AST_CDR_FLAG_LOCKED);
05575 }
05576 } else {
05577 ast_log(LOG_WARNING, "Asked to run MixMonitor on this call, but cannot find the MixMonitor app!\n");
05578 }
05579 }
05580 }
05581
05582 leave_queue(qe);
05583 if (!ast_strlen_zero(url) && ast_channel_supports_html(peer)) {
05584 ast_debug(1, "app_queue: sendurl=%s.\n", url);
05585 ast_channel_sendurl(peer, url);
05586 }
05587
05588
05589
05590 if (!ast_strlen_zero(macro)) {
05591 macroexec = ast_strdupa(macro);
05592 } else {
05593 if (qe->parent->membermacro) {
05594 macroexec = ast_strdupa(qe->parent->membermacro);
05595 }
05596 }
05597
05598 if (!ast_strlen_zero(macroexec)) {
05599 ast_debug(1, "app_queue: macro=%s.\n", macroexec);
05600 ast_app_exec_macro(qe->chan, peer, macroexec);
05601 }
05602
05603
05604
05605 if (!ast_strlen_zero(gosub)) {
05606 gosubexec = ast_strdupa(gosub);
05607 } else {
05608 if (qe->parent->membergosub) {
05609 gosubexec = ast_strdupa(qe->parent->membergosub);
05610 }
05611 }
05612
05613 if (!ast_strlen_zero(gosubexec)) {
05614 char *gosub_args = NULL;
05615 char *gosub_argstart;
05616
05617 ast_debug(1, "app_queue: gosub=%s.\n", gosubexec);
05618
05619 gosub_argstart = strchr(gosubexec, ',');
05620 if (gosub_argstart) {
05621 const char *what_is_s = "s";
05622 *gosub_argstart = 0;
05623 if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
05624 ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
05625 what_is_s = "~~s~~";
05626 }
05627 if (ast_asprintf(&gosub_args, "%s,%s,1(%s)", gosubexec, what_is_s, gosub_argstart + 1) < 0) {
05628 gosub_args = NULL;
05629 }
05630 *gosub_argstart = ',';
05631 } else {
05632 const char *what_is_s = "s";
05633 if (!ast_exists_extension(peer, gosubexec, "s", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL)) &&
05634 ast_exists_extension(peer, gosubexec, "~~s~~", 1, S_COR(ast_channel_caller(peer)->id.number.valid, ast_channel_caller(peer)->id.number.str, NULL))) {
05635 what_is_s = "~~s~~";
05636 }
05637 if (ast_asprintf(&gosub_args, "%s,%s,1", gosubexec, what_is_s) < 0) {
05638 gosub_args = NULL;
05639 }
05640 }
05641 if (gosub_args) {
05642 ast_app_exec_sub(qe->chan, peer, gosub_args, 0);
05643 ast_free(gosub_args);
05644 } else {
05645 ast_log(LOG_ERROR, "Could not Allocate string for Gosub arguments -- Gosub Call Aborted!\n");
05646 }
05647 }
05648
05649 if (!ast_strlen_zero(agi)) {
05650 ast_debug(1, "app_queue: agi=%s.\n", agi);
05651 application = pbx_findapp("agi");
05652 if (application) {
05653 agiexec = ast_strdupa(agi);
05654 pbx_exec(qe->chan, application, agiexec);
05655 } else {
05656 ast_log(LOG_WARNING, "Asked to execute an AGI on this channel, but could not find application (agi)!\n");
05657 }
05658 }
05659 qe->handled++;
05660 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "CONNECT", "%ld|%s|%ld", (long) time(NULL) - qe->start, ast_channel_uniqueid(peer),
05661 (long)(orig - to > 0 ? (orig - to) / 1000 : 0));
05662
05663 if (ast_channel_cdr(qe->chan)) {
05664 struct ast_cdr *cdr;
05665 struct ast_cdr *newcdr;
05666
05667
05668 cdr = ast_channel_cdr(qe->chan);
05669 while (cdr->next) {
05670 cdr = cdr->next;
05671 }
05672
05673
05674 if ((strcasecmp(cdr->uniqueid, ast_channel_uniqueid(qe->chan))) &&
05675 (strcasecmp(cdr->linkedid, ast_channel_uniqueid(qe->chan))) &&
05676 (newcdr = ast_cdr_dup(cdr))) {
05677 ast_channel_lock(qe->chan);
05678 ast_cdr_init(newcdr, qe->chan);
05679 ast_cdr_reset(newcdr, 0);
05680 cdr = ast_cdr_append(cdr, newcdr);
05681 cdr = cdr->next;
05682 ast_channel_unlock(qe->chan);
05683 }
05684
05685 if (update_cdr) {
05686 ast_copy_string(cdr->dstchannel, member->membername, sizeof(cdr->dstchannel));
05687 }
05688 }
05689
05690 if (qe->parent->eventwhencalled)
05691
05692
05693
05694
05695
05696
05697
05698
05699
05700
05701
05702
05703
05704
05705
05706
05707
05708
05709 manager_event(EVENT_FLAG_AGENT, "AgentConnect",
05710 "Queue: %s\r\n"
05711 "Uniqueid: %s\r\n"
05712 "Channel: %s\r\n"
05713 "Member: %s\r\n"
05714 "MemberName: %s\r\n"
05715 "HoldTime: %ld\r\n"
05716 "BridgedChannel: %s\r\n"
05717 "RingTime: %ld\r\n"
05718 "%s",
05719 queuename, ast_channel_uniqueid(qe->chan), ast_channel_name(peer), member->interface, member->membername,
05720 (long) time(NULL) - qe->start, ast_channel_uniqueid(peer), (long)(orig - to > 0 ? (orig - to) / 1000 : 0),
05721 qe->parent->eventwhencalled == QUEUE_EVENT_VARIABLES ? vars2manager(qe->chan, vars, sizeof(vars)) : "");
05722 ast_copy_string(oldcontext, ast_channel_context(qe->chan), sizeof(oldcontext));
05723 ast_copy_string(oldexten, ast_channel_exten(qe->chan), sizeof(oldexten));
05724
05725 if ((queue_end_bridge = ao2_alloc(sizeof(*queue_end_bridge), NULL))) {
05726 queue_end_bridge->q = qe->parent;
05727 queue_end_bridge->chan = qe->chan;
05728 bridge_config.end_bridge_callback = end_bridge_callback;
05729 bridge_config.end_bridge_callback_data = queue_end_bridge;
05730 bridge_config.end_bridge_callback_data_fixup = end_bridge_callback_data_fixup;
05731
05732
05733
05734
05735 queue_t_ref(qe->parent, "For bridge_config reference");
05736 }
05737
05738 time(&callstart);
05739 transfer_ds = setup_transfer_datastore(qe, member, callstart, callcompletedinsl);
05740 bridge = ast_bridge_call(qe->chan,peer, &bridge_config);
05741
05742
05743
05744
05745
05746 ast_channel_lock(qe->chan);
05747 if (!attended_transfer_occurred(qe->chan)) {
05748 struct ast_datastore *tds;
05749
05750
05751 if (!(ast_channel_softhangup_internal_flag(qe->chan) | ast_channel_softhangup_internal_flag(peer)) && (strcasecmp(oldcontext, ast_channel_context(qe->chan)) || strcasecmp(oldexten, ast_channel_exten(qe->chan)))) {
05752 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "TRANSFER", "%s|%s|%ld|%ld|%d",
05753 ast_channel_exten(qe->chan), ast_channel_context(qe->chan), (long) (callstart - qe->start),
05754 (long) (time(NULL) - callstart), qe->opos);
05755 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
05756 } else if (ast_check_hangup(qe->chan)) {
05757 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "COMPLETECALLER", "%ld|%ld|%d",
05758 (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
05759 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), CALLER);
05760 } else {
05761 ast_queue_log(queuename, ast_channel_uniqueid(qe->chan), member->membername, "COMPLETEAGENT", "%ld|%ld|%d",
05762 (long) (callstart - qe->start), (long) (time(NULL) - callstart), qe->opos);
05763 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), AGENT);
05764 }
05765 if ((tds = ast_channel_datastore_find(qe->chan, &queue_transfer_info, NULL))) {
05766 ast_channel_datastore_remove(qe->chan, tds);
05767 }
05768 ast_channel_unlock(qe->chan);
05769 update_queue(qe->parent, member, callcompletedinsl, (time(NULL) - callstart));
05770 } else {
05771 ast_channel_unlock(qe->chan);
05772
05773
05774 send_agent_complete(qe, queuename, peer, member, callstart, vars, sizeof(vars), TRANSFER);
05775 }
05776
05777 if (transfer_ds) {
05778 ast_datastore_free(transfer_ds);
05779 }
05780
05781 if (!ast_check_hangup(peer) && ast_test_flag(&opts, OPT_CALLEE_GO_ON)) {
05782 int goto_res;
05783
05784 if (!ast_strlen_zero(opt_args[OPT_ARG_CALLEE_GO_ON])) {
05785 ast_replace_subargument_delimiter(opt_args[OPT_ARG_CALLEE_GO_ON]);
05786 goto_res = ast_parseable_goto(peer, opt_args[OPT_ARG_CALLEE_GO_ON]);
05787 } else {
05788 goto_res = ast_goto_if_exists(peer, caller_context, caller_extension,
05789 caller_priority + 1);
05790 }
05791 if (goto_res || ast_pbx_start(peer)) {
05792 ast_autoservice_chan_hangup_peer(qe->chan, peer);
05793 }
05794 } else {
05795 ast_autoservice_chan_hangup_peer(qe->chan, peer);
05796 }
05797
05798 res = bridge ? bridge : 1;
05799 ao2_ref(member, -1);
05800 }
05801 out:
05802 hangupcalls(outgoing, NULL, qe->cancel_answered_elsewhere);
05803
05804 return res;
05805 }
05806
05807 static int wait_a_bit(struct queue_ent *qe)
05808 {
05809
05810 int retrywait = qe->parent->retry * 1000;
05811
05812 int res = ast_waitfordigit(qe->chan, retrywait);
05813 if (res > 0 && !valid_exit(qe, res)) {
05814 res = 0;
05815 }
05816
05817 return res;
05818 }
05819
05820 static struct member *interface_exists(struct call_queue *q, const char *interface)
05821 {
05822 struct member *mem;
05823 struct ao2_iterator mem_iter;
05824
05825 if (!q) {
05826 return NULL;
05827 }
05828 mem_iter = ao2_iterator_init(q->members, 0);
05829 while ((mem = ao2_iterator_next(&mem_iter))) {
05830 if (!strcasecmp(interface, mem->interface)) {
05831 ao2_iterator_destroy(&mem_iter);
05832 return mem;
05833 }
05834 ao2_ref(mem, -1);
05835 }
05836 ao2_iterator_destroy(&mem_iter);
05837
05838 return NULL;
05839 }
05840
05841
05842
05843
05844
05845
05846
05847 static void dump_queue_members(struct call_queue *pm_queue)
05848 {
05849 struct member *cur_member;
05850 struct ast_str *value;
05851 struct ao2_iterator mem_iter;
05852
05853 if (!pm_queue) {
05854 return;
05855 }
05856
05857
05858
05859 if (!(value = ast_str_create(4096))) {
05860 return;
05861 }
05862
05863 mem_iter = ao2_iterator_init(pm_queue->members, 0);
05864 while ((cur_member = ao2_iterator_next(&mem_iter))) {
05865 if (!cur_member->dynamic) {
05866 ao2_ref(cur_member, -1);
05867 continue;
05868 }
05869
05870 ast_str_append(&value, 0, "%s%s;%d;%d;%s;%s",
05871 ast_str_strlen(value) ? "|" : "",
05872 cur_member->interface,
05873 cur_member->penalty,
05874 cur_member->paused,
05875 cur_member->membername,
05876 cur_member->state_interface);
05877
05878 ao2_ref(cur_member, -1);
05879 }
05880 ao2_iterator_destroy(&mem_iter);
05881
05882 if (ast_str_strlen(value) && !cur_member) {
05883 if (ast_db_put(pm_family, pm_queue->name, ast_str_buffer(value))) {
05884 ast_log(LOG_WARNING, "failed to create persistent dynamic entry!\n");
05885 }
05886 } else {
05887
05888 ast_db_del(pm_family, pm_queue->name);
05889 }
05890
05891 ast_free(value);
05892 }
05893
05894
05895
05896
05897
05898
05899
05900 static int remove_from_queue(const char *queuename, const char *interface)
05901 {
05902 struct call_queue *q, tmpq = {
05903 .name = queuename,
05904 };
05905 struct member *mem, tmpmem;
05906 int res = RES_NOSUCHQUEUE;
05907
05908 ast_copy_string(tmpmem.interface, interface, sizeof(tmpmem.interface));
05909 if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Temporary reference for interface removal"))) {
05910 ao2_lock(q);
05911 if ((mem = ao2_find(q->members, &tmpmem, OBJ_POINTER))) {
05912
05913
05914 if (mem->realtime && !ast_strlen_zero(mem->rt_uniqueid) && negative_penalty_invalid) {
05915 update_realtime_member_field(mem, q->name, "penalty", "-1");
05916 } else if (!mem->dynamic) {
05917 ao2_ref(mem, -1);
05918 ao2_unlock(q);
05919 queue_t_unref(q, "Interface wasn't dynamic, expiring temporary reference");
05920 return RES_NOT_DYNAMIC;
05921 }
05922
05923
05924
05925
05926
05927
05928
05929
05930
05931
05932
05933
05934
05935
05936 manager_event(EVENT_FLAG_AGENT, "QueueMemberRemoved",
05937 "Queue: %s\r\n"
05938 "Location: %s\r\n"
05939 "MemberName: %s\r\n",
05940 q->name, mem->interface, mem->membername);
05941 ao2_unlink(q->members, mem);
05942 ao2_ref(mem, -1);
05943
05944 if (queue_persistent_members) {
05945 dump_queue_members(q);
05946 }
05947
05948 if (!num_available_members(q)) {
05949 ast_devstate_changed(AST_DEVICE_INUSE, "Queue:%s_avail", q->name);
05950 }
05951
05952 res = RES_OKAY;
05953 } else {
05954 res = RES_EXISTS;
05955 }
05956 ao2_unlock(q);
05957 queue_t_unref(q, "Expiring temporary reference");
05958 }
05959
05960 return res;
05961 }
05962
05963
05964
05965
05966
05967
05968
05969
05970 static int add_to_queue(const char *queuename, const char *interface, const char *membername, int penalty, int paused, int dump, const char *state_interface)
05971 {
05972 struct call_queue *q;
05973 struct member *new_member, *old_member;
05974 int res = RES_NOSUCHQUEUE;
05975
05976
05977
05978 if (!(q = find_load_queue_rt_friendly(queuename))) {
05979 return res;
05980 }
05981
05982 ao2_lock(q);
05983 if ((old_member = interface_exists(q, interface)) == NULL) {
05984 if ((new_member = create_queue_member(interface, membername, penalty, paused, state_interface, q->ringinuse))) {
05985 new_member->ringinuse = q->ringinuse;
05986 new_member->dynamic = 1;
05987 ao2_link(q->members, new_member);
05988
05989
05990
05991
05992
05993
05994
05995
05996
05997
05998
05999
06000
06001
06002
06003
06004
06005
06006
06007
06008
06009 manager_event(EVENT_FLAG_AGENT, "QueueMemberAdded",
06010 "Queue: %s\r\n"
06011 "Location: %s\r\n"
06012 "MemberName: %s\r\n"
06013 "StateInterface: %s\r\n"
06014 "Membership: %s\r\n"
06015 "Penalty: %d\r\n"
06016 "CallsTaken: %d\r\n"
06017 "LastCall: %d\r\n"
06018 "Status: %d\r\n"
06019 "Paused: %d\r\n",
06020 q->name, new_member->interface, new_member->membername, state_interface,
06021 "dynamic",
06022 new_member->penalty, new_member->calls, (int) new_member->lastcall,
06023 new_member->status, new_member->paused);
06024
06025 if (is_member_available(new_member)) {
06026 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s_avail", q->name);
06027 }
06028
06029 ao2_ref(new_member, -1);
06030 new_member = NULL;
06031
06032 if (dump) {
06033 dump_queue_members(q);
06034 }
06035
06036 res = RES_OKAY;
06037 } else {
06038 res = RES_OUTOFMEMORY;
06039 }
06040 } else {
06041 ao2_ref(old_member, -1);
06042 res = RES_EXISTS;
06043 }
06044 ao2_unlock(q);
06045 queue_t_unref(q, "Expiring temporary reference");
06046
06047 return res;
06048 }
06049
06050 static int set_member_paused(const char *queuename, const char *interface, const char *reason, int paused)
06051 {
06052 int found = 0;
06053 struct call_queue *q;
06054 struct member *mem;
06055 struct ao2_iterator queue_iter;
06056 int failed;
06057
06058 queue_iter = ao2_iterator_init(queues, 0);
06059 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate over queues"))) {
06060 ao2_lock(q);
06061 if (ast_strlen_zero(queuename) || !strcasecmp(q->name, queuename)) {
06062 if ((mem = interface_exists(q, interface))) {
06063 if (mem->paused == paused) {
06064 ast_debug(1, "%spausing already-%spaused queue member %s:%s\n", (paused ? "" : "un"), (paused ? "" : "un"), q->name, interface);
06065 }
06066
06067 failed = 0;
06068 if (mem->realtime) {
06069 failed = update_realtime_member_field(mem, q->name, "paused", paused ? "1" : "0");
06070 }
06071
06072 if (failed) {
06073 ast_log(LOG_WARNING, "Failed %spausing realtime queue member %s:%s\n", (paused ? "" : "un"), q->name, interface);
06074 ao2_ref(mem, -1);
06075 ao2_unlock(q);
06076 queue_t_unref(q, "Done with iterator");
06077 continue;
06078 }
06079 found++;
06080
06081
06082 if (found == 1) {
06083
06084
06085 if (ast_strlen_zero(queuename)) {
06086 ast_queue_log("NONE", "NONE", interface, (paused ? "PAUSEALL" : "UNPAUSEALL"), "%s", "");
06087 }
06088 }
06089
06090 mem->paused = paused;
06091
06092 if (queue_persistent_members) {
06093 dump_queue_members(q);
06094 }
06095
06096 if (is_member_available(mem)) {
06097 ast_devstate_changed(AST_DEVICE_NOT_INUSE, "Queue:%s_avail", q->name);
06098 } else if (!num_available_members(q)) {
06099 ast_devstate_changed(AST_DEVICE_INUSE, "Queue:%s_avail", q->name);
06100 }
06101
06102 ast_queue_log(q->name, "NONE", mem->membername, (paused ? "PAUSE" : "UNPAUSE"), "%s", S_OR(reason, ""));
06103
06104
06105
06106
06107
06108
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119 if (!ast_strlen_zero(reason)) {
06120 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
06121 "Queue: %s\r\n"
06122 "Location: %s\r\n"
06123 "MemberName: %s\r\n"
06124 "Paused: %d\r\n"
06125 "Reason: %s\r\n",
06126 q->name, mem->interface, mem->membername, paused, reason);
06127 } else {
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138
06139
06140
06141
06142
06143 manager_event(EVENT_FLAG_AGENT, "QueueMemberPaused",
06144 "Queue: %s\r\n"
06145 "Location: %s\r\n"
06146 "MemberName: %s\r\n"
06147 "Paused: %d\r\n",
06148 q->name, mem->interface, mem->membername, paused);
06149 }
06150 ao2_ref(mem, -1);
06151 }
06152 }
06153
06154 if (!ast_strlen_zero(queuename) && !strcasecmp(queuename, q->name)) {
06155 ao2_unlock(q);
06156 queue_t_unref(q, "Done with iterator");
06157 break;
06158 }
06159
06160 ao2_unlock(q);
06161 queue_t_unref(q, "Done with iterator");
06162 }
06163 ao2_iterator_destroy(&queue_iter);
06164
06165 return found ? RESULT_SUCCESS : RESULT_FAILURE;
06166 }
06167
06168
06169
06170
06171
06172
06173
06174
06175
06176
06177 static int set_member_penalty_help_members(struct call_queue *q, const char *interface, int penalty)
06178 {
06179 struct member *mem;
06180 int foundinterface = 0;
06181 char rtpenalty[80];
06182
06183 ao2_lock(q);
06184 if ((mem = interface_exists(q, interface))) {
06185 foundinterface++;
06186 if (!mem->realtime) {
06187 mem->penalty = penalty;
06188 } else {
06189 sprintf(rtpenalty, "%i", penalty);
06190 update_realtime_member_field(mem, q->name, "penalty", rtpenalty);
06191 }
06192 ast_queue_log(q->name, "NONE", interface, "PENALTY", "%d", penalty);
06193
06194
06195
06196
06197
06198
06199
06200
06201
06202
06203
06204
06205
06206 manager_event(EVENT_FLAG_AGENT, "QueueMemberPenalty",
06207 "Queue: %s\r\n"
06208 "Location: %s\r\n"
06209 "Penalty: %d\r\n",
06210 q->name, mem->interface, penalty);
06211 ao2_ref(mem, -1);
06212 }
06213 ao2_unlock(q);
06214
06215 return foundinterface;
06216 }
06217
06218 static int set_member_ringinuse_help_members(struct call_queue *q, const char *interface, int ringinuse)
06219 {
06220 struct member *mem;
06221 int foundinterface = 0;
06222 char rtringinuse[80];
06223
06224 ao2_lock(q);
06225 if ((mem = interface_exists(q, interface))) {
06226 foundinterface++;
06227 if (!mem->realtime) {
06228 mem->ringinuse = ringinuse;
06229 } else {
06230 sprintf(rtringinuse, "%i", ringinuse);
06231 update_realtime_member_field(mem, q->name, realtime_ringinuse_field, rtringinuse);
06232 }
06233 ast_queue_log(q->name, "NONE", interface, "RINGINUSE", "%d", ringinuse);
06234
06235
06236
06237
06238
06239
06240
06241
06242
06243
06244
06245
06246
06247
06248
06249
06250
06251
06252 manager_event(EVENT_FLAG_AGENT, "QueueMemberRinginuse",
06253 "Queue: %s\r\n"
06254 "Location: %s\r\n"
06255 "Ringinuse: %d\r\n",
06256 q->name, mem->interface, ringinuse);
06257 ao2_ref(mem, -1);
06258 }
06259 ao2_unlock(q);
06260
06261 return foundinterface;
06262 }
06263
06264 static int set_member_value_help_members(struct call_queue *q, const char *interface, int property, int value)
06265 {
06266 switch(property) {
06267 case MEMBER_PENALTY:
06268 return set_member_penalty_help_members(q, interface, value);
06269
06270 case MEMBER_RINGINUSE:
06271 return set_member_ringinuse_help_members(q, interface, value);
06272
06273 default:
06274 ast_log(LOG_ERROR, "Attempted to set invalid property\n");
06275 return 0;
06276 }
06277 }
06278
06279
06280
06281
06282
06283
06284
06285
06286
06287 static int set_member_value(const char *queuename, const char *interface, int property, int value)
06288 {
06289 int foundinterface = 0, foundqueue = 0;
06290 struct call_queue *q;
06291 struct ast_config *queue_config = NULL;
06292 struct ao2_iterator queue_iter;
06293
06294
06295 switch (property) {
06296 case MEMBER_PENALTY:
06297 if (value < 0 && !negative_penalty_invalid) {
06298 ast_log(LOG_ERROR, "Invalid penalty (%d)\n", value);
06299 return RESULT_FAILURE;
06300 }
06301 }
06302
06303 if (ast_strlen_zero(queuename)) {
06304 if (ast_check_realtime("queues")) {
06305 char *name;
06306 queue_config = ast_load_realtime_multientry("queues", "name LIKE", "%", SENTINEL);
06307 if (queue_config) {
06308 for (name = ast_category_browse(queue_config, NULL);
06309 !ast_strlen_zero(name);
06310 name = ast_category_browse(queue_config, name)) {
06311 if ((q = find_load_queue_rt_friendly(name))) {
06312 foundqueue++;
06313 foundinterface += set_member_value_help_members(q, interface, property, value);
06314 }
06315 }
06316 }
06317 }
06318
06319
06320 queue_iter = ao2_iterator_init(queues, 0);
06321 while ((q = ao2_t_iterator_next(&queue_iter, "Iterate through queues"))) {
06322 foundqueue++;
06323 foundinterface += set_member_value_help_members(q, interface, property, value);
06324 }
06325 ao2_iterator_destroy(&queue_iter);
06326 } else {
06327 if ((q = find_load_queue_rt_friendly(queuename))) {
06328 foundqueue++;
06329 foundinterface += set_member_value_help_members(q, interface, property, value);
06330 }
06331 }
06332
06333 if (foundinterface) {
06334 return RESULT_SUCCESS;
06335 } else if (!foundqueue) {
06336 ast_log (LOG_ERROR, "Invalid queuename\n");
06337 } else {
06338 ast_log (LOG_ERROR, "Invalid interface\n");
06339 }
06340
06341 return RESULT_FAILURE;
06342 }
06343
06344
06345
06346
06347 static int get_member_penalty(char *queuename, char *interface)
06348 {
06349 int foundqueue = 0, penalty;
06350 struct call_queue *q, tmpq = {
06351 .name = queuename,
06352 };
06353 struct member *mem;
06354
06355 if ((q = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Search for queue"))) {
06356 foundqueue = 1;
06357 ao2_lock(q);
06358 if ((mem = interface_exists(q, interface))) {
06359 penalty = mem->penalty;
06360 ao2_ref(mem, -1);
06361 ao2_unlock(q);
06362 queue_t_unref(q, "Search complete");
06363 return penalty;
06364 }
06365 ao2_unlock(q);
06366 queue_t_unref(q, "Search complete");
06367 }
06368
06369
06370 if (foundqueue) {
06371 ast_log (LOG_ERROR, "Invalid queuename\n");
06372 } else {
06373 ast_log (LOG_ERROR, "Invalid interface\n");
06374 }
06375
06376 return RESULT_FAILURE;
06377 }
06378
06379
06380 static void reload_queue_members(void)
06381 {
06382 char *cur_ptr;
06383 const char *queue_name;
06384 char *member;
06385 char *interface;
06386 char *membername = NULL;
06387 char *state_interface;
06388 char *penalty_tok;
06389 int penalty = 0;
06390 char *paused_tok;
06391 int paused = 0;
06392 struct ast_db_entry *db_tree;
06393 struct ast_db_entry *entry;
06394 struct call_queue *cur_queue;
06395 char *queue_data;
06396
06397
06398 db_tree = ast_db_gettree(pm_family, NULL);
06399 for (entry = db_tree; entry; entry = entry->next) {
06400
06401 queue_name = entry->key + strlen(pm_family) + 2;
06402
06403 {
06404 struct call_queue tmpq = {
06405 .name = queue_name,
06406 };
06407 cur_queue = ao2_t_find(queues, &tmpq, OBJ_POINTER, "Reload queue members");
06408 }
06409
06410 if (!cur_queue) {
06411 cur_queue = find_load_queue_rt_friendly(queue_name);
06412 }
06413
06414 if (!cur_queue) {
06415
06416
06417 ast_log(LOG_WARNING, "Error loading persistent queue: '%s': it does not exist\n", queue_name);
06418 ast_db_del(pm_family, queue_name);
06419 continue;
06420 }
06421
06422 if (ast_db_get_allocated(pm_family, queue_name, &queue_data)) {
06423 queue_t_unref(cur_queue, "Expire reload reference");
06424 continue;
06425 }
06426
06427 cur_ptr = queue_data;
06428 while ((member = strsep(&cur_ptr, ",|"))) {
06429 if (ast_strlen_zero(member)) {
06430 continue;
06431 }
06432
06433 interface = strsep(&member, ";");
06434 penalty_tok = strsep(&member, ";");
06435 paused_tok = strsep(&member, ";");
06436 membername = strsep(&member, ";");
06437 state_interface = strsep(&member, ";");
06438
06439 if (!penalty_tok) {
06440 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (penalty)\n", queue_name);
06441 break;
06442 }
06443 penalty = strtol(penalty_tok, NULL, 10);
06444 if (errno == ERANGE) {
06445 ast_log(LOG_WARNING, "Error converting penalty: %s: Out of range.\n", penalty_tok);
06446 break;
06447 }
06448
06449 if (!paused_tok) {
06450 ast_log(LOG_WARNING, "Error parsing persistent member string for '%s' (paused)\n", queue_name);
06451 break;
06452 }
06453 paused = strtol(paused_tok, NULL, 10);
06454 if ((errno == ERANGE) || paused < 0 || paused > 1) {
06455 ast_log(LOG_WARNING, "Error converting paused: %s: Expected 0 or 1.\n", paused_tok);
06456 break;
06457 }
06458
06459 ast_debug(1, "Reload Members: Queue: %s Member: %s Name: %s Penalty: %d Paused: %d\n", queue_name, interface, membername, penalty, paused);
06460
06461 if (add_to_queue(queue_name, interface, membername, penalty, paused, 0, state_interface) == RES_OUTOFMEMORY) {
06462 ast_log(LOG_ERROR, "Out of Memory when reloading persistent queue member\n");
06463 break;
06464 }
06465 }
06466 queue_t_unref(cur_queue, "Expire reload reference");
06467 ast_free(queue_data);
06468 }
06469
06470 if (db_tree) {
06471 ast_log(LOG_NOTICE, "Queue members successfully reloaded from database.\n");
06472 ast_db_freetree(db_tree);
06473 }
06474 }
06475
06476
06477 static int pqm_exec(struct ast_channel *chan, const char *data)
06478 {
06479 char *parse;
06480 AST_DECLARE_APP_ARGS(args,
06481 AST_APP_ARG(queuename);
06482 AST_APP_ARG(interface);
06483 AST_APP_ARG(options);
06484 AST_APP_ARG(reason);
06485 );
06486
06487 if (ast_strlen_zero(data)) {
06488 ast_log(LOG_WARNING, "PauseQueueMember requires an argument ([queuename],interface[,options][,reason])\n");
06489 return -1;
06490 }
06491
06492 parse = ast_strdupa(data);
06493
06494 AST_STANDARD_APP_ARGS(args, parse);
06495
06496 if (ast_strlen_zero(args.interface)) {
06497 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
06498 return -1;
06499 }
06500
06501 if (set_member_paused(args.queuename, args.interface, args.reason, 1)) {
06502 ast_log(LOG_WARNING, "Attempt to pause interface %s, not found\n", args.interface);
06503 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "NOTFOUND");
06504 return 0;
06505 }
06506
06507 pbx_builtin_setvar_helper(chan, "PQMSTATUS", "PAUSED");
06508
06509 return 0;
06510 }
06511
06512
06513 static int upqm_exec(struct ast_channel *chan, const char *data)
06514 {
06515 char *parse;
06516 AST_DECLARE_APP_ARGS(args,
06517 AST_APP_ARG(queuename);
06518 AST_APP_ARG(interface);
06519 AST_APP_ARG(options);
06520 AST_APP_ARG(reason);
06521 );
06522
06523 if (ast_strlen_zero(data)) {
06524 ast_log(LOG_WARNING, "UnpauseQueueMember requires an argument ([queuename],interface[,options[,reason]])\n");
06525 return -1;
06526 }
06527
06528 parse = ast_strdupa(data);
06529
06530 AST_STANDARD_APP_ARGS(args, parse);
06531
06532 if (ast_strlen_zero(args.interface)) {
06533 ast_log(LOG_WARNING, "Missing interface argument to PauseQueueMember ([queuename],interface[,options[,reason]])\n");
06534 return -1;
06535 }
06536
06537 if (set_member_paused(args.queuename, args.interface, args.reason, 0)) {
06538 ast_log(LOG_WARNING, "Attempt to unpause interface %s, not found\n", args.interface);
06539 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "NOTFOUND");
06540 return 0;
06541 }
06542
06543 pbx_builtin_setvar_helper(chan, "UPQMSTATUS", "UNPAUSED");
06544
06545 return 0;
06546 }
06547
06548
06549 static int rqm_exec(struct ast_channel *chan, const char *data)
06550 {
06551 int res=-1;
06552 char *parse, *temppos = NULL;
06553 struct member *mem = NULL;
06554
06555 AST_DECLARE_APP_ARGS(args,
06556 AST_APP_ARG(queuename);
06557 AST_APP_ARG(interface);
06558 );
06559
06560
06561 if (ast_strlen_zero(data)) {
06562 ast_log(LOG_WARNING, "RemoveQueueMember requires an argument (queuename[,interface])\n");
06563 return -1;
06564 }
06565
06566 parse = ast_strdupa(data);
06567
06568 AST_STANDARD_APP_ARGS(args, parse);
06569
06570 if (ast_strlen_zero(args.interface)) {
06571 args.interface = ast_strdupa(ast_channel_name(chan));
06572 temppos = strrchr(args.interface, '-');
06573 if (temppos) {
06574 *temppos = '\0';
06575 }
06576 }
06577
06578 ast_debug(1, "queue: %s, member: %s\n", args.queuename, args.interface);
06579
06580 if (log_membername_as_agent) {
06581 mem = find_member_by_queuename_and_interface(args.queuename, args.interface);
06582 }
06583
06584 switch (remove_from_queue(args.queuename, args.interface)) {
06585 case RES_OKAY:
06586 if (!mem || ast_strlen_zero(mem->membername)) {
06587 ast_queue_log(args.queuename, ast_channel_uniqueid(chan), args.interface, "REMOVEMEMBER", "%s", "");
06588 } else {
06589 ast_queue_log(args.queuename, ast_channel_uniqueid(chan), mem->membername, "REMOVEMEMBER", "%s", "");
06590 }
06591 ast_log(LOG_NOTICE, "Removed interface '%s' from queue '%s'\n", args.interface, args.queuename);
06592 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "REMOVED");
06593 res = 0;
06594 break;
06595 case RES_EXISTS:
06596 ast_debug(1, "Unable to remove interface '%s' from queue '%s': Not there\n", args.interface, args.queuename);
06597 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTINQUEUE");
06598 res = 0;
06599 break;
06600 case RES_NOSUCHQUEUE:
06601 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': No such queue\n", args.queuename);
06602 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOSUCHQUEUE");
06603 res = 0;
06604 break;
06605 case RES_NOT_DYNAMIC:
06606 ast_log(LOG_WARNING, "Unable to remove interface from queue '%s': '%s' is not a dynamic member\n", args.queuename, args.interface);
06607 pbx_builtin_setvar_helper(chan, "RQMSTATUS", "NOTDYNAMIC");
06608 res = 0;
06609 break;
06610 }
06611
06612 if (mem) {
06613 ao2_ref(mem, -1);
06614 }
06615
06616 return res;
06617 }
06618
06619
06620 static int aqm_exec(struct ast_channel *chan, const char