#include "asterisk/linkedlists.h"


Go to the source code of this file.
Data Structures | |
| struct | ast_call_feature |
| main call feature structure More... | |
Defines | |
| #define | FEATURE_APP_ARGS_LEN 256 |
| #define | FEATURE_APP_LEN 64 |
| #define | FEATURE_EXTEN_LEN 32 |
| #define | FEATURE_MAX_LEN 11 |
| #define | FEATURE_MOH_LEN 80 |
| #define | FEATURE_RETURN_HANGUP -1 |
| #define | FEATURE_RETURN_KEEPTRYING 24 |
| #define | FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
| #define | FEATURE_RETURN_PARKFAILED 25 |
| #define | FEATURE_RETURN_PASSDIGITS 21 |
| #define | FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
| #define | FEATURE_RETURN_STOREDIGITS 22 |
| #define | FEATURE_RETURN_SUCCESS 23 |
| #define | FEATURE_RETURN_SUCCESSBREAK 0 |
| #define | FEATURE_SENSE_CHAN (1 << 0) |
| #define | FEATURE_SENSE_PEER (1 << 1) |
| #define | FEATURE_SNAME_LEN 32 |
| #define | PARK_APP_NAME "Park" |
Typedefs | |
| typedef int(* | ast_feature_operation )(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data) |
Functions | |
| int | ast_bridge_call (struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config) |
| Bridge a call, optionally allowing redirection. | |
| int | ast_feature_detect (struct ast_channel *chan, struct ast_flags *features, char *code, struct ast_call_feature *feature) |
| detect a feature before bridging | |
| int | ast_masq_park_call (struct ast_channel *rchan, struct ast_channel *host, int timeout, int *extout) |
| Park a call via a masqueraded channel. | |
| int | ast_park_call (struct ast_channel *chan, struct ast_channel *host, int timeout, int *extout) |
| Park a call and read back parked location. | |
| char * | ast_parking_ext (void) |
| Determine system parking extension Returns the call parking extension for drivers that provide special call parking help. | |
| int | ast_pickup_call (struct ast_channel *chan) |
| Pickup a call. | |
| char * | ast_pickup_ext (void) |
| Determine system call pickup extension. | |
| void | ast_register_feature (struct ast_call_feature *feature) |
| register new feature into feature_set | |
| void | ast_unregister_feature (struct ast_call_feature *feature) |
| unregister feature from feature_set | |
Definition in file features.h.
| #define FEATURE_APP_ARGS_LEN 256 |
| #define FEATURE_APP_LEN 64 |
| #define FEATURE_EXTEN_LEN 32 |
| #define FEATURE_MAX_LEN 11 |
| #define FEATURE_MOH_LEN 80 |
| #define FEATURE_RETURN_HANGUP -1 |
| #define FEATURE_RETURN_KEEPTRYING 24 |
Definition at line 45 of file features.h.
Referenced by feature_exec_app(), and feature_interpret_helper().
| #define FEATURE_RETURN_NO_HANGUP_PEER AST_PBX_NO_HANGUP_PEER |
Definition at line 41 of file features.h.
| #define FEATURE_RETURN_PARKFAILED 25 |
Definition at line 46 of file features.h.
Referenced by builtin_blindtransfer(), and masq_park_call().
| #define FEATURE_RETURN_PASSDIGITS 21 |
Definition at line 42 of file features.h.
Referenced by ast_bridge_call(), and feature_interpret_helper().
| #define FEATURE_RETURN_PBX_KEEPALIVE AST_PBX_KEEPALIVE |
Definition at line 40 of file features.h.
| #define FEATURE_RETURN_STOREDIGITS 22 |
Definition at line 43 of file features.h.
Referenced by detect_disconnect(), and feature_interpret_helper().
| #define FEATURE_RETURN_SUCCESS 23 |
Definition at line 44 of file features.h.
Referenced by ast_bridge_call(), builtin_atxfer(), builtin_automonitor(), builtin_blindtransfer(), feature_exec_app(), and feature_interpret_helper().
| #define FEATURE_RETURN_SUCCESSBREAK 0 |
| #define FEATURE_SENSE_CHAN (1 << 0) |
Definition at line 48 of file features.h.
Referenced by ast_bridge_call(), feature_exec_app(), and feature_interpret().
| #define FEATURE_SENSE_PEER (1 << 1) |
| #define FEATURE_SNAME_LEN 32 |
| #define PARK_APP_NAME "Park" |
| typedef int(* ast_feature_operation)(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, char *code, int sense, void *data) |
Definition at line 51 of file features.h.
| int ast_bridge_call | ( | struct ast_channel * | chan, | |
| struct ast_channel * | peer, | |||
| struct ast_bridge_config * | config | |||
| ) |
Bridge a call, optionally allowing redirection.
append the event to featurecode. we rely on the string being zero-filled, and not overflowing it.
Definition at line 2115 of file res_features.c.
References ast_channel::_state, ast_cdr::accountcode, ast_channel::accountcode, add_features_datastores(), ast_channel::amaflags, ast_cdr::amaflags, ast_cdr::answer, ast_channel::appl, ast_answer(), AST_BRIDGE_RETRY, ast_bridged_channel(), ast_cdr_alloc(), ast_cdr_answer(), AST_CDR_ANSWERED, ast_cdr_detach(), ast_cdr_discard(), ast_cdr_dup(), ast_cdr_end(), AST_CDR_FLAG_BRIDGED, AST_CDR_FLAG_DIALED, AST_CDR_FLAG_MAIN, AST_CDR_FLAG_POST_DISABLED, AST_CDR_NOANSWER, ast_cdr_setaccount(), ast_cdr_setanswer(), ast_cdr_setcid(), ast_cdr_setdisposition(), ast_cdr_specialized_reset(), ast_cdr_start(), ast_cdr_update(), ast_channel_bridge(), ast_channel_lock, ast_channel_setoption(), ast_channel_start_silence_generator(), ast_channel_stop_silence_generator(), ast_channel_unlock, ast_check_hangup(), ast_clear_flag, AST_CONTROL_BUSY, AST_CONTROL_CONGESTION, AST_CONTROL_FLASH, AST_CONTROL_HANGUP, AST_CONTROL_HOLD, AST_CONTROL_OPTION, AST_CONTROL_RINGING, AST_CONTROL_UNHOLD, ast_copy_string(), ast_default_amaflags, ast_dtmf_stream(), ast_exists_extension(), AST_FEATURE_NO_H_EXTEN, AST_FEATURE_PLAY_WARNING, AST_FLAG_BRIDGE_HANGUP_DONT, AST_FLAG_BRIDGE_HANGUP_RUN, AST_FLAG_IN_AUTOLOOP, AST_FLAG_ZOMBIE, AST_FRAME_CONTROL, AST_FRAME_DTMF, AST_FRAME_DTMF_BEGIN, AST_FRAME_DTMF_END, ast_frfree, ast_get_channel_by_name_locked(), ast_indicate(), ast_indicate_data(), ast_log(), AST_MAX_EXTENSION, ast_opt_end_cdr_before_h_exten, ast_opt_transmit_silence, AST_OPTION_AUDIO_MODE, AST_OPTION_FLAG_REQUEST, AST_OPTION_RELAXDTMF, AST_OPTION_TDD, AST_OPTION_TONE_VERIFY, ast_set2_flag, ast_set_flag, ast_spawn_extension(), AST_STATE_RINGING, AST_STATE_UP, ast_strdupa, ast_strlen_zero(), ast_test_flag, ast_tvcmp(), ast_tvdiff_ms(), ast_tvnow(), ast_tvzero(), ast_verbose(), ast_write(), ast_channel::cdr, ast_cdr::channel, ast_channel::cid, ast_callerid::cid_num, clear_dialed_interfaces(), ast_channel::context, ast_option_header::data, ast_frame::data, ast_channel::data, ast_frame::datalen, ast_cdr::dcontext, ast_cdr::disposition, ast_cdr::dst, ast_cdr::dstchannel, ast_bridge_config::end_bridge_callback, ast_bridge_config::end_bridge_callback_data, ast_bridge_config::end_sound, ast_channel::exten, f, feature_check(), feature_interpret(), FEATURE_MAX_LEN, FEATURE_RETURN_PASSDIGITS, FEATURE_RETURN_SUCCESS, FEATURE_SENSE_CHAN, FEATURE_SENSE_PEER, ast_bridge_config::feature_timer, ast_bridge_config::features_callee, ast_bridge_config::features_caller, ast_bridge_config::firstpass, ast_option_header::flag, ast_frame::frametype, ast_cdr::lastapp, ast_cdr::lastdata, LOG_DEBUG, LOG_WARNING, ast_channel::name, ast_cdr::next, ast_option_header::option, option_debug, option_verbose, pbx_builtin_getvar_helper(), pbx_builtin_setvar_helper(), pbx_exec(), pbx_findapp(), pick_unlocked_cdr(), ast_bridge_config::play_warning, ast_channel::priority, S_OR, set_bridge_features_on_config(), set_config_flags(), ast_cdr::start, ast_bridge_config::start_sound, ast_bridge_config::start_time, ast_frame::subclass, ast_channel::uniqueid, ast_cdr::uniqueid, ast_cdr::userfield, VERBOSE_PREFIX_2, ast_channel::visible_indication, ast_bridge_config::warning_freq, and ast_bridge_config::warning_sound.
Referenced by app_exec(), ast_bridge_call_thread(), builtin_atxfer(), park_exec(), and try_calling().
02116 { 02117 /* Copy voice back and forth between the two channels. Give the peer 02118 the ability to transfer calls with '#<extension' syntax. */ 02119 struct ast_frame *f; 02120 struct ast_channel *who; 02121 char chan_featurecode[FEATURE_MAX_LEN + 1]=""; 02122 char peer_featurecode[FEATURE_MAX_LEN + 1]=""; 02123 char orig_channame[AST_MAX_EXTENSION]; 02124 char orig_peername[AST_MAX_EXTENSION]; 02125 02126 int res; 02127 int diff; 02128 int hasfeatures=0; 02129 int hadfeatures=0; 02130 int autoloopflag; 02131 int sendingdtmfdigit = 0; 02132 struct ast_option_header *aoh; 02133 struct ast_bridge_config backup_config; 02134 struct ast_cdr *bridge_cdr = NULL; 02135 struct ast_cdr *orig_peer_cdr = NULL; 02136 struct ast_cdr *chan_cdr = chan->cdr; /* the proper chan cdr, if there are forked cdrs */ 02137 struct ast_cdr *peer_cdr = peer->cdr; /* the proper chan cdr, if there are forked cdrs */ 02138 struct ast_cdr *new_chan_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02139 struct ast_cdr *new_peer_cdr = NULL; /* the proper chan cdr, if there are forked cdrs */ 02140 struct ast_silence_generator *silgen = NULL; 02141 02142 memset(&backup_config, 0, sizeof(backup_config)); 02143 02144 config->start_time = ast_tvnow(); 02145 02146 if (chan && peer) { 02147 pbx_builtin_setvar_helper(chan, "BRIDGEPEER", peer->name); 02148 pbx_builtin_setvar_helper(peer, "BRIDGEPEER", chan->name); 02149 } else if (chan) { 02150 pbx_builtin_setvar_helper(chan, "BLINDTRANSFER", NULL); 02151 } 02152 02153 set_bridge_features_on_config(config, pbx_builtin_getvar_helper(chan, "BRIDGE_FEATURES")); 02154 add_features_datastores(chan, peer, config); 02155 02156 /* This is an interesting case. One example is if a ringing channel gets redirected to 02157 * an extension that picks up a parked call. This will make sure that the call taken 02158 * out of parking gets told that the channel it just got bridged to is still ringing. */ 02159 if (chan->_state == AST_STATE_RINGING && peer->visible_indication != AST_CONTROL_RINGING) { 02160 ast_indicate(peer, AST_CONTROL_RINGING); 02161 } 02162 02163 if (monitor_ok) { 02164 const char *monitor_exec; 02165 struct ast_channel *src = NULL; 02166 if (!monitor_app) { 02167 if (!(monitor_app = pbx_findapp("Monitor"))) 02168 monitor_ok=0; 02169 } 02170 if ((monitor_exec = pbx_builtin_getvar_helper(chan, "AUTO_MONITOR"))) 02171 src = chan; 02172 else if ((monitor_exec = pbx_builtin_getvar_helper(peer, "AUTO_MONITOR"))) 02173 src = peer; 02174 if (monitor_app && src) { 02175 char *tmp = ast_strdupa(monitor_exec); 02176 pbx_exec(src, monitor_app, tmp); 02177 } 02178 } 02179 02180 set_config_flags(chan, peer, config); 02181 config->firstpass = 1; 02182 02183 /* Answer if need be */ 02184 if (ast_answer(chan)) 02185 return -1; 02186 02187 ast_copy_string(orig_channame,chan->name,sizeof(orig_channame)); 02188 ast_copy_string(orig_peername,peer->name,sizeof(orig_peername)); 02189 orig_peer_cdr = peer_cdr; 02190 02191 if (!chan_cdr || (chan_cdr && !ast_test_flag(chan_cdr, AST_CDR_FLAG_POST_DISABLED))) { 02192 02193 if (chan_cdr) { 02194 ast_set_flag(chan_cdr, AST_CDR_FLAG_MAIN); 02195 ast_cdr_update(chan); 02196 bridge_cdr = ast_cdr_dup(chan_cdr); 02197 /* rip any forked CDR's off of the chan_cdr and attach 02198 * them to the bridge_cdr instead */ 02199 bridge_cdr->next = chan_cdr->next; 02200 chan_cdr->next = NULL; 02201 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02202 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02203 if (peer_cdr && !ast_strlen_zero(peer_cdr->userfield)) { 02204 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 02205 } 02206 ast_cdr_setaccount(peer, chan->accountcode); 02207 } else { 02208 /* better yet, in a xfer situation, find out why the chan cdr got zapped (pun unintentional) */ 02209 bridge_cdr = ast_cdr_alloc(); /* this should be really, really rare/impossible? */ 02210 ast_copy_string(bridge_cdr->channel, chan->name, sizeof(bridge_cdr->channel)); 02211 ast_copy_string(bridge_cdr->dstchannel, peer->name, sizeof(bridge_cdr->dstchannel)); 02212 ast_copy_string(bridge_cdr->uniqueid, chan->uniqueid, sizeof(bridge_cdr->uniqueid)); 02213 ast_copy_string(bridge_cdr->lastapp, S_OR(chan->appl, ""), sizeof(bridge_cdr->lastapp)); 02214 ast_copy_string(bridge_cdr->lastdata, S_OR(chan->data, ""), sizeof(bridge_cdr->lastdata)); 02215 ast_cdr_setcid(bridge_cdr, chan); 02216 bridge_cdr->disposition = (chan->_state == AST_STATE_UP) ? AST_CDR_ANSWERED : AST_CDR_NOANSWER; 02217 bridge_cdr->amaflags = chan->amaflags ? chan->amaflags : ast_default_amaflags; 02218 ast_copy_string(bridge_cdr->accountcode, chan->accountcode, sizeof(bridge_cdr->accountcode)); 02219 /* Destination information */ 02220 ast_copy_string(bridge_cdr->dst, chan->exten, sizeof(bridge_cdr->dst)); 02221 ast_copy_string(bridge_cdr->dcontext, chan->context, sizeof(bridge_cdr->dcontext)); 02222 if (peer_cdr) { 02223 bridge_cdr->start = peer_cdr->start; 02224 ast_copy_string(bridge_cdr->userfield, peer_cdr->userfield, sizeof(bridge_cdr->userfield)); 02225 } else { 02226 ast_cdr_start(bridge_cdr); 02227 } 02228 } 02229 /* peer_cdr->answer will be set when a macro runs on the peer; 02230 in that case, the bridge answer will be delayed while the 02231 macro plays on the peer channel. The peer answered the call 02232 before the macro started playing. To the phone system, 02233 this is billable time for the call, even tho the caller 02234 hears nothing but ringing while the macro does its thing. */ 02235 02236 /* Another case where the peer cdr's time will be set, is when 02237 A self-parks by pickup up phone and dialing 700, then B 02238 picks up A by dialing its parking slot; there may be more 02239 practical paths that get the same result, tho... in which 02240 case you get the previous answer time from the Park... which 02241 is before the bridge's start time, so I added in the 02242 tvcmp check to the if below */ 02243 02244 if (peer_cdr && !ast_tvzero(peer_cdr->answer) && ast_tvcmp(peer_cdr->answer, bridge_cdr->start) >= 0) { 02245 ast_cdr_setanswer(bridge_cdr, peer_cdr->answer); 02246 ast_cdr_setdisposition(bridge_cdr, peer_cdr->disposition); 02247 if (chan_cdr) { 02248 ast_cdr_setanswer(chan_cdr, peer_cdr->answer); 02249 ast_cdr_setdisposition(chan_cdr, peer_cdr->disposition); 02250 } 02251 } else { 02252 ast_cdr_answer(bridge_cdr); 02253 if (chan_cdr) { 02254 ast_cdr_answer(chan_cdr); /* for the sake of cli status checks */ 02255 } 02256 } 02257 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT) && (chan_cdr || peer_cdr)) { 02258 if (chan_cdr) { 02259 ast_set_flag(chan_cdr, AST_CDR_FLAG_BRIDGED); 02260 } 02261 if (peer_cdr) { 02262 ast_set_flag(peer_cdr, AST_CDR_FLAG_BRIDGED); 02263 } 02264 } 02265 /* the DIALED flag may be set if a dialed channel is transfered 02266 * and then bridged to another channel. In order for the 02267 * bridge CDR to be written, the DIALED flag must not be 02268 * present. */ 02269 ast_clear_flag(bridge_cdr, AST_CDR_FLAG_DIALED); 02270 } 02271 02272 /* If we are bridging a call, stop worrying about forwarding loops. We presume that if 02273 * a call is being bridged, that the humans in charge know what they're doing. If they 02274 * don't, well, what can we do about that? */ 02275 clear_dialed_interfaces(chan); 02276 clear_dialed_interfaces(peer); 02277 02278 for (;;) { 02279 struct ast_channel *other; /* used later */ 02280 02281 res = ast_channel_bridge(chan, peer, config, &f, &who); 02282 02283 /* When frame is not set, we are probably involved in a situation 02284 where we've timed out. 02285 When frame is set, we'll come thru this code twice; once for DTMF_BEGIN 02286 and also for DTMF_END. If we flow into the following 'if' for both, then 02287 our wait times are cut in half, as both will subtract from the 02288 feature_timer. Not good! 02289 */ 02290 if (config->feature_timer && (!f || f->frametype == AST_FRAME_DTMF_END)) { 02291 /* Update time limit for next pass */ 02292 diff = ast_tvdiff_ms(ast_tvnow(), config->start_time); 02293 if (res == AST_BRIDGE_RETRY) { 02294 /* The feature fully timed out but has not been updated. Skip 02295 * the potential round error from the diff calculation and 02296 * explicitly set to expired. */ 02297 config->feature_timer = -1; 02298 } else { 02299 config->feature_timer -= diff; 02300 } 02301 02302 if (hasfeatures) { 02303 /* Running on backup config, meaning a feature might be being 02304 activated, but that's no excuse to keep things going 02305 indefinitely! */ 02306 if (backup_config.feature_timer && ((backup_config.feature_timer -= diff) <= 0)) { 02307 if (option_debug) 02308 ast_log(LOG_DEBUG, "Timed out, realtime this time!\n"); 02309 config->feature_timer = 0; 02310 who = chan; 02311 if (f) 02312 ast_frfree(f); 02313 f = NULL; 02314 res = 0; 02315 } else if (config->feature_timer <= 0) { 02316 /* Not *really* out of time, just out of time for 02317 digits to come in for features. */ 02318 if (option_debug) 02319 ast_log(LOG_DEBUG, "Timed out for feature!\n"); 02320 if (!ast_strlen_zero(peer_featurecode)) { 02321 ast_dtmf_stream(chan, peer, peer_featurecode, 0); 02322 memset(peer_featurecode, 0, sizeof(peer_featurecode)); 02323 } 02324 if (!ast_strlen_zero(chan_featurecode)) { 02325 ast_dtmf_stream(peer, chan, chan_featurecode, 0); 02326 memset(chan_featurecode, 0, sizeof(chan_featurecode)); 02327 } 02328 if (f) 02329 ast_frfree(f); 02330 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02331 if (!hasfeatures) { 02332 /* Restore original (possibly time modified) bridge config */ 02333 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02334 memset(&backup_config, 0, sizeof(backup_config)); 02335 } 02336 hadfeatures = hasfeatures; 02337 /* Continue as we were */ 02338 continue; 02339 } else if (!f) { 02340 /* The bridge returned without a frame and there is a feature in progress. 02341 * However, we don't think the feature has quite yet timed out, so just 02342 * go back into the bridge. */ 02343 continue; 02344 } 02345 } else { 02346 if (config->feature_timer <=0) { 02347 /* We ran out of time */ 02348 config->feature_timer = 0; 02349 who = chan; 02350 if (f) 02351 ast_frfree(f); 02352 f = NULL; 02353 res = 0; 02354 } 02355 } 02356 } 02357 if (res < 0) { 02358 if (!ast_test_flag(chan, AST_FLAG_ZOMBIE) && !ast_test_flag(peer, AST_FLAG_ZOMBIE) && !ast_check_hangup(chan) && !ast_check_hangup(peer)) 02359 ast_log(LOG_WARNING, "Bridge failed on channels %s and %s\n", chan->name, peer->name); 02360 goto before_you_go; 02361 } 02362 02363 if (!f || (f->frametype == AST_FRAME_CONTROL && 02364 (f->subclass == AST_CONTROL_HANGUP || f->subclass == AST_CONTROL_BUSY || 02365 f->subclass == AST_CONTROL_CONGESTION ) ) ) { 02366 res = -1; 02367 break; 02368 } 02369 /* many things should be sent to the 'other' channel */ 02370 other = (who == chan) ? peer : chan; 02371 if (f->frametype == AST_FRAME_CONTROL) { 02372 switch (f->subclass) { 02373 case AST_CONTROL_RINGING: 02374 case AST_CONTROL_FLASH: 02375 case -1: 02376 ast_indicate(other, f->subclass); 02377 break; 02378 case AST_CONTROL_HOLD: 02379 case AST_CONTROL_UNHOLD: 02380 ast_indicate_data(other, f->subclass, f->data, f->datalen); 02381 break; 02382 case AST_CONTROL_OPTION: 02383 aoh = f->data; 02384 /* Forward option Requests, but only ones we know are safe 02385 * These are ONLY sent by chan_iax2 and I'm not convinced that 02386 * they are useful. I haven't deleted them entirely because I 02387 * just am not sure of the ramifications of removing them. */ 02388 if (aoh && aoh->flag == AST_OPTION_FLAG_REQUEST) { 02389 switch (ntohs(aoh->option)) { 02390 case AST_OPTION_TONE_VERIFY: 02391 case AST_OPTION_TDD: 02392 case AST_OPTION_RELAXDTMF: 02393 case AST_OPTION_AUDIO_MODE: 02394 ast_channel_setoption(other, ntohs(aoh->option), aoh->data, 02395 f->datalen - sizeof(struct ast_option_header), 0); 02396 } 02397 } 02398 break; 02399 } 02400 } else if (f->frametype == AST_FRAME_DTMF_BEGIN) { 02401 struct ast_flags *cfg; 02402 char dtmfcode[2] = { f->subclass, }; 02403 size_t featurelen; 02404 02405 if (who == chan) { 02406 featurelen = strlen(chan_featurecode); 02407 cfg = &(config->features_caller); 02408 } else { 02409 featurelen = strlen(peer_featurecode); 02410 cfg = &(config->features_callee); 02411 } 02412 /* Take a peek if this (possibly) matches a feature. If not, just pass this 02413 * DTMF along untouched. If this is not the first digit of a multi-digit code 02414 * then we need to fall through and stream the characters if it matches */ 02415 if (featurelen == 0 02416 && feature_check(chan, cfg, &dtmfcode[0]) == FEATURE_RETURN_PASSDIGITS) { 02417 if (option_debug > 3) { 02418 ast_log(LOG_DEBUG, "Passing DTMF through, since it is not a feature code\n"); 02419 } 02420 ast_write(other, f); 02421 sendingdtmfdigit = 1; 02422 } else { 02423 /* If ast_opt_transmit_silence is set, then we need to make sure we are 02424 * transmitting something while we hold on to the DTMF waiting for a 02425 * feature. */ 02426 if (!silgen && ast_opt_transmit_silence) { 02427 silgen = ast_channel_start_silence_generator(other); 02428 } 02429 if (option_debug > 3) { 02430 ast_log(LOG_DEBUG, "Not passing DTMF through, since it may be a feature code\n"); 02431 } 02432 } 02433 } else if (f->frametype == AST_FRAME_DTMF) { 02434 char *featurecode; 02435 int sense; 02436 02437 hadfeatures = hasfeatures; 02438 /* This cannot overrun because the longest feature is one shorter than our buffer */ 02439 if (who == chan) { 02440 sense = FEATURE_SENSE_CHAN; 02441 featurecode = chan_featurecode; 02442 } else { 02443 sense = FEATURE_SENSE_PEER; 02444 featurecode = peer_featurecode; 02445 } 02446 02447 if (sendingdtmfdigit == 1) { 02448 /* We let the BEGIN go through happily, so let's not bother with the END, 02449 * since we already know it's not something we bother with */ 02450 ast_write(other, f); 02451 sendingdtmfdigit = 0; 02452 } else { 02453 /*! append the event to featurecode. we rely on the string being zero-filled, and 02454 * not overflowing it. 02455 * \todo XXX how do we guarantee the latter ? 02456 */ 02457 featurecode[strlen(featurecode)] = f->subclass; 02458 /* Get rid of the frame before we start doing "stuff" with the channels */ 02459 ast_frfree(f); 02460 f = NULL; 02461 if (silgen) { 02462 ast_channel_stop_silence_generator(other, silgen); 02463 silgen = NULL; 02464 } 02465 config->feature_timer = backup_config.feature_timer; 02466 res = feature_interpret(chan, peer, config, featurecode, sense); 02467 switch(res) { 02468 case FEATURE_RETURN_PASSDIGITS: 02469 ast_dtmf_stream(other, who, featurecode, 0); 02470 /* Fall through */ 02471 case FEATURE_RETURN_SUCCESS: 02472 memset(featurecode, 0, sizeof(chan_featurecode)); 02473 break; 02474 } 02475 if (res >= FEATURE_RETURN_PASSDIGITS) { 02476 res = 0; 02477 } else { 02478 break; 02479 } 02480 hasfeatures = !ast_strlen_zero(chan_featurecode) || !ast_strlen_zero(peer_featurecode); 02481 if (hadfeatures && !hasfeatures) { 02482 /* Restore backup */ 02483 memcpy(config, &backup_config, sizeof(struct ast_bridge_config)); 02484 memset(&backup_config, 0, sizeof(struct ast_bridge_config)); 02485 } else if (hasfeatures) { 02486 if (!hadfeatures) { 02487 /* Backup configuration */ 02488 memcpy(&backup_config, config, sizeof(struct ast_bridge_config)); 02489 /* Setup temporary config options */ 02490 config->play_warning = 0; 02491 ast_clear_flag(&(config->features_caller), AST_FEATURE_PLAY_WARNING); 02492 ast_clear_flag(&(config->features_callee), AST_FEATURE_PLAY_WARNING); 02493 config->warning_freq = 0; 02494 config->warning_sound = NULL; 02495 config->end_sound = NULL; 02496 config->start_sound = NULL; 02497 config->firstpass = 0; 02498 } 02499 config->start_time = ast_tvnow(); 02500 config->feature_timer = featuredigittimeout; 02501 if (option_debug) { 02502 ast_log(LOG_DEBUG, "Set time limit to %ld\n", config->feature_timer); 02503 } 02504 } 02505 } 02506 } 02507 if (f) 02508 ast_frfree(f); 02509 02510 } 02511 02512 before_you_go: 02513 /* Just in case something weird happened and we didn't clean up the silence generator... */ 02514 if (silgen) { 02515 ast_channel_stop_silence_generator(who == chan ? peer : chan, silgen); 02516 silgen = NULL; 02517 } 02518 if (ast_test_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT)) { 02519 ast_clear_flag(chan,AST_FLAG_BRIDGE_HANGUP_DONT); /* its job is done */ 02520 if (bridge_cdr) { 02521 ast_cdr_discard(bridge_cdr); 02522 /* QUESTION: should we copy bridge_cdr fields to the peer before we throw it away? */ 02523 } 02524 return res; /* if we shouldn't do the h-exten, we shouldn't do the bridge cdr, either! */ 02525 } 02526 02527 if (config->end_bridge_callback) { 02528 config->end_bridge_callback(config->end_bridge_callback_data); 02529 } 02530 02531 if (!ast_test_flag(&(config->features_caller),AST_FEATURE_NO_H_EXTEN) && 02532 ast_exists_extension(chan, chan->context, "h", 1, chan->cid.cid_num)) { 02533 struct ast_cdr *swapper = NULL; 02534 char savelastapp[AST_MAX_EXTENSION]; 02535 char savelastdata[AST_MAX_EXTENSION]; 02536 char save_exten[AST_MAX_EXTENSION]; 02537 int save_prio, spawn_error = 0; 02538 02539 autoloopflag = ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP); 02540 ast_set_flag(chan, AST_FLAG_IN_AUTOLOOP); 02541 if (bridge_cdr && ast_opt_end_cdr_before_h_exten) { 02542 ast_cdr_end(bridge_cdr); 02543 } 02544 /* swap the bridge cdr and the chan cdr for a moment, and let the endbridge 02545 dialplan code operate on it */ 02546 ast_channel_lock(chan); 02547 if (bridge_cdr) { 02548 swapper = chan->cdr; 02549 ast_copy_string(savelastapp, bridge_cdr->lastapp, sizeof(bridge_cdr->lastapp)); 02550 ast_copy_string(savelastdata, bridge_cdr->lastdata, sizeof(bridge_cdr->lastdata)); 02551 chan->cdr = bridge_cdr; 02552 } 02553 ast_copy_string(save_exten, chan->exten, sizeof(save_exten)); 02554 ast_copy_string(chan->exten, "h", sizeof(chan->exten)); 02555 save_prio = chan->priority; 02556 chan->priority = 1; 02557 ast_channel_unlock(chan); 02558 while(ast_exists_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num)) { 02559 if ((spawn_error = ast_spawn_extension(chan, chan->context, chan->exten, chan->priority, chan->cid.cid_num))) { 02560 /* Something bad happened, or a hangup has been requested. */ 02561 if (option_debug) 02562 ast_log(LOG_DEBUG, "Spawn h extension (%s,%s,%d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02563 if (option_verbose > 1) 02564 ast_verbose( VERBOSE_PREFIX_2 "Spawn h extension (%s, %s, %d) exited non-zero on '%s'\n", chan->context, chan->exten, chan->priority, chan->name); 02565 break; 02566 } 02567 chan->priority++; 02568 } 02569 /* swap it back */ 02570 ast_channel_lock(chan); 02571 ast_copy_string(chan->exten, save_exten, sizeof(chan->exten)); 02572 chan->priority = save_prio; 02573 if (bridge_cdr) { 02574 if (chan->cdr == bridge_cdr) { 02575 chan->cdr = swapper; 02576 } else { 02577 bridge_cdr = NULL; 02578 } 02579 } 02580 if (chan->priority != 1 || !spawn_error) { 02581 ast_set_flag(chan, AST_FLAG_BRIDGE_HANGUP_RUN); 02582 } 02583 ast_channel_unlock(chan); 02584 /* protect the lastapp/lastdata against the effects of the hangup/dialplan code */ 02585 if (bridge_cdr) { 02586 ast_copy_string(bridge_cdr->lastapp, savelastapp, sizeof(bridge_cdr->lastapp)); 02587 ast_copy_string(bridge_cdr->lastdata, savelastdata, sizeof(bridge_cdr->lastdata)); 02588 } 02589 ast_set2_flag(chan, autoloopflag, AST_FLAG_IN_AUTOLOOP); 02590 } 02591 02592 /* obey the NoCDR() wishes. -- move the DISABLED flag to the bridge CDR if it was set on the channel during the bridge... */ 02593 new_chan_cdr = pick_unlocked_cdr(chan->cdr); /* the proper chan cdr, if there are forked cdrs */ 02594 if (bridge_cdr && new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED)) { 02595 ast_set_flag(bridge_cdr, AST_CDR_FLAG_POST_DISABLED); 02596 } 02597 02598 /* we can post the bridge CDR at this point */ 02599 if (bridge_cdr) { 02600 ast_cdr_end(bridge_cdr); 02601 ast_cdr_detach(bridge_cdr); 02602 } 02603 02604 /* do a specialized reset on the beginning channel 02605 CDR's, if they still exist, so as not to mess up 02606 issues in future bridges; 02607 02608 Here are the rules of the game: 02609 1. The chan and peer channel pointers will not change 02610 during the life of the bridge. 02611 2. But, in transfers, the channel names will change. 02612 between the time the bridge is started, and the 02613 time the channel ends. 02614 Usually, when a channel changes names, it will 02615 also change CDR pointers. 02616 3. Usually, only one of the two channels (chan or peer) 02617 will change names. 02618 4. Usually, if a channel changes names during a bridge, 02619 it is because of a transfer. Usually, in these situations, 02620 it is normal to see 2 bridges running simultaneously, and 02621 it is not unusual to see the two channels that change 02622 swapped between bridges. 02623 5. After a bridge occurs, we have 2 or 3 channels' CDRs 02624 to attend to; if the chan or peer changed names, 02625 we have the before and after attached CDR's. 02626 */ 02627 02628 if (new_chan_cdr) { 02629 struct ast_channel *chan_ptr = NULL; 02630 02631 if (strcasecmp(orig_channame, chan->name) != 0) { 02632 /* old channel */ 02633 chan_ptr = ast_get_channel_by_name_locked(orig_channame); 02634 if (chan_ptr) { 02635 if (!ast_bridged_channel(chan_ptr)) { 02636 struct ast_cdr *cur; 02637 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02638 if (cur == chan_cdr) { 02639 break; 02640 } 02641 } 02642 if (cur) 02643 ast_cdr_specialized_reset(chan_cdr,0); 02644 } 02645 ast_channel_unlock(chan_ptr); 02646 } 02647 /* new channel */ 02648 ast_cdr_specialized_reset(new_chan_cdr,0); 02649 } else { 02650 ast_cdr_specialized_reset(chan->cdr, 0); /* nothing changed, reset the chan cdr */ 02651 } 02652 } 02653 02654 { 02655 struct ast_channel *chan_ptr = NULL; 02656 new_peer_cdr = pick_unlocked_cdr(peer->cdr); /* the proper chan cdr, if there are forked cdrs */ 02657 if (new_chan_cdr && ast_test_flag(new_chan_cdr, AST_CDR_FLAG_POST_DISABLED) && new_peer_cdr && !ast_test_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED)) 02658 ast_set_flag(new_peer_cdr, AST_CDR_FLAG_POST_DISABLED); /* DISABLED is viral-- it will propagate across a bridge */ 02659 if (strcasecmp(orig_peername, peer->name) != 0) { 02660 /* old channel */ 02661 chan_ptr = ast_get_channel_by_name_locked(orig_peername); 02662 if (chan_ptr) { 02663 if (!ast_bridged_channel(chan_ptr)) { 02664 struct ast_cdr *cur; 02665 for (cur = chan_ptr->cdr; cur; cur = cur->next) { 02666 if (cur == peer_cdr) { 02667 break; 02668 } 02669 } 02670 if (cur) 02671 ast_cdr_specialized_reset(peer_cdr,0); 02672 } 02673 ast_channel_unlock(chan_ptr); 02674 } 02675 /* new channel */ 02676 if (new_peer_cdr) { 02677 ast_cdr_specialized_reset(new_peer_cdr, 0); 02678 } 02679 } else { 02680 ast_cdr_specialized_reset(peer->cdr, 0); /* nothing changed, reset the peer cdr */ 02681 } 02682 } 02683 02684 return res; 02685 }
| int ast_feature_detect | ( | struct ast_channel * | chan, | |
| struct ast_flags * | features, | |||
| char * | code, | |||
| struct ast_call_feature * | feature | |||
| ) |
detect a feature before bridging
| chan | ||
| ast_flags | ptr | |
| char | ptr of input code |
| ast_call_feature | ptr to be set if found |
Definition at line 1649 of file res_features.c.
References FEATURE_INTERPRET_DETECT, and feature_interpret_helper().
Referenced by detect_disconnect().
01649 { 01650 01651 return feature_interpret_helper(chan, NULL, NULL, code, 0, NULL, features, FEATURE_INTERPRET_DETECT, feature); 01652 }
| int ast_masq_park_call | ( | struct ast_channel * | rchan, | |
| struct ast_channel * | host, | |||
| int | timeout, | |||
| int * | extout | |||
| ) |
Park a call via a masqueraded channel.
| rchan | the real channel to be parked | |
| host | the channel to have the parking read to Masquerade the channel rchan into a new, empty channel which is then parked with ast_park_call | |
| timeout | is a timeout in milliseconds | |
| extout | is a parameter to an int that will hold the parked location, or NULL if you want |
Definition at line 785 of file res_features.c.
References masq_park_call().
Referenced by handle_exec(), manager_park(), mgcp_ss(), parkandannounce_exec(), rpt_exec(), and ss_thread().
00786 { 00787 return masq_park_call(rchan, peer, timeout, extout, 0, NULL); 00788 }
| int ast_park_call | ( | struct ast_channel * | chan, | |
| struct ast_channel * | peer, | |||
| int | timeout, | |||
| int * | extout | |||
| ) |
Park a call and read back parked location.
| chan | the channel to actually be parked | |
| host | the channel which will have the parked location read to Park the channel chan, and read back the parked location to the host. If the call is not picked up within a specified period of time, then the call will return to the last step that it was in (in terms of exten, priority and context) | |
| timeout | is a timeout in milliseconds | |
| extout | is a parameter to an int that will hold the parked location, or NULL if you want |
Definition at line 724 of file res_features.c.
References park_call_full().
Referenced by iax_park_thread(), and sip_park_thread().
00725 { 00726 return park_call_full(chan, peer, timeout, extout, NULL, NULL); 00727 }
| char* ast_parking_ext | ( | void | ) |
Determine system parking extension Returns the call parking extension for drivers that provide special call parking help.
Definition at line 376 of file res_features.c.
Referenced by builtin_atxfer(), builtin_blindtransfer(), dp_lookup(), handle_request_refer(), load_config(), mgcp_ss(), socket_process(), and ss_thread().
00377 { 00378 return parking_ext; 00379 }
| int ast_pickup_call | ( | struct ast_channel * | chan | ) |
Pickup a call.
Definition at line 3418 of file res_features.c.
References ast_channel::_state, ast_channel_unlock, ast_channel_walk_locked(), AST_FLAG_ZOMBIE, ast_log(), AST_STATE_RING, AST_STATE_RINGING, ast_test_flag, ast_channel::callgroup, LOG_DEBUG, LOG_WARNING, ast_channel::masq, ast_channel::name, option_debug, ast_channel::pbx, pickup_do(), and ast_channel::pickupgroup.
Referenced by cb_events(), handle_request_invite(), mgcp_ss(), and ss_thread().
03419 { 03420 struct ast_channel *cur = NULL; 03421 int res = -1; 03422 03423 while ( (cur = ast_channel_walk_locked(cur)) != NULL) { 03424 if (!cur->pbx && 03425 (cur != chan) && 03426 (chan->pickupgroup & cur->callgroup) && 03427 ((cur->_state == AST_STATE_RINGING) || 03428 (cur->_state == AST_STATE_RING)) && 03429 !cur->masq && 03430 !ast_test_flag(cur, AST_FLAG_ZOMBIE)) { 03431 break; 03432 } 03433 ast_channel_unlock(cur); 03434 } 03435 if (cur) { 03436 res = pickup_do(chan, cur); 03437 if (res) { 03438 ast_log(LOG_WARNING, "pickup %s failed by %s\n", cur->name, chan->name); 03439 } 03440 ast_channel_unlock(cur); 03441 } else { 03442 if (option_debug) 03443 ast_log(LOG_DEBUG, "No call pickup possible... for %s\n", chan->name); 03444 } 03445 return res; 03446 }
| char* ast_pickup_ext | ( | void | ) |
Determine system call pickup extension.
Definition at line 381 of file res_features.c.
Referenced by cb_events(), get_destination(), handle_request_invite(), handle_showfeatures(), mgcp_ss(), and ss_thread().
00382 { 00383 return pickup_ext; 00384 }
| void ast_register_feature | ( | struct ast_call_feature * | feature | ) |
register new feature into feature_set
| feature | an ast_call_feature object which contains a keysequence and a callback function which is called when this keysequence is pressed during a call. |
Definition at line 1375 of file res_features.c.
References ast_log(), AST_RWLIST_INSERT_HEAD, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_verbose(), ast_call_feature::feature_entry, LOG_NOTICE, option_verbose, ast_call_feature::sname, and VERBOSE_PREFIX_2.
Referenced by load_config().
01376 { 01377 if (!feature) { 01378 ast_log(LOG_NOTICE,"You didn't pass a feature!\n"); 01379 return; 01380 } 01381 01382 AST_RWLIST_WRLOCK(&feature_list); 01383 AST_RWLIST_INSERT_HEAD(&feature_list, feature, feature_entry); 01384 AST_RWLIST_UNLOCK(&feature_list); 01385 01386 if (option_verbose >= 2) { 01387 ast_verbose(VERBOSE_PREFIX_2 "Registered Feature '%s'\n",feature->sname); 01388 } 01389 }
| void ast_unregister_feature | ( | struct ast_call_feature * | feature | ) |
unregister feature from feature_set
| feature | the ast_call_feature object which was registered before |
Definition at line 1392 of file res_features.c.
References AST_RWLIST_REMOVE, AST_RWLIST_UNLOCK, AST_RWLIST_WRLOCK, ast_call_feature::feature_entry, and free.
01393 { 01394 if (!feature) 01395 return; 01396 01397 AST_RWLIST_WRLOCK(&feature_list); 01398 AST_RWLIST_REMOVE(&feature_list, feature, feature_entry); 01399 AST_RWLIST_UNLOCK(&feature_list); 01400 01401 free(feature); 01402 }
1.5.6