diff options
Diffstat (limited to 'res')
-rw-r--r-- | res/ari/ari_model_validators.c | 379 | ||||
-rw-r--r-- | res/ari/ari_model_validators.h | 63 | ||||
-rw-r--r-- | res/res_stasis.c | 2 | ||||
-rw-r--r-- | res/stasis/app.c | 155 |
4 files changed, 573 insertions, 26 deletions
diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c index b1482fa87..88cfc2697 100644 --- a/res/ari/ari_model_validators.c +++ b/res/ari/ari_model_validators.c @@ -1552,6 +1552,373 @@ ari_validator ast_ari_validate_application_replaced_fn(void) return ast_ari_validate_application_replaced; } +int ast_ari_validate_bridge_attended_transfer(struct ast_json *json) +{ + int res = 1; + struct ast_json_iter *iter; + int has_type = 0; + int has_application = 0; + int has_destination_type = 0; + int has_is_external = 0; + int has_result = 0; + int has_transferer_first_leg = 0; + int has_transferer_second_leg = 0; + + for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_type = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field type failed validation\n"); + res = 0; + } + } else + if (strcmp("application", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_application = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field application failed validation\n"); + res = 0; + } + } else + if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_date( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field timestamp failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_application", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_application failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_bridge", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_bridge failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_link_first_leg", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_link_first_leg failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_link_second_leg", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_link_second_leg failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_threeway_bridge", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_bridge( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_threeway_bridge failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_threeway_channel", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_threeway_channel failed validation\n"); + res = 0; + } + } else + if (strcmp("destination_type", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_destination_type = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field destination_type failed validation\n"); + res = 0; + } + } else + if (strcmp("is_external", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_is_external = 1; + prop_is_valid = ast_ari_validate_boolean( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field is_external failed validation\n"); + res = 0; + } + } else + if (strcmp("result", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_result = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field result failed validation\n"); + res = 0; + } + } else + if (strcmp("transferer_first_leg", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_transferer_first_leg = 1; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field transferer_first_leg failed validation\n"); + res = 0; + } + } else + if (strcmp("transferer_first_leg_bridge", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_bridge( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field transferer_first_leg_bridge failed validation\n"); + res = 0; + } + } else + if (strcmp("transferer_second_leg", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_transferer_second_leg = 1; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field transferer_second_leg failed validation\n"); + res = 0; + } + } else + if (strcmp("transferer_second_leg_bridge", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_bridge( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer field transferer_second_leg_bridge failed validation\n"); + res = 0; + } + } else + { + ast_log(LOG_ERROR, + "ARI BridgeAttendedTransfer has undocumented field %s\n", + ast_json_object_iter_key(iter)); + res = 0; + } + } + + if (!has_type) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field type\n"); + res = 0; + } + + if (!has_application) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field application\n"); + res = 0; + } + + if (!has_destination_type) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field destination_type\n"); + res = 0; + } + + if (!has_is_external) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field is_external\n"); + res = 0; + } + + if (!has_result) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field result\n"); + res = 0; + } + + if (!has_transferer_first_leg) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field transferer_first_leg\n"); + res = 0; + } + + if (!has_transferer_second_leg) { + ast_log(LOG_ERROR, "ARI BridgeAttendedTransfer missing required field transferer_second_leg\n"); + res = 0; + } + + return res; +} + +ari_validator ast_ari_validate_bridge_attended_transfer_fn(void) +{ + return ast_ari_validate_bridge_attended_transfer; +} + +int ast_ari_validate_bridge_blind_transfer(struct ast_json *json) +{ + int res = 1; + struct ast_json_iter *iter; + int has_type = 0; + int has_application = 0; + int has_channel = 0; + int has_context = 0; + int has_exten = 0; + int has_is_external = 0; + int has_result = 0; + + for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { + if (strcmp("type", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_type = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field type failed validation\n"); + res = 0; + } + } else + if (strcmp("application", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_application = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field application failed validation\n"); + res = 0; + } + } else + if (strcmp("timestamp", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_date( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field timestamp failed validation\n"); + res = 0; + } + } else + if (strcmp("bridge", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + prop_is_valid = ast_ari_validate_bridge( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field bridge failed validation\n"); + res = 0; + } + } else + if (strcmp("channel", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_channel = 1; + prop_is_valid = ast_ari_validate_channel( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field channel failed validation\n"); + res = 0; + } + } else + if (strcmp("context", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_context = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field context failed validation\n"); + res = 0; + } + } else + if (strcmp("exten", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_exten = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field exten failed validation\n"); + res = 0; + } + } else + if (strcmp("is_external", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_is_external = 1; + prop_is_valid = ast_ari_validate_boolean( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field is_external failed validation\n"); + res = 0; + } + } else + if (strcmp("result", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_result = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer field result failed validation\n"); + res = 0; + } + } else + { + ast_log(LOG_ERROR, + "ARI BridgeBlindTransfer has undocumented field %s\n", + ast_json_object_iter_key(iter)); + res = 0; + } + } + + if (!has_type) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field type\n"); + res = 0; + } + + if (!has_application) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field application\n"); + res = 0; + } + + if (!has_channel) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field channel\n"); + res = 0; + } + + if (!has_context) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field context\n"); + res = 0; + } + + if (!has_exten) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field exten\n"); + res = 0; + } + + if (!has_is_external) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field is_external\n"); + res = 0; + } + + if (!has_result) { + ast_log(LOG_ERROR, "ARI BridgeBlindTransfer missing required field result\n"); + res = 0; + } + + return res; +} + +ari_validator ast_ari_validate_bridge_blind_transfer_fn(void) +{ + return ast_ari_validate_bridge_blind_transfer; +} + int ast_ari_validate_bridge_created(struct ast_json *json) { int res = 1; @@ -3211,6 +3578,12 @@ int ast_ari_validate_event(struct ast_json *json) if (strcmp("ApplicationReplaced", discriminator) == 0) { return ast_ari_validate_application_replaced(json); } else + if (strcmp("BridgeAttendedTransfer", discriminator) == 0) { + return ast_ari_validate_bridge_attended_transfer(json); + } else + if (strcmp("BridgeBlindTransfer", discriminator) == 0) { + return ast_ari_validate_bridge_blind_transfer(json); + } else if (strcmp("BridgeCreated", discriminator) == 0) { return ast_ari_validate_bridge_created(json); } else @@ -3364,6 +3737,12 @@ int ast_ari_validate_message(struct ast_json *json) if (strcmp("ApplicationReplaced", discriminator) == 0) { return ast_ari_validate_application_replaced(json); } else + if (strcmp("BridgeAttendedTransfer", discriminator) == 0) { + return ast_ari_validate_bridge_attended_transfer(json); + } else + if (strcmp("BridgeBlindTransfer", discriminator) == 0) { + return ast_ari_validate_bridge_blind_transfer(json); + } else if (strcmp("BridgeCreated", discriminator) == 0) { return ast_ari_validate_bridge_created(json); } else diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h index ffe003903..c299724eb 100644 --- a/res/ari/ari_model_validators.h +++ b/res/ari/ari_model_validators.h @@ -537,6 +537,42 @@ int ast_ari_validate_application_replaced(struct ast_json *json); ari_validator ast_ari_validate_application_replaced_fn(void); /*! + * \brief Validator for BridgeAttendedTransfer. + * + * Notification that an attended transfer has occurred. + * + * \param json JSON object to validate. + * \returns True (non-zero) if valid. + * \returns False (zero) if invalid. + */ +int ast_ari_validate_bridge_attended_transfer(struct ast_json *json); + +/*! + * \brief Function pointer to ast_ari_validate_bridge_attended_transfer(). + * + * See \ref ast_ari_model_validators.h for more details. + */ +ari_validator ast_ari_validate_bridge_attended_transfer_fn(void); + +/*! + * \brief Validator for BridgeBlindTransfer. + * + * Notification that a blind transfer has occurred. + * + * \param json JSON object to validate. + * \returns True (non-zero) if valid. + * \returns False (zero) if invalid. + */ +int ast_ari_validate_bridge_blind_transfer(struct ast_json *json); + +/*! + * \brief Function pointer to ast_ari_validate_bridge_blind_transfer(). + * + * See \ref ast_ari_model_validators.h for more details. + */ +ari_validator ast_ari_validate_bridge_blind_transfer_fn(void); + +/*! * \brief Validator for BridgeCreated. * * Notification that a bridge has been created. @@ -1137,6 +1173,33 @@ ari_validator ast_ari_validate_application_fn(void); * - type: string (required) * - application: string (required) * - timestamp: Date + * BridgeAttendedTransfer + * - type: string (required) + * - application: string (required) + * - timestamp: Date + * - destination_application: string + * - destination_bridge: string + * - destination_link_first_leg: Channel + * - destination_link_second_leg: Channel + * - destination_threeway_bridge: Bridge + * - destination_threeway_channel: Channel + * - destination_type: string (required) + * - is_external: boolean (required) + * - result: string (required) + * - transferer_first_leg: Channel (required) + * - transferer_first_leg_bridge: Bridge + * - transferer_second_leg: Channel (required) + * - transferer_second_leg_bridge: Bridge + * BridgeBlindTransfer + * - type: string (required) + * - application: string (required) + * - timestamp: Date + * - bridge: Bridge + * - channel: Channel (required) + * - context: string (required) + * - exten: string (required) + * - is_external: boolean (required) + * - result: string (required) * BridgeCreated * - type: string (required) * - application: string (required) diff --git a/res/res_stasis.c b/res/res_stasis.c index 32de9a041..f6fc0ac6e 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -591,7 +591,7 @@ struct ast_bridge *stasis_app_bridge_create(const char *type, const char *name) int capabilities; int flags = AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM | AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_SWAP_INHIBIT_TO - | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED; + | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY; if (ast_strlen_zero(type) || !strcmp(type, "mixing")) { capabilities = AST_BRIDGE_CAPABILITY_1TO1MIX | diff --git a/res/stasis/app.c b/res/stasis/app.c index 8e9872aec..dc322b6bf 100644 --- a/res/stasis/app.c +++ b/res/stasis/app.c @@ -41,8 +41,8 @@ struct stasis_app { struct stasis_topic *topic; /*! Router for handling messages forwarded to \a topic. */ struct stasis_message_router *router; - /*! Subscription to watch for bridge merge messages */ - struct stasis_subscription *bridge_merge_sub; + /*! Router for handling messages to the bridge all \a topic. */ + struct stasis_message_router *bridge_router; /*! Container of the channel forwards to this app's topic. */ struct ao2_container *forwards; /*! Callback function for this application. */ @@ -255,7 +255,7 @@ static void app_dtor(void *obj) ast_verb(1, "Destroying Stasis app %s\n", app->name); ast_assert(app->router == NULL); - ast_assert(app->bridge_merge_sub == NULL); + ast_assert(app->bridge_router == NULL); ao2_cleanup(app->topic); app->topic = NULL; @@ -589,37 +589,127 @@ static void sub_bridge_update_handler(void *data, app_send(app, json); } + +/*! \brief Helper function for determining if the application is subscribed to a given entity */ +static int bridge_app_subscribed(struct stasis_app *app, const char *uniqueid) +{ + struct app_forwards *forwards = NULL; + + forwards = ao2_find(app->forwards, uniqueid, OBJ_SEARCH_KEY); + if (!forwards) { + return 0; + } + + ao2_ref(forwards, -1); + return 1; +} + static void bridge_merge_handler(void *data, struct stasis_subscription *sub, struct stasis_message *message) { struct stasis_app *app = data; struct ast_bridge_merge_message *merge; - RAII_VAR(struct app_forwards *, forwards, NULL, ao2_cleanup); - if (stasis_subscription_final_message(sub, message)) { - ao2_cleanup(app); + merge = stasis_message_data(message); + + /* Find out if we're subscribed to either bridge */ + if (bridge_app_subscribed(app, merge->from->uniqueid) || + bridge_app_subscribed(app, merge->to->uniqueid)) { + /* Forward the message to the app */ + stasis_publish(app->topic, message); } +} - if (stasis_message_type(message) != ast_bridge_merge_message_type()) { - return; +/*! \brief Callback function for checking if channels in a bridge are subscribed to */ +static int bridge_app_subscribed_involved(struct stasis_app *app, struct ast_bridge_snapshot *snapshot) +{ + int subscribed = 0; + struct ao2_iterator iter; + char *uniqueid; + + if (bridge_app_subscribed(app, snapshot->uniqueid)) { + return 1; } - merge = stasis_message_data(message); + iter = ao2_iterator_init(snapshot->channels, 0); + for (; (uniqueid = ao2_iterator_next(&iter)); ao2_ref(uniqueid, -1)) { + if (bridge_app_subscribed(app, uniqueid)) { + subscribed = 1; + ao2_ref(uniqueid, -1); + break; + } + } + ao2_iterator_destroy(&iter); - /* Find out if we're subscribed to either bridge */ - forwards = ao2_find(app->forwards, merge->from->uniqueid, - OBJ_SEARCH_KEY); - if (!forwards) { - forwards = ao2_find(app->forwards, merge->to->uniqueid, - OBJ_SEARCH_KEY); + return subscribed; +} + +static void bridge_blind_transfer_handler(void *data, struct stasis_subscription *sub, + struct stasis_message *message) +{ + struct stasis_app *app = data; + struct ast_bridge_blob *blob = stasis_message_data(message); + + if (bridge_app_subscribed(app, blob->channel->uniqueid) || + bridge_app_subscribed_involved(app, blob->bridge)) { + stasis_publish(app->topic, message); } +} - if (!forwards) { - return; +static void bridge_attended_transfer_handler(void *data, struct stasis_subscription *sub, + struct stasis_message *message) +{ + struct stasis_app *app = data; + struct ast_attended_transfer_message *transfer_msg = stasis_message_data(message); + int subscribed = 0; + + subscribed = bridge_app_subscribed(app, transfer_msg->to_transferee.channel_snapshot->uniqueid); + if (!subscribed) { + subscribed = bridge_app_subscribed(app, transfer_msg->to_transfer_target.channel_snapshot->uniqueid); + } + if (!subscribed && transfer_msg->to_transferee.bridge_snapshot) { + subscribed = bridge_app_subscribed_involved(app, transfer_msg->to_transferee.bridge_snapshot); + } + if (!subscribed && transfer_msg->to_transfer_target.bridge_snapshot) { + subscribed = bridge_app_subscribed_involved(app, transfer_msg->to_transfer_target.bridge_snapshot); + } + + if (!subscribed) { + switch (transfer_msg->dest_type) { + case AST_ATTENDED_TRANSFER_DEST_BRIDGE_MERGE: + subscribed = bridge_app_subscribed(app, transfer_msg->dest.bridge); + break; + case AST_ATTENDED_TRANSFER_DEST_LINK: + subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[0]->uniqueid); + if (!subscribed) { + subscribed = bridge_app_subscribed(app, transfer_msg->dest.links[1]->uniqueid); + } + break; + break; + case AST_ATTENDED_TRANSFER_DEST_THREEWAY: + subscribed = bridge_app_subscribed_involved(app, transfer_msg->dest.threeway.bridge_snapshot); + if (!subscribed) { + subscribed = bridge_app_subscribed(app, transfer_msg->dest.threeway.channel_snapshot->uniqueid); + } + break; + default: + break; + } + } + + if (subscribed) { + stasis_publish(app->topic, message); } +} - /* Forward the message to the app */ - stasis_publish(app->topic, message); +static void bridge_default_handler(void *data, struct stasis_subscription *sub, + struct stasis_message *message) +{ + struct stasis_app *app = data; + + if (stasis_subscription_final_message(sub, message)) { + ao2_cleanup(app); + } } struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *data) @@ -652,12 +742,27 @@ struct stasis_app *app_create(const char *name, stasis_app_cb handler, void *dat return NULL; } - app->bridge_merge_sub = stasis_subscribe(ast_bridge_topic_all(), - bridge_merge_handler, app); - if (!app->bridge_merge_sub) { + app->bridge_router = stasis_message_router_create(ast_bridge_topic_all()); + if (!app->bridge_router) { + return NULL; + } + + res |= stasis_message_router_add(app->bridge_router, + ast_bridge_merge_message_type(), bridge_merge_handler, app); + + res |= stasis_message_router_add(app->bridge_router, + ast_blind_transfer_type(), bridge_blind_transfer_handler, app); + + res |= stasis_message_router_add(app->bridge_router, + ast_attended_transfer_type(), bridge_attended_transfer_handler, app); + + res |= stasis_message_router_set_default(app->bridge_router, + bridge_default_handler, app); + + if (res != 0) { return NULL; } - /* Subscription holds a reference */ + /* Bridge router holds a reference */ ao2_ref(app, +1); app->router = stasis_message_router_create(app->topic); @@ -739,8 +844,8 @@ void app_shutdown(struct stasis_app *app) stasis_message_router_unsubscribe(app->router); app->router = NULL; - stasis_unsubscribe(app->bridge_merge_sub); - app->bridge_merge_sub = NULL; + stasis_message_router_unsubscribe(app->bridge_router); + app->bridge_router = NULL; } int app_is_active(struct stasis_app *app) |