GUACAMOLE-629: Merge allow "argv" instructions to be sent from server to client.

diff --git a/src/libguac/Makefile.am b/src/libguac/Makefile.am
index dc96a87..a624080 100644
--- a/src/libguac/Makefile.am
+++ b/src/libguac/Makefile.am
@@ -54,6 +54,7 @@
     guacamole/pool.h                  \
     guacamole/pool-types.h            \
     guacamole/protocol.h              \
+    guacamole/protocol-constants.h    \
     guacamole/protocol-types.h        \
     guacamole/socket-constants.h      \
     guacamole/socket.h                \
diff --git a/src/libguac/client.c b/src/libguac/client.c
index 80eb4ea..6440453 100644
--- a/src/libguac/client.c
+++ b/src/libguac/client.c
@@ -516,6 +516,26 @@
 
 }
 
+void guac_client_stream_argv(guac_client* client, guac_socket* socket,
+        const char* mimetype, const char* name, const char* value) {
+
+    /* Allocate new stream for argument value */
+    guac_stream* stream = guac_client_alloc_stream(client);
+
+    /* Declare stream as containing connection parameter data */
+    guac_protocol_send_argv(socket, stream, mimetype, name);
+
+    /* Write parameter data */
+    guac_protocol_send_blobs(socket, stream, value, strlen(value));
+
+    /* Terminate stream */
+    guac_protocol_send_end(socket, stream);
+
+    /* Free allocated stream */
+    guac_client_free_stream(client, stream);
+
+}
+
 void guac_client_stream_png(guac_client* client, guac_socket* socket,
         guac_composite_mode mode, const guac_layer* layer, int x, int y,
         cairo_surface_t* surface) {
diff --git a/src/libguac/encode-jpeg.c b/src/libguac/encode-jpeg.c
index 1aeb23b..8e145d8 100644
--- a/src/libguac/encode-jpeg.c
+++ b/src/libguac/encode-jpeg.c
@@ -59,7 +59,7 @@
     /**
      * The output buffer.
      */
-    unsigned char buffer[6048];
+    unsigned char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH];
 
 } guac_jpeg_destination_mgr;
 
diff --git a/src/libguac/encode-png.c b/src/libguac/encode-png.c
index 7d4b6c7..20d2f5d 100644
--- a/src/libguac/encode-png.c
+++ b/src/libguac/encode-png.c
@@ -56,7 +56,7 @@
     /**
      * Buffer of pending PNG data.
      */
-    char buffer[6048];
+    char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH];
 
     /**
      * The number of bytes currently stored in the buffer.
diff --git a/src/libguac/encode-webp.c b/src/libguac/encode-webp.c
index 5c2237d..43c5a00 100644
--- a/src/libguac/encode-webp.c
+++ b/src/libguac/encode-webp.c
@@ -52,7 +52,7 @@
     /**
      * Buffer of pending WebP data.
      */
-    char buffer[6048];
+    char buffer[GUAC_PROTOCOL_BLOB_MAX_LENGTH];
 
     /**
      * The number of bytes currently stored in the buffer.
diff --git a/src/libguac/guacamole/client.h b/src/libguac/guacamole/client.h
index 2d01573..88d1f41 100644
--- a/src/libguac/guacamole/client.h
+++ b/src/libguac/guacamole/client.h
@@ -549,6 +549,33 @@
 int guac_client_get_processing_lag(guac_client* client);
 
 /**
+ * Streams the given connection parameter value over an argument value stream
+ * ("argv" instruction), exposing the current value of the named connection
+ * parameter to all users of the given client. The argument value stream will
+ * be automatically allocated and freed.
+ *
+ * @param client
+ *     The Guacamole client for which the argument value stream should be
+ *     allocated.
+ *
+ * @param socket
+ *     The socket over which instructions associated with the argument value
+ *     stream should be sent.
+ *
+ * @param mimetype
+ *     The mimetype of the data within the connection parameter value being
+ *     sent.
+ *
+ * @param name
+ *     The name of the connection parameter being sent.
+ *
+ * @param value
+ *     The current value of the connection parameter being sent.
+ */
+void guac_client_stream_argv(guac_client* client, guac_socket* socket,
+        const char* mimetype, const char* name, const char* value);
+
+/**
  * Streams the image data of the given surface over an image stream ("img"
  * instruction) as PNG-encoded data. The image stream will be automatically
  * allocated and freed.
diff --git a/src/libguac/guacamole/protocol-constants.h b/src/libguac/guacamole/protocol-constants.h
new file mode 100644
index 0000000..afa67bb
--- /dev/null
+++ b/src/libguac/guacamole/protocol-constants.h
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef GUAC_PROTOCOL_CONSTANTS_H
+#define GUAC_PROTOCOL_CONSTANTS_H
+
+/**
+ * Constants related to the Guacamole protocol.
+ *
+ * @file protocol-constants.h
+ */
+
+/**
+ * This defines the overall protocol version that this build of libguac
+ * supports.  The protocol version is used to provide compatibility between
+ * potentially different versions of Guacamole server and clients.  The
+ * version number is a MAJOR_MINOR_PATCH version that matches the versioning
+ * used throughout the components of the Guacamole project.  This version
+ * will not necessarily increment with the other components, unless additional
+ * functionality is introduced that affects compatibility.
+ * 
+ * This version is passed by the __guac_protocol_send_args() function from the
+ * server to the client during the client/server handshake.
+ */
+#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_1_0"
+
+/**
+ * The maximum number of bytes that should be sent in any one blob instruction
+ * to ensure the instruction does not exceed the maximum allowed instruction
+ * size.
+ *
+ * @see GUAC_INSTRUCTION_MAX_LENGTH 
+ */
+#define GUAC_PROTOCOL_BLOB_MAX_LENGTH 6048
+
+#endif
+
diff --git a/src/libguac/guacamole/protocol.h b/src/libguac/guacamole/protocol.h
index 0b462b4..f4e0288 100644
--- a/src/libguac/guacamole/protocol.h
+++ b/src/libguac/guacamole/protocol.h
@@ -30,6 +30,7 @@
 
 #include "layer-types.h"
 #include "object-types.h"
+#include "protocol-constants.h"
 #include "protocol-types.h"
 #include "socket-types.h"
 #include "stream-types.h"
@@ -38,20 +39,6 @@
 #include <cairo/cairo.h>
 #include <stdarg.h>
 
-/**
- * This defines the overall protocol version that this build of libguac
- * supports.  The protocol version is used to provide compatibility between
- * potentially different versions of Guacamole server and clients.  The
- * version number is a MAJOR_MINOR_PATCH version that matches the versioning
- * used throughout the components of the Guacamole project.  This version
- * will not necessarily increment with the other components, unless additional
- * functionality is introduced that affects compatibility.
- * 
- * This version is passed by the __guac_protocol_send_args() function from the
- * server to the client during the client/server handshake.
- */
-#define GUACAMOLE_PROTOCOL_VERSION "VERSION_1_1_0"
-
 /* CONTROL INSTRUCTIONS */
 
 /**
@@ -449,6 +436,37 @@
         const void* data, int count);
 
 /**
+ * Sends a series of blob instructions, splitting the given data across the
+ * number of instructions required to ensure the size of each blob does not
+ * exceed GUAC_PROTOCOL_BLOB_MAX_LENGTH. If the size of data provided is zero,
+ * no blob instructions are sent.
+ *
+ * If an error occurs sending any blob instruction, a non-zero value is
+ * returned, guac_error is set appropriately, and no further blobs are sent.
+ *
+ * @see GUAC_PROTOCOL_BLOB_MAX_LENGTH
+ *
+ * @param socket
+ *     The guac_socket connection to use to send the blob instructions.
+ *
+ * @param stream
+ *     The stream to associate with each blob sent.
+ *
+ * @param data
+ *     The data which should be sent using the required number of blob
+ *     instructions.
+ *
+ * @param count
+ *     The number of bytes within the given buffer of data that must be
+ *     written.
+ *
+ * @return
+ *     Zero on success, non-zero on error.
+ */
+int guac_protocol_send_blobs(guac_socket* socket, const guac_stream* stream,
+        const void* data, int count);
+
+/**
  * Sends an end instruction over the given guac_socket connection.
  *
  * If an error occurs sending the instruction, a non-zero value is
@@ -933,6 +951,31 @@
 /* TEXT INSTRUCTIONS */
 
 /**
+ * Sends an argv instruction over the given guac_socket connection.
+ *
+ * If an error occurs sending the instruction, a non-zero value is
+ * returned, and guac_error is set appropriately.
+ *
+ * @param socket
+ *     The guac_socket connection to use to send the connection parameter
+ *     value.
+ *
+ * @param stream
+ *     The stream to use to send the connection parameter value.
+ *
+ * @param mimetype
+ *     The mimetype of the connection parameter value being sent.
+ *
+ * @param name
+ *     The name of the connection parameter whose current value is being sent.
+ *
+ * @return
+ *     Zero on success, non-zero on error.
+ */
+int guac_protocol_send_argv(guac_socket* socket, guac_stream* stream,
+        const char* mimetype, const char* name);
+
+/**
  * Sends a clipboard instruction over the given guac_socket connection.
  *
  * If an error occurs sending the instruction, a non-zero value is
diff --git a/src/libguac/guacamole/user.h b/src/libguac/guacamole/user.h
index f920c32..702160f 100644
--- a/src/libguac/guacamole/user.h
+++ b/src/libguac/guacamole/user.h
@@ -677,6 +677,32 @@
 void guac_user_free_object(guac_user* user, guac_object* object);
 
 /**
+ * Streams the given connection parameter value over an argument value stream
+ * ("argv" instruction), exposing the current value of the named connection
+ * parameter to the given user. The argument value stream will be automatically
+ * allocated and freed.
+ *
+ * @param user
+ *     The Guacamole user who should receive the connection parameter value.
+ *
+ * @param socket
+ *     The socket over which instructions associated with the argument value
+ *     stream should be sent.
+ *
+ * @param mimetype
+ *     The mimetype of the data within the connection parameter value being
+ *     sent.
+ *
+ * @param name
+ *     The name of the connection parameter being sent.
+ *
+ * @param value
+ *     The current value of the connection parameter being sent.
+ */
+void guac_user_stream_argv(guac_user* user, guac_socket* socket,
+        const char* mimetype, const char* name, const char* value);
+
+/**
  * Streams the image data of the given surface over an image stream ("img"
  * instruction) as PNG-encoded data. The image stream will be automatically
  * allocated and freed.
diff --git a/src/libguac/protocol.c b/src/libguac/protocol.c
index 46a9858..ff73a55 100644
--- a/src/libguac/protocol.c
+++ b/src/libguac/protocol.c
@@ -125,6 +125,26 @@
 
 }
 
+int guac_protocol_send_argv(guac_socket* socket, guac_stream* stream,
+        const char* mimetype, const char* name) {
+
+    int ret_val;
+
+    guac_socket_instruction_begin(socket);
+    ret_val =
+           guac_socket_write_string(socket, "4.argv,")
+        || __guac_socket_write_length_int(socket, stream->index)
+        || guac_socket_write_string(socket, ",")
+        || __guac_socket_write_length_string(socket, mimetype)
+        || guac_socket_write_string(socket, ",")
+        || __guac_socket_write_length_string(socket, name)
+        || guac_socket_write_string(socket, ";");
+
+    guac_socket_instruction_end(socket);
+    return ret_val;
+
+}
+
 int guac_protocol_send_arc(guac_socket* socket, const guac_layer* layer,
         int x, int y, int radius, double startAngle, double endAngle,
         int negative) {
@@ -195,6 +215,33 @@
 
 }
 
+int guac_protocol_send_blobs(guac_socket* socket, const guac_stream* stream,
+        const void* data, int count) {
+
+    int ret_val = 0;
+
+    /* Send blob instructions while data remains and instructions are being
+     * sent successfully */
+    while (count > 0 && ret_val == 0) {
+
+        /* Limit blob size to maximum allowed */
+        int blob_size = count;
+        if (blob_size > GUAC_PROTOCOL_BLOB_MAX_LENGTH)
+            blob_size = GUAC_PROTOCOL_BLOB_MAX_LENGTH;
+
+        /* Send next blob of data */
+        ret_val = guac_protocol_send_blob(socket, stream, data, blob_size);
+
+        /* Advance to next blob */
+        data = (const char*) data + blob_size;
+        count -= blob_size;
+
+    }
+
+    return ret_val;
+
+}
+
 int guac_protocol_send_body(guac_socket* socket, const guac_object* object,
         const guac_stream* stream, const char* mimetype, const char* name) {
 
diff --git a/src/libguac/raw_encoder.c b/src/libguac/raw_encoder.c
index 9086a37..888bde7 100644
--- a/src/libguac/raw_encoder.c
+++ b/src/libguac/raw_encoder.c
@@ -121,25 +121,8 @@
     guac_socket* socket = audio->client->socket;
     guac_stream* stream = audio->stream;
 
-    unsigned char* current = state->buffer;
-    int remaining = state->written;
-
     /* Flush all data in buffer as blobs */
-    while (remaining > 0) {
-
-        /* Determine size of blob to be written */
-        int chunk_size = remaining;
-        if (chunk_size > 6048)
-            chunk_size = 6048;
-
-        /* Send audio data */
-        guac_protocol_send_blob(socket, stream, current, chunk_size);
-
-        /* Advance to next blob */
-        current += chunk_size;
-        remaining -= chunk_size;
-
-    }
+    guac_protocol_send_blobs(socket, stream, state->buffer, state->written);
 
     /* All data has been flushed */
     state->written = 0;
diff --git a/src/libguac/user.c b/src/libguac/user.c
index 9145b27..aaa51bb 100644
--- a/src/libguac/user.c
+++ b/src/libguac/user.c
@@ -229,6 +229,26 @@
 
 }
 
+void guac_user_stream_argv(guac_user* user, guac_socket* socket,
+        const char* mimetype, const char* name, const char* value) {
+
+    /* Allocate new stream for argument value */
+    guac_stream* stream = guac_user_alloc_stream(user);
+
+    /* Declare stream as containing connection parameter data */
+    guac_protocol_send_argv(socket, stream, mimetype, name);
+
+    /* Write parameter data */
+    guac_protocol_send_blobs(socket, stream, value, strlen(value));
+
+    /* Terminate stream */
+    guac_protocol_send_end(socket, stream);
+
+    /* Free allocated stream */
+    guac_user_free_stream(user, stream);
+
+}
+
 void guac_user_stream_png(guac_user* user, guac_socket* socket,
         guac_composite_mode mode, const guac_layer* layer, int x, int y,
         cairo_surface_t* surface) {