diff options
-rw-r--r-- | apps/app_agent_pool.c | 6 | ||||
-rw-r--r-- | apps/confbridge/conf_chan_announce.c | 3 | ||||
-rw-r--r-- | channels/chan_sip.c | 3 | ||||
-rw-r--r-- | include/asterisk/bridge.h | 42 | ||||
-rw-r--r-- | include/asterisk/bridge_channel.h | 2 | ||||
-rw-r--r-- | include/asterisk/features.h | 14 | ||||
-rw-r--r-- | main/bridge.c | 26 | ||||
-rw-r--r-- | main/bridge_basic.c | 9 | ||||
-rw-r--r-- | main/bridge_channel.c | 2 | ||||
-rw-r--r-- | main/channel.c | 127 | ||||
-rw-r--r-- | main/core_local.c | 2 | ||||
-rw-r--r-- | main/core_unreal.c | 3 | ||||
-rw-r--r-- | main/features.c | 9 | ||||
-rw-r--r-- | res/parking/parking_applications.c | 3 | ||||
-rw-r--r-- | res/parking/parking_bridge_features.c | 3 | ||||
-rw-r--r-- | res/parking/parking_tests.c | 39 | ||||
-rw-r--r-- | res/res_pjsip_refer.c | 3 | ||||
-rw-r--r-- | res/stasis/control.c | 13 | ||||
-rw-r--r-- | tests/test_cdr.c | 50 | ||||
-rw-r--r-- | tests/test_cel.c | 6 |
20 files changed, 235 insertions, 130 deletions
diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c index 54a0a4a50..4493b2e09 100644 --- a/apps/app_agent_pool.c +++ b/apps/app_agent_pool.c @@ -1509,7 +1509,8 @@ static void agent_run(struct agent_pvt *agent, struct ast_channel *logged) * want to put the agent back into the holding bridge for the * next caller. */ - ast_bridge_join(holding, logged, NULL, &features, NULL, 1); + ast_bridge_join(holding, logged, NULL, &features, NULL, + AST_BRIDGE_JOIN_PASS_REFERENCE); if (logged != agent->logged) { /* This channel is no longer the logged in agent. */ break; @@ -1890,7 +1891,8 @@ static int agent_request_exec(struct ast_channel *chan, const char *data) } ast_indicate(chan, AST_CONTROL_RINGING); - ast_bridge_join(caller_bridge, chan, NULL, &caller_features, NULL, 1); + ast_bridge_join(caller_bridge, chan, NULL, &caller_features, NULL, + AST_BRIDGE_JOIN_PASS_REFERENCE); ast_bridge_features_cleanup(&caller_features); return -1; diff --git a/apps/confbridge/conf_chan_announce.c b/apps/confbridge/conf_chan_announce.c index df48aed33..952ef988e 100644 --- a/apps/confbridge/conf_chan_announce.c +++ b/apps/confbridge/conf_chan_announce.c @@ -196,7 +196,8 @@ int conf_announce_channel_push(struct ast_channel *ast) ast_set_flag(&features->feature_flags, AST_BRIDGE_CHANNEL_FLAG_IMMOVABLE); /* Impart the output channel into the bridge */ - if (ast_bridge_impart(p->bridge, chan, NULL, features, 0)) { + if (ast_bridge_impart(p->bridge, chan, NULL, features, + AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); return -1; diff --git a/channels/chan_sip.c b/channels/chan_sip.c index bec53b776..d118adc67 100644 --- a/channels/chan_sip.c +++ b/channels/chan_sip.c @@ -24986,7 +24986,8 @@ static int handle_invite_replaces(struct sip_pvt *p, struct sip_request *req, ast_channel_unlock(replaces_chan); if (bridge) { - if (ast_bridge_impart(bridge, c, replaces_chan, NULL, 1)) { + if (ast_bridge_impart(bridge, c, replaces_chan, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(c); } } else { diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index d351b0fea..610e0f944 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -422,6 +422,13 @@ int ast_bridge_destroy(struct ast_bridge *bridge, int cause); */ void ast_bridge_notify_masquerade(struct ast_channel *chan); +enum ast_bridge_join_flags { + /*! The bridge reference is being passed by the caller. */ + AST_BRIDGE_JOIN_PASS_REFERENCE = (1 << 0), + /*! The initial bridge join does not cause a COLP exchange. */ + AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP = (1 << 1), +}; + /*! * \brief Join (blocking) a channel to a bridge * @@ -430,7 +437,7 @@ void ast_bridge_notify_masquerade(struct ast_channel *chan); * \param swap Channel to swap out if swapping * \param features Bridge features structure * \param tech_args Optional Bridging tech optimization parameters for this channel. - * \param pass_reference TRUE if the bridge reference is being passed by the caller. + * \param flags defined by enum ast_bridge_join_flags. * * \note Absolutely _NO_ locks should be held before calling * this function since it blocks. @@ -441,7 +448,7 @@ void ast_bridge_notify_masquerade(struct ast_channel *chan); * Example usage: * * \code - * ast_bridge_join(bridge, chan, NULL, NULL, NULL, 0); + * ast_bridge_join(bridge, chan, NULL, NULL, NULL, AST_BRIDGE_JOIN_PASS_REFERENCE); * \endcode * * This adds a channel pointed to by the chan pointer to the bridge pointed to by @@ -460,7 +467,18 @@ int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, - int pass_reference); + enum ast_bridge_join_flags flags); + +enum ast_bridge_impart_flags { + /*! Field describing what the caller can do with the channel after it is imparted. */ + AST_BRIDGE_IMPART_CHAN_MASK = (1 << 0), + /*! The caller wants to reclaim the channel using ast_bridge_depart(). */ + AST_BRIDGE_IMPART_CHAN_DEPARTABLE = (0 << 0), + /*! The caller is passing channel control entirely to the bridging system. */ + AST_BRIDGE_IMPART_CHAN_INDEPENDENT = (1 << 0), + /*! The initial bridge join does not cause a COLP exchange. */ + AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP = (1 << 1), +}; /*! * \brief Impart (non-blocking) a channel onto a bridge @@ -469,7 +487,7 @@ int ast_bridge_join(struct ast_bridge *bridge, * \param chan Channel to impart (The channel reference is stolen if impart successful.) * \param swap Channel to swap out if swapping. NULL if not swapping. * \param features Bridge features structure. - * \param independent TRUE if caller does not want to reclaim the channel using ast_bridge_depart(). + * \param flags defined by enum ast_bridge_impart_flags. * * \note The features parameter must be NULL or obtained by * ast_bridge_features_new(). You must not dereference features @@ -478,12 +496,12 @@ int ast_bridge_join(struct ast_bridge *bridge, * \note chan is locked by this function. * * \retval 0 on success - * \retval -1 on failure + * \retval -1 on failure (Caller still has ownership of chan) * * Example usage: * * \code - * ast_bridge_impart(bridge, chan, NULL, NULL, 0); + * ast_bridge_impart(bridge, chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_INDEPENDENT); * \endcode * * \details @@ -501,20 +519,26 @@ int ast_bridge_join(struct ast_bridge *bridge, * features structure can be specified in the features * parameter. * - * \note If you impart a channel as not independent you MUST + * \note If you impart a channel with + * AST_BRIDGE_IMPART_CHAN_DEPARTABLE you MUST * ast_bridge_depart() the channel if this call succeeds. The * bridge channel thread is created join-able. The implication * is that the channel is special and will not behave like a * normal channel. * - * \note If you impart a channel as independent you must not + * \note If you impart a channel with + * AST_BRIDGE_IMPART_CHAN_INDEPENDENT you must not * ast_bridge_depart() the channel. The bridge channel thread * is created non-join-able. The channel must be treated as if * it were placed into the bridge by ast_bridge_join(). * Channels placed into a bridge by ast_bridge_join() are * removed by a third party using ast_bridge_remove(). */ -int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int independent); +int ast_bridge_impart(struct ast_bridge *bridge, + struct ast_channel *chan, + struct ast_channel *swap, + struct ast_bridge_features *features, + enum ast_bridge_impart_flags flags) attribute_warn_unused_result; /*! * \brief Depart a channel from a bridge diff --git a/include/asterisk/bridge_channel.h b/include/asterisk/bridge_channel.h index de67347bb..73c657019 100644 --- a/include/asterisk/bridge_channel.h +++ b/include/asterisk/bridge_channel.h @@ -122,6 +122,8 @@ struct ast_bridge_channel { unsigned int just_joined:1; /*! TRUE if the channel is suspended from the bridge. */ unsigned int suspended:1; + /*! TRUE if the COLP update on initial join is inhibited. */ + unsigned int inhibit_colp:1; /*! TRUE if the channel must wait for an ast_bridge_depart to reclaim the channel. */ unsigned int depart_wait:1; /* ^-- These flags change while the bridge is locked or before the channel is in the bridge. */ diff --git a/include/asterisk/features.h b/include/asterisk/features.h index af9b77749..b63124c2f 100644 --- a/include/asterisk/features.h +++ b/include/asterisk/features.h @@ -39,8 +39,14 @@ enum { AST_FEATURE_FLAG_BYBOTH = (3 << 3), }; -/*! \brief Bridge a call, optionally allowing redirection */ -int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct ast_bridge_config *config); +/*! + * \brief Bridge a call, optionally allowing redirection + * + * \note The function caller is assumed to have already done the + * COLP exchange for the initial bridging of the two channels if + * it was desired. + */ +int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config); /*! * \brief Bridge a call, and add additional flags to the bridge @@ -53,6 +59,10 @@ int ast_bridge_call(struct ast_channel *chan, struct ast_channel *peer,struct as * \param peer The called channel * \param config Bridge configuration for the channels * \param flags Additional flags to set on the created bridge + * + * \note The function caller is assumed to have already done the + * COLP exchange for the initial bridging of the two channels if + * it was desired. */ int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *peer, struct ast_bridge_config *config, unsigned int flags); diff --git a/main/bridge.c b/main/bridge.c index 45820c3fa..19350ed84 100644 --- a/main/bridge.c +++ b/main/bridge.c @@ -1433,13 +1433,13 @@ int ast_bridge_join(struct ast_bridge *bridge, struct ast_channel *swap, struct ast_bridge_features *features, struct ast_bridge_tech_optimizations *tech_args, - int pass_reference) + enum ast_bridge_join_flags flags) { struct ast_bridge_channel *bridge_channel; int res = 0; bridge_channel = bridge_channel_internal_alloc(bridge); - if (pass_reference) { + if (flags & AST_BRIDGE_JOIN_PASS_REFERENCE) { ao2_ref(bridge, -1); } if (!bridge_channel) { @@ -1468,6 +1468,7 @@ int ast_bridge_join(struct ast_bridge *bridge, bridge_channel->chan = chan; bridge_channel->swap = swap; bridge_channel->features = features; + bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP); if (!res) { res = bridge_channel_internal_join(bridge_channel); @@ -1546,7 +1547,11 @@ static void *bridge_channel_ind_thread(void *data) return NULL; } -int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struct ast_channel *swap, struct ast_bridge_features *features, int independent) +int ast_bridge_impart(struct ast_bridge *bridge, + struct ast_channel *chan, + struct ast_channel *swap, + struct ast_bridge_features *features, + enum ast_bridge_impart_flags flags) { int res = 0; struct ast_bridge_channel *bridge_channel; @@ -1585,12 +1590,14 @@ int ast_bridge_impart(struct ast_bridge *bridge, struct ast_channel *chan, struc bridge_channel->chan = chan; bridge_channel->swap = swap; bridge_channel->features = features; - bridge_channel->depart_wait = independent ? 0 : 1; + bridge_channel->inhibit_colp = !!(flags & AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP); + bridge_channel->depart_wait = + (flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_DEPARTABLE; bridge_channel->callid = ast_read_threadstorage_callid(); /* Actually create the thread that will handle the channel */ if (!res) { - if (independent) { + if ((flags & AST_BRIDGE_IMPART_CHAN_MASK) == AST_BRIDGE_IMPART_CHAN_INDEPENDENT) { res = ast_pthread_create_detached(&bridge_channel->thread, NULL, bridge_channel_ind_thread, bridge_channel); } else { @@ -2191,7 +2198,8 @@ int ast_bridge_add_channel(struct ast_bridge *bridge, struct ast_channel *chan, ast_answer(yanked_chan); } ast_channel_ref(yanked_chan); - if (ast_bridge_impart(bridge, yanked_chan, NULL, features, 1)) { + if (ast_bridge_impart(bridge, yanked_chan, NULL, features, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { /* It is possible for us to yank a channel and have some other * thread start a PBX on the channl after we yanked it. In particular, * this can theoretically happen on the ;2 of a Local channel if we @@ -3638,7 +3646,8 @@ static enum ast_transfer_result blind_transfer_bridge(struct ast_channel *transf ast_hangup(local); return AST_BRIDGE_TRANSFER_FAIL; } - if (ast_bridge_impart(bridge, local, transferer, NULL, 1)) { + if (ast_bridge_impart(bridge, local, transferer, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(local); return AST_BRIDGE_TRANSFER_FAIL; } @@ -3808,7 +3817,8 @@ static enum ast_transfer_result attended_transfer_bridge(struct ast_channel *cha return AST_BRIDGE_TRANSFER_FAIL; } - if (ast_bridge_impart(bridge1, local_chan, chan1, NULL, 1)) { + if (ast_bridge_impart(bridge1, local_chan, chan1, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(local_chan); return AST_BRIDGE_TRANSFER_FAIL; } diff --git a/main/bridge_basic.c b/main/bridge_basic.c index 103099d8b..aaa77caea 100644 --- a/main/bridge_basic.c +++ b/main/bridge_basic.c @@ -2289,7 +2289,8 @@ static enum attended_transfer_state recalling_exit(struct attended_transfer_prop */ ast_bridge_features_ds_set(props->recall_target, &props->transferer_features); ast_channel_ref(props->recall_target); - if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, 1)) { + if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(props->recall_target); return TRANSFER_FAIL; } @@ -2380,7 +2381,8 @@ static int retransfer_enter(struct attended_transfer_properties *props) } ast_channel_ref(props->recall_target); - if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, 1)) { + if (ast_bridge_impart(props->transferee_bridge, props->recall_target, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_log(LOG_ERROR, "Unable to place recall target into bridge\n"); ast_hangup(props->recall_target); return -1; @@ -3067,7 +3069,8 @@ static int feature_attended_transfer(struct ast_bridge_channel *bridge_channel, * choice is to give it a bump */ ast_channel_ref(props->transfer_target); - if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL, 1)) { + if (ast_bridge_impart(props->target_bridge, props->transfer_target, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_log(LOG_ERROR, "Unable to place transfer target into bridge.\n"); ast_stream_and_wait(bridge_channel->chan, props->failsound, AST_DIGIT_NONE); ast_bridge_channel_write_unhold(bridge_channel); diff --git a/main/bridge_channel.c b/main/bridge_channel.c index 1aa82abfc..2917e83c5 100644 --- a/main/bridge_channel.c +++ b/main/bridge_channel.c @@ -2000,7 +2000,7 @@ int bridge_channel_internal_join(struct ast_bridge_channel *bridge_channel) BRIDGE_CHANNEL_STATE_END_NO_DISSOLVE, bridge_channel->bridge->cause); res = -1; } - bridge_reconfigured(bridge_channel->bridge, 1); + bridge_reconfigured(bridge_channel->bridge, !bridge_channel->inhibit_colp); if (bridge_channel->state == BRIDGE_CHANNEL_STATE_WAIT) { /* diff --git a/main/channel.c b/main/channel.c index f085d31e8..7ba3e6c39 100644 --- a/main/channel.c +++ b/main/channel.c @@ -4380,6 +4380,89 @@ const char *ast_channel_amaflags2string(enum ama_flags flag) } } +/*! + * \internal + * \brief Preprocess connected line update. + * \since 12.0.0 + * + * \param chan channel to change the indication + * \param data pointer to payload data + * \param datalen size of payload data + * + * \note This function assumes chan is locked. + * + * \retval 0 keep going. + * \retval -1 quit now. + */ +static int indicate_connected_line(struct ast_channel *chan, const void *data, size_t datalen) +{ + struct ast_party_connected_line *chan_connected = ast_channel_connected(chan); + struct ast_party_connected_line *chan_indicated = ast_channel_connected_indicated(chan); + struct ast_party_connected_line connected; + unsigned char current[1024]; + unsigned char proposed[1024]; + int current_size; + int proposed_size; + int res; + + ast_party_connected_line_set_init(&connected, chan_connected); + res = ast_connected_line_parse_data(data, datalen, &connected); + if (!res) { + ast_channel_set_connected_line(chan, &connected, NULL); + } + ast_party_connected_line_free(&connected); + if (res) { + return -1; + } + + current_size = ast_connected_line_build_data(current, sizeof(current), + chan_indicated, NULL); + proposed_size = ast_connected_line_build_data(proposed, sizeof(proposed), + chan_connected, NULL); + if (current_size == -1 || proposed_size == -1) { + return -1; + } + + if (current_size == proposed_size && !memcmp(current, proposed, current_size)) { + ast_debug(1, "%s: Dropping redundant connected line update \"%s\" <%s>.\n", + ast_channel_name(chan), + S_COR(chan_connected->id.name.valid, chan_connected->id.name.str, ""), + S_COR(chan_connected->id.number.valid, chan_connected->id.number.str, "")); + return -1; + } + + ast_party_connected_line_copy(chan_indicated, chan_connected); + return 0; +} + +/*! + * \internal + * \brief Preprocess redirecting update. + * \since 12.0.0 + * + * \param chan channel to change the indication + * \param data pointer to payload data + * \param datalen size of payload data + * + * \note This function assumes chan is locked. + * + * \retval 0 keep going. + * \retval -1 quit now. + */ +static int indicate_redirecting(struct ast_channel *chan, const void *data, size_t datalen) +{ + struct ast_party_redirecting redirecting; + int res; + + ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(chan)); + res = ast_redirecting_parse_data(data, datalen, &redirecting); + if (!res) { + ast_channel_set_redirecting(chan, &redirecting, NULL); + } + ast_party_redirecting_free(&redirecting); + return res ? -1 : 0; +} + int ast_indicate_data(struct ast_channel *chan, int _condition, const void *data, size_t datalen) { @@ -4414,7 +4497,6 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, /* who knows what we will get back! the anticipation is killing me. */ if (!(awesome_frame = ast_framehook_list_write_event(ast_channel_framehooks(chan), awesome_frame)) || awesome_frame->frametype != AST_FRAME_CONTROL) { - res = 0; goto indicate_cleanup; } @@ -4426,46 +4508,15 @@ int ast_indicate_data(struct ast_channel *chan, int _condition, switch (condition) { case AST_CONTROL_CONNECTED_LINE: - { - struct ast_party_connected_line connected; - unsigned char current[1024], proposed[1024]; - int current_size, proposed_size; - - ast_party_connected_line_set_init(&connected, ast_channel_connected(chan)); - res = ast_connected_line_parse_data(data, datalen, &connected); - if (!res) { - ast_channel_set_connected_line(chan, &connected, NULL); - } - ast_party_connected_line_free(&connected); - - current_size = ast_connected_line_build_data(current, sizeof(current), - ast_channel_connected_indicated(chan), NULL); - proposed_size = ast_connected_line_build_data(proposed, sizeof(proposed), - ast_channel_connected(chan), NULL); - - if (current_size == -1 || proposed_size == -1) { - goto indicate_cleanup; - } - - if (!res && current_size == proposed_size && - !memcmp(current, proposed, current_size)) { - goto indicate_cleanup; - } - - ast_party_connected_line_copy(ast_channel_connected_indicated(chan), - ast_channel_connected(chan)); + if (indicate_connected_line(chan, data, datalen)) { + res = 0; + goto indicate_cleanup; } break; case AST_CONTROL_REDIRECTING: - { - struct ast_party_redirecting redirecting; - - ast_party_redirecting_set_init(&redirecting, ast_channel_redirecting(chan)); - res = ast_redirecting_parse_data(data, datalen, &redirecting); - if (!res) { - ast_channel_set_redirecting(chan, &redirecting, NULL); - } - ast_party_redirecting_free(&redirecting); + if (indicate_redirecting(chan, data, datalen)) { + res = 0; + goto indicate_cleanup; } break; case AST_CONTROL_HOLD: diff --git a/main/core_local.c b/main/core_local.c index 88bf3ae4c..d4ec06d9f 100644 --- a/main/core_local.c +++ b/main/core_local.c @@ -687,7 +687,7 @@ static int local_call(struct ast_channel *ast, const char *dest, int timeout) publish_local_bridge_message(p); ast_answer(chan); res = ast_bridge_impart(p->action.bridge.join, chan, p->action.bridge.swap, - p->action.bridge.features, 1); + p->action.bridge.features, AST_BRIDGE_IMPART_CHAN_INDEPENDENT); ao2_ref(p->action.bridge.join, -1); p->action.bridge.join = NULL; ao2_cleanup(p->action.bridge.swap); diff --git a/main/core_unreal.c b/main/core_unreal.c index 07748b442..7e457f484 100644 --- a/main/core_unreal.c +++ b/main/core_unreal.c @@ -758,7 +758,8 @@ int ast_unreal_channel_push_to_bridge(struct ast_channel *ast, struct ast_bridge ast_set_flag(&features->feature_flags, flags); /* Impart the semi2 channel into the bridge */ - if (ast_bridge_impart(bridge, chan, NULL, features, 1)) { + if (ast_bridge_impart(bridge, chan, NULL, features, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_bridge_features_destroy(features); ast_channel_unref(chan); return -1; diff --git a/main/features.c b/main/features.c index 32fccf7a6..cb4abbb44 100644 --- a/main/features.c +++ b/main/features.c @@ -675,7 +675,8 @@ int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *pee ast_bridge_basic_set_flags(bridge, flags); /* Put peer into the bridge */ - if (ast_bridge_impart(bridge, peer, NULL, peer_features, 1)) { + if (ast_bridge_impart(bridge, peer, NULL, peer_features, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT | AST_BRIDGE_IMPART_INHIBIT_JOIN_COLP)) { ast_bridge_destroy(bridge, 0); ast_bridge_features_cleanup(&chan_features); bridge_failed_peer_goto(chan, peer); @@ -683,7 +684,8 @@ int ast_bridge_call_with_flags(struct ast_channel *chan, struct ast_channel *pee } /* Join bridge */ - ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, 1); + ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, + AST_BRIDGE_JOIN_PASS_REFERENCE | AST_BRIDGE_JOIN_INHIBIT_JOIN_COLP); /* * If the bridge was broken for a hangup that isn't real, then @@ -1129,7 +1131,8 @@ static int bridge_exec(struct ast_channel *chan, const char *data) goto done; } - ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, 1); + ast_bridge_join(bridge, chan, NULL, &chan_features, NULL, + AST_BRIDGE_JOIN_PASS_REFERENCE); ast_bridge_features_cleanup(&chan_features); diff --git a/res/parking/parking_applications.c b/res/parking/parking_applications.c index e34b403e2..fc74ac2be 100644 --- a/res/parking/parking_applications.c +++ b/res/parking/parking_applications.c @@ -639,7 +639,8 @@ static int parked_call_app_exec(struct ast_channel *chan, const char *data) } /* Now we should try to join the new bridge ourselves... */ - ast_bridge_join(retrieval_bridge, chan, NULL, &chan_features, NULL, 1); + ast_bridge_join(retrieval_bridge, chan, NULL, &chan_features, NULL, + AST_BRIDGE_JOIN_PASS_REFERENCE); ast_bridge_features_cleanup(&chan_features); diff --git a/res/parking/parking_bridge_features.c b/res/parking/parking_bridge_features.c index 1f0237b9e..0e5e05d8f 100644 --- a/res/parking/parking_bridge_features.c +++ b/res/parking/parking_bridge_features.c @@ -316,7 +316,8 @@ static int parking_blind_transfer_park(struct ast_bridge_channel *bridge_channel return -1; } - if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL, 1)) { + if (ast_bridge_impart(bridge_channel->bridge, transfer_chan, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { ast_hangup(transfer_chan); return -1; } diff --git a/res/parking/parking_tests.c b/res/parking/parking_tests.c index 57edd37ce..e046ca8cf 100644 --- a/res/parking/parking_tests.c +++ b/res/parking/parking_tests.c @@ -82,6 +82,12 @@ static void safe_channel_release(struct ast_channel *chan) ast_channel_release(chan); } +static void do_sleep(struct timespec *to_sleep) +{ + while ((nanosleep(to_sleep, to_sleep) == -1) && (errno == EINTR)) { + } +} + static int fake_fixup(struct ast_channel *clonechan, struct ast_channel *original) { return 0; @@ -99,7 +105,6 @@ static struct parking_lot *generate_test_parking_lot(const char *name, int low_s struct parking_lot *test_lot; test_cfg = parking_lot_cfg_create(name); - if (!test_cfg) { return NULL; } @@ -120,7 +125,6 @@ static struct parking_lot *generate_test_parking_lot(const char *name, int low_s } test_lot = parking_lot_build_or_update(test_cfg, 1); - if (!test_lot) { return NULL; } @@ -195,7 +199,6 @@ AST_TEST_DEFINE(park_call) RAII_VAR(struct ast_channel *, chan_alice, NULL, safe_channel_release); RAII_VAR(struct ast_bridge *, parking_bridge, NULL, ao2_cleanup); - struct ast_bridge_features chan_features; struct timespec to_sleep = {1, 0}; switch (cmd) { @@ -219,7 +222,6 @@ AST_TEST_DEFINE(park_call) } chan_alice = create_alice_channel(); - if (!chan_alice) { ast_test_status_update(test, "Failed to create test channel to park. Test failed.\n"); dispose_test_lot(test_lot, 1); @@ -227,27 +229,23 @@ AST_TEST_DEFINE(park_call) } ast_channel_state_set(chan_alice, AST_STATE_UP); - pbx_builtin_setvar_helper(chan_alice, "BLINDTRANSFER", ast_channel_name(chan_alice)); parking_bridge = park_application_setup(chan_alice, chan_alice, TEST_LOT_NAME, NULL); - if (!parking_bridge) { ast_test_status_update(test, "Failed to get the parking bridge for '%s'. Test failed.\n", TEST_LOT_NAME); dispose_test_lot(test_lot, 1); return AST_TEST_FAIL; } - if (ast_bridge_features_init(&chan_features)) { - ast_bridge_features_cleanup(&chan_features); - ast_test_status_update(test, "Failed to initialize bridge features. Test failed.\n"); + if (ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) { + ast_test_status_update(test, "Failed to impart alice into parking lot. Test failed.\n"); dispose_test_lot(test_lot, 1); return AST_TEST_FAIL; } - ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL, 0); - - while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); + do_sleep(&to_sleep); ast_bridge_depart(chan_alice); @@ -255,6 +253,7 @@ AST_TEST_DEFINE(park_call) if (dispose_test_lot(test_lot, 1)) { ast_test_status_update(test, "Found parking lot in container after attempted removal. Test failed.\n"); + return AST_TEST_FAIL; } return AST_TEST_PASS; @@ -353,8 +352,6 @@ AST_TEST_DEFINE(retrieve_call) .resolution = PARK_ANSWERED, }; - struct ast_bridge_features chan_features; - switch (cmd) { case TEST_INIT: info->name = "park_retrieve"; @@ -383,7 +380,6 @@ AST_TEST_DEFINE(retrieve_call) } ast_channel_state_set(chan_alice, AST_STATE_UP); - pbx_builtin_setvar_helper(chan_alice, "BLINDTRANSFER", ast_channel_name(chan_alice)); parking_bridge = park_application_setup(chan_alice, chan_alice, TEST_LOT_NAME, NULL); @@ -393,26 +389,23 @@ AST_TEST_DEFINE(retrieve_call) return AST_TEST_FAIL; } - if (ast_bridge_features_init(&chan_features)) { - ast_bridge_features_cleanup(&chan_features); - ast_test_status_update(test, "Failed to initialize bridge features. Test failed.\n"); + if (ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_DEPARTABLE)) { + ast_test_status_update(test, "Failed to impart alice into parking lot. Test failed.\n"); dispose_test_lot(test_lot, 1); return AST_TEST_FAIL; } - ast_bridge_impart(parking_bridge, chan_alice, NULL, NULL, 0); - - while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); + do_sleep(&to_sleep); retrieved_user = parking_lot_retrieve_parked_user(test_lot, 701); if (!retrieved_user) { ast_test_status_update(test, "Failed to retrieve the parked user from the expected parking space. Test failed.\n"); - failure = 1; goto test_cleanup; } - ast_test_status_update(test, "Successfully retrieved parked user from the parking lot. Validating user data. Test failed.\n"); + ast_test_status_update(test, "Successfully retrieved parked user from the parking lot. Validating user data.\n"); if (!parked_users_match(retrieved_user, &expected_user, test)) { ast_test_status_update(test, "Parked user validation failed\n"); diff --git a/res/res_pjsip_refer.c b/res/res_pjsip_refer.c index a2ad3bf4d..cca5a7c39 100644 --- a/res/res_pjsip_refer.c +++ b/res/res_pjsip_refer.c @@ -768,7 +768,8 @@ static int refer_incoming_invite_request(struct ast_sip_session *session, struct response = 500; } } else { - if (ast_bridge_impart(invite.bridge, session->channel, invite.channel, NULL, 1)) { + if (ast_bridge_impart(invite.bridge, session->channel, invite.channel, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { response = 500; } } diff --git a/res/stasis/control.c b/res/stasis/control.c index 8530abd9f..2c3a10980 100644 --- a/res/stasis/control.c +++ b/res/stasis/control.c @@ -117,7 +117,6 @@ static struct stasis_app_command *exec_command( command_fn = command_fn ? : noop_cb; command = command_create(command_fn, data); - if (!command) { return NULL; } @@ -166,7 +165,6 @@ static void *app_control_dial(struct stasis_app_control *control, ast_dial_set_global_timeout(dial, dial_data->timeout); res = ast_dial_run(dial, NULL, 0); - if (res != AST_DIAL_RESULT_ANSWERED || !(new_chan = ast_dial_answered_steal(dial))) { return NULL; } @@ -176,8 +174,12 @@ static void *app_control_dial(struct stasis_app_control *control, return NULL; } - ast_bridge_impart(bridge, new_chan, NULL, NULL, 1); - stasis_app_control_add_channel_to_bridge(control, bridge); + if (ast_bridge_impart(bridge, new_chan, NULL, NULL, + AST_BRIDGE_IMPART_CHAN_INDEPENDENT)) { + ast_hangup(new_chan); + } else { + stasis_app_control_add_channel_to_bridge(control, bridge); + } return NULL; } @@ -566,8 +568,7 @@ static void *app_control_add_channel_to_bridge( chan, NULL, /* swap channel */ NULL, /* features */ - 0); /* independent - false allows us to ast_bridge_depart() */ - + AST_BRIDGE_IMPART_CHAN_DEPARTABLE); if (res != 0) { ast_log(LOG_ERROR, "Error adding channel to bridge\n"); ast_channel_pbx_set(chan, control->pbx); diff --git a/tests/test_cdr.c b/tests/test_cdr.c index 4fd1bdb90..f1e577e76 100644 --- a/tests/test_cdr.c +++ b/tests/test_cdr.c @@ -559,7 +559,7 @@ AST_TEST_DEFINE(test_cdr_outbound_bridged_call) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); chan_bob = ast_channel_alloc(0, AST_STATE_DOWN, NULL, NULL, "200", NULL, NULL, ast_channel_linkedid(chan_alice), 0, CHANNEL_TECH_NAME "/Bob"); ast_copy_string(bob_expected.linkedid, ast_channel_linkedid(chan_bob), sizeof(bob_expected.linkedid)); @@ -576,7 +576,7 @@ AST_TEST_DEFINE(test_cdr_outbound_bridged_call) while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); @@ -686,7 +686,7 @@ AST_TEST_DEFINE(test_cdr_single_bridge) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); @@ -761,7 +761,7 @@ AST_TEST_DEFINE(test_cdr_single_bridge_continue) ast_test_validate(test, bridge_one != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge_one, chan, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge_one, chan, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); @@ -844,14 +844,14 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_a) bridge = ast_bridge_basic_new(); ast_test_validate(test, bridge != NULL); - ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); EMULATE_APP_DATA(chan_bob, 1, "Answer", ""); ast_setstate(chan_bob, AST_STATE_UP); EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); - ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); ast_bridge_depart(chan_alice); @@ -937,10 +937,10 @@ AST_TEST_DEFINE(test_cdr_single_twoparty_bridge_b) EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); ast_bridge_depart(chan_alice); @@ -1056,21 +1056,21 @@ AST_TEST_DEFINE(test_cdr_single_multiparty_bridge) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); EMULATE_APP_DATA(chan_bob, 1, "Answer", ""); ast_setstate(chan_bob, AST_STATE_UP); EMULATE_APP_DATA(chan_bob, 2, "Bridge", ""); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); EMULATE_APP_DATA(chan_charlie, 1, "Answer", ""); ast_setstate(chan_charlie, AST_STATE_UP); EMULATE_APP_DATA(chan_charlie, 2, "Bridge", ""); - ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); @@ -1669,8 +1669,8 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_a) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0); - ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_caller, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_callee, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); @@ -1743,9 +1743,9 @@ AST_TEST_DEFINE(test_cdr_dial_answer_twoparty_bridge_b) bridge = ast_bridge_basic_new(); ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_callee, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_callee, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_caller, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_caller, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); ast_bridge_depart(chan_caller); ast_bridge_depart(chan_callee); @@ -1902,18 +1902,18 @@ AST_TEST_DEFINE(test_cdr_dial_answer_multiparty) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_charlie, NULL, NULL, 0)); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_charlie, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_david, NULL, NULL, 0)); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_david, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0)); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_test_validate(test, 0 == ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0)); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_test_validate(test, 0 == ast_bridge_depart(chan_alice)); - ast_test_validate(test, 0 == ast_bridge_depart(chan_bob)); - ast_test_validate(test, 0 == ast_bridge_depart(chan_charlie)); - ast_test_validate(test, 0 == ast_bridge_depart(chan_david)); + ast_test_validate(test, !ast_bridge_depart(chan_alice)); + ast_test_validate(test, !ast_bridge_depart(chan_bob)); + ast_test_validate(test, !ast_bridge_depart(chan_charlie)); + ast_test_validate(test, !ast_bridge_depart(chan_david)); HANGUP_CHANNEL(chan_alice, AST_CAUSE_NORMAL); HANGUP_CHANNEL(chan_bob, AST_CAUSE_NORMAL); @@ -1992,9 +1992,9 @@ AST_TEST_DEFINE(test_cdr_park) ast_test_validate(test, bridge != NULL); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_alice, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_alice, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); - ast_bridge_impart(bridge, chan_bob, NULL, NULL, 0); + ast_test_validate(test, !ast_bridge_impart(bridge, chan_bob, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); while ((nanosleep(&to_sleep, &to_sleep) == -1) && (errno == EINTR)); ast_bridge_depart(chan_alice); ast_bridge_depart(chan_bob); diff --git a/tests/test_cel.c b/tests/test_cel.c index d440ebf53..c084ce394 100644 --- a/tests/test_cel.c +++ b/tests/test_cel.c @@ -109,7 +109,7 @@ static void do_sleep(void) } while (0) #define BRIDGE_EXIT(channel, bridge) do { \ - ast_test_validate(test, 0 == ast_bridge_depart(channel)); \ + ast_test_validate(test, !ast_bridge_depart(channel)); \ BRIDGE_EXIT_EVENT(channel, bridge); \ mid_test_sync(); \ } while (0) @@ -129,7 +129,7 @@ static void do_sleep(void) } while (0) #define BRIDGE_ENTER(channel, bridge) do { \ - ast_test_validate(test, 0 == ast_bridge_impart(bridge, channel, NULL, NULL, 0)); \ + ast_test_validate(test, !ast_bridge_impart(bridge, channel, NULL, NULL, AST_BRIDGE_IMPART_CHAN_DEPARTABLE)); \ do_sleep(); \ BRIDGE_ENTER_EVENT(channel, bridge); \ mid_test_sync(); \ @@ -1417,7 +1417,7 @@ AST_TEST_DEFINE(test_cel_dial_pickup) ast_test_validate(test, extra != NULL); APPEND_EVENT(chan_callee, AST_CEL_PICKUP, NULL, extra); - ast_test_validate(test, 0 == ast_do_pickup(chan_charlie, chan_callee)); + ast_test_validate(test, !ast_do_pickup(chan_charlie, chan_callee)); } /* Hang up the masqueraded zombie */ |