void guac_rdpdr_register_printer(guac_rdpdrPlugin* rdpdr) { int id = rdpdr->devices_registered++; /* Get new device */ guac_rdpdr_device* device = &(rdpdr->devices[id]); guac_rdpdr_printer_data* printer_data; /* Init device */ device->rdpdr = rdpdr; device->device_id = id; device->device_name = "Guacamole Printer"; // device->device_name = "V2 Cloud Printer"; /* 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; /* Init data */ printer_data = malloc(sizeof(guac_rdpdr_printer_data)); printer_data->stream = guac_client_alloc_stream(rdpdr->client); device->data = printer_data; }
guac_stream* guac_sftp_download_file(guac_client* client, char* filename) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; guac_stream* stream; LIBSSH2_SFTP_HANDLE* file; /* Attempt to open file for reading */ file = libssh2_sftp_open(client_data->sftp_session, filename, LIBSSH2_FXF_READ, 0); if (file == NULL) { guac_client_log_error(client, "Unable to read file \"%s\": %s", filename, libssh2_sftp_last_error(client_data->sftp_session)); return NULL; } /* Allocate stream */ stream = guac_client_alloc_stream(client); stream->ack_handler = guac_sftp_ack_handler; stream->data = file; /* Send stream start, strip name */ filename = basename(filename); guac_protocol_send_file(client->socket, stream, "application/octet-stream", filename); guac_socket_flush(client->socket); return stream; }
guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encoder* encoder, int rate, int channels, int bps) { guac_audio_stream* audio; /* Allocate stream */ audio = (guac_audio_stream*) calloc(1, sizeof(guac_audio_stream)); audio->client = client; audio->stream = guac_client_alloc_stream(client); /* Load PCM properties */ audio->rate = rate; audio->channels = channels; audio->bps = bps; /* Assign encoder for owner, abort if no encoder can be found */ if (!guac_client_for_owner(client, guac_audio_assign_encoder, audio)) { guac_client_free_stream(client, audio->stream); free(audio); return NULL; } /* Call handler, if defined */ if (audio->encoder->begin_handler) audio->encoder->begin_handler(audio); return audio; }
guac_audio_stream* guac_audio_stream_alloc(guac_client* client, guac_audio_encoder* encoder) { guac_audio_stream* audio; /* Choose an encoding if not specified */ if (encoder == NULL) { int i; /* For each supported mimetype, check for an associated encoder */ for (i=0; client->info.audio_mimetypes[i] != NULL; i++) { const char* mimetype = client->info.audio_mimetypes[i]; #ifdef ENABLE_OGG /* If Ogg is supported, done. */ if (strcmp(mimetype, ogg_encoder->mimetype) == 0) { encoder = ogg_encoder; break; } #endif /* If wav is supported, done. */ if (strcmp(mimetype, wav_encoder->mimetype) == 0) { encoder = wav_encoder; break; } } /* end for each mimetype */ /* If still no encoder could be found, fail */ if (encoder == NULL) return NULL; } /* Allocate stream */ audio = (guac_audio_stream*) malloc(sizeof(guac_audio_stream)); audio->client = client; /* Reset buffer stats */ audio->used = 0; audio->length = 0x40000; audio->encoded_data_used = 0; audio->encoded_data_length = 0x40000; /* Allocate buffers */ audio->pcm_data = malloc(audio->length); audio->encoded_data = malloc(audio->encoded_data_length); /* Assign encoder */ audio->encoder = encoder; audio->stream = guac_client_alloc_stream(client); return audio; }
void guac_rdpdr_start_download(guac_rdpdr_device* device, const char* path) { /* Get client and stream */ guac_client* client = device->rdpdr->client; int file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, path, ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); /* If file opened successfully, start stream */ if (file_id >= 0) { guac_rdp_stream* rdp_stream; const char* basename; int i; char c; /* Associate stream with transfer status */ guac_stream* stream = guac_client_alloc_stream(client); stream->data = rdp_stream = malloc(sizeof(guac_rdp_stream)); stream->ack_handler = guac_rdp_download_ack_handler; rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; rdp_stream->download_status.file_id = file_id; rdp_stream->download_status.offset = 0; /* Get basename from absolute path */ i=0; basename = path; do { c = path[i]; if (c == '/' || c == '\\') basename = &(path[i+1]); i++; } while (c != '\0'); GUAC_RDP_DEBUG(2, "Initiating download of \"%s\"", path); /* Begin stream */ guac_protocol_send_file(client->socket, stream, "application/octet-stream", basename); guac_socket_flush(client->socket); } else guac_client_log(client, GUAC_LOG_ERROR, "Unable to download \"%s\"", path); }
void guac_client_stream_jpeg(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality) { /* Allocate new stream for image */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/jpeg", x, y); /* Write JPEG data */ guac_jpeg_write(socket, stream, surface, quality); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); }
void guac_svc_process_connect(rdpSvcPlugin* plugin) { /* Get corresponding guac_rdp_svc */ guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin; guac_rdp_svc* svc = svc_plugin->svc; /* NULL out pExtendedData so we don't lose our guac_rdp_svc due to an * automatic free() within libfreerdp */ plugin->channel_entry_points.pExtendedData = NULL; /* Create pipe */ svc->output_pipe = guac_client_alloc_stream(svc->client); /* Notify of pipe's existence */ guac_rdp_svc_send_pipe(svc->client->socket, svc); /* Log connection to static channel */ guac_client_log(svc->client, GUAC_LOG_INFO, "Static channel \"%s\" connected.", svc->name); }
void guac_client_stream_webp(guac_client* client, guac_socket* socket, guac_composite_mode mode, const guac_layer* layer, int x, int y, cairo_surface_t* surface, int quality, int lossless) { #ifdef ENABLE_WEBP /* Allocate new stream for image */ guac_stream* stream = guac_client_alloc_stream(client); /* Declare stream as containing image data */ guac_protocol_send_img(socket, stream, mode, layer, "image/webp", x, y); /* Write WebP data */ guac_webp_write(socket, stream, surface, quality, lossless); /* Terminate stream */ guac_protocol_send_end(socket, stream); /* Free allocated stream */ guac_client_free_stream(client, stream); #else /* Do nothing if WebP support is not built in */ #endif }
int guac_rdp_download_get_handler(guac_client* client, guac_object* object, char* name) { /* Get filesystem, ignore request if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) return 0; /* Attempt to open file for reading */ int file_id = guac_rdp_fs_open(fs, name, ACCESS_GENERIC_READ, 0, DISP_FILE_OPEN, 0); if (file_id < 0) { guac_client_log(client, GUAC_LOG_INFO, "Unable to read file \"%s\"", name); return 0; } /* Get opened file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id); if (file == NULL) { guac_client_log(fs->client, GUAC_LOG_DEBUG, "%s: Successful open produced bad file_id: %i", __func__, file_id); return 0; } /* If directory, send contents of directory */ if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { /* Create stream data */ guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); rdp_stream->type = GUAC_RDP_LS_STREAM; rdp_stream->ls_status.fs = fs; rdp_stream->ls_status.file_id = file_id; strncpy(rdp_stream->ls_status.directory_name, name, sizeof(rdp_stream->ls_status.directory_name)); /* Allocate stream for body */ guac_stream* stream = guac_client_alloc_stream(client); stream->ack_handler = guac_rdp_ls_ack_handler; stream->data = rdp_stream; /* Init JSON object state */ guac_common_json_begin_object(client, stream, &rdp_stream->ls_status.json_state); /* Associate new stream with get request */ guac_protocol_send_body(client->socket, object, stream, GUAC_CLIENT_STREAM_INDEX_MIMETYPE, name); } /* Otherwise, send file contents */ else { /* Create stream data */ guac_rdp_stream* rdp_stream = malloc(sizeof(guac_rdp_stream)); rdp_stream->type = GUAC_RDP_DOWNLOAD_STREAM; rdp_stream->download_status.file_id = file_id; rdp_stream->download_status.offset = 0; /* Allocate stream for body */ guac_stream* stream = guac_client_alloc_stream(client); stream->data = rdp_stream; stream->ack_handler = guac_rdp_download_ack_handler; /* Associate new stream with get request */ guac_protocol_send_body(client->socket, object, stream, "application/octet-stream", name); } guac_socket_flush(client->socket); return 0; }
/** * Guacamole client plugin entry point. This function will be called by guacd * when the protocol associated with this plugin is selected. * * @param client * A newly-allocated guac_client structure representing the client which * connected to guacd. * * @param argc * The number of arguments within the argv array. * * @param argv * All arguments passed during the Guacamole protocol handshake. These * arguments correspond identically in both order and number to the * arguments listed in GUAC_CLIENT_ARGS. */ int guac_client_init(guac_client* client, int argc, char** argv) { /* Validate argument count */ if (argc != STREAMTEST_ARGS_COUNT) { guac_client_log(client, GUAC_LOG_ERROR, "Wrong number of arguments."); return 1; } /* Allocate stream for media */ streamtest_playback_mode mode; guac_stream* stream = guac_client_alloc_stream(client); /* Determine playback mode from mimetype */ if (strncmp(argv[IDX_MIMETYPE], "audio/", 6) == 0) { mode = STREAMTEST_AUDIO; guac_client_log(client, GUAC_LOG_DEBUG, "Recognized type \"%s\" as audio", argv[IDX_MIMETYPE]); } else if (strncmp(argv[IDX_MIMETYPE], "video/", 6) == 0) { mode = STREAMTEST_VIDEO; guac_client_log(client, GUAC_LOG_DEBUG, "Recognized type \"%s\" as video", argv[IDX_MIMETYPE]); } /* Abort if type cannot be recognized */ else { guac_client_log(client, GUAC_LOG_ERROR, "Invalid media type \"%s\" (not audio nor video)", argv[IDX_MIMETYPE]); return 1; } /* Initialize streaming depending on playback mode */ switch (mode) { /* Set up progress bar for audio streams */ case STREAMTEST_AUDIO: /* Begin audio stream */ guac_protocol_send_audio(client->socket, stream, argv[IDX_MIMETYPE]); /* Init display */ guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, STREAMTEST_PROGRESS_WIDTH, STREAMTEST_PROGRESS_HEIGHT); break; /* Set up generic video area for video streams */ case STREAMTEST_VIDEO: /* Begin video stream */ guac_protocol_send_video(client->socket, stream, GUAC_DEFAULT_LAYER, argv[IDX_MIMETYPE]); /* Init display */ guac_protocol_send_size(client->socket, GUAC_DEFAULT_LAYER, client->info.optimal_width, client->info.optimal_height); break; /* There are no other playback modes */ default: assert(false); } /* Attempt to open specified file, abort on error */ int fd = open(argv[IDX_FILENAME], O_RDONLY); if (fd == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to open \"%s\": %s", argv[IDX_FILENAME], strerror(errno)); return 1; } int file_size = streamtest_get_file_size(fd); if (file_size == -1) { guac_client_log(client, GUAC_LOG_ERROR, "Unable to determine size of file \"%s\": %s", argv[IDX_FILENAME], strerror(errno)); return 1; } guac_client_log(client, GUAC_LOG_DEBUG, "Successfully opened file \"%s\" (%i bytes)", argv[IDX_FILENAME], file_size); /* Allocate state structure */ streamtest_state* state = malloc(sizeof(streamtest_state)); /* Set frame duration/size */ state->frame_duration = atoi(argv[IDX_FRAME_USECS]); state->frame_bytes = atoi(argv[IDX_BYTES_PER_FRAME]); state->frame_buffer = malloc(state->frame_bytes); guac_client_log(client, GUAC_LOG_DEBUG, "Frames will last %i microseconds and contain %i bytes", state->frame_duration, state->frame_bytes); /* Start with the file closed, playback not paused */ state->mode = mode; state->stream = stream; state->fd = fd; state->paused = false; state->file_size = file_size; /* Set client handlers and data */ client->handle_messages = streamtest_client_message_handler; client->key_handler = streamtest_client_key_handler; client->free_handler = streamtest_client_free_handler; client->data = state; /* Render initial progress bar */ streamtest_render_progress(client); guac_socket_flush(client->socket); /* Initialization complete */ return 0; }