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