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