GUACAMOLE-445: Implement per-device announce stream, set it up with device initalization, and collect them all during the annonuce process.
This commit is contained in:
parent
e68fe81938
commit
a1ec5d9ad7
@ -29,6 +29,7 @@
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/protocol.h>
|
||||
#include <guacamole/socket.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
#ifdef ENABLE_WINPR
|
||||
#include <winpr/stream.h>
|
||||
@ -36,21 +37,6 @@
|
||||
#include "compat/winpr-stream.h"
|
||||
#endif
|
||||
|
||||
static void guac_rdpdr_device_fs_announce_handler(guac_rdpdr_device* device,
|
||||
wStream* output_stream, int device_id) {
|
||||
|
||||
/* Filesystem header */
|
||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, "Sending filesystem");
|
||||
Stream_Write_UINT32(output_stream, RDPDR_DTYP_FILESYSTEM);
|
||||
Stream_Write_UINT32(output_stream, device_id);
|
||||
Stream_Write(output_stream, "GUAC\0\0\0\0", 8); /* DOS name */
|
||||
|
||||
/* Filesystem data */
|
||||
Stream_Write_UINT32(output_stream, GUAC_FILESYSTEM_NAME_LENGTH);
|
||||
Stream_Write(output_stream, GUAC_FILESYSTEM_NAME, GUAC_FILESYSTEM_NAME_LENGTH);
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device,
|
||||
wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) {
|
||||
|
||||
@ -128,6 +114,9 @@ static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device,
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) {
|
||||
|
||||
Stream_Free(device->device_announce, 1);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) {
|
||||
@ -143,9 +132,21 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) {
|
||||
device->rdpdr = rdpdr;
|
||||
device->device_id = id;
|
||||
device->device_name = "Guacamole Filesystem";
|
||||
int device_name_len = guac_utf8_strlen(device->device_name);
|
||||
device->device_type = RDPDR_DTYP_FILESYSTEM;
|
||||
device->dos_name = "GUACFS\0\0";
|
||||
|
||||
/* Set up the device announcement */
|
||||
device->device_announce_len = 20 + device_name_len;
|
||||
device->device_announce = Stream_New(NULL, device->device_announce_len);
|
||||
Stream_Write_UINT32(device->device_announce, device->device_type);
|
||||
Stream_Write_UINT32(device->device_announce, device->device_id);
|
||||
Stream_Write(device->device_announce, device->dos_name, 8);
|
||||
Stream_Write_UINT32(device->device_announce, device_name_len);
|
||||
Stream_Write(device->device_announce, device->device_name, device_name_len);
|
||||
|
||||
|
||||
/* Set handlers */
|
||||
device->announce_handler = guac_rdpdr_device_fs_announce_handler;
|
||||
device->iorequest_handler = guac_rdpdr_device_fs_iorequest_handler;
|
||||
device->free_handler = guac_rdpdr_device_fs_free_handler;
|
||||
|
||||
|
@ -22,9 +22,11 @@
|
||||
#include "rdp.h"
|
||||
#include "rdpdr_messages.h"
|
||||
#include "rdpdr_service.h"
|
||||
#include "unicode.h"
|
||||
|
||||
#include <freerdp/utils/svc_plugin.h>
|
||||
#include <guacamole/client.h>
|
||||
#include <guacamole/unicode.h>
|
||||
|
||||
#ifdef ENABLE_WINPR
|
||||
#include <winpr/stream.h>
|
||||
@ -122,20 +124,29 @@ static void guac_rdpdr_send_client_capability(guac_rdpdrPlugin* rdpdr) {
|
||||
|
||||
static void guac_rdpdr_send_client_device_list_announce_request(guac_rdpdrPlugin* rdpdr) {
|
||||
|
||||
int i;
|
||||
wStream* output_stream = Stream_New(NULL, 256);
|
||||
/* Calculate number of bytes needed for the stream */
|
||||
int streamBytes = 16;
|
||||
for (int i=0; i < rdpdr->devices_registered; i++)
|
||||
streamBytes += rdpdr->devices[i].device_announce_len;
|
||||
|
||||
/* Allocate the stream */
|
||||
wStream* output_stream = Stream_New(NULL, streamBytes);
|
||||
|
||||
/* Write header */
|
||||
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
||||
Stream_Write_UINT16(output_stream, PAKID_CORE_DEVICELIST_ANNOUNCE);
|
||||
|
||||
/* List devices */
|
||||
/* Get the stream for each of the devices. */
|
||||
Stream_Write_UINT32(output_stream, rdpdr->devices_registered);
|
||||
for (i=0; i<rdpdr->devices_registered; i++) {
|
||||
guac_rdpdr_device* device = &(rdpdr->devices[i]);
|
||||
device->announce_handler(device, output_stream, i);
|
||||
for (int i=0; i<rdpdr->devices_registered; i++) {
|
||||
|
||||
Stream_Write(output_stream,
|
||||
Stream_Buffer(rdpdr->devices[i].device_announce),
|
||||
rdpdr->devices[i].device_announce_len);
|
||||
|
||||
guac_client_log(rdpdr->client, GUAC_LOG_INFO, "Registered device %i (%s)",
|
||||
device->device_id, device->device_name);
|
||||
rdpdr->devices[i].device_id, rdpdr->devices[i].device_name);
|
||||
|
||||
}
|
||||
|
||||
svc_plugin_send((rdpSvcPlugin*) rdpdr, output_stream);
|
||||
|
@ -133,38 +133,6 @@ void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device,
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_printer_announce_handler(guac_rdpdr_device* device,
|
||||
wStream* output_stream, int device_id) {
|
||||
|
||||
/* Printer header */
|
||||
guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, "Sending printer");
|
||||
Stream_Write_UINT32(output_stream, RDPDR_DTYP_PRINT);
|
||||
Stream_Write_UINT32(output_stream, device_id);
|
||||
Stream_Write(output_stream, "PRN1\0\0\0\0", 8); /* DOS name */
|
||||
|
||||
/* Printer data */
|
||||
int settings_length = guac_utf8_strlen(device->device_name);
|
||||
int printer_name_length = (settings_length + 1) * 2;
|
||||
char printer_name[printer_name_length];
|
||||
guac_rdp_utf8_to_utf16((const unsigned char*)device->device_name,
|
||||
settings_length, printer_name, printer_name_length);
|
||||
printer_name[printer_name_length - 2] = '\0';
|
||||
printer_name[printer_name_length - 1] = '\0';
|
||||
Stream_Write_UINT32(output_stream, 24 + GUAC_PRINTER_DRIVER_LENGTH + printer_name_length);
|
||||
Stream_Write_UINT32(output_stream,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER
|
||||
| RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER);
|
||||
Stream_Write_UINT32(output_stream, 0); /* reserved - must be 0 */
|
||||
Stream_Write_UINT32(output_stream, 0); /* PnPName length (PnPName is ultimately ignored) */
|
||||
Stream_Write_UINT32(output_stream, GUAC_PRINTER_DRIVER_LENGTH); /* DriverName length */
|
||||
Stream_Write_UINT32(output_stream, printer_name_length); /* PrinterName length */
|
||||
Stream_Write_UINT32(output_stream, 0); /* CachedFields length */
|
||||
|
||||
Stream_Write(output_stream, GUAC_PRINTER_DRIVER, GUAC_PRINTER_DRIVER_LENGTH);
|
||||
Stream_Write(output_stream, printer_name, printer_name_length);
|
||||
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* device,
|
||||
wStream* input_stream, int file_id, int completion_id, int major_func, int minor_func) {
|
||||
|
||||
@ -196,7 +164,9 @@ static void guac_rdpdr_device_printer_iorequest_handler(guac_rdpdr_device* devic
|
||||
}
|
||||
|
||||
static void guac_rdpdr_device_printer_free_handler(guac_rdpdr_device* device) {
|
||||
/* Do nothing */
|
||||
|
||||
Stream_Free(device->device_announce, 1);
|
||||
|
||||
}
|
||||
|
||||
void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr, char* printer_name) {
|
||||
@ -210,9 +180,41 @@ void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr, char* printer_name) {
|
||||
device->rdpdr = rdpdr;
|
||||
device->device_id = id;
|
||||
device->device_name = printer_name;
|
||||
int device_name_len = guac_utf8_strlen(device->device_name);
|
||||
device->device_type = RDPDR_DTYP_PRINT;
|
||||
device->dos_name = "PRN1\0\0\0\0";
|
||||
|
||||
/* Set up device announce stream */
|
||||
int prt_name_len = (device_name_len + 1) * 2;
|
||||
device->device_announce_len = 44 + prt_name_len
|
||||
+ GUAC_PRINTER_DRIVER_LENGTH;
|
||||
device->device_announce = Stream_New(NULL, device->device_announce_len);
|
||||
|
||||
/* Write common information. */
|
||||
Stream_Write_UINT32(device->device_announce, device->device_type);
|
||||
Stream_Write_UINT32(device->device_announce, device->device_id);
|
||||
Stream_Write(device->device_announce, device->dos_name, 8);
|
||||
|
||||
/* DeviceDataLength */
|
||||
Stream_Write_UINT32(device->device_announce, 24 + prt_name_len + GUAC_PRINTER_DRIVER_LENGTH);
|
||||
|
||||
/* Begin printer-specific information */
|
||||
Stream_Write_UINT32(device->device_announce,
|
||||
RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER
|
||||
| RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER); /* Printer flags */
|
||||
Stream_Write_UINT32(device->device_announce, 0); /* Reserved - must be 0. */
|
||||
Stream_Write_UINT32(device->device_announce, 0); /* PnPName Length - ignored. */
|
||||
Stream_Write_UINT32(device->device_announce, GUAC_PRINTER_DRIVER_LENGTH);
|
||||
Stream_Write_UINT32(device->device_announce, prt_name_len);
|
||||
Stream_Write_UINT32(device->device_announce, 0); /* CachedFields length. */
|
||||
|
||||
Stream_Write(device->device_announce, GUAC_PRINTER_DRIVER, GUAC_PRINTER_DRIVER_LENGTH);
|
||||
guac_rdp_utf8_to_utf16((const unsigned char*) device->device_name,
|
||||
device_name_len + 1, (char*) Stream_Pointer(device->device_announce),
|
||||
prt_name_len);
|
||||
Stream_Seek(device->device_announce, prt_name_len);
|
||||
|
||||
/* Set handlers */
|
||||
device->announce_handler = guac_rdpdr_device_printer_announce_handler;
|
||||
device->iorequest_handler = guac_rdpdr_device_printer_iorequest_handler;
|
||||
device->free_handler = guac_rdpdr_device_printer_free_handler;
|
||||
|
||||
|
@ -34,6 +34,13 @@
|
||||
/**
|
||||
* Registers a new printer device within the RDPDR plugin. This must be done
|
||||
* before RDPDR connection finishes.
|
||||
*
|
||||
* @param rdpdr
|
||||
* The RDP device redirection plugin where the device is registered.
|
||||
*
|
||||
* @param printer_name
|
||||
* The name of the printer that will be registered with the RDP
|
||||
* connection and passed through to the server.
|
||||
*/
|
||||
void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr, char* printer_name);
|
||||
|
||||
|
@ -74,15 +74,30 @@ struct guac_rdpdr_device {
|
||||
int device_id;
|
||||
|
||||
/**
|
||||
* An arbitrary device name, used for logging purposes only.
|
||||
* Device name, used for logging and for passthrough to the
|
||||
* server.
|
||||
*/
|
||||
const char* device_name;
|
||||
|
||||
/**
|
||||
* Handler which will be called when the RDPDR plugin is forming the client
|
||||
* device announce list.
|
||||
* The type of RDPDR device that this represents.
|
||||
*/
|
||||
guac_rdpdr_device_announce_handler* announce_handler;
|
||||
uint32_t device_type;
|
||||
|
||||
/**
|
||||
* The DOS name of the device. Max 8 bytes, including terminator.
|
||||
*/
|
||||
const char *dos_name;
|
||||
|
||||
/**
|
||||
* The stream that stores the RDPDR device announcement for this device.
|
||||
*/
|
||||
wStream* device_announce;
|
||||
|
||||
/**
|
||||
* The length of the device_announce wStream.
|
||||
*/
|
||||
int device_announce_len;
|
||||
|
||||
/**
|
||||
* Handler which should be called for every I/O request received.
|
||||
@ -90,7 +105,7 @@ struct guac_rdpdr_device {
|
||||
guac_rdpdr_device_iorequest_handler* iorequest_handler;
|
||||
|
||||
/**
|
||||
* Handlel which should be called when the device is being free'd.
|
||||
* Handler which should be called when the device is being freed.
|
||||
*/
|
||||
guac_rdpdr_device_free_handler* free_handler;
|
||||
|
||||
@ -154,7 +169,7 @@ void guac_rdpdr_process_terminate(rdpSvcPlugin* plugin);
|
||||
void guac_rdpdr_process_event(rdpSvcPlugin* plugin, wMessage* event);
|
||||
|
||||
/**
|
||||
* Creates a new stream which contains the ommon DR_DEVICE_IOCOMPLETION header
|
||||
* Creates a new stream which contains the common DR_DEVICE_IOCOMPLETION header
|
||||
* used for virtually all responses.
|
||||
*/
|
||||
wStream* guac_rdpdr_new_io_completion(guac_rdpdr_device* device,
|
||||
|
Loading…
Reference in New Issue
Block a user