diff --git a/apps/app_agent_pool.c b/apps/app_agent_pool.c index c968153e64de3a4887da7a5bc895d0831ca9b96b..2b0d1f8b8557e480e0eb6cafd30178c89d2b93c8 100644 --- a/apps/app_agent_pool.c +++ b/apps/app_agent_pool.c @@ -1366,7 +1366,8 @@ static struct ast_bridge *bridge_agent_hold_new(void) bridge = bridge_alloc(sizeof(struct ast_bridge), &bridge_agent_hold_v_table); bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM - | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED); + | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED, + "AgentPool", NULL); bridge = bridge_register(bridge); return bridge; } diff --git a/apps/app_bridgewait.c b/apps/app_bridgewait.c index 8e615f05ff2ae40693d45a7568cd7ad529ce21d7..aa83e0b70a2a6bab5638fe0314705caabb6bfe3b 100644 --- a/apps/app_bridgewait.c +++ b/apps/app_bridgewait.c @@ -360,7 +360,8 @@ static struct wait_bridge_wrapper *get_wait_bridge_wrapper(const char *bridge_na bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM | AST_BRIDGE_FLAG_SWAP_INHIBIT_TO | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM - | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_DISSOLVE_EMPTY); + | AST_BRIDGE_FLAG_TRANSFER_PROHIBITED | AST_BRIDGE_FLAG_DISSOLVE_EMPTY, + APP_NAME, bridge_name); if (!bridge) { return NULL; diff --git a/apps/app_confbridge.c b/apps/app_confbridge.c index 9688f2f460407f3112ca3f90cdeabbfb8ba34fe7..300d2c7e139e1b4ef7b4c8074e5fbee1c370a0a2 100644 --- a/apps/app_confbridge.c +++ b/apps/app_confbridge.c @@ -1218,7 +1218,8 @@ static struct confbridge_conference *join_conference_bridge(const char *conferen /* Create an actual bridge that will do the audio mixing */ conference->bridge = ast_bridge_base_new(AST_BRIDGE_CAPABILITY_MULTIMIX, - AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY); + AST_BRIDGE_FLAG_MASQUERADE_ONLY | AST_BRIDGE_FLAG_TRANSFER_BRIDGE_ONLY, + app, conference_name); if (!conference->bridge) { ao2_ref(conference, -1); conference = NULL; diff --git a/doc/appdocsxml.xslt b/doc/appdocsxml.xslt index 33ff7338808fcad06e5cffa35b903c0ab752a91e..8cbeaa3a52c11a0e366bdb112e9d3e2569b8480a 100644 --- a/doc/appdocsxml.xslt +++ b/doc/appdocsxml.xslt @@ -118,6 +118,18 @@ </xsl:attribute> <para>Technology in use by the bridge</para> </xsl:element> + <xsl:element name="parameter"> + <xsl:attribute name="name"> + <xsl:value-of select="concat(@prefix, 'BridgeCreator')"/> + </xsl:attribute> + <para>Entity that created the bridge if applicable</para> + </xsl:element> + <xsl:element name="parameter"> + <xsl:attribute name="name"> + <xsl:value-of select="concat(@prefix, 'BridgeName')"/> + </xsl:attribute> + <para>Name used to refer to the bridge by its BridgeCreator if applicable</para> + </xsl:element> <xsl:element name="parameter"> <xsl:attribute name="name"> <xsl:value-of select="concat(@prefix,'BridgeNumChannels')"/> diff --git a/include/asterisk/bridge.h b/include/asterisk/bridge.h index fdb3803ad24efe5d4f92cb0ea0b7b8bf6d16ba2f..0706b3aed14cd2240e5e0a60180f5b9ebb39b1d6 100644 --- a/include/asterisk/bridge.h +++ b/include/asterisk/bridge.h @@ -312,8 +312,15 @@ struct ast_bridge { unsigned int dissolved:1; /*! TRUE if the bridge construction was completed. */ unsigned int construction_completed:1; - /*! Immutable bridge UUID. */ - char uniqueid[AST_UUID_STR_LEN]; + + AST_DECLARE_STRING_FIELDS( + /*! Immutable name of the creator for the bridge */ + AST_STRING_FIELD(creator); + /*! Immutable name given to the bridge by its creator */ + AST_STRING_FIELD(name); + /*! Immutable bridge UUID. */ + AST_STRING_FIELD(uniqueid); + ); }; /*! \brief Bridge base class virtual method table. */ @@ -324,6 +331,8 @@ extern struct ast_bridge_methods ast_bridge_base_v_table; * * \param capabilities The capabilities that we require to be used on the bridge * \param flags Flags that will alter the behavior of the bridge + * \param creator Entity that created the bridge (optional) + * \param name Name given to the bridge by its creator (optional, requires named creator) * * \retval a pointer to a new bridge on success * \retval NULL on failure @@ -338,7 +347,7 @@ extern struct ast_bridge_methods ast_bridge_base_v_table; * This creates a no frills two party bridge that will be * destroyed once one of the channels hangs up. */ -struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags); +struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name); /*! * \brief Try locking the bridge. diff --git a/include/asterisk/bridge_internal.h b/include/asterisk/bridge_internal.h index 871abb8c5002de008771e88d16d172a6fe30a97a..e9726a1ab480cef6cb17a2632e9742dcb45eef0c 100644 --- a/include/asterisk/bridge_internal.h +++ b/include/asterisk/bridge_internal.h @@ -87,6 +87,8 @@ struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_ * \param self Bridge to operate upon. (Tolerates a NULL pointer) * \param capabilities The capabilities that we require to be used on the bridge * \param flags Flags that will alter the behavior of the bridge + * \param creator Entity that created the bridge (optional) + * \param name Name given to the bridge by its creator (optional, requires named creator) * * \retval self on success * \retval NULL on failure, self is already destroyed @@ -96,13 +98,13 @@ struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_ * \code * struct ast_bridge *bridge; * bridge = bridge_alloc(sizeof(*bridge), &ast_bridge_base_v_table); - * bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE_HANGUP); + * bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_1TO1MIX, AST_BRIDGE_FLAG_DISSOLVE_HANGUP, NULL, NULL); * \endcode * * This creates a no frills two party bridge that will be * destroyed once one of the channels hangs up. */ -struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags); +struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name); /*! * \internal diff --git a/include/asterisk/stasis_app.h b/include/asterisk/stasis_app.h index 56e039b43eea4b107f7843f616d1608745968807..ac5c648931b4faa71f3e045155af2f69e9352af8 100644 --- a/include/asterisk/stasis_app.h +++ b/include/asterisk/stasis_app.h @@ -597,11 +597,12 @@ int stasis_app_control_queue_control(struct stasis_app_control *control, * \brief Create a bridge of the specified type. * * \param type The type of bridge to be created + * \param name Optional name to give to the bridge * * \return New bridge. * \return \c NULL on error. */ -struct ast_bridge *stasis_app_bridge_create(const char *type); +struct ast_bridge *stasis_app_bridge_create(const char *type, const char *name); /*! * \brief Returns the bridge with the given id. diff --git a/include/asterisk/stasis_bridges.h b/include/asterisk/stasis_bridges.h index 9412bf0b780b5b8934939751281df9bb6d2f9168..2d15a33320ad14bbb78a5151d275c1706023a740 100644 --- a/include/asterisk/stasis_bridges.h +++ b/include/asterisk/stasis_bridges.h @@ -42,6 +42,10 @@ struct ast_bridge_snapshot { AST_STRING_FIELD(technology); /*! Bridge subclass that is handling the bridge */ AST_STRING_FIELD(subclass); + /*! Creator of the bridge */ + AST_STRING_FIELD(creator); + /*! Name given to the bridge by its creator */ + AST_STRING_FIELD(name); ); /*! AO2 container of bare channel uniqueid strings participating in the bridge. * Allocated from ast_str_container_alloc() */ diff --git a/main/bridge.c b/main/bridge.c index e2c46ac7493ab92cb13e7ca2134ea7863119d76e..8fd7847ecaf79cf50af1436efbfe64ddbe68aab8 100644 --- a/main/bridge.c +++ b/main/bridge.c @@ -533,9 +533,11 @@ static void bridge_tech_deferred_destroy(struct ast_bridge *bridge, struct ast_f struct ast_bridge dummy_bridge = { .technology = deferred->tech, .tech_pvt = deferred->tech_pvt, + .creator = bridge->creator, + .name = bridge->name, + .uniqueid = bridge->uniqueid, }; - ast_copy_string(dummy_bridge.uniqueid, bridge->uniqueid, sizeof(dummy_bridge.uniqueid)); ast_debug(1, "Bridge %s: calling %s technology destructor (deferred, dummy)\n", dummy_bridge.uniqueid, dummy_bridge.technology->name); dummy_bridge.technology->destroy(&dummy_bridge); @@ -679,6 +681,8 @@ static void destroy_bridge(void *obj) cleanup_video_mode(bridge); stasis_cp_single_unsubscribe(bridge->topics); + + ast_string_field_free_memory(bridge); } struct ast_bridge *bridge_register(struct ast_bridge *bridge) @@ -714,19 +718,35 @@ struct ast_bridge *bridge_alloc(size_t size, const struct ast_bridge_methods *v_ } bridge = ao2_alloc(size, destroy_bridge); - if (bridge) { - bridge->v_table = v_table; + if (!bridge) { + return NULL; + } + + if (ast_string_field_init(bridge, 80)) { + ao2_cleanup(bridge); + return NULL; } + + bridge->v_table = v_table; + return bridge; } -struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags) +struct ast_bridge *bridge_base_init(struct ast_bridge *self, uint32_t capabilities, unsigned int flags, const char *creator, const char *name) { + char uuid_hold[AST_UUID_STR_LEN]; + if (!self) { return NULL; } - ast_uuid_generate_str(self->uniqueid, sizeof(self->uniqueid)); + ast_uuid_generate_str(uuid_hold, AST_UUID_STR_LEN); + ast_string_field_set(self, uniqueid, uuid_hold); + ast_string_field_set(self, creator, creator); + if (!ast_strlen_zero(creator)) { + ast_string_field_set(self, name, name); + } + ast_set_flag(&self->feature_flags, flags); self->allowed_capabilities = capabilities; @@ -881,12 +901,12 @@ struct ast_bridge_methods ast_bridge_base_v_table = { .get_merge_priority = bridge_base_get_merge_priority, }; -struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags) +struct ast_bridge *ast_bridge_base_new(uint32_t capabilities, unsigned int flags, const char *creator, const char *name) { void *bridge; bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_base_v_table); - bridge = bridge_base_init(bridge, capabilities, flags); + bridge = bridge_base_init(bridge, capabilities, flags, creator, name); bridge = bridge_register(bridge); return bridge; } @@ -991,6 +1011,9 @@ static int smart_bridge_operation(struct ast_bridge *bridge) struct ast_bridge dummy_bridge = { .technology = bridge->technology, .tech_pvt = bridge->tech_pvt, + .creator = bridge->creator, + .name = bridge->name, + .uniqueid = bridge->uniqueid, }; if (bridge->dissolved) { @@ -1043,8 +1066,6 @@ static int smart_bridge_operation(struct ast_bridge *bridge) return 0; } - ast_copy_string(dummy_bridge.uniqueid, bridge->uniqueid, sizeof(dummy_bridge.uniqueid)); - if (old_technology->destroy) { struct tech_deferred_destroy deferred_tech_destroy = { .tech = dummy_bridge.technology, diff --git a/main/bridge_basic.c b/main/bridge_basic.c index eaec68995b77ea3fab8e2ee7f9e49ff0d8b06ba0..317c574a67626da0e49a35ad25a2b0eb20cba726 100644 --- a/main/bridge_basic.c +++ b/main/bridge_basic.c @@ -3239,7 +3239,7 @@ struct ast_bridge *ast_bridge_basic_new(void) bridge = bridge_alloc(sizeof(struct ast_bridge), &ast_bridge_basic_v_table); bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_NATIVE | AST_BRIDGE_CAPABILITY_1TO1MIX - | AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS); + | AST_BRIDGE_CAPABILITY_MULTIMIX, NORMAL_FLAGS, NULL, NULL); bridge = bridge_basic_personality_alloc(bridge); bridge = bridge_register(bridge); return bridge; diff --git a/main/manager_bridges.c b/main/manager_bridges.c index e012ebb6d64a694de78dcf7ae2b59d6ec070d8c8..90281283d7c58ade7a53bb73a0c074c8cf871e95 100644 --- a/main/manager_bridges.c +++ b/main/manager_bridges.c @@ -156,10 +156,14 @@ struct ast_str *ast_manager_build_bridge_state_string_prefix( "%sBridgeUniqueid: %s\r\n" "%sBridgeType: %s\r\n" "%sBridgeTechnology: %s\r\n" + "%sBridgeCreator: %s\r\n" + "%sBridgeName: %s\r\n" "%sBridgeNumChannels: %d\r\n", prefix, snapshot->uniqueid, prefix, snapshot->subclass, prefix, snapshot->technology, + prefix, ast_strlen_zero(snapshot->creator) ? "<unknown>": snapshot->creator, + prefix, ast_strlen_zero(snapshot->name) ? "<unknown>": snapshot->name, prefix, snapshot->num_channels); if (!res) { ast_free(out); diff --git a/main/stasis_bridges.c b/main/stasis_bridges.c index b92d048bc091a9ce516c2925aab7c52df834b94e..7f6679b00003580110dcd4c2381a0bebb88675ec 100644 --- a/main/stasis_bridges.c +++ b/main/stasis_bridges.c @@ -242,6 +242,8 @@ struct ast_bridge_snapshot *ast_bridge_snapshot_create(struct ast_bridge *bridge ast_string_field_set(snapshot, uniqueid, bridge->uniqueid); ast_string_field_set(snapshot, technology, bridge->technology->name); ast_string_field_set(snapshot, subclass, bridge->v_table->name); + ast_string_field_set(snapshot, creator, bridge->creator); + ast_string_field_set(snapshot, name, bridge->name); snapshot->feature_flags = bridge->feature_flags; snapshot->capabilities = bridge->technology->capabilities; @@ -548,11 +550,13 @@ struct ast_json *ast_bridge_snapshot_to_json( return NULL; } - json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: o}", + json_bridge = ast_json_pack("{s: s, s: s, s: s, s: s, s: s, s: s, s: o}", "id", snapshot->uniqueid, "technology", snapshot->technology, "bridge_type", capability2str(snapshot->capabilities), "bridge_class", snapshot->subclass, + "creator", snapshot->creator, + "name", snapshot->name, "channels", json_channels); if (!json_bridge) { return NULL; diff --git a/res/ari/ari_model_validators.c b/res/ari/ari_model_validators.c index d99240bd8681e8cdab281e98089766721a159e2e..a04818045c86660836dc25aef6a689d4fdef0b64 100644 --- a/res/ari/ari_model_validators.c +++ b/res/ari/ari_model_validators.c @@ -891,7 +891,9 @@ int ast_ari_validate_bridge(struct ast_json *json) int has_bridge_class = 0; int has_bridge_type = 0; int has_channels = 0; + int has_creator = 0; int has_id = 0; + int has_name = 0; int has_technology = 0; for (iter = ast_json_object_iter(json); iter; iter = ast_json_object_iter_next(json, iter)) { @@ -926,6 +928,16 @@ int ast_ari_validate_bridge(struct ast_json *json) res = 0; } } else + if (strcmp("creator", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_creator = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Bridge field creator failed validation\n"); + res = 0; + } + } else if (strcmp("id", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_id = 1; @@ -936,6 +948,16 @@ int ast_ari_validate_bridge(struct ast_json *json) res = 0; } } else + if (strcmp("name", ast_json_object_iter_key(iter)) == 0) { + int prop_is_valid; + has_name = 1; + prop_is_valid = ast_ari_validate_string( + ast_json_object_iter_value(iter)); + if (!prop_is_valid) { + ast_log(LOG_ERROR, "ARI Bridge field name failed validation\n"); + res = 0; + } + } else if (strcmp("technology", ast_json_object_iter_key(iter)) == 0) { int prop_is_valid; has_technology = 1; @@ -969,11 +991,21 @@ int ast_ari_validate_bridge(struct ast_json *json) res = 0; } + if (!has_creator) { + ast_log(LOG_ERROR, "ARI Bridge missing required field creator\n"); + res = 0; + } + if (!has_id) { ast_log(LOG_ERROR, "ARI Bridge missing required field id\n"); res = 0; } + if (!has_name) { + ast_log(LOG_ERROR, "ARI Bridge missing required field name\n"); + res = 0; + } + if (!has_technology) { ast_log(LOG_ERROR, "ARI Bridge missing required field technology\n"); res = 0; diff --git a/res/ari/ari_model_validators.h b/res/ari/ari_model_validators.h index 22ab43be8990274ebde7895b581db03eeb14a1f4..3266939508d128e840d4d28f8a1f7324f975504d 100644 --- a/res/ari/ari_model_validators.h +++ b/res/ari/ari_model_validators.h @@ -1083,7 +1083,9 @@ ari_validator ast_ari_validate_application_fn(void); * - bridge_class: string (required) * - bridge_type: string (required) * - channels: List[string] (required) + * - creator: string (required) * - id: string (required) + * - name: string (required) * - technology: string (required) * LiveRecording * - cause: string diff --git a/res/ari/resource_bridges.c b/res/ari/resource_bridges.c index c074718160703fad4889525d92d51a83cba8d9c5..ed3eba82edc702cee675ed73101afda9f27b7fcd 100644 --- a/res/ari/resource_bridges.c +++ b/res/ari/resource_bridges.c @@ -695,7 +695,7 @@ void ast_ari_bridges_create(struct ast_variable *headers, struct ast_ari_bridges_create_args *args, struct ast_ari_response *response) { - RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type), ao2_cleanup); + RAII_VAR(struct ast_bridge *, bridge, stasis_app_bridge_create(args->type, args->name), ao2_cleanup); RAII_VAR(struct ast_bridge_snapshot *, snapshot, NULL, ao2_cleanup); if (!bridge) { diff --git a/res/ari/resource_bridges.h b/res/ari/resource_bridges.h index c5a832275ab96ac2af64149b673356e73b457168..a7ccd31201ad9de4ec2684e84dc382cac941f52e 100644 --- a/res/ari/resource_bridges.h +++ b/res/ari/resource_bridges.h @@ -54,6 +54,8 @@ void ast_ari_bridges_list(struct ast_variable *headers, struct ast_ari_bridges_l struct ast_ari_bridges_create_args { /*! \brief Type of bridge to create. */ const char *type; + /*! \brief Name to give to the bridge being created. */ + const char *name; }; /*! * \brief Create a new bridge. diff --git a/res/parking/parking_bridge.c b/res/parking/parking_bridge.c index 9bc13454f65f92e96987add2aba5226dfe88f746..bb9dbf30d8979e2d6398adf5ec5bc6ebe5cc4a1b 100644 --- a/res/parking/parking_bridge.c +++ b/res/parking/parking_bridge.c @@ -456,7 +456,7 @@ struct ast_bridge *bridge_parking_new(struct parking_lot *bridge_lot) bridge = bridge_alloc(sizeof(struct ast_bridge_parking), &ast_bridge_parking_v_table); bridge = bridge_base_init(bridge, AST_BRIDGE_CAPABILITY_HOLDING, AST_BRIDGE_FLAG_MERGE_INHIBIT_TO | AST_BRIDGE_FLAG_MERGE_INHIBIT_FROM - | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM); + | AST_BRIDGE_FLAG_SWAP_INHIBIT_FROM, "Parking", bridge_lot->name); bridge = ast_bridge_parking_init(bridge, bridge_lot); bridge = bridge_register(bridge); return bridge; diff --git a/res/res_ari_bridges.c b/res/res_ari_bridges.c index a68fbf6ac0194dd592d93bcce2e9b7e4a2665b67..242512d90af2446b66b1d90339159eab3efdea9a 100644 --- a/res/res_ari_bridges.c +++ b/res/res_ari_bridges.c @@ -127,6 +127,9 @@ static void ast_ari_bridges_create_cb( if (strcmp(i->name, "type") == 0) { args.type = (i->value); } else + if (strcmp(i->name, "name") == 0) { + args.name = (i->value); + } else {} } /* Look for a JSON request entity */ @@ -149,6 +152,10 @@ static void ast_ari_bridges_create_cb( if (field) { args.type = ast_json_string_get(field); } + field = ast_json_object_get(body, "name"); + if (field) { + args.name = ast_json_string_get(field); + } ast_ari_bridges_create(headers, &args, response); #if defined(AST_DEVMODE) code = response->response_code; diff --git a/res/res_stasis.c b/res/res_stasis.c index 691462722e549eea34944b771ec83a2f41ce0000..71a18a07ff718c582c9ae17a321b6aaf795ffcae 100644 --- a/res/res_stasis.c +++ b/res/res_stasis.c @@ -585,7 +585,7 @@ static void control_unlink(struct stasis_app_control *control) ao2_cleanup(control); } -struct ast_bridge *stasis_app_bridge_create(const char *type) +struct ast_bridge *stasis_app_bridge_create(const char *type, const char *name) { struct ast_bridge *bridge; int capabilities; @@ -604,7 +604,7 @@ struct ast_bridge *stasis_app_bridge_create(const char *type) return NULL; } - bridge = ast_bridge_base_new(capabilities, flags); + bridge = ast_bridge_base_new(capabilities, flags, "Stasis", name); if (bridge) { if (!ao2_link(app_bridges, bridge)) { ast_bridge_destroy(bridge, 0); diff --git a/rest-api/api-docs/bridges.json b/rest-api/api-docs/bridges.json index d7f63ad144bad912f930b211af518e6530d088ef..33a0d659b229919b5bf8863360dd500b924b0151 100644 --- a/rest-api/api-docs/bridges.json +++ b/rest-api/api-docs/bridges.json @@ -38,6 +38,14 @@ "holding" ] } + }, + { + "name": "name", + "description": "Name to give to the bridge being created.", + "paramType": "query", + "required": false, + "allowMultiple": false, + "dataType": "string" } ] } @@ -502,6 +510,16 @@ "description": "Bridging class", "required": true }, + "creator": { + "type": "string", + "description": "Entity that created the bridge", + "required": true + }, + "name": { + "type": "string", + "description": "Name the creator gave the bridge", + "required": true + }, "channels": { "type": "List[string]", "description": "Ids of channels participating in this bridge",