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; }
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; }
/** * Writes the contents of the PNG write state as a blob to its associated * socket. * * @param write_state * The write state to flush. */ static void guac_png_flush_data(guac_png_write_state* write_state) { /* Send blob */ guac_protocol_send_blob(write_state->socket, write_state->stream, write_state->buffer, write_state->buffer_size); /* Clear buffer */ write_state->buffer_size = 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; }
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; }
static void* guac_rdpdr_print_filter_output_thread(void* data) { guac_rdpdr_device* device = (guac_rdpdr_device*) data; guac_rdpdr_printer_data* printer_data = (guac_rdpdr_printer_data*) device->data; int length; char buffer[8192]; /* Write all output as blobs */ while ((length = read(printer_data->printer_output, buffer, sizeof(buffer))) > 0) guac_protocol_send_blob(device->rdpdr->client->socket, printer_data->stream, buffer, length); /* Log any error */ if (length < 0) guac_client_log(device->rdpdr->client, GUAC_LOG_ERROR, "Error reading from filter: %s", strerror(errno)); return NULL; }
/** * Writes the given buffer as a set of blob instructions to the given socket. * The buffer will be split into as many blob instructions as necessary. * * @param socket * The guac_socket over which the blob instructions should be sent. * * @param stream * The stream to associate with each blob. * * @param buffer * The buffer containing the data that should be sent over the given * guac_socket as blobs. * * @param length * The number of bytes within the given buffer. */ static void streamtest_write_blobs(guac_socket* socket, guac_stream* stream, unsigned char* buffer, int length) { /* Flush all data in buffer as blobs */ while (length > 0) { /* Determine size of blob to be written */ int chunk_size = length; if (chunk_size > 6048) chunk_size = 6048; /* Send audio data */ guac_protocol_send_blob(socket, stream, buffer, chunk_size); /* Advance to next blob */ buffer += chunk_size; length -= chunk_size; } }
void guac_svc_process_receive(rdpSvcPlugin* plugin, wStream* input_stream) { /* Get corresponding guac_rdp_svc */ guac_svcPlugin* svc_plugin = (guac_svcPlugin*) plugin; guac_rdp_svc* svc = svc_plugin->svc; /* Fail if output not created */ if (svc->output_pipe == NULL) { guac_client_log(svc->client, GUAC_LOG_ERROR, "Output for channel \"%s\" dropped.", svc->name); return; } /* Send blob */ guac_protocol_send_blob(svc->client->socket, svc->output_pipe, Stream_Buffer(input_stream), Stream_Length(input_stream)); guac_socket_flush(svc->client->socket); }