int guac_rdp_download_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* Get filesystem, return error if no filesystem */ guac_rdp_fs* fs = ((rdp_guac_client_data*) client->data)->filesystem; if (fs == NULL) { guac_protocol_send_ack(client->socket, stream, "FAIL (NO FS)", GUAC_PROTOCOL_STATUS_SERVER_ERROR); guac_socket_flush(client->socket); return 0; } /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = guac_rdp_fs_read(fs, rdp_stream->download_status.file_id, rdp_stream->download_status.offset, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) { rdp_stream->download_status.offset += bytes_read; guac_protocol_send_blob(client->socket, stream, buffer, bytes_read); } /* If EOF, send end */ else if (bytes_read == 0) { guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); free(rdp_stream); } /* Otherwise, fail stream */ else { guac_client_log(client, GUAC_LOG_ERROR, "Error reading file for download"); guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); free(rdp_stream); } guac_socket_flush(client->socket); } /* Otherwise, return stream to client */ else guac_client_free_stream(client, stream); return 0; }
void guac_audio_stream_end(guac_audio_stream* audio) { double duration; /* Flush stream and finish encoding */ guac_audio_stream_flush(audio); audio->encoder->end_handler(audio); /* Calculate duration of PCM data */ duration = ((double) (audio->pcm_bytes_written * 1000 * 8)) / audio->rate / audio->channels / audio->bps; /* Send audio */ guac_protocol_send_audio(audio->client->socket, audio->stream, audio->stream->index, audio->encoder->mimetype, duration); guac_protocol_send_blob(audio->client->socket, audio->stream, audio->encoded_data, audio->encoded_data_used); guac_protocol_send_end(audio->client->socket, audio->stream); /* Clear data */ audio->encoded_data_used = 0; }
void guac_rdpdr_process_print_job_close(guac_rdpdr_device* device, wStream* input_stream, int completion_id) { guac_rdpdr_printer_data* printer_data = (guac_rdpdr_printer_data*) device->data; wStream* output_stream = guac_rdpdr_new_io_completion(device, completion_id, STATUS_SUCCESS, 1); Stream_Write_UINT32(output_stream, 0); /* padding*/ /* Close input and wait for output thread to finish */ close(printer_data->printer_input); pthread_join(printer_data->printer_output_thread, NULL); /* Close file descriptors */ close(printer_data->printer_output); /* Close file */ guac_client_log(device->rdpdr->client, GUAC_LOG_INFO, "Print job closed"); guac_protocol_send_end(device->rdpdr->client->socket, printer_data->stream); svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); }
int guac_sftp_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { ssh_guac_client_data* client_data = (ssh_guac_client_data*) client->data; LIBSSH2_SFTP_HANDLE* file = (LIBSSH2_SFTP_HANDLE*) stream->data; /* If successful, read data */ if (status == GUAC_PROTOCOL_STATUS_SUCCESS) { /* Attempt read into buffer */ char buffer[4096]; int bytes_read = libssh2_sftp_read(file, buffer, sizeof(buffer)); /* If bytes read, send as blob */ if (bytes_read > 0) guac_protocol_send_blob(client->socket, stream, buffer, bytes_read); /* If EOF, send end */ else if (bytes_read == 0) { guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); } /* Otherwise, fail stream */ else { guac_client_log_error(client, "Error reading file: %s", libssh2_sftp_last_error(client_data->sftp_session)); guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); } guac_socket_flush(client->socket); } /* Otherwise, return stream to client */ else guac_client_free_stream(client, stream); return 0; }
/** * Callback for guac_client_foreach_user() which sends clipboard data to each * connected client. * * @param user * The user to send the clipboard data to. * * @param * A pointer to the guac_common_clipboard structure containing the * clipboard data that should be sent to the given user. * * @return * Always NULL. */ static void* __send_user_clipboard(guac_user* user, void* data) { guac_common_clipboard* clipboard = (guac_common_clipboard*) data; char* current = clipboard->buffer; int remaining = clipboard->length; /* Begin stream */ guac_stream* stream = guac_user_alloc_stream(user); guac_protocol_send_clipboard(user->socket, stream, clipboard->mimetype); guac_user_log(user, GUAC_LOG_DEBUG, "Created stream %i for %s clipboard data.", stream->index, clipboard->mimetype); /* Split clipboard into chunks */ while (remaining > 0) { /* Calculate size of next block */ int block_size = GUAC_COMMON_CLIPBOARD_BLOCK_SIZE; if (remaining < block_size) block_size = remaining; /* Send block */ guac_protocol_send_blob(user->socket, stream, current, block_size); guac_user_log(user, GUAC_LOG_DEBUG, "Sent %i bytes of clipboard data on stream %i.", block_size, stream->index); /* Next block */ remaining -= block_size; current += block_size; } guac_user_log(user, GUAC_LOG_DEBUG, "Clipboard stream %i complete.", stream->index); /* End stream */ guac_protocol_send_end(user->socket, stream); guac_user_free_stream(user, stream); return NULL; }
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_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_ls_ack_handler(guac_client* client, guac_stream* stream, char* message, guac_protocol_status status) { int blob_written = 0; const char* filename; guac_rdp_stream* rdp_stream = (guac_rdp_stream*) stream->data; /* If unsuccessful, free stream and abort */ if (status != GUAC_PROTOCOL_STATUS_SUCCESS) { guac_rdp_fs_close(rdp_stream->ls_status.fs, rdp_stream->ls_status.file_id); guac_client_free_stream(client, stream); free(rdp_stream); return 0; } /* While directory entries remain */ while ((filename = guac_rdp_fs_read_dir(rdp_stream->ls_status.fs, rdp_stream->ls_status.file_id)) != NULL && !blob_written) { char absolute_path[GUAC_RDP_FS_MAX_PATH]; /* Skip current and parent directory entries */ if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) continue; /* Concatenate into absolute path - skip if invalid */ if (!guac_rdp_fs_append_filename(absolute_path, rdp_stream->ls_status.directory_name, filename)) { guac_client_log(client, GUAC_LOG_DEBUG, "Skipping filename \"%s\" - filename is invalid or " "resulting path is too long", filename); continue; } /* Attempt to open file to determine type */ int file_id = guac_rdp_fs_open(rdp_stream->ls_status.fs, absolute_path, ACCESS_GENERIC_READ, 0, DISP_FILE_OPEN, 0); if (file_id < 0) continue; /* Get opened file */ guac_rdp_fs_file* file = guac_rdp_fs_get_file(rdp_stream->ls_status.fs, file_id); if (file == NULL) { guac_client_log(rdp_stream->ls_status.fs->client, GUAC_LOG_DEBUG, "%s: Successful open produced bad file_id: %i", __func__, file_id); return 0; } /* Determine mimetype */ const char* mimetype; if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) mimetype = GUAC_CLIENT_STREAM_INDEX_MIMETYPE; else mimetype = "application/octet-stream"; /* Write entry */ blob_written |= guac_common_json_write_property(client, stream, &rdp_stream->ls_status.json_state, absolute_path, mimetype); guac_rdp_fs_close(rdp_stream->ls_status.fs, file_id); } /* Complete JSON and cleanup at end of directory */ if (filename == NULL) { /* Complete JSON object */ guac_common_json_end_object(client, stream, &rdp_stream->ls_status.json_state); guac_common_json_flush(client, stream, &rdp_stream->ls_status.json_state); /* Clean up resources */ guac_rdp_fs_close(rdp_stream->ls_status.fs, rdp_stream->ls_status.file_id); free(rdp_stream); /* Signal of stream */ guac_protocol_send_end(client->socket, stream); guac_client_free_stream(client, stream); } guac_socket_flush(client->socket); return 0; }