GUACAMOLE-25: Implement parsing of audio mimetypes.
This commit is contained in:
parent
8ccf61e6b1
commit
320f564daf
@ -30,16 +30,130 @@
|
|||||||
#include <guacamole/stream.h>
|
#include <guacamole/stream.h>
|
||||||
#include <guacamole/user.h>
|
#include <guacamole/user.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the given raw audio mimetype, producing the corresponding rate,
|
||||||
|
* number of channels, and bytes per sample.
|
||||||
|
*
|
||||||
|
* @param mimetype
|
||||||
|
* The raw auduio mimetype to parse.
|
||||||
|
*
|
||||||
|
* @param rate
|
||||||
|
* A pointer to an int where the sample rate for the PCM format described
|
||||||
|
* by the given mimetype should be stored.
|
||||||
|
*
|
||||||
|
* @param channels
|
||||||
|
* A pointer to an int where the number of channels used by the PCM format
|
||||||
|
* described by the given mimetype should be stored.
|
||||||
|
*
|
||||||
|
* @param bps
|
||||||
|
* A pointer to an int where the number of bytes used the PCM format for
|
||||||
|
* each sample (independent of number of channels) described by the given
|
||||||
|
* mimetype should be stored.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* Zero if the given mimetype is a raw audio mimetype and has been parsed
|
||||||
|
* successfully, non-zero otherwise.
|
||||||
|
*/
|
||||||
|
static int guac_rdp_audio_parse_mimetype(const char* mimetype,
|
||||||
|
int* rate, int* channels, int* bps) {
|
||||||
|
|
||||||
|
int parsed_rate = -1;
|
||||||
|
int parsed_channels = 1;
|
||||||
|
int parsed_bps;
|
||||||
|
|
||||||
|
/* PCM audio with one byte per sample */
|
||||||
|
if (strncmp(mimetype, "audio/L8;", 9) == 0) {
|
||||||
|
mimetype += 8; /* Advance to semicolon ONLY */
|
||||||
|
parsed_bps = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PCM audio with two bytes per sample */
|
||||||
|
else if (strncmp(mimetype, "audio/L16;", 10) == 0) {
|
||||||
|
mimetype += 9; /* Advance to semicolon ONLY */
|
||||||
|
parsed_bps = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Unsupported mimetype */
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Parse each parameter name/value pair within the mimetype */
|
||||||
|
do {
|
||||||
|
|
||||||
|
/* Advance to first character of parameter (current is either a
|
||||||
|
* semicolon or a comma) */
|
||||||
|
mimetype++;
|
||||||
|
|
||||||
|
/* Parse number of channels */
|
||||||
|
if (strncmp(mimetype, "channels=", 9) == 0) {
|
||||||
|
|
||||||
|
mimetype += 9;
|
||||||
|
parsed_channels = strtol(mimetype, (char**) &mimetype, 10);
|
||||||
|
|
||||||
|
/* Fail if value invalid / out of range */
|
||||||
|
if (errno == EINVAL || errno == ERANGE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse number of rate */
|
||||||
|
else if (strncmp(mimetype, "rate=", 5) == 0) {
|
||||||
|
|
||||||
|
mimetype += 5;
|
||||||
|
parsed_rate = strtol(mimetype, (char**) &mimetype, 10);
|
||||||
|
|
||||||
|
/* Fail if value invalid / out of range */
|
||||||
|
if (errno == EINVAL || errno == ERANGE)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Advance to next parameter */
|
||||||
|
mimetype = strchr(mimetype, ',');
|
||||||
|
|
||||||
|
} while (mimetype != NULL);
|
||||||
|
|
||||||
|
/* Mimetype is invalid if rate was not specified */
|
||||||
|
if (rate == -1)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
/* Parse success */
|
||||||
|
*rate = parsed_rate;
|
||||||
|
*channels = parsed_channels;
|
||||||
|
*bps = parsed_bps;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int guac_rdp_audio_handler(guac_user* user, guac_stream* stream,
|
int guac_rdp_audio_handler(guac_user* user, guac_stream* stream,
|
||||||
char* mimetype) {
|
char* mimetype) {
|
||||||
|
|
||||||
guac_client* client = user->client;
|
guac_client* client = user->client;
|
||||||
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
guac_rdp_client* rdp_client = (guac_rdp_client*) client->data;
|
||||||
|
|
||||||
|
int rate;
|
||||||
|
int channels;
|
||||||
|
int bps;
|
||||||
|
|
||||||
|
/* Parse mimetype, abort on parse error */
|
||||||
|
if (guac_rdp_audio_parse_mimetype(mimetype, &rate, &channels, &bps)) {
|
||||||
|
guac_user_log(user, GUAC_LOG_WARN, "Denying user audio stream with "
|
||||||
|
"unsupported mimetype: \"%s\"", mimetype);
|
||||||
|
guac_protocol_send_ack(user->socket, stream, "Unsupported audio "
|
||||||
|
"mimetype", GUAC_PROTOCOL_STATUS_CLIENT_BAD_TYPE);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* FIXME: Assuming mimetype of "audio/L16;rate=44100,channels=2" */
|
/* FIXME: Assuming mimetype of "audio/L16;rate=44100,channels=2" */
|
||||||
|
else {
|
||||||
|
guac_user_log(user, GUAC_LOG_DEBUG, "rate=%i, channels=%i, bps=%i",
|
||||||
|
rate, channels, bps);
|
||||||
|
}
|
||||||
|
|
||||||
/* Init stream data */
|
/* Init stream data */
|
||||||
stream->blob_handler = guac_rdp_audio_blob_handler;
|
stream->blob_handler = guac_rdp_audio_blob_handler;
|
||||||
|
Loading…
Reference in New Issue
Block a user