Refactor of guac_read_instruction, migrate to new guac_read_instruction
This commit is contained in:
parent
5214b1538d
commit
857c2e03c9
@ -73,6 +73,12 @@ typedef enum guac_status {
|
||||
*/
|
||||
GUAC_STATUS_INPUT_TIMEOUT,
|
||||
|
||||
/**
|
||||
* An error occurred, and further information about the error is already
|
||||
* stored in errno.
|
||||
*/
|
||||
GUAC_STATUS_SEE_ERRNO,
|
||||
|
||||
/**
|
||||
* An error prevented the operation from writing to its associated
|
||||
* output stream.
|
||||
|
@ -143,19 +143,7 @@ typedef struct guac_instruction {
|
||||
|
||||
|
||||
/**
|
||||
* Frees all memory allocated to the given instruction opcode
|
||||
* and arguments. The instruction structure itself will not
|
||||
* be freed.
|
||||
*
|
||||
* @param instruction The instruction to free.
|
||||
*/
|
||||
void guac_free_instruction_data(guac_instruction* instruction);
|
||||
|
||||
|
||||
/**
|
||||
* Frees all memory allocated to the given instruction. This
|
||||
* includes freeing memory allocated for the structure
|
||||
* itself.
|
||||
* Frees all memory allocated to the given instruction.
|
||||
*
|
||||
* @param instruction The instruction to free.
|
||||
*/
|
||||
@ -345,23 +333,20 @@ int guac_instructions_waiting(GUACIO* io, int usec_timeout);
|
||||
/**
|
||||
* Reads a single instruction from the given GUACIO connection.
|
||||
*
|
||||
* If an error occurs reading the instruction, a non-zero value is
|
||||
* returned, and guac_error is set appropriately.
|
||||
* If an error occurs reading the instruction, NULL is returned,
|
||||
* and guac_error is set appropriately.
|
||||
*
|
||||
* @param io The GUACIO connection to use.
|
||||
* @param usec_timeout The maximum number of microseconds to wait before
|
||||
* giving up.
|
||||
* @param parsed_instruction A pointer to a guac_instruction structure which
|
||||
* will be populated with data read from the given
|
||||
* GUACIO connection.
|
||||
* @return A positive value if data was successfully read, negative on
|
||||
* error, or zero if the instruction could not be read completely
|
||||
* because the timeout elapsed, in which case subsequent calls to
|
||||
* @return A new instruction if data was successfully read, NULL on
|
||||
* error or if the instruction could not be read completely
|
||||
* because the timeout elapsed, in which case guac_error will be
|
||||
* set to GUAC_STATUS_INPUT_TIMEOUT and subsequent calls to
|
||||
* guac_read_instruction() will return the parsed instruction once
|
||||
* enough data is available.
|
||||
*/
|
||||
int guac_read_instruction(GUACIO* io, int usec_timeout,
|
||||
guac_instruction* parsed_instruction);
|
||||
guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout);
|
||||
|
||||
/**
|
||||
* Returns an arbitrary timestamp. The difference between return values of any
|
||||
|
@ -151,7 +151,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
char** argv;
|
||||
|
||||
/* Instruction */
|
||||
guac_instruction instruction;
|
||||
guac_instruction* instruction;
|
||||
|
||||
/* Wait for select instruction */
|
||||
for (;;) {
|
||||
@ -172,19 +172,19 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = guac_read_instruction(io, usec_timeout, &instruction);
|
||||
if (result < 0) {
|
||||
instruction = guac_read_instruction(io, usec_timeout);
|
||||
if (instruction == NULL) {
|
||||
guac_close(io);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Select instruction read */
|
||||
if (result > 0) {
|
||||
else {
|
||||
|
||||
if (strcmp(instruction.opcode, "select") == 0) {
|
||||
if (strcmp(instruction->opcode, "select") == 0) {
|
||||
|
||||
/* Get protocol from message */
|
||||
char* protocol = instruction.argv[0];
|
||||
char* protocol = instruction->argv[0];
|
||||
|
||||
strcat(protocol_lib, protocol);
|
||||
strcat(protocol_lib, ".so");
|
||||
@ -199,7 +199,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
guac_send_error(io, "Could not load server-side client plugin.");
|
||||
guac_flush(io);
|
||||
guac_close(io);
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -213,7 +213,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
guac_send_error(io, "Invalid server-side client plugin.");
|
||||
guac_flush(io);
|
||||
guac_close(io);
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -225,7 +225,7 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
guac_send_error(io, "Invalid server-side client plugin.");
|
||||
guac_flush(io);
|
||||
guac_close(io);
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -234,16 +234,16 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
|| guac_flush(io)
|
||||
) {
|
||||
guac_close(io);
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
break;
|
||||
|
||||
} /* end if select */
|
||||
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
}
|
||||
|
||||
}
|
||||
@ -267,35 +267,35 @@ guac_client* guac_get_client(int client_fd, int usec_timeout) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = guac_read_instruction(io, usec_timeout, &instruction);
|
||||
if (result < 0) {
|
||||
instruction = guac_read_instruction(io, usec_timeout);
|
||||
if (instruction == NULL) {
|
||||
guac_log_error("Error reading instruction while waiting for connect");
|
||||
guac_close(io);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Connect instruction read */
|
||||
if (result > 0) {
|
||||
else {
|
||||
|
||||
if (strcmp(instruction.opcode, "connect") == 0) {
|
||||
if (strcmp(instruction->opcode, "connect") == 0) {
|
||||
|
||||
/* Initialize client arguments */
|
||||
argc = instruction.argc;
|
||||
argv = instruction.argv;
|
||||
argc = instruction->argc;
|
||||
argv = instruction->argv;
|
||||
|
||||
if (alias.client_init(client, argc, argv) != 0) {
|
||||
/* NOTE: On error, proxy client will send appropriate error message */
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
guac_close(io);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
return client;
|
||||
|
||||
} /* end if connect */
|
||||
|
||||
guac_free_instruction_data(&instruction);
|
||||
guac_free_instruction(instruction);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,6 +49,7 @@ const char* __GUAC_STATUS_SUCCESS_STR = "Success";
|
||||
const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory";
|
||||
const char* __GUAC_STATUS_NO_INPUT_STR = "End of input stream";
|
||||
const char* __GUAC_STATUS_INPUT_TIMEOUT_STR = "Read timeout";
|
||||
const char* __GUAC_STATUS_SEE_ERRNO_STR = "(see value of errno)";
|
||||
const char* __GUAC_STATUS_OUTPUT_ERROR_STR = "Output error";
|
||||
const char* __GUAC_STATUS_BAD_ARGUMENT_STR = "Invalid argument";
|
||||
const char* __GUAC_STATUS_BAD_STATE_STR = "Illegal state";
|
||||
@ -75,6 +76,10 @@ const char* guac_status_string(guac_status status) {
|
||||
case GUAC_STATUS_INPUT_TIMEOUT:
|
||||
return __GUAC_STATUS_INPUT_TIMEOUT_STR;
|
||||
|
||||
/* Further information in errno */
|
||||
case GUAC_STATUS_SEE_ERRNO:
|
||||
return __GUAC_STATUS_SEE_ERRNO_STR;
|
||||
|
||||
/* Output error */
|
||||
case GUAC_STATUS_OUTPUT_ERROR:
|
||||
return __GUAC_STATUS_OUTPUT_ERROR_STR;
|
||||
|
@ -117,7 +117,7 @@ ssize_t __guac_write(GUACIO* io, const char* buf, int count) {
|
||||
|
||||
/* Record errors in guac_error */
|
||||
if (retval < 0)
|
||||
guac_error = GUAC_STATUS_OUTPUT_ERROR;
|
||||
guac_error = GUAC_STATUS_SEE_ERRNO;
|
||||
|
||||
return retval;
|
||||
}
|
||||
@ -317,7 +317,7 @@ int guac_select(GUACIO* io, int usec_timeout) {
|
||||
}
|
||||
|
||||
/* Properly set guac_error */
|
||||
if (retval < 0) guac_error = GUAC_STATUS_INPUT_ERROR;
|
||||
if (retval < 0) guac_error = GUAC_STATUS_SEE_ERRNO;
|
||||
if (retval == 0) guac_error = GUAC_STATUS_INPUT_TIMEOUT;
|
||||
|
||||
return retval;
|
||||
|
@ -62,6 +62,7 @@
|
||||
|
||||
#include "guacio.h"
|
||||
#include "protocol.h"
|
||||
#include "error.h"
|
||||
|
||||
ssize_t __guac_write_length_string(GUACIO* io, const char* str) {
|
||||
|
||||
@ -328,7 +329,7 @@ int guac_send_cursor(GUACIO* io, int x, int y, cairo_surface_t* surface) {
|
||||
}
|
||||
|
||||
|
||||
int __guac_fill___instructionbuf(GUACIO* io) {
|
||||
int __guac_fill_instructionbuf(GUACIO* io) {
|
||||
|
||||
int retval;
|
||||
|
||||
@ -356,8 +357,7 @@ int __guac_fill___instructionbuf(GUACIO* io) {
|
||||
}
|
||||
|
||||
/* Returns new instruction if one exists, or NULL if no more instructions. */
|
||||
int guac_read_instruction(GUACIO* io, int usec_timeout,
|
||||
guac_instruction* parsed_instruction) {
|
||||
guac_instruction* guac_read_instruction(GUACIO* io, int usec_timeout) {
|
||||
|
||||
int retval;
|
||||
int i = io->__instructionbuf_parse_start;
|
||||
@ -407,19 +407,59 @@ int guac_read_instruction(GUACIO* io, int usec_timeout,
|
||||
/* Finish parse if terminator is a semicolon */
|
||||
if (terminator == ';') {
|
||||
|
||||
guac_instruction* parsed_instruction;
|
||||
int j;
|
||||
|
||||
/* Allocate instruction */
|
||||
parsed_instruction = malloc(sizeof(guac_instruction));
|
||||
if (parsed_instruction == NULL) {
|
||||
guac_error = GUAC_STATUS_NO_MEMORY;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Init parsed instruction */
|
||||
parsed_instruction->argc = io->__instructionbuf_elementc - 1;
|
||||
parsed_instruction->argv = malloc(sizeof(char*) * parsed_instruction->argc);
|
||||
|
||||
/* Fail if memory could not be alloc'd for argv */
|
||||
if (parsed_instruction->argv == NULL) {
|
||||
guac_error = GUAC_STATUS_NO_MEMORY;
|
||||
free(parsed_instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set opcode */
|
||||
parsed_instruction->opcode = strdup(io->__instructionbuf_elementv[0]);
|
||||
|
||||
/* Fail if memory could not be alloc'd for opcode */
|
||||
if (parsed_instruction->opcode == NULL) {
|
||||
guac_error = GUAC_STATUS_NO_MEMORY;
|
||||
free(parsed_instruction->argv);
|
||||
free(parsed_instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* Copy element values to parsed instruction */
|
||||
for (j=0; j<parsed_instruction->argc; j++)
|
||||
for (j=0; j<parsed_instruction->argc; j++) {
|
||||
parsed_instruction->argv[j] = strdup(io->__instructionbuf_elementv[j+1]);
|
||||
|
||||
/* Free memory and fail if out of mem */
|
||||
if (parsed_instruction->argv[j] == NULL) {
|
||||
guac_error = GUAC_STATUS_NO_MEMORY;
|
||||
|
||||
/* Free all alloc'd argv values */
|
||||
while (--j >= 0)
|
||||
free(parsed_instruction->argv[j]);
|
||||
|
||||
free(parsed_instruction->opcode);
|
||||
free(parsed_instruction->argv);
|
||||
free(parsed_instruction);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Reset buffer */
|
||||
memmove(io->__instructionbuf, io->__instructionbuf + i + 1, io->__instructionbuf_used_length - i - 1);
|
||||
io->__instructionbuf_used_length -= i + 1;
|
||||
@ -427,7 +467,7 @@ int guac_read_instruction(GUACIO* io, int usec_timeout,
|
||||
io->__instructionbuf_elementc = 0;
|
||||
|
||||
/* Done */
|
||||
return 1;
|
||||
return parsed_instruction;
|
||||
|
||||
} /* end if terminator */
|
||||
|
||||
@ -444,12 +484,20 @@ int guac_read_instruction(GUACIO* io, int usec_timeout,
|
||||
/* No instruction yet? Get more data ... */
|
||||
retval = guac_select(io, usec_timeout);
|
||||
if (retval <= 0)
|
||||
return retval;
|
||||
return NULL;
|
||||
|
||||
/* If more data is available, fill into buffer */
|
||||
retval = __guac_fill___instructionbuf(io);
|
||||
if (retval < 0) return retval; /* Error */
|
||||
if (retval == 0) return -1; /* EOF */
|
||||
retval = __guac_fill_instructionbuf(io);
|
||||
|
||||
/* Error, guac_error already set */
|
||||
if (retval < 0)
|
||||
return NULL;
|
||||
|
||||
/* EOF */
|
||||
if (retval == 0) {
|
||||
guac_error = GUAC_STATUS_NO_INPUT;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user