guacamole-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jmuehl...@apache.org
Subject [10/26] incubator-guacamole-server git commit: GUACAMOLE-25: Handle the server's Sound Formats PDU.
Date Thu, 02 Jun 2016 18:45:17 GMT
GUACAMOLE-25: Handle the server's Sound Formats PDU.


Project: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/commit/86806a37
Tree: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/tree/86806a37
Diff: http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/diff/86806a37

Branch: refs/heads/master
Commit: 86806a37592624707aaa7450f6b4fe06bb1cf469
Parents: 503ffb0
Author: Michael Jumper <mjumper@apache.org>
Authored: Sun Apr 17 02:11:29 2016 -0700
Committer: Michael Jumper <mjumper@apache.org>
Committed: Wed May 25 13:50:28 2016 -0700

----------------------------------------------------------------------
 src/protocols/rdp/guac_ai/ai_messages.c | 147 ++++++++++++++++++++++++++-
 src/protocols/rdp/guac_ai/ai_messages.h |  59 +++++++++++
 2 files changed, 204 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/86806a37/src/protocols/rdp/guac_ai/ai_messages.c
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/guac_ai/ai_messages.c b/src/protocols/rdp/guac_ai/ai_messages.c
index c799a44..d4cc28d 100644
--- a/src/protocols/rdp/guac_ai/ai_messages.c
+++ b/src/protocols/rdp/guac_ai/ai_messages.c
@@ -35,6 +35,126 @@
 #include "compat/winpr-stream.h"
 #endif
 
+/**
+ * Reads AUDIO_FORMAT data from the given stream into the given struct.
+ *
+ * @param stream
+ *     The stream to read AUDIO_FORMAT data from.
+ *
+ * @param format
+ *     The structure to populate with data from the stream.
+ */
+static void guac_rdp_ai_read_format(wStream* stream,
+        guac_rdp_ai_format* format) {
+
+    /* Read audio format into structure */
+    Stream_Read_UINT16(stream, format->tag); /* wFormatTag */
+    Stream_Read_UINT16(stream, format->channels); /* nChannels */
+    Stream_Read_UINT32(stream, format->rate); /* nSamplesPerSec */
+    Stream_Read_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */
+    Stream_Read_UINT16(stream, format->block_align); /* nBlockAlign */
+    Stream_Read_UINT16(stream, format->bps); /* wBitsPerSample */
+    Stream_Read_UINT16(stream, format->data_size); /* cbSize */
+
+    /* Read arbitrary data block (if applicable) */
+    if (format->data_size != 0) {
+        format->data = Stream_Pointer(stream); /* data */
+        Stream_Seek(stream, format->data_size);
+    }
+
+}
+
+/**
+ * Writes AUDIO_FORMAT data to the given stream from the given struct.
+ *
+ * @param stream
+ *     The stream to write AUDIO_FORMAT data to.
+ *
+ * @param format
+ *     The structure containing the data that should be written to the stream.
+ */
+static void guac_rdp_ai_write_format(wStream* stream,
+        guac_rdp_ai_format* format) {
+
+    /* Write audio format into structure */
+    Stream_Write_UINT16(stream, format->tag); /* wFormatTag */
+    Stream_Write_UINT16(stream, format->channels); /* nChannels */
+    Stream_Write_UINT32(stream, format->rate); /* nSamplesPerSec */
+    Stream_Write_UINT32(stream, format->bytes_per_sec); /* nAvgBytesPerSec */
+    Stream_Write_UINT16(stream, format->block_align); /* nBlockAlign */
+    Stream_Write_UINT16(stream, format->bps); /* wBitsPerSample */
+    Stream_Write_UINT16(stream, format->data_size); /* cbSize */
+
+    /* Write arbitrary data block (if applicable) */
+    if (format->data_size != 0)
+        Stream_Write(stream, format->data, format->data_size);
+
+}
+
+/**
+ * Sends a Data Incoming PDU along the given channel. A Data Incoming PDU is
+ * used by the client to indicate to the server that format or audio data is
+ * about to be sent.
+ *
+ * @param channel
+ *     The channel along which the PDU should be sent.
+ */
+static void guac_rdp_ai_send_incoming_data(IWTSVirtualChannel* channel) {
+
+    /* Build response version PDU */
+    wStream* response = Stream_New(NULL, 1);
+    Stream_Write_UINT8(response, GUAC_RDP_MSG_SNDIN_DATA_INCOMING); /* MessageId */
+
+    /* Send response */
+    channel->Write(channel, (UINT32) Stream_GetPosition(response),
+            Stream_Buffer(response), NULL);
+    Stream_Free(response, TRUE);
+
+}
+
+/**
+ * Sends a Sound Formats PDU along the given channel. A Sound Formats PDU is
+ * used by the client to indicate to the server which formats of audio it
+ * supports (in response to the server sending exactly the same type of PDU).
+ * This PDU MUST be preceded by the Data Incoming PDU.
+ *
+ * @param channel
+ *     The channel along which the PDU should be sent.
+ *
+ * @param formats
+ *     An array of all supported formats.
+ *
+ * @param num_formats
+ *     The number of entries in the formats array.
+ */
+static void guac_rdp_ai_send_formats(IWTSVirtualChannel* channel,
+        guac_rdp_ai_format* formats, int num_formats) {
+
+    int index;
+    int packet_size = 9;
+
+    /* Calculate packet size */
+    for (index = 0; index < num_formats; index++)
+        packet_size += 18 + formats[index].data_size;
+
+    wStream* stream = Stream_New(NULL, packet_size);
+
+    /* Write header */
+    Stream_Write_UINT8(stream, GUAC_RDP_MSG_SNDIN_FORMATS); /* MessageId */
+    Stream_Write_UINT32(stream, num_formats); /* NumFormats */
+    Stream_Write_UINT32(stream, packet_size); /* cbSizeFormatsPacket  */
+
+    /* Write all formats */
+    for (index = 0; index < num_formats; index++)
+        guac_rdp_ai_write_format(stream, &(formats[index]));
+
+    /* Send PDU */
+    channel->Write(channel, (UINT32) Stream_GetPosition(stream),
+            Stream_Buffer(stream), NULL);
+    Stream_Free(stream, TRUE);
+
+}
+
 void guac_rdp_ai_process_version(guac_client* client,
         IWTSVirtualChannel* channel, wStream* stream) {
 
@@ -61,8 +181,31 @@ void guac_rdp_ai_process_version(guac_client* client,
 void guac_rdp_ai_process_formats(guac_client* client,
         IWTSVirtualChannel* channel, wStream* stream) {
 
-    /* STUB */
-    guac_client_log(client, GUAC_LOG_DEBUG, "AUDIO_INPUT: formats");
+    UINT32 num_formats;
+    Stream_Read_UINT32(stream, num_formats); /* NumFormats */
+    Stream_Seek_UINT32(stream); /* cbSizeFormatsPacket (MUST BE IGNORED) */
+
+    UINT32 index;
+    for (index = 0; index < num_formats; index++) {
+
+        guac_rdp_ai_format format;
+        guac_rdp_ai_read_format(stream, &format);
+
+        /* Ignore anything but WAVE_FORMAT_PCM */
+        if (format.tag != GUAC_RDP_WAVE_FORMAT_PCM)
+            continue;
+
+        /* Accept single format */
+        guac_rdp_ai_send_incoming_data(channel);
+        guac_rdp_ai_send_formats(channel, &format, 1);
+        return;
+
+    }
+
+    /* No formats available */
+    guac_client_log(client, GUAC_LOG_WARNING, "AUDIO_INPUT: No WAVE format.");
+    guac_rdp_ai_send_incoming_data(channel);
+    guac_rdp_ai_send_formats(channel, NULL, 0);
 
 }
 

http://git-wip-us.apache.org/repos/asf/incubator-guacamole-server/blob/86806a37/src/protocols/rdp/guac_ai/ai_messages.h
----------------------------------------------------------------------
diff --git a/src/protocols/rdp/guac_ai/ai_messages.h b/src/protocols/rdp/guac_ai/ai_messages.h
index 96282e5..55cf6e9 100644
--- a/src/protocols/rdp/guac_ai/ai_messages.h
+++ b/src/protocols/rdp/guac_ai/ai_messages.h
@@ -32,6 +32,12 @@
 #endif
 
 /**
+ * The format tag associated with raw wave audio (WAVE_FORMAT_PCM). This format
+ * is required to be supported by all RDP servers.
+ */
+#define GUAC_RDP_WAVE_FORMAT_PCM 0x01
+
+/**
  * The message ID associated with the AUDIO_INPUT Version PDU. The Version PDU
  * is sent by both the client and the server to indicate their version of the
  * AUDIO_INPUT channel protocol (which must always be 1).
@@ -80,6 +86,59 @@
 #define GUAC_RDP_MSG_SNDIN_FORMATCHANGE 0x07
 
 /**
+ * An AUDIO_INPUT format, analogous to the AUDIO_FORMAT structure defined
+ * within Microsoft's RDP documentation.
+ */
+typedef struct guac_rdp_ai_format {
+
+    /**
+     * The "format tag" denoting the overall format of audio data received,
+     * such as WAVE_FORMAT_PCM.
+     */
+    UINT16 tag;
+
+    /**
+     * The number of audio channels.
+     */
+    UINT16 channels;
+
+    /**
+     * The number of samples per second.
+     */
+    UINT32 rate;
+
+    /**
+     * The average number of bytes required for one second of audio.
+     */
+    UINT32 bytes_per_sec;
+
+    /**
+     * The absolute minimum number of bytes required to process audio in this
+     * format.
+     */
+    UINT16 block_align;
+
+    /**
+     * The number of bits per sample.
+     */
+    UINT16 bps;
+
+    /**
+     * The size of the arbitrary data block, if any. The meaning of the data
+     * within the arbitrary data block is determined by the format tag.
+     * WAVE_FORMAT_PCM audio has no associated arbitrary data.
+     */
+    UINT16 data_size;
+
+    /**
+     * Optional arbitrary data whose meaning is determined by the format tag.
+     * WAVE_FORMAT_PCM audio has no associated arbitrary data.
+     */
+    BYTE* data;
+
+} guac_rdp_ai_format;
+
+/**
  * Processes a Version PDU received from the RDP server. The Version PDU is
  * sent by the server to indicate its version of the AUDIO_INPUT channel
  * protocol (which must always be 1).


Mime
View raw message