Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AudioBridge-List_Announcements #3391

Merged
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 99 additions & 12 deletions src/plugins/janus_audiobridge.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,23 +75,24 @@ room-<unique room ID>: {
* (invalid JSON, invalid request) which will always result in a
* synchronous error response even for asynchronous requests.
*
* \c create , \c edit , \c destroy , \c exists, \c allowed, \c kick, \c list,
* \c mute , \c unmute , \c mute_room , \c unmute_room , \c listparticipants ,
* \c resetdecoder , \c rtp_forward, \c stop_rtp_forward , \c list_forwarders ,
* \c play_file , \c is_playing and \c stop_file are synchronous requests,
* which means you'll get a response directly within the context of the
* transaction. \c create allows you to create a new audio conference bridge
* dynamically, as an alternative to using the configuration file; \c edit
* allows you to dynamically edit some room properties (e.g., the PIN);
* \c create, \c edit, \c destroy, \c exists, \c allowed, \c kick, \c list,
* \c mute, \c unmute, \c mute_room, \c unmute_room, \c listparticipants,
* \c listannouncements, \c resetdecoder, \c rtp_forward, \c stop_rtp_forward,
* \c list_forwarders, \c play_file, \c is_playing and \c stop_file are
* synchronous requests, which means you'll get a response directly within
* the context of the transaction. \c create allows you to create a new audio
* conference bridge dynamically, as an alternative to using the configuration file;
* \c edit allows you to dynamically edit some room properties (e.g., the PIN);
* \c destroy removes an audio conference bridge and destroys it, kicking
* all the users out as part of the process; \c exists allows you to
* check whether a specific audio conference exists; \c allowed allows
* you to edit who's allowed to join a room via ad-hoc tokens; \c list
* lists all the available rooms, while \c listparticipants lists all
* the participants of a specific room and their details; \c resetdecoder
* marks the Opus decoder for the participant as invalid, and forces it
* to be recreated (which might be needed if the audio for generated by
* the participant becomes garbled); \c rtp_forward allows you to forward
* the participants of a specific room and their details; \c listannouncements
* list all playing announcements of a specific room and their details;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lists (missing s)

* \c resetdecoder marks the Opus decoder for the participant as invalid, and
* forces it to be recreated (which might be needed if the audio for generated
* by the participant becomes garbled); \c rtp_forward allows you to forward
* the mix of an AudioBridge room via RTP to a separate component (e.g.,
* for broadcasting it to a wider audience, or for processing/recording),
* whereas \c stop_rtp_forward can remove an existing forwarder; a list
Expand Down Expand Up @@ -750,6 +751,36 @@ room-<unique room ID>: {
"file_id" : "<unique string ID of the announcement>",
"playing" : <true|false>
}
\endverbatim
*
* To get a list of the announcements in a specific room, you
* can make use of the \c listannouncements request, which has to be
* formatted as follows:
*
\verbatim
{
"request" : "listannouncements",
"room" : <unique numeric ID of the room>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed in my previous comments, I think this should be protected by the room's secret. Only admins should be allowed to see which announcements exist in the room, since a secret is required to play them in the first place.

}
\endverbatim
*
* A successful request will produce a list of announcements in a
* \c announcements response:
*
\verbatim
{
"audiobridge" : "announcements",
"room" : <unique numeric ID of the room>,
"announcements" : [ // Array of announcement objects
{ // Announcement #1
"file_id" : "<unique string ID of the announcement>",
"filename": "<path to the Opus file to play>",
"playing" : <true|false, whether or not the file is playing>,
"loop": <true|false, depending on whether or not the file is playing in a loop forever>
}
// Other announcements
]
}
\endverbatim
*
* As anticipated, when not looping a playback will automatically stop and
Expand Down Expand Up @@ -5448,6 +5479,62 @@ static json_t *janus_audiobridge_process_synchronous_request(janus_audiobridge_s
json_object_set_new(response, "playing", playing ? json_true() : json_false());
goto prepare_response;
#endif
} else if(!strcasecmp(request_text, "listannouncements")) {
/* List all announcements in a room */
if(!string_ids) {
JANUS_VALIDATE_JSON_OBJECT(root, room_parameters,
error_code, error_cause, TRUE,
JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT);
} else {
JANUS_VALIDATE_JSON_OBJECT(root, roomstr_parameters,
error_code, error_cause, TRUE,
JANUS_AUDIOBRIDGE_ERROR_MISSING_ELEMENT, JANUS_AUDIOBRIDGE_ERROR_INVALID_ELEMENT);
}
if(error_code != 0)
goto prepare_response;
json_t *room = json_object_get(root, "room");
guint64 room_id = 0;
char room_id_num[30], *room_id_str = NULL;
if(!string_ids) {
room_id = json_integer_value(room);
g_snprintf(room_id_num, sizeof(room_id_num), "%"SCNu64, room_id);
room_id_str = room_id_num;
} else {
room_id_str = (char *)json_string_value(room);
}
janus_mutex_lock(&rooms_mutex);
janus_audiobridge_room *audiobridge = g_hash_table_lookup(rooms,
string_ids ? (gpointer)room_id_str : (gpointer)&room_id);
if(audiobridge == NULL) {
janus_mutex_unlock(&rooms_mutex);
error_code = JANUS_AUDIOBRIDGE_ERROR_NO_SUCH_ROOM;
JANUS_LOG(LOG_ERR, "No such room (%s)\n", room_id_str);
g_snprintf(error_cause, 512, "No such room (%s)", room_id_str);
goto prepare_response;
}
janus_refcount_increase(&audiobridge->ref);
/* Return a list of all announcements */
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is missing the secret check, as discussed in my previous comment. You can refer to how other requests handle it to see how it can be done in a short snippet. Besides, you're also missing a check on whether the audiobridge instance has already been marked as destroyed, which must happen before increasing the reference.

json_t *list = json_array();
GHashTableIter iter;
gpointer value;
g_hash_table_iter_init(&iter, audiobridge->anncs);
while(g_hash_table_iter_next(&iter, NULL, &value)) {
janus_audiobridge_participant *p = value;
json_t *pl = json_object();
json_object_set_new(pl, "file_id", json_string(p->annc->id));
if(p->annc->filename)
json_object_set_new(pl, "filename", json_string(p->annc->filename));
json_object_set_new(pl, "playing", p->annc->started ? json_true() : json_false());
json_object_set_new(pl, "loop", p->annc->loop ? json_true() : json_false());
json_array_append_new(list, pl);
}
janus_refcount_decrease(&audiobridge->ref);
janus_mutex_unlock(&rooms_mutex);
response = json_object();
json_object_set_new(response, "audiobridge", json_string("announcements"));
json_object_set_new(response, "room", string_ids ? json_string(room_id_str) : json_integer(room_id));
json_object_set_new(response, "announcements", list);
goto prepare_response;
} else if(!strcasecmp(request_text, "stop_file")) {
#ifndef HAVE_LIBOGG
JANUS_LOG(LOG_VERB, "Playing files unsupported in this instance\n");
Expand Down