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