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: 266878 $")
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) {
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 == 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)) {
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(int 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(int 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(int 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 int formats[2] = {bridge_channel->chan->readformat, bridge_channel->chan->writeformat};
00541
00542
00543 if (!(bridge->technology->formats & bridge_channel->chan->readformat)) {
00544 int best_format = ast_best_codec(bridge->technology->formats);
00545
00546
00547 if (option_debug) {
00548 char codec_buf[512];
00549 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats);
00550 ast_debug(1, "Bridge technology %s wants to read any of formats %s(%d) but channel has %s(%d)\n", bridge->technology->name, codec_buf, bridge->technology->formats, ast_getformatname(formats[0]), formats[0]);
00551 }
00552
00553 if (ast_set_read_format(bridge_channel->chan, best_format)) {
00554 ast_log(LOG_WARNING, "Failed to set channel %s to read format %s(%d)\n", bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00555 return -1;
00556 }
00557 ast_debug(1, "Bridge %p put channel %s into read format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00558 } else {
00559 ast_debug(1, "Bridge %p is happy that channel %s already has read format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[0]), formats[0]);
00560 }
00561
00562 if (!(bridge->technology->formats & formats[1])) {
00563 int best_format = ast_best_codec(bridge->technology->formats);
00564
00565
00566 if (option_debug) {
00567 char codec_buf[512];
00568 ast_getformatname_multiple(codec_buf, sizeof(codec_buf), bridge->technology->formats);
00569 ast_debug(1, "Bridge technology %s wants to write any of formats %s(%d) but channel has %s(%d)\n", bridge->technology->name, codec_buf, bridge->technology->formats, ast_getformatname(formats[1]), formats[1]);
00570 }
00571
00572 if (ast_set_write_format(bridge_channel->chan, best_format)) {
00573 ast_log(LOG_WARNING, "Failed to set channel %s to write format %s(%d)\n", bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00574 return -1;
00575 }
00576 ast_debug(1, "Bridge %p put channel %s into write format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(best_format), best_format);
00577 } else {
00578 ast_debug(1, "Bridge %p is happy that channel %s already has write format %s(%d)\n", bridge, bridge_channel->chan->name, ast_getformatname(formats[1]), formats[1]);
00579 }
00580
00581 return 0;
00582 }
00583
00584
00585 static int smart_bridge_operation(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel, int count)
00586 {
00587 int new_capabilities = 0;
00588 struct ast_bridge_technology *new_technology = NULL, *old_technology = bridge->technology;
00589 struct ast_bridge temp_bridge = {
00590 .technology = bridge->technology,
00591 .bridge_pvt = bridge->bridge_pvt,
00592 };
00593 struct ast_bridge_channel *bridge_channel2 = NULL;
00594
00595
00596 if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_1TO1MIX) {
00597 if (count <= 2) {
00598 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);
00599 return 0;
00600 }
00601 new_capabilities = AST_BRIDGE_CAPABILITY_MULTIMIX;
00602 } else if (bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) {
00603 if (count > 2) {
00604 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);
00605 return 0;
00606 }
00607 new_capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX;
00608 }
00609
00610 if (!new_capabilities) {
00611 ast_debug(1, "Bridge '%p' has no new capabilities, not performing smart bridge operation.\n", bridge);
00612 return 0;
00613 }
00614
00615
00616 if (!(new_technology = find_best_technology(new_capabilities))) {
00617 ast_debug(1, "Smart bridge operation was unable to find new bridge technology with capabilities %d to satisfy bridge %p\n", new_capabilities, bridge);
00618 return -1;
00619 }
00620
00621 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);
00622
00623
00624 if (bridge->thread != AST_PTHREADT_NULL) {
00625
00626 if (new_technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD) {
00627 ast_debug(1, "Telling current bridge thread for bridge %p to refresh\n", bridge);
00628 bridge->refresh = 1;
00629 bridge_poke(bridge);
00630 } else {
00631 pthread_t bridge_thread = bridge->thread;
00632 ast_debug(1, "Telling current bridge thread for bridge %p to stop\n", bridge);
00633 bridge->stop = 1;
00634 bridge_poke(bridge);
00635 ao2_unlock(bridge);
00636 pthread_join(bridge_thread, NULL);
00637 ao2_lock(bridge);
00638 }
00639 }
00640
00641
00642 bridge->bridge_pvt = NULL;
00643 bridge->technology = new_technology;
00644
00645
00646 if (new_technology->create) {
00647 ast_debug(1, "Giving bridge technology %s the bridge structure %p to setup\n", new_technology->name, bridge);
00648 if (new_technology->create(bridge)) {
00649 ast_debug(1, "Bridge technology %s failed to setup bridge structure %p\n", new_technology->name, bridge);
00650 }
00651 }
00652
00653
00654 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel2, entry) {
00655
00656 if (bridge_channel == bridge_channel2) {
00657 continue;
00658 }
00659
00660
00661 if (old_technology->leave) {
00662 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);
00663 if (old_technology->leave(&temp_bridge, bridge_channel2)) {
00664 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);
00665 }
00666 }
00667
00668
00669 bridge_make_compatible(bridge, bridge_channel2);
00670
00671
00672 if (new_technology->join) {
00673 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", new_technology->name, bridge_channel2, bridge);
00674 if (new_technology->join(bridge, bridge_channel2)) {
00675 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", new_technology->name, bridge_channel2, bridge);
00676 }
00677 }
00678
00679
00680 pthread_kill(bridge_channel2->thread, SIGURG);
00681 ast_mutex_lock(&bridge_channel2->lock);
00682 ast_cond_signal(&bridge_channel2->cond);
00683 ast_mutex_unlock(&bridge_channel2->lock);
00684 }
00685
00686
00687 if (old_technology->destroy) {
00688 ast_debug(1, "Giving bridge technology %s the bridge structure %p (really %p) to destroy\n", old_technology->name, &temp_bridge, bridge);
00689 if (old_technology->destroy(&temp_bridge)) {
00690 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);
00691 }
00692 }
00693
00694
00695 if (old_technology->mod) {
00696 ast_module_unref(old_technology->mod);
00697 }
00698
00699 return 0;
00700 }
00701
00702
00703 static enum ast_bridge_channel_state bridge_channel_join_multithreaded(struct ast_bridge_channel *bridge_channel)
00704 {
00705 int fds[4] = { -1, }, nfds = 0, i = 0, outfd = -1, ms = -1;
00706 struct ast_channel *chan = NULL;
00707
00708
00709 if (bridge_channel->bridge->technology->fd) {
00710 for (i = 0; i < 4; i ++) {
00711 if (bridge_channel->fds[i] >= 0) {
00712 fds[nfds++] = bridge_channel->fds[i];
00713 }
00714 }
00715 }
00716
00717 ao2_unlock(bridge_channel->bridge);
00718
00719
00720 if (!bridge_channel->suspended) {
00721 ast_debug(1, "Going into a multithreaded waitfor for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00722 chan = ast_waitfor_nandfds(&bridge_channel->chan, 1, fds, nfds, NULL, &outfd, &ms);
00723 } else {
00724 ast_mutex_lock(&bridge_channel->lock);
00725 ast_debug(1, "Going into a multithreaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00726 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00727 ast_mutex_unlock(&bridge_channel->lock);
00728 }
00729
00730 ao2_lock(bridge_channel->bridge);
00731
00732 if (!bridge_channel->suspended) {
00733 ast_bridge_handle_trip(bridge_channel->bridge, bridge_channel, chan, outfd);
00734 }
00735
00736 return bridge_channel->state;
00737 }
00738
00739
00740 static enum ast_bridge_channel_state bridge_channel_join_singlethreaded(struct ast_bridge_channel *bridge_channel)
00741 {
00742 ao2_unlock(bridge_channel->bridge);
00743 ast_mutex_lock(&bridge_channel->lock);
00744 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00745 ast_debug(1, "Going into a single threaded signal wait for bridge channel %p of bridge %p\n", bridge_channel, bridge_channel->bridge);
00746 ast_cond_wait(&bridge_channel->cond, &bridge_channel->lock);
00747 }
00748 ast_mutex_unlock(&bridge_channel->lock);
00749 ao2_lock(bridge_channel->bridge);
00750
00751 return bridge_channel->state;
00752 }
00753
00754
00755 static void bridge_channel_suspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00756 {
00757 bridge_channel->suspended = 1;
00758
00759 bridge_array_remove(bridge, bridge_channel->chan);
00760
00761 if (bridge->technology->suspend) {
00762 bridge->technology->suspend(bridge, bridge_channel);
00763 }
00764
00765 return;
00766 }
00767
00768
00769 static void bridge_channel_unsuspend(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00770 {
00771 bridge_channel->suspended =0;
00772
00773 bridge_array_add(bridge, bridge_channel->chan);
00774
00775 if (bridge->technology->unsuspend) {
00776 bridge->technology->unsuspend(bridge, bridge_channel);
00777 }
00778
00779 return;
00780 }
00781
00782
00783 static void bridge_channel_feature(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00784 {
00785 struct ast_bridge_features *features = (bridge_channel->features ? bridge_channel->features : &bridge->features);
00786 struct ast_bridge_features_hook *hook = NULL;
00787 char dtmf[MAXIMUM_DTMF_FEATURE_STRING] = "";
00788 int look_for_dtmf = 1, dtmf_len = 0;
00789
00790
00791 ast_set_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00792
00793
00794 while (look_for_dtmf) {
00795 int res = ast_waitfordigit(bridge_channel->chan, 3000);
00796
00797
00798 if (!res) {
00799 ast_debug(1, "DTMF feature string collection on bridge channel %p timed out\n", bridge_channel);
00800 break;
00801 } else if (res < 0) {
00802 ast_debug(1, "DTMF feature string collection failed on bridge channel %p for some reason\n", bridge_channel);
00803 break;
00804 }
00805
00806
00807 dtmf[dtmf_len++] = res;
00808
00809 ast_debug(1, "DTMF feature string on bridge channel %p is now '%s'\n", bridge_channel, dtmf);
00810
00811
00812 look_for_dtmf = 0;
00813
00814
00815 AST_LIST_TRAVERSE(&features->hooks, hook, entry) {
00816
00817 if (!strcmp(hook->dtmf, dtmf)) {
00818 ast_debug(1, "DTMF feature hook %p matched DTMF string '%s' on bridge channel %p\n", hook, dtmf, bridge_channel);
00819 break;
00820 } else if (!strncmp(hook->dtmf, dtmf, dtmf_len)) {
00821 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);
00822 look_for_dtmf = 1;
00823 } else {
00824 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);
00825 }
00826 }
00827
00828
00829 if (dtmf_len == MAXIMUM_DTMF_FEATURE_STRING) {
00830 break;
00831 }
00832 }
00833
00834
00835 ast_clear_flag(bridge_channel->chan, AST_FLAG_END_DTMF_ONLY);
00836
00837
00838 if (hook) {
00839 hook->callback(bridge, bridge_channel, hook->hook_pvt);
00840 } else {
00841 ast_bridge_dtmf_stream(bridge, dtmf, bridge_channel->chan);
00842 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00843 }
00844
00845 return;
00846 }
00847
00848
00849 static void bridge_channel_dtmf_stream(struct ast_bridge *bridge, struct ast_bridge_channel *bridge_channel)
00850 {
00851 char dtmf_q[8] = "";
00852
00853 ast_copy_string(dtmf_q, bridge_channel->dtmf_stream_q, sizeof(dtmf_q));
00854 bridge_channel->dtmf_stream_q[0] = '\0';
00855
00856 ast_debug(1, "Playing DTMF stream '%s' out to bridge channel %p\n", dtmf_q, bridge_channel);
00857 ast_dtmf_stream(bridge_channel->chan, NULL, dtmf_q, 250, 0);
00858
00859 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_WAIT);
00860
00861 return;
00862 }
00863
00864
00865 static enum ast_bridge_channel_state bridge_channel_join(struct ast_bridge_channel *bridge_channel)
00866 {
00867 int formats[2] = { bridge_channel->chan->readformat, bridge_channel->chan->writeformat };
00868 enum ast_bridge_channel_state state;
00869
00870
00871 bridge_channel->thread = pthread_self();
00872
00873 ast_debug(1, "Joining bridge channel %p to bridge %p\n", bridge_channel, bridge_channel->bridge);
00874
00875 ao2_lock(bridge_channel->bridge);
00876
00877 state = bridge_channel->state;
00878
00879
00880 AST_LIST_INSERT_TAIL(&bridge_channel->bridge->channels, bridge_channel, entry);
00881 bridge_channel->bridge->num++;
00882
00883 bridge_array_add(bridge_channel->bridge, bridge_channel->chan);
00884
00885 if (bridge_channel->swap) {
00886 struct ast_bridge_channel *bridge_channel2 = NULL;
00887
00888
00889 if ((bridge_channel2 = find_bridge_channel(bridge_channel->bridge, bridge_channel->swap))) {
00890 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);
00891 ast_bridge_change_state(bridge_channel2, AST_BRIDGE_CHANNEL_STATE_HANGUP);
00892 }
00893
00894 bridge_channel->swap = NULL;
00895 } else if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00896
00897 smart_bridge_operation(bridge_channel->bridge, bridge_channel, bridge_channel->bridge->num);
00898 }
00899
00900
00901 bridge_make_compatible(bridge_channel->bridge, bridge_channel);
00902
00903
00904 if (bridge_channel->bridge->technology->join) {
00905 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);
00906 if (bridge_channel->bridge->technology->join(bridge_channel->bridge, bridge_channel)) {
00907 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00908 }
00909 }
00910
00911
00912 while (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_WAIT) {
00913
00914 bridge_channel->chan->bridge = bridge_channel->bridge;
00915
00916 if (bridge_channel->bridge->thread == AST_PTHREADT_NULL && (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_THREAD)) {
00917 bridge_channel->bridge->stop = 0;
00918 ast_debug(1, "Starting a bridge thread for bridge %p\n", bridge_channel->bridge);
00919 ao2_ref(bridge_channel->bridge, +1);
00920 if (ast_pthread_create(&bridge_channel->bridge->thread, NULL, bridge_thread, bridge_channel->bridge)) {
00921 ast_debug(1, "Failed to create a bridge thread for bridge %p, giving it another go.\n", bridge_channel->bridge);
00922 ao2_ref(bridge_channel->bridge, -1);
00923 continue;
00924 }
00925 }
00926
00927 state = (bridge_channel->bridge->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTITHREADED ? bridge_channel_join_multithreaded(bridge_channel) : bridge_channel_join_singlethreaded(bridge_channel));
00928
00929 if (state == AST_BRIDGE_CHANNEL_STATE_FEATURE) {
00930 bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00931 bridge_channel_feature(bridge_channel->bridge, bridge_channel);
00932 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00933 } else if (state == AST_BRIDGE_CHANNEL_STATE_DTMF) {
00934 bridge_channel_suspend(bridge_channel->bridge, bridge_channel);
00935 bridge_channel_dtmf_stream(bridge_channel->bridge, bridge_channel);
00936 bridge_channel_unsuspend(bridge_channel->bridge, bridge_channel);
00937 }
00938 }
00939
00940 bridge_channel->chan->bridge = NULL;
00941
00942
00943 if (bridge_channel->state == AST_BRIDGE_CHANNEL_STATE_END) {
00944 bridge_check_dissolve(bridge_channel->bridge, bridge_channel);
00945 }
00946
00947
00948 if (bridge_channel->bridge->technology->leave) {
00949 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);
00950 if (bridge_channel->bridge->technology->leave(bridge_channel->bridge, bridge_channel)) {
00951 ast_debug(1, "Bridge technology %s failed to leave %p from bridge %p\n", bridge_channel->bridge->technology->name, bridge_channel, bridge_channel->bridge);
00952 }
00953 }
00954
00955
00956 bridge_channel->bridge->num--;
00957 AST_LIST_REMOVE(&bridge_channel->bridge->channels, bridge_channel, entry);
00958
00959 bridge_array_remove(bridge_channel->bridge, bridge_channel->chan);
00960
00961
00962 if (ast_test_flag(&bridge_channel->bridge->feature_flags, AST_BRIDGE_FLAG_SMART)) {
00963 smart_bridge_operation(bridge_channel->bridge, NULL, bridge_channel->bridge->num);
00964 }
00965
00966 ao2_unlock(bridge_channel->bridge);
00967
00968
00969 if (bridge_channel->chan->readformat != formats[0]) {
00970 ast_debug(1, "Bridge is returning %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00971 if (ast_set_read_format(bridge_channel->chan, formats[0])) {
00972 ast_debug(1, "Bridge failed to return channel %p to read format %s(%d)\n", bridge_channel, ast_getformatname(formats[0]), formats[0]);
00973 }
00974 }
00975 if (bridge_channel->chan->writeformat != formats[1]) {
00976 ast_debug(1, "Bridge is returning %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00977 if (ast_set_write_format(bridge_channel->chan, formats[1])) {
00978 ast_debug(1, "Bridge failed to return channel %p to write format %s(%d)\n", bridge_channel, ast_getformatname(formats[1]), formats[1]);
00979 }
00980 }
00981
00982 return bridge_channel->state;
00983 }
00984
00985 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)
00986 {
00987 struct ast_bridge_channel bridge_channel = {
00988 .chan = chan,
00989 .swap = swap,
00990 .bridge = bridge,
00991 .features = features,
00992 };
00993 enum ast_bridge_channel_state state;
00994
00995
00996 ast_mutex_init(&bridge_channel.lock);
00997 ast_cond_init(&bridge_channel.cond, NULL);
00998
00999 ao2_ref(bridge_channel.bridge, +1);
01000
01001 state = bridge_channel_join(&bridge_channel);
01002
01003 ao2_ref(bridge_channel.bridge, -1);
01004
01005
01006 ast_mutex_destroy(&bridge_channel.lock);
01007 ast_cond_destroy(&bridge_channel.cond);
01008
01009 return state;
01010 }
01011
01012
01013 static void *bridge_channel_thread(void *data)
01014 {
01015 struct ast_bridge_channel *bridge_channel = data;
01016 enum ast_bridge_channel_state state;
01017
01018 state = bridge_channel_join(bridge_channel);
01019
01020 ao2_ref(bridge_channel->bridge, -1);
01021
01022
01023 if (state == AST_BRIDGE_CHANNEL_STATE_END || state == AST_BRIDGE_CHANNEL_STATE_HANGUP) {
01024 ast_hangup(bridge_channel->chan);
01025 }
01026
01027
01028 ast_mutex_destroy(&bridge_channel->lock);
01029 ast_cond_destroy(&bridge_channel->cond);
01030 ast_free(bridge_channel);
01031
01032 return NULL;
01033 }
01034
01035 int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features)
01036 {
01037 struct ast_bridge_channel *bridge_channel = NULL;
01038
01039
01040 if (!(bridge_channel = ast_calloc(1, sizeof(*bridge_channel)))) {
01041 return -1;
01042 }
01043
01044
01045 bridge_channel->chan = chan;
01046 bridge_channel->swap = swap;
01047 bridge_channel->bridge = bridge;
01048 bridge_channel->features = features;
01049
01050
01051 ast_mutex_init(&bridge_channel->lock);
01052 ast_cond_init(&bridge_channel->cond, NULL);
01053
01054
01055 ao2_ref(bridge, +1);
01056
01057
01058 if (ast_pthread_create(&bridge_channel->thread, NULL, bridge_channel_thread, bridge_channel)) {
01059 ao2_ref(bridge, -1);
01060 ast_cond_destroy(&bridge_channel->cond);
01061 ast_mutex_destroy(&bridge_channel->lock);
01062 ast_free(bridge_channel);
01063 return -1;
01064 }
01065
01066 return 0;
01067 }
01068
01069 int ast_bridge_depart(struct ast_bridge *bridge, struct ast_channel *chan)
01070 {
01071 struct ast_bridge_channel *bridge_channel = NULL;
01072 pthread_t thread;
01073
01074 ao2_lock(bridge);
01075
01076
01077 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01078 ao2_unlock(bridge);
01079 return -1;
01080 }
01081
01082 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DEPART);
01083 thread = bridge_channel->thread;
01084
01085 ao2_unlock(bridge);
01086
01087 pthread_join(thread, NULL);
01088
01089 return 0;
01090 }
01091
01092 int ast_bridge_remove(struct ast_bridge *bridge, struct ast_channel *chan)
01093 {
01094 struct ast_bridge_channel *bridge_channel = NULL;
01095
01096 ao2_lock(bridge);
01097
01098
01099 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01100 ao2_unlock(bridge);
01101 return -1;
01102 }
01103
01104 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_HANGUP);
01105
01106 ao2_unlock(bridge);
01107
01108 return 0;
01109 }
01110
01111 int ast_bridge_merge(struct ast_bridge *bridge0, struct ast_bridge *bridge1)
01112 {
01113 struct ast_bridge_channel *bridge_channel = NULL;
01114
01115 ao2_lock(bridge0);
01116 ao2_lock(bridge1);
01117
01118
01119 if ((bridge0->num + bridge1->num) > 2 && (!(bridge0->technology->capabilities & AST_BRIDGE_CAPABILITY_MULTIMIX) && !ast_test_flag(&bridge0->feature_flags, AST_BRIDGE_FLAG_SMART))) {
01120 ao2_unlock(bridge1);
01121 ao2_unlock(bridge0);
01122 ast_debug(1, "Can't merge bridge %p into bridge %p, multimix is needed and it could not be acquired.\n", bridge1, bridge0);
01123 return -1;
01124 }
01125
01126 ast_debug(1, "Merging channels from bridge %p into bridge %p\n", bridge1, bridge0);
01127
01128
01129 if (smart_bridge_operation(bridge0, NULL, bridge0->num + bridge1->num)) {
01130 ao2_unlock(bridge1);
01131 ao2_unlock(bridge0);
01132 ast_debug(1, "Can't merge bridge %p into bridge %p, tried to perform smart bridge operation and failed.\n", bridge1, bridge0);
01133 return -1;
01134 }
01135
01136
01137 if (bridge1->thread) {
01138 ast_debug(1, "Telling bridge thread on bridge %p to stop as it is being merged into %p\n", bridge1, bridge0);
01139 bridge1->thread = AST_PTHREADT_STOP;
01140 }
01141
01142
01143 while ((bridge_channel = AST_LIST_REMOVE_HEAD(&bridge1->channels, entry))) {
01144
01145 if (bridge1->technology->leave) {
01146 ast_debug(1, "Giving bridge technology %s notification that %p is leaving bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01147 if (bridge1->technology->leave(bridge1, bridge_channel)) {
01148 ast_debug(1, "Bridge technology %s failed to allow %p to leave bridge %p\n", bridge1->technology->name, bridge_channel, bridge1);
01149 }
01150 }
01151
01152
01153 bridge1->num--;
01154 ao2_ref(bridge1, -1);
01155
01156 bridge_array_remove(bridge1, bridge_channel->chan);
01157
01158
01159 bridge_channel->bridge = bridge0;
01160 AST_LIST_INSERT_TAIL(&bridge0->channels, bridge_channel, entry);
01161 bridge0->num++;
01162 ao2_ref(bridge0, +1);
01163
01164 bridge_array_add(bridge0, bridge_channel->chan);
01165
01166
01167 bridge_make_compatible(bridge0, bridge_channel);
01168
01169
01170 if (bridge0->technology->join) {
01171 ast_debug(1, "Giving bridge technology %s notification that %p is joining bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01172 if (bridge0->technology->join(bridge0, bridge_channel)) {
01173 ast_debug(1, "Bridge technology %s failed to join %p to bridge %p\n", bridge0->technology->name, bridge_channel, bridge0);
01174 }
01175 }
01176
01177
01178 pthread_kill(bridge_channel->thread, SIGURG);
01179 ast_mutex_lock(&bridge_channel->lock);
01180 ast_cond_signal(&bridge_channel->cond);
01181 ast_mutex_unlock(&bridge_channel->lock);
01182 }
01183
01184 ast_debug(1, "Merged channels from bridge %p into bridge %p\n", bridge1, bridge0);
01185
01186 ao2_unlock(bridge1);
01187 ao2_unlock(bridge0);
01188
01189 return 0;
01190 }
01191
01192 int ast_bridge_suspend(struct ast_bridge *bridge, struct ast_channel *chan)
01193 {
01194 struct ast_bridge_channel *bridge_channel;
01195
01196 ao2_lock(bridge);
01197
01198 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01199 ao2_unlock(bridge);
01200 return -1;
01201 }
01202
01203 bridge_channel_suspend(bridge, bridge_channel);
01204
01205 ao2_unlock(bridge);
01206
01207 return 0;
01208 }
01209
01210 int ast_bridge_unsuspend(struct ast_bridge *bridge, struct ast_channel *chan)
01211 {
01212 struct ast_bridge_channel *bridge_channel;
01213
01214 ao2_lock(bridge);
01215
01216 if (!(bridge_channel = find_bridge_channel(bridge, chan))) {
01217 ao2_unlock(bridge);
01218 return -1;
01219 }
01220
01221 bridge_channel_unsuspend(bridge, bridge_channel);
01222
01223 ao2_unlock(bridge);
01224
01225 return 0;
01226 }
01227
01228 void ast_bridge_technology_suspend(struct ast_bridge_technology *technology)
01229 {
01230 technology->suspended = 1;
01231 return;
01232 }
01233
01234 void ast_bridge_technology_unsuspend(struct ast_bridge_technology *technology)
01235 {
01236 technology->suspended = 0;
01237 return;
01238 }
01239
01240 int ast_bridge_features_register(enum ast_bridge_builtin_feature feature, ast_bridge_features_hook_callback callback, const char *dtmf)
01241 {
01242 if (builtin_features_handlers[feature]) {
01243 return -1;
01244 }
01245
01246 if (!ast_strlen_zero(dtmf)) {
01247 ast_copy_string(builtin_features_dtmf[feature], dtmf, sizeof(builtin_features_dtmf[feature]));
01248 }
01249
01250 builtin_features_handlers[feature] = callback;
01251
01252 return 0;
01253 }
01254
01255 int ast_bridge_features_unregister(enum ast_bridge_builtin_feature feature)
01256 {
01257 if (!builtin_features_handlers[feature]) {
01258 return -1;
01259 }
01260
01261 builtin_features_handlers[feature] = NULL;
01262
01263 return 0;
01264 }
01265
01266 int ast_bridge_features_hook(struct ast_bridge_features *features, const char *dtmf, ast_bridge_features_hook_callback callback, void *hook_pvt)
01267 {
01268 struct ast_bridge_features_hook *hook = NULL;
01269
01270
01271 if (!(hook = ast_calloc(1, sizeof(*hook)))) {
01272 return -1;
01273 }
01274
01275 ast_copy_string(hook->dtmf, dtmf, sizeof(hook->dtmf));
01276 hook->callback = callback;
01277 hook->hook_pvt = hook_pvt;
01278
01279
01280 AST_LIST_INSERT_TAIL(&features->hooks, hook, entry);
01281
01282 features->usable = 1;
01283
01284 return 0;
01285 }
01286
01287 int ast_bridge_features_enable(struct ast_bridge_features *features, enum ast_bridge_builtin_feature feature, const char *dtmf, void *config)
01288 {
01289
01290 if (ast_strlen_zero(dtmf)) {
01291 dtmf = builtin_features_dtmf[feature];
01292
01293 if (ast_strlen_zero(dtmf)) {
01294 ast_debug(1, "Failed to enable built in feature %d on %p, no DTMF string is available for it.\n", feature, features);
01295 return -1;
01296 }
01297 }
01298
01299 if (!builtin_features_handlers[feature]) {
01300 return -1;
01301 }
01302
01303
01304 return ast_bridge_features_hook(features, dtmf, builtin_features_handlers[feature], config);
01305 }
01306
01307 int ast_bridge_features_set_flag(struct ast_bridge_features *features, enum ast_bridge_feature_flags flag)
01308 {
01309 ast_set_flag(&features->feature_flags, flag);
01310 features->usable = 1;
01311 return 0;
01312 }
01313
01314 int ast_bridge_features_init(struct ast_bridge_features *features)
01315 {
01316
01317 memset(features, 0, sizeof(*features));
01318
01319
01320 AST_LIST_HEAD_INIT_NOLOCK(&features->hooks);
01321
01322 return 0;
01323 }
01324
01325 int ast_bridge_features_cleanup(struct ast_bridge_features *features)
01326 {
01327 struct ast_bridge_features_hook *hook = NULL;
01328
01329
01330 while ((hook = AST_LIST_REMOVE_HEAD(&features->hooks, entry))) {
01331 ast_free(hook);
01332 }
01333
01334 return 0;
01335 }
01336
01337 int ast_bridge_dtmf_stream(struct ast_bridge *bridge, const char *dtmf, struct ast_channel *chan)
01338 {
01339 struct ast_bridge_channel *bridge_channel = NULL;
01340
01341 ao2_lock(bridge);
01342
01343 AST_LIST_TRAVERSE(&bridge->channels, bridge_channel, entry) {
01344 if (bridge_channel->chan == chan) {
01345 continue;
01346 }
01347 ast_copy_string(bridge_channel->dtmf_stream_q, dtmf, sizeof(bridge_channel->dtmf_stream_q));
01348 ast_bridge_change_state(bridge_channel, AST_BRIDGE_CHANNEL_STATE_DTMF);
01349 }
01350
01351 ao2_unlock(bridge);
01352
01353 return 0;
01354 }