ast_json_object_update(json_object, extras);
}
+ ast_bridge_lock(conference->bridge);
msg = ast_bridge_blob_create(type,
conference->bridge,
chan,
json_object);
+ ast_bridge_unlock(conference->bridge);
+
if (!msg) {
return;
}
* \brief Generate a snapshot of the bridge state. This is an ao2 object, so
* ao2_cleanup() to deallocate.
*
+ * \pre Bridge is locked
+ *
* \param bridge The bridge from which to generate a snapshot
*
* \retval AO2 refcounted snapshot on success
* \since 12
* \brief Publish the state of a bridge
*
+ * \pre Bridge is locked
+ *
* \param bridge The bridge for which to publish state
*/
void ast_bridge_publish_state(struct ast_bridge *bridge);
* \since 12
* \brief Publish a bridge merge
*
+ * \pre Bridges involved are locked
+ *
* \param to The bridge to which channels are being added
* \param from The bridge from which channels are being removed
*/
/*!
* \brief Publish a blind transfer event
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Whether the blind transfer was initiated externally (e.g. via AMI or native protocol)
* \param result The success or failure of the transfer
* Publish an \ref ast_attended_transfer_message with the dest_type set to
* \c AST_ATTENDED_TRANSFER_DEST_FAIL.
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer. Will always be a type of failure.
*
* In either case, two bridges enter, one leaves.
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer.
* this results from merging two bridges together. The difference is that a
* transferer channel survives the bridge merge
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer.
* \li A transferee channel leaving a bridge to run an app
* \li A bridge of transferees running an app (via a local channel)
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer.
* When this type of transfer occurs, the two bridges continue to exist after the
* transfer and a local channel is used to link the two bridges together.
*
- * \pre No channels or bridges are locked
+ * \pre Bridges involved are locked. Channels involved are not locked.
*
* \param is_external Indicates if the transfer was initiated externally
* \param result The result of the transfer.
{
RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup);
+ ast_bridge_lock(bridge);
snapshot = ast_bridge_snapshot_create(bridge);
+ ast_bridge_unlock(bridge);
+
if (!snapshot) {
return NULL;
}
{
if (bridge) {
bridge->construction_completed = 1;
+ ast_bridge_lock(bridge);
ast_bridge_publish_state(bridge);
+ ast_bridge_unlock(bridge);
if (!ao2_link(bridges, bridge)) {
ast_bridge_destroy(bridge, 0);
bridge = NULL;
struct ast_bridge_channel_pair pair;
pair.channel = transferer;
pair.bridge = bridge;
+ ast_bridge_lock(bridge);
ast_bridge_publish_blind_transfer(is_external, result, &pair, context, exten);
+ ast_bridge_unlock(bridge);
}
enum ast_transfer_result ast_bridge_transfer_blind(int is_external,
RAII_VAR(struct ast_bridge_channel *, to_target_bridge_channel, NULL, ao2_cleanup);
RAII_VAR(struct ao2_container *, channels, NULL, ao2_cleanup);
RAII_VAR(struct ast_channel *, transferee, NULL, ao2_cleanup);
- struct ast_bridge *the_bridge;
+ struct ast_bridge *the_bridge = NULL;
struct ast_channel *chan_bridged;
struct ast_channel *chan_unbridged;
int transfer_prohibited;
set_transfer_variables_all(to_transferee, channels, 1);
if (do_bridge_transfer) {
- res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, &publication);
- goto end;
+ ast_bridge_lock(the_bridge);
+ res = attended_transfer_bridge(chan_bridged, chan_unbridged, the_bridge, NULL, &publication);
+ ast_bridge_unlock(the_bridge);
+ goto end;
}
transferee = get_transferee(channels, chan_bridged);
ast_bridge_remove(the_bridge, chan_bridged);
+ ast_bridge_lock(the_bridge);
publish_attended_transfer_app(&publication, app);
+ ast_bridge_unlock(the_bridge);
res = AST_BRIDGE_TRANSFER_SUCCESS;
end:
* All failure paths have deferred publishing a stasis message until this point
*/
if (res != AST_BRIDGE_TRANSFER_SUCCESS) {
+ if (to_transferee_bridge && to_target_bridge) {
+ ast_bridge_lock_both(to_transferee_bridge, to_target_bridge);
+ } else if (the_bridge) {
+ ast_bridge_lock(the_bridge);
+ }
+
publish_attended_transfer_fail(&publication, res);
+
+ if (to_transferee_bridge && to_target_bridge) {
+ ast_bridge_unlock(to_transferee_bridge);
+ ast_bridge_unlock(to_target_bridge);
+ } else if (the_bridge) {
+ ast_bridge_unlock(the_bridge);
+ }
}
stasis_publish_data_cleanup(&publication);
return res;
.bridge = props->target_bridge,
};
+ ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
ast_bridge_publish_attended_transfer_bridge_merge(0, AST_BRIDGE_TRANSFER_SUCCESS,
&transferee, &transfer_target, props->transferee_bridge);
+ ast_bridge_unlock(transferee.bridge);
+ ast_bridge_unlock(transfer_target.bridge);
}
/*!
.bridge = props->transferee_bridge,
};
+ ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
ast_bridge_publish_attended_transfer_threeway(0, AST_BRIDGE_TRANSFER_SUCCESS,
&transferee, &transfer_target, &threeway);
+ ast_bridge_unlock(transferee.bridge);
+ ast_bridge_unlock(transfer_target.bridge);
}
/*!
.bridge = props->target_bridge,
};
+ ast_bridge_lock_both(transferee.bridge, transfer_target.bridge);
ast_bridge_publish_attended_transfer_fail(0, AST_BRIDGE_TRANSFER_FAIL,
&transferee, &transfer_target);
+ ast_bridge_unlock(transferee.bridge);
+ ast_bridge_unlock(transfer_target.bridge);
}
/*!
return;
}
+ ast_bridge_lock(bridge);
snapshot = ast_bridge_snapshot_create(bridge);
+ ast_bridge_unlock(bridge);
+
if (!snapshot) {
ast_ari_response_error(
response, 500, "Internal Error",
return;
}
+ ast_bridge_lock(bridge);
snapshot = ast_bridge_snapshot_create(bridge);
+ ast_bridge_unlock(bridge);
+
if (!snapshot) {
ast_ari_response_error(
response, 500, "Internal Error",
pair.bridge = bridge;
pair.channel = chan_alice;
+ ast_bridge_lock(bridge);
ast_bridge_publish_blind_transfer(1, AST_BRIDGE_TRANSFER_SUCCESS,
&pair, "transfer_context", "transfer_extension");
+ ast_bridge_unlock(bridge);
BLINDTRANSFER_EVENT(chan_alice, bridge, "transfer_extension", "transfer_context");
BRIDGE_EXIT(chan_alice, bridge);