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 #include "asterisk.h"
00027
00028 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 319920 $")
00029
00030 #include <signal.h>
00031
00032 #include "asterisk/logger.h"
00033 #include "asterisk/channel.h"
00034 #include "asterisk/options.h"
00035 #include "asterisk/utils.h"
00036 #include "asterisk/lock.h"
00037 #include "asterisk/linkedlists.h"
00038 #include "asterisk/bridging.h"
00039 #include "asterisk/bridging_technology.h"
00040 #include "asterisk/app.h"
00041 #include "asterisk/file.h"
00042 #include "asterisk/module.h"
00043 #include "asterisk/astobj2.h"
00044
00045 static AST_RWLIST_HEAD_STATIC(bridge_technologies, ast_bridge_technology);
00046
00047
00048 #define BRIDGE_ARRAY_START 128
00049
00050
00051 #define BRIDGE_ARRAY_GROW 32
00052
00053
00054 static char builtin_features_dtmf[AST_BRIDGE_BUILTIN_END][MAXIMUM_DTMF_FEATURE_STRING];
00055
00056
00057 static void *builtin_features_handlers[AST_BRIDGE_BUILTIN_END];
00058
00059 int __ast_bridge_technology_register(struct ast_bridge_technology *technology, struct ast_module *module)
00060 {
00061 struct ast_bridge_technology *current = NULL;
00062
00063
00064 if (ast_strlen_zero(technology->name) || !technology->capabilities || !technology->write) {
00065 ast_log(LOG_WARNING, "Bridge technology %s failed registration sanity check.\n", technology->name);
00066 return -1;
00067 }
00068
00069 AST_RWLIST_WRLOCK(&bridge_technologies);
00070
00071
00072 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00073 if ((!strcasecmp(current->name, technology->name)) || (current == technology)) {
00074 ast_log(LOG_WARNING, "A bridge technology of %s already claims to exist in our world.\n", technology->name);
00075 AST_RWLIST_UNLOCK(&bridge_technologies);
00076 return -1;
00077 }
00078 }
00079
00080
00081 technology->mod = module;
00082
00083
00084 AST_RWLIST_INSERT_TAIL(&bridge_technologies, technology, entry);
00085
00086 AST_RWLIST_UNLOCK(&bridge_technologies);
00087
00088 if (option_verbose > 1) {
00089 ast_verbose(VERBOSE_PREFIX_2 "Registered bridge technology %s\n", technology->name);
00090 }
00091
00092 return 0;
00093 }
00094
00095 int ast_bridge_technology_unregister(struct ast_bridge_technology *technology)
00096 {
00097 struct ast_bridge_technology *current = NULL;
00098
00099 AST_RWLIST_WRLOCK(&bridge_technologies);
00100
00101
00102 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&bridge_technologies, current, entry) {
00103 if (current == technology) {
00104 AST_RWLIST_REMOVE_CURRENT(entry);
00105 if (option_verbose > 1) {
00106 ast_verbose(VERBOSE_PREFIX_2 "Unregistered bridge technology %s\n", technology->name);
00107 }
00108 break;
00109 }
00110 }
00111 AST_RWLIST_TRAVERSE_SAFE_END;
00112
00113 AST_RWLIST_UNLOCK(&bridge_technologies);
00114
00115 return current ? 0 : -1;
00116 }
00117
00118 void ast_bridge_change_state(struct ast_bridge_channel *bridge_channel, enum ast_bridge_channel_state new_state)
00119 {
00120
00121 bridge_channel->state = new_state;
00122
00123
00124 if (!pthread_equal(pthread_self(), bridge_channel->thread)) {
00125 pthread_kill(bridge_channel->thread, SIGURG);
00126 ast_mutex_lock(&bridge_channel->lock);
00127 ast_cond_signal(&bridge_channel->cond);
00128 ast_mutex_unlock(&bridge_channel->lock);
00129 }
00130
00131 return;
00132 }
00133
00134
00135 static void bridge_poke(struct ast_bridge *bridge)
00136 {
00137
00138 if (bridge->thread != AST_PTHREADT_NULL && bridge->thread != AST_PTHREADT_STOP) {
00139 pthread_kill(bridge->thread, SIGURG);
00140 }
00141
00142 return;
00143 }
00144
00145
00146
00147
00148
00149 static void bridge_array_add(struct ast_bridge *bridge, struct ast_channel *chan)
00150 {
00151
00152 while (bridge->waiting) {
00153 bridge_poke(bridge);
00154 sched_yield();
00155 }
00156
00157 bridge->array[bridge->array_num++] = chan;
00158
00159 ast_debug(1, "Added channel %s(%p) to bridge array on %p, new count is %d\n", chan->name, chan, bridge, (int)bridge->array_num);
00160
00161
00162 if (bridge->array_num == bridge->array_size) {
00163 struct ast_channel **tmp;
00164 ast_debug(1, "Growing bridge array on %p from %d to %d\n", bridge, (int)bridge->array_size, (int)bridge->array_size + BRIDGE_ARRAY_GROW);
00165 if (!(tmp = ast_realloc(bridge->array, (bridge->array_size + BRIDGE_ARRAY_GROW) * sizeof(struct ast_channel *)))) {
00166 ast_log(LOG_ERROR, "Failed to allocate more space for another channel on bridge '%p', this is not going to end well\n", bridge);
00167 return;
00168 }
00169 bridge->array = tmp;
00170 bridge->array_size += BRIDGE_ARRAY_GROW;
00171 }
00172
00173 return;
00174 }
00175
00176
00177
00178
00179
00180 static void bridge_array_remove(struct ast_bridge *bridge, struct ast_channel *chan)
00181 {
00182 int i;
00183
00184
00185 while (bridge->waiting) {
00186 bridge_poke(bridge);
00187 sched_yield();
00188 }
00189
00190 for (i = 0; i < bridge->array_num; i++) {
00191 if (bridge->array[i] == chan) {
00192 bridge->array[i] = (bridge->array[(bridge->array_num - 1)] != chan ? bridge->array[(bridge->array_num - 1)] : NULL);
00193 bridge->array[(bridge->array_num - 1)] = NULL;
00194 bridge->array_num--;
00195 ast_debug(1, "Removed channel %p from bridge array on %p, new count is %d\n", chan, bridge, (int)bridge->array_num);
00196 break;
00197 }
00198 }
00199
00200 return;
00201 }
00202
00203
00204 static struct ast_bridge_channel *find_bridge_channel(struct ast_bridge *bridge, struct ast_channel *chan)
00205 {
00206 struct ast_bridge_channel *bridge_channel = NULL;
00207
00208 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00209 if (bridge_channel->chan == chan) {
00210 break;
00211 }
00212 }
00213
00214 return bridge_channel;
00215 }
00216
00217
00218 static void bridge_check_dissolve(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00219 {
00220 struct ast_bridge_channel *bridge_channel2 = NULL;
00221
00222 if (!ast_test_flag(&bridge->feature_flags, AST_BRIDGE_FLAG_DISSOLVE) && (!bridge_channel->features || !bridge_channel->features->usable || !ast_test_flag(&bridge_channel->features->feature_flags, AST_BRIDGE_FLAG_DISSOLVE))) {
00223 return;
00224 }
00225
00226 ast_debug(1, "Dissolving bridge %p\n", bridge);
00227
00228 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00229 if (bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_END && bridge_channel2->state != AST_BRIDGE_CHANNEL_STATE_DEPART) {
00230 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00231 }
00232 }
00233
00234
00235 bridge->stop = 1;
00236
00237 return;
00238 }
00239
00240
00241 static struct ast_frame *bridge_handle_dtmf(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_frame *frame)
00242 {
00243 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00244 struct ast_bridge_features_hook *hook = NULL;
00245
00246
00247 if (!features->usable) {
00248 return frame;
00249 }
00250
00251
00252 AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00253 if (hook->dtmf[0] == frame->subclass.integer) {
00254 ast_frfree(frame);
00255 frame = NULL;
00256 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_FEATURE);
00257 break;
00258 }
00259 }
00260
00261 return frame;
00262 }
00263
00264
00265 static int bridge_drop_control_frame(int subclass)
00266 {
00267 switch (subclass) {
00268 case AST_CONTROL_ANSWER:
00269 case -1:
00270 return 1;
00271 default:
00272 return 0;
00273 }
00274 }
00275
00276 void ast_bridge_handle_trip(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, struct ast_channel *chan, int outfd)
00277 {
00278
00279 if (chan && !bridge_channel) {
00280 bridge_channel = find_bridge_channel(bridge, chan);
00281 }
00282
00283
00284 if (chan && bridge_channel) {
00285 struct ast_frame *frame = (((bridge->features.mute) || (bridge_channel->features && bridge_channel->features->mute)) ? ast_read_noaudio(chan) : ast_read(chan));
00286
00287
00288 if (!frame || (frame->frametype == AST_FRAME_CONTROL && frame->subclass.integer == AST_CONTROL_HANGUP)) {
00289
00290 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00291 } else if (frame->frametype == AST_FRAME_CONTROL && bridge_drop_control_frame(frame->subclass.integer)) {
00292 ast_debug(1, "Dropping control frame from bridge channel %p\n", bridge_channel);
00293 } else {
00294 if (frame->frametype == AST_FRAME_DTMF_BEGIN) {
00295 frame = bridge_handle_dtmf(bridge, bridge_channel, frame);
00296 }
00297
00298 if (frame) {
00299 bridge->technology->write(bridge, bridge_channel, frame);
00300 }
00301 }
00302
00303 if (frame) {
00304 ast_frfree(frame);
00305 }
00306 return;
00307 }
00308
00309
00310 if (outfd > -1 && bridge->technology->fd) {
00311 bridge->technology->fd(bridge, bridge_channel, outfd);
00312 return;
00313 }
00314
00315
00316 if (bridge->technology->poke && bridge_channel) {
00317 bridge->technology->poke(bridge, bridge_channel);
00318 return;
00319 }
00320
00321 return;
00322 }
00323
00324
00325 static int generic_thread_loop(struct ast_bridge *bridge)
00326 {
00327 while (!bridge->stop && !bridge->refresh && bridge->array_num) {
00328 struct ast_channel *winner = NULL;
00329 int to = -1;
00330
00331
00332 if (bridge->array_num > 1) {
00333 struct ast_channel *first = bridge->array[0];
00334 memmove(bridge->array, bridge->array + 1, sizeof(struct ast_channel *) * (bridge->array_num - 1));
00335 bridge->array[(bridge->array_num - 1)] = first;
00336 }
00337
00338
00339 bridge->waiting = 1;
00340 ao2_unlock(bridge);
00341 winner = ast_waitfor_n(bridge->array, (int)bridge->array_num, &to);
00342 bridge->waiting = 0;
00343 ao2_lock(bridge);
00344
00345
00346 ast_bridge_handle_trip(bridge, NULL, winner, -1);
00347 }
00348
00349 return 0;
00350 }
00351
00352
00353 static void *bridge_thread(void *data)
00354 {
00355 struct ast_bridge *bridge = data;
00356 int res = 0;
00357
00358 ao2_lock(bridge);
00359
00360 ast_debug(1, "Started bridge thread for %p\n", bridge);
00361
00362
00363 while (!bridge->stop && bridge->array_num && !res) {
00364
00365 bridge->refresh = 0;
00366
00367 ast_debug(1, "Launching bridge thread function %p for bridge %p\n", (bridge->technology->thread ? bridge->technology->thread : &generic_thread_loop), bridge);
00368
00369
00370 res = (bridge->technology->thread ? bridge->technology->thread(bridge) : generic_thread_loop(bridge));
00371 }
00372
00373 ast_debug(1, "Ending bridge thread for %p\n", bridge);
00374
00375
00376 bridge->thread = AST_PTHREADT_NULL;
00377 ao2_unlock(bridge);
00378
00379 ao2_ref(bridge, -1);
00380
00381 return NULL;
00382 }
00383
00384
00385 static struct ast_bridge_technology *find_best_technology(enum ast_bridge_capability capabilities)
00386 {
00387 struct ast_bridge_technology *current = NULL, *best = NULL;
00388
00389 AST_RWLIST_RDLOCK(&bridge_technologies);
00390 AST_RWLIST_TRAVERSE(&bridge_technologies, current, entry) {
00391 ast_debug(1, "Bridge technology %s has capabilities %d and we want %d\n", current->name, current->capabilities, capabilities);
00392 if (current->suspended) {
00393 ast_debug(1, "Bridge technology %s is suspended. Skipping.\n", current->name);
00394 continue;
00395 }
00396 if (!(current->capabilities & capabilities)) {
00397 ast_debug(1, "Bridge technology %s does not have the capabilities we need.\n", current->name);
00398 continue;
00399 }
00400 if (best && best->preference < current->preference) {
00401 ast_debug(1, "Bridge technology %s has preference %d while %s has preference %d. Skipping.\n", current->name, current->preference, best->name, best->preference);
00402 continue;
00403 }
00404 best = current;
00405 }
00406
00407 if (best) {
00408
00409 if (best->mod) {
00410 ast_module_ref(best->mod);
00411 }
00412 ast_debug(1, "Chose bridge technology %s\n", best->name);
00413 }
00414
00415 AST_RWLIST_UNLOCK(&bridge_technologies);
00416
00417 return best;
00418 }
00419
00420 static void destroy_bridge(void *obj)
00421 {
00422 struct ast_bridge *bridge = obj;
00423
00424 ast_debug(1, "Actually destroying bridge %p, nobody wants it anymore\n", bridge);
00425
00426
00427 if (bridge->technology->destroy) {
00428 ast_debug(1, "Giving bridge technology %s the bridge structure %p to destroy\n", bridge->technology->name, bridge);
00429 if (bridge->technology->destroy(bridge)) {
00430 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p... trying our best\n", bridge->technology->name, bridge);
00431 }
00432 }
00433
00434
00435 if (bridge->technology->mod) {
00436 ast_module_unref(bridge->technology->mod);
00437 }
00438
00439
00440 ast_bridge_features_cleanup(&bridge->features);
00441
00442
00443 ast_free(bridge->array);
00444
00445 return;
00446 }
00447
00448 struct ast_bridge *ast_bridge_new(enum ast_bridge_capability capabilities, int flags)
00449 {
00450 struct ast_bridge *bridge = NULL;
00451 struct ast_bridge_technology *bridge_technology = NULL;
00452
00453
00454 if (flags & AST_BRIDGE_FLAG_SMART) {
00455 struct ast_bridge *other_bridge;
00456
00457 if (!(other_bridge = ast_bridge_new((capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) ? AST_BRIDGE_CAPABILITY_MULTIMIX : AST_BRIDGE_CAPABILITY_1TO1MIX, 0))) {
00458 return NULL;
00459 }
00460
00461 ast_bridge_destroy(other_bridge);
00462 }
00463
00464
00465
00466 bridge_technology = (capabilities ? find_best_technology(capabilities) : find_best_technology(AST_BRIDGE_CAPABILITY_1TO1MIX));
00467
00468
00469 if (!bridge_technology) {
00470 ast_debug(1, "Failed to find a bridge technology to satisfy capabilities %d\n", capabilities);
00471 return NULL;
00472 }
00473
00474
00475 if (!(bridge = ao2_alloc(sizeof(*bridge), destroy_bridge))) {
00476 return NULL;
00477 }
00478
00479 bridge->technology = bridge_technology;
00480 bridge->thread = AST_PTHREADT_NULL;
00481
00482
00483 bridge->array = ast_calloc(BRIDGE_ARRAY_START, sizeof(struct ast_channel*));
00484 bridge->array_size = BRIDGE_ARRAY_START;
00485
00486 ast_set_flag(&bridge->feature_flags, flags);
00487
00488
00489 if (bridge->technology->create) {
00490 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", bridge->technology->name, bridge);
00491 if (bridge->technology->create(bridge)) {
00492 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", bridge->technology->name, bridge);
00493 ao2_ref(bridge, -1);
00494 bridge = NULL;
00495 }
00496 }
00497
00498 return bridge;
00499 }
00500
00501 int ast_bridge_check(enum ast_bridge_capability capabilities)
00502 {
00503 struct ast_bridge_technology *bridge_technology = NULL;
00504
00505 if (!(bridge_technology = find_best_technology(capabilities))) {
00506 return 0;
00507 }
00508
00509 ast_module_unref(bridge_technology->mod);
00510
00511 return 1;
00512 }
00513
00514 int ast_bridge_destroy(struct ast_bridge *bridge)
00515 {
00516 struct ast_bridge_channel *bridge_channel = NULL;
00517
00518 ao2_lock(bridge);
00519
00520 bridge->stop = 1;
00521
00522 bridge_poke(bridge);
00523
00524 ast_debug(1, "Telling all channels in bridge %p to end and leave the party\n", bridge);
00525
00526
00527 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
00528 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_END);
00529 }
00530
00531 ao2_unlock(bridge);
00532
00533 ao2_ref(bridge, -1);
00534
00535 return 0;
00536 }
00537
00538 static int bridge_make_compatible(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00539 {
00540 format_t formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat};
00541
00542
00543 if (!(bridge->technology->formats & bridge_channel->chan->readformat)) {
00544 format_t best_format = ast_best_codec(bridge->technology->formats);
00545
00546
00547 if (option_debug) {
00548 char codec_buf[512];
00549 ast_debug(1, "Bridge technology %s wants to read any of formats %s but channel has %s\n", bridge->technology->name,
00550 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats),
00551 ast_getformatname(formats[0]));
00552 }
00553
00554 if (ast_set_read_format(bridge_channel->chan, best_format)) {
00555 ast_log(LOG_WARNING, "Failed to set channel %s to read format %s\n", bridge_channel->chan->name, ast_getformatname(best_format));
00556 return -1;
00557 }
00558 ast_debug(1, "Bridge %p put channel %s into read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format));
00559 } else {
00560 ast_debug(1, "Bridge %p is happy that channel %s already has read format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[0]));
00561 }
00562
00563 if (!(bridge->technology->formats & formats[1])) {
00564 int best_format = ast_best_codec(bridge->technology->formats);
00565
00566
00567 if (option_debug) {
00568 char codec_buf[512];
00569 ast_debug(1, "Bridge technology %s wants to write any of formats %s but channel has %s\n", bridge->technology->name,
00570 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats),
00571 ast_getformatname(formats[1]));
00572 }
00573
00574 if (ast_set_write_format(bridge_channel->chan, best_format)) {
00575 ast_log(LOG_WARNING, "Failed to set channel %s to write format %s\n", bridge_channel->chan->name, ast_getformatname(best_format));
00576 return -1;
00577 }
00578 ast_debug(1, "Bridge %p put channel %s into write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format));
00579 } else {
00580 ast_debug(1, "Bridge %p is happy that channel %s already has write format %s\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[1]));
00581 }
00582
00583 return 0;
00584 }
00585
00586
00587 static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
00588 {
00589 enum ast_bridge_capability new_capabilities = 0;
00590 struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
00591 struct ast_bridge temp_bridge = {
00592 .technology = bridge->technology,
00593 .bridge_pvt = bridge->bridge_pvt,
00594 };
00595 struct ast_bridge_channel *bridge_channel2 = NULL;
00596
00597
00598 if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
00599 if (count <= 2) {
00600 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
00601 return 0;
00602 }
00603 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
00604 } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
00605 if (count > 2) {
00606 ast_debug(1, "Bridge %p channel count (%d) is within limits for bridge technology %s, not performing smart bridge operation.\n", bridge, count, bridge->technology->name);
00607 return 0;
00608 }
00609 new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
00610 }
00611
00612 if (!new_capabilities) {
00613 ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge);
00614 return 0;
00615 }
00616
00617
00618 if (!(new_technology = find_best_technology(new_capabilities))) {
00619 ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %d to satisfy bridge %p\n", new_capabilities, bridge);
00620 return -1;
00621 }
00622
00623 ast_debug(1, "Performing smart bridge operation on bridge %p, moving from bridge technology %s to %s\n", bridge, old_technology->name, new_technology->name);
00624
00625
00626 if (bridge->thread != AST_PTHREADT_NULL) {
00627
00628 if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
00629 ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
00630 bridge->refresh = 1;
00631 bridge_poke(bridge);
00632 } else {
00633 pthread_t bridge_thread = bridge->thread;
00634 ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
00635 bridge->stop = 1;
00636 bridge_poke(bridge);
00637 ao2_unlock(bridge);
00638 pthread_join(bridge_thread, NULL);
00639 ao2_lock(bridge);
00640 }
00641 }
00642
00643
00644 bridge->bridge_pvt = NULL;
00645 bridge->technology = new_technology;
00646
00647
00648 if (new_technology->create) {
00649 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
00650 if (new_technology->create(bridge)) {
00651 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
00652 }
00653 }
00654
00655
00656 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00657
00658 if (bridge_channel == bridge_channel2) {
00659 continue;
00660 }
00661
00662
00663 if (old_technology->leave) {
00664 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p (really %p)\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
00665 if (old_technology->leave(&temp_bridge, bridge_channel2)) {
00666 ast_debug(1, "Bridge technology %s failed to allow %p (really %p) to leave bridge %p\n", old_technology->name, bridge_channel2, &temp_bridge, bridge);
00667 }
00668 }
00669
00670
00671 bridge_make_compatible(bridge, bridge_channel2);
00672
00673
00674 if (new_technology->join) {
00675 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
00676 if (new_technology->join(bridge, bridge_channel2)) {
00677 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
00678 }
00679 }
00680
00681
00682 pthread_kill(bridge_channel2->thread, SIGURG);
00683 ast_mutex_lock(&bridge_channel2->lock);
00684 ast_cond_signal(&bridge_channel2->cond);
00685 ast_mutex_unlock(&bridge_channel2->lock);
00686 }
00687
00688
00689 if (old_technology->destroy) {
00690 ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
00691 if (old_technology->destroy(&temp_bridge)) {
00692 ast_debug(1, "Bridge technology %s failed to destroy bridge structure %p (really %p)... some memory may have leaked\n", old_technology->name, &temp_bridge, bridge);
00693 }
00694 }
00695
00696
00697 if (old_technology->mod) {
00698 ast_module_unref(old_technology->mod);
00699 }
00700
00701 return 0;
00702 }
00703
00704
00705 static enum ast_bridge_channel_state bridge_channel_join_multithreaded(struct ast_bridge_channel *bridge_channel)
00706 {
00707 int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
00708 struct ast_channel *chan = NULL;
00709
00710
00711 if (bridge_channel->bridge->technology->fd) {
00712 for (i = 0; i < 4; i ++) {
00713 if (bridge_channel->fds[i] >= 0) {
00714 fds[nfds++] = bridge_channel->fds[i];
00715 }
00716 }
00717 }
00718
00719 ao2_unlock(bridge_channel->bridge);
00720
00721
00722 if (!bridge_channel->suspended) {
00723 ast_debug(1, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00724 chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
00725 } else {
00726 ast_mutex_lock(&bridge_channel->lock);
00727 ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00728 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00729 ast_mutex_unlock(&bridge_channel->lock);
00730 }
00731
00732 ao2_lock(bridge_channel->bridge);
00733
00734 if (!bridge_channel->suspended) {
00735 ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
00736 }
00737
00738 return bridge_channel->state;
00739 }
00740
00741
00742 static enum ast_bridge_channel_state bridge_channel_join_singlethreaded(struct ast_bridge_channel *bridge_channel)
00743 {
00744 ao2_unlock(bridge_channel->bridge);
00745 ast_mutex_lock(&bridge_channel->lock);
00746 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00747 ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00748 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00749 }
00750 ast_mutex_unlock(&bridge_channel->lock);
00751 ao2_lock(bridge_channel->bridge);
00752
00753 return bridge_channel->state;
00754 }
00755
00756
00757 static void bridge_channel_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00758 {
00759 bridge_channel->suspended = 1;
00760
00761 bridge_array_remove(bridge, bridge_channel->chan);
00762
00763 if (bridge->technology->suspend) {
00764 bridge->technology->suspend(bridge, bridge_channel);
00765 }
00766
00767 return;
00768 }
00769
00770
00771 static void bridge_channel_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00772 {
00773 bridge_channel->suspended =0;
00774
00775 bridge_array_add(bridge, bridge_channel->chan);
00776
00777 if (bridge->technology->unsuspend) {
00778 bridge->technology->unsuspend(bridge, bridge_channel);
00779 }
00780
00781 return;
00782 }
00783
00784
00785 static void bridge_channel_feature(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00786 {
00787 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00788 struct ast_bridge_features_hook *hook = NULL;
00789 char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = "";
00790 int look_for_dtmf = 1, dtmf_len = 0;
00791
00792
00793 ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00794
00795
00796 while (look_for_dtmf) {
00797 int res = ast_waitfordigit(bridge_channel->chan, 3000);
00798
00799
00800 if (!res) {
00801 ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
00802 break;
00803 } else if (res < 0) {
00804 ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel);
00805 break;
00806 }
00807
00808
00809 dtmf[dtmf_len++] = res;
00810
00811 ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
00812
00813
00814 look_for_dtmf = 0;
00815
00816
00817 AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00818
00819 if (!strcmp(hook->dtmf, dtmf)) {
00820 ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
00821 break;
00822 } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) {
00823 ast_debug(1, "DTMF feature hook %p can match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
00824 look_for_dtmf = 1;
00825 } else {
00826 ast_debug(1, "DTMF feature hook %p does not match DTMF string '%s', it wants '%s', on bridge channel %p\n", hook, dtmf, hook->dtmf, bridge_channel);
00827 }
00828 }
00829
00830
00831 if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) {
00832 break;
00833 }
00834 }
00835
00836
00837 ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00838
00839
00840 if (hook) {
00841 hook->callback(bridge, bridge_channel, hook->hook_pvt);
00842 } else {
00843 ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan);
00844 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00845 }
00846
00847 return;
00848 }
00849
00850
00851 static void bridge_channel_dtmf_stream(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00852 {
00853 char dtmf_q[8] = "";
00854
00855 ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q));
00856 bridge_channel->dtmf_stream_q[0] = '\0';
00857
00858 ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
00859 ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0);
00860
00861 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00862
00863 return;
00864 }
00865
00866
00867 static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_channel *bridge_channel)
00868 {
00869 int formats[2] = { bridge_channel->chan->readformat, bridge_channel->chan->writeformat };
00870 enum ast_bridge_channel_state state;
00871
00872
00873 bridge_channel->thread = pthread_self();
00874
00875 ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge);
00876
00877 ao2_lock(bridge_channel->bridge);
00878
00879 state = bridge_channel->state;
00880
00881
00882 AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
00883 bridge_channel->bridge->num++;
00884
00885 bridge_array_add(bridge_channel->bridge, bridge_channel->chan);
00886
00887 if (bridge_channel->swap) {
00888 struct ast_bridge_channel *bridge_channel2 = NULL;
00889
00890
00891 if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) {
00892 ast_debug(1, "Swapping bridge channel %p out from bridge %p so bridge channel %p can slip in\n", bridge_channel2, bridge_channel->bridge, bridge_channel);
00893 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00894 }
00895
00896 bridge_channel->swap = NULL;
00897 } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00898
00899 smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num);
00900 }
00901
00902
00903 bridge_make_compatible(bridge_channel->bridge, bridge_channel);
00904
00905
00906 if (bridge_channel->bridge->technology->join) {
00907 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00908 if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) {
00909 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00910 }
00911 }
00912
00913
00914 while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00915
00916 bridge_channel->chan->bridge = bridge_channel->bridge;
00917
00918 if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
00919 bridge_channel->bridge->stop = 0;
00920 ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
00921 ao2_ref(bridge_channel->bridge, +1);
00922 if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {
00923 ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge);
00924 ao2_ref(bridge_channel->bridge, -1);
00925 continue;
00926 }
00927 }
00928
00929 state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel));
00930
00931 if (state == AST_BRIDGE_CHANNEL_STATE_FEATURE) {
00932 bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00933 bridge_channel_feature(bridge_channel->bridge, bridge_channel);
00934 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00935 } else if (state == AST_BRIDGE_CHANNEL_STATE_DTMF) {
00936 bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00937 bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel);
00938 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00939 }
00940 }
00941
00942 bridge_channel->chan->bridge = NULL;
00943
00944
00945 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) {
00946 bridge_check_dissolve(bridge_channel->bridge, bridge_channel);
00947 }
00948
00949
00950 if (bridge_channel->bridge->technology->leave) {
00951 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00952 if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) {
00953 ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00954 }
00955 }
00956
00957
00958 bridge_channel->bridge->num--;
00959 AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry);
00960
00961 bridge_array_remove(bridge_channel->bridge, bridge_channel->chan);
00962
00963
00964 if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00965 smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num);
00966 }
00967
00968 ao2_unlock(bridge_channel->bridge);
00969
00970
00971 if (bridge_channel->chan->readformat != formats[0]) {
00972 ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00973 if (ast_set_read_format(bridge_channel->chan, formats[0])) {
00974 ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00975 }
00976 }
00977 if (bridge_channel->chan->writeformat != formats[1]) {
00978 ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00979 if (ast_set_write_format(bridge_channel->chan, formats[1])) {
00980 ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00981 }
00982 }
00983
00984 return bridge_channel->state;
00985 }
00986
00987 enum ast_bridge_channel_state ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
00988 {
00989 struct ast_bridge_channel bridge_channel = {
00990 .chan = chan,
00991 .swap = swap,
00992 .bridge = bridge,
00993 .features = features,
00994 };
00995 enum ast_bridge_channel_state state;
00996
00997
00998 ast_mutex_init(&bridge_channel.lock);
00999 ast_cond_init(&bridge_channel.cond, NULL);
01000
01001 ao2_ref(bridge_channel.bridge, +1);
01002
01003 state = bridge_channel_join(&bridge_channel);
01004
01005 ao2_ref(bridge_channel.bridge, -1);
01006
01007
01008 ast_mutex_destroy(&bridge_channel.lock);
01009 ast_cond_destroy(&bridge_channel.cond);
01010
01011 return state;
01012 }
01013
01014
01015 static void *bridge_channel_thread(void *data)
01016 {
01017 struct ast_bridge_channel *bridge_channel = data;
01018 enum ast_bridge_channel_state state;
01019
01020 state = bridge_channel_join(bridge_channel);
01021
01022 ao2_ref(bridge_channel->bridge, -1);
01023
01024
01025 if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) {
01026 ast_hangup(bridge_channel->chan);
01027 }
01028
01029
01030 ast_mutex_destroy(&bridge_channel->lock);
01031 ast_cond_destroy(&bridge_channel->cond);
01032 ast_free(bridge_channel);
01033
01034 return NULL;
01035 }
01036
01037 int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
01038 {
01039 struct ast_bridge_channel *bridge_channel = NULL;
01040
01041
01042 if (!(bridge_channel = ast_calloc(1, sizeof(*bridge_channel)))) {
01043 return -1;
01044 }
01045
01046
01047 bridge_channel->chan = chan;
01048 bridge_channel->swap = swap;
01049 bridge_channel->bridge = bridge;
01050 bridge_channel->features = features;
01051
01052
01053 ast_mutex_init(&bridge_channel->lock);
01054 ast_cond_init(&bridge_channel->cond, NULL);
01055
01056
01057 ao2_ref(bridge, +1);
01058
01059
01060 if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
01061 ao2_ref(bridge, -1);
01062 ast_cond_destroy(&bridge_channel->cond);
01063 ast_mutex_destroy(&bridge_channel->lock);
01064 ast_free(bridge_channel);
01065 return -1;
01066 }
01067
01068 return 0;
01069 }
01070
01071 int ast_bridge_depart(struct ast_bridge *bridge, struct ast_channel *chan)
01072 {
01073 struct ast_bridge_channel *bridge_channel = NULL;
01074 pthread_t thread;
01075
01076 ao2_lock(bridge);
01077
01078
01079 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01080 ao2_unlock(bridge);
01081 return -1;
01082 }
01083
01084 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
01085 thread = bridge_channel->thread;
01086
01087 ao2_unlock(bridge);
01088
01089 pthread_join(thread, NULL);
01090
01091 return 0;
01092 }
01093
01094 int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
01095 {
01096 struct ast_bridge_channel *bridge_channel = NULL;
01097
01098 ao2_lock(bridge);
01099
01100
01101 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01102 ao2_unlock(bridge);
01103 return -1;
01104 }
01105
01106 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
01107
01108 ao2_unlock(bridge);
01109
01110 return 0;
01111 }
01112
01113 int ast_bridge_merge(struct ast_bridge *bridge0, struct ast_bridge *bridge1)
01114 {
01115 struct ast_bridge_channel *bridge_channel = NULL;
01116
01117 ao2_lock(bridge0);
01118 ao2_lock(bridge1);
01119
01120
01121 if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) {
01122 ao2_unlock(bridge1);
01123 ao2_unlock(bridge0);
01124 ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0);
01125 return -1;
01126 }
01127
01128 ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0);
01129
01130
01131 if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) {
01132 ao2_unlock(bridge1);
01133 ao2_unlock(bridge0);
01134 ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0);
01135 return -1;
01136 }
01137
01138
01139 if (bridge1->thread) {
01140 ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
01141 bridge1->thread = AST_PTHREADT_STOP;
01142 }
01143
01144
01145 while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) {
01146
01147 if (bridge1->technology->leave) {
01148 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01149 if (bridge1->technology->leave(bridge1, bridge_channel)) {
01150 ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01151 }
01152 }
01153
01154
01155 bridge1->num--;
01156 ao2_ref(bridge1, -1);
01157
01158 bridge_array_remove(bridge1, bridge_channel->chan);
01159
01160
01161 bridge_channel->bridge = bridge0;
01162 AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry);
01163 bridge0->num++;
01164 ao2_ref(bridge0, +1);
01165
01166 bridge_array_add(bridge0, bridge_channel->chan);
01167
01168
01169 bridge_make_compatible(bridge0, bridge_channel);
01170
01171
01172 if (bridge0->technology->join) {
01173 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01174 if (bridge0->technology->join(bridge0, bridge_channel)) {
01175 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01176 }
01177 }
01178
01179
01180 pthread_kill(bridge_channel->thread, SIGURG);
01181 ast_mutex_lock(&bridge_channel->lock);
01182 ast_cond_signal(&bridge_channel->cond);
01183 ast_mutex_unlock(&bridge_channel->lock);
01184 }
01185
01186 ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);
01187
01188 ao2_unlock(bridge1);
01189 ao2_unlock(bridge0);
01190
01191 return 0;
01192 }
01193
01194 int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
01195 {
01196 struct ast_bridge_channel *bridge_channel;
01197
01198 ao2_lock(bridge);
01199
01200 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01201 ao2_unlock(bridge);
01202 return -1;
01203 }
01204
01205 bridge_channel_suspend(bridge, bridge_channel);
01206
01207 ao2_unlock(bridge);
01208
01209 return 0;
01210 }
01211
01212 int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
01213 {
01214 struct ast_bridge_channel *bridge_channel;
01215
01216 ao2_lock(bridge);
01217
01218 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01219 ao2_unlock(bridge);
01220 return -1;
01221 }
01222
01223 bridge_channel_unsuspend(bridge, bridge_channel);
01224
01225 ao2_unlock(bridge);
01226
01227 return 0;
01228 }
01229
01230 void ast_bridge_technology_suspend(struct ast_bridge_technology *technology)
01231 {
01232 technology->suspended = 1;
01233 return;
01234 }
01235
01236 void ast_bridge_technology_unsuspend(struct ast_bridge_technology *technology)
01237 {
01238 technology->suspended = 0;
01239 return;
01240 }
01241
01242 int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf)
01243 {
01244 if (builtin_features_handlers[feature]) {
01245 return -1;
01246 }
01247
01248 if (!ast_strlen_zero(dtmf)) {
01249 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
01250 }
01251
01252 builtin_features_handlers[feature] = callback;
01253
01254 return 0;
01255 }
01256
01257 int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
01258 {
01259 if (!builtin_features_handlers[feature]) {
01260 return -1;
01261 }
01262
01263 builtin_features_handlers[feature] = NULL;
01264
01265 return 0;
01266 }
01267
01268 int ast_bridge_features_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt)
01269 {
01270 struct ast_bridge_features_hook *hook = NULL;
01271
01272
01273 if (!(hook = ast_calloc(1, sizeof(*hook)))) {
01274 return -1;
01275 }
01276
01277 ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf));
01278 hook->callback = callback;
01279 hook->hook_pvt = hook_pvt;
01280
01281
01282 AST_LIST_INSERT_TAIL(&features->hooks, hook, entry);
01283
01284 features->usable = 1;
01285
01286 return 0;
01287 }
01288
01289 int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config)
01290 {
01291
01292 if (ast_strlen_zero(dtmf)) {
01293 dtmf = builtin_features_dtmf[feature];
01294
01295 if (ast_strlen_zero(dtmf)) {
01296 ast_debug(1, "Failed to enable built in feature %d on %p, no DTMF string is available for it.\n", feature, features);
01297 return -1;
01298 }
01299 }
01300
01301 if (!builtin_features_handlers[feature]) {
01302 return -1;
01303 }
01304
01305
01306 return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config);
01307 }
01308
01309 int ast_bridge_features_set_flag(struct ast_bridge_features *features, enum ast_bridge_feature_flags flag)
01310 {
01311 ast_set_flag(&features->feature_flags, flag);
01312 features->usable = 1;
01313 return 0;
01314 }
01315
01316 int ast_bridge_features_init(struct ast_bridge_features *features)
01317 {
01318
01319 memset(features, 0, sizeof(*features));
01320
01321
01322 AST_LIST_HEAD_INIT_NOLOCK(&features->hooks);
01323
01324 return 0;
01325 }
01326
01327 int ast_bridge_features_cleanup(struct ast_bridge_features *features)
01328 {
01329 struct ast_bridge_features_hook *hook = NULL;
01330
01331
01332 while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) {
01333 ast_free(hook);
01334 }
01335
01336 return 0;
01337 }
01338
01339 int ast_bridge_dtmf_stream(struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan)
01340 {
01341 struct ast_bridge_channel *bridge_channel = NULL;
01342
01343 ao2_lock(bridge);
01344
01345 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01346 if (bridge_channel->chan == chan) {
01347 continue;
01348 }
01349 ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q));
01350 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF);
01351 }
01352
01353 ao2_unlock(bridge);
01354
01355 return 0;
01356 }