Пример #1
0
int guac_instruction_waiting(guac_socket* socket, int usec_timeout) {

    if (socket->__instructionbuf_used_length > 0)
        return 1;

    return guac_socket_select(socket, usec_timeout);
}
Пример #2
0
int guac_instruction_waiting(guac_socket* socket, int usec_timeout) {

    if (socket->__instructionbuf_unparsed_end >
            socket->__instructionbuf_unparsed_start)
        return 1;

    return guac_socket_select(socket, usec_timeout);
}
Пример #3
0
int guac_parser_read(guac_parser* parser, guac_socket* socket, int usec_timeout) {

    char* unparsed_end   = parser->__instructionbuf_unparsed_end;
    char* unparsed_start = parser->__instructionbuf_unparsed_start;
    char* instr_start    = parser->__instructionbuf_unparsed_start;
    char* buffer_end     = parser->__instructionbuf + sizeof(parser->__instructionbuf);

    /* Begin next instruction if previous was ended */
    if (parser->state == GUAC_PARSE_COMPLETE)
        guac_parser_reset(parser);

    while (parser->state != GUAC_PARSE_COMPLETE
        && parser->state != GUAC_PARSE_ERROR) {

        /* Add any available data to buffer */
        int parsed = guac_parser_append(parser, unparsed_start, unparsed_end - unparsed_start);

        /* Read more data if not enough data to parse */
        if (parsed == 0 && parser->state != GUAC_PARSE_ERROR) {

            int retval;

            /* If no space left to read, fail */
            if (unparsed_end == buffer_end) {

                /* Shift backward if possible */
                if (instr_start != parser->__instructionbuf) {

                    int i;

                    /* Shift buffer */
                    int offset = instr_start - parser->__instructionbuf;
                    memmove(parser->__instructionbuf, instr_start,
                            unparsed_end - instr_start);

                    /* Update tracking pointers */
                    unparsed_end -= offset;
                    unparsed_start -= offset;
                    instr_start = parser->__instructionbuf;

                    /* Update parsed elements, if any */
                    for (i=0; i < parser->__elementc; i++)
                        parser->__elementv[i] -= offset;

                }

                /* Otherwise, no memory to read */
                else {
                    guac_error = GUAC_STATUS_NO_MEMORY;
                    guac_error_message = "Instruction too long";
                    return -1;
                }

            }

            /* No instruction yet? Get more data ... */
            retval = guac_socket_select(socket, usec_timeout);
            if (retval <= 0)
                return -1;
           
            /* Attempt to fill buffer */
            retval = guac_socket_read(socket, unparsed_end,
                    buffer_end - unparsed_end);

            /* Set guac_error if read unsuccessful */
            if (retval < 0) {
                guac_error = GUAC_STATUS_SEE_ERRNO;
                guac_error_message = "Error filling instruction buffer";
                return -1;
            }

            /* EOF */
            if (retval == 0) {
                guac_error = GUAC_STATUS_CLOSED;
                guac_error_message = "End of stream reached while "
                                     "reading instruction";
                return -1;
            }

            /* Update internal buffer */
            unparsed_end += retval;

        }

        /* If data was parsed, advance buffer */
        else
            unparsed_start += parsed;

    } /* end while parsing data */

    /* Fail on error */
    if (parser->state == GUAC_PARSE_ERROR) {
        guac_error = GUAC_STATUS_PROTOCOL_ERROR;
        guac_error_message = "Instruction parse error";
        return -1;
    }

    parser->__instructionbuf_unparsed_start = unparsed_start;
    parser->__instructionbuf_unparsed_end = unparsed_end;
    return 0;

}
Пример #4
0
/* Returns new instruction if one exists, or NULL if no more instructions. */
guac_instruction* guac_instruction_read(guac_socket* socket,
        int usec_timeout) {

    int retval;
   
    /* Loop until a instruction is read */
    for (;;) {

        /* Length of element, in Unicode characters */
        int element_length = 0;

        /* Length of element, in bytes */
        int element_byte_length = 0;

        /* Current position within the element, in Unicode characters */
        int current_unicode_length = 0;

        /* Position within buffer */
        int i = socket->__instructionbuf_parse_start;

        /* Parse instruction in buffer */
        while (i < socket->__instructionbuf_used_length) {

            /* Read character from buffer */
            char c = socket->__instructionbuf[i++];

            /* If digit, calculate element length */
            if (c >= '0' && c <= '9')
                element_length = element_length * 10 + c - '0';

            /* Otherwise, if end of length */
            else if (c == '.') {

                /* Calculate element byte length by walking buffer */
                while (i + element_byte_length <
                            socket->__instructionbuf_used_length
                    && current_unicode_length < element_length) {

                    /* Get next byte */
                    c = socket->__instructionbuf[i + element_byte_length];

                    /* Update byte and character lengths */
                    element_byte_length += guac_utf8_charsize((unsigned) c);
                    current_unicode_length++;

                }

                /* Verify element is fully read */
                if (current_unicode_length == element_length) {

                    /* Get element value */
                    char* elementv = &(socket->__instructionbuf[i]);
                   
                    /* Get terminator, set null terminator of elementv */ 
                    char terminator = elementv[element_byte_length];
                    elementv[element_byte_length] = '\0';

                    /* Move to char after terminator of element */
                    i += element_byte_length+1;

                    /* Reset element length */
                    element_length =
                    element_byte_length =
                    current_unicode_length = 0;

                    /* As element has been read successfully, update
                     * parse start */
                    socket->__instructionbuf_parse_start = i;

                    /* Save element */
                    socket->__instructionbuf_elementv[socket->__instructionbuf_elementc++] = elementv;

                    /* 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;
                            guac_error_message = "Could not allocate memory for parsed instruction";
                            return NULL;
                        }

                        /* Init parsed instruction */
                        parsed_instruction->argc = socket->__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;
                            guac_error_message = "Could not allocate memory for arguments of parsed instruction";
                            free(parsed_instruction);
                            return NULL;
                        }

                        /* Set opcode */
                        parsed_instruction->opcode = strdup(socket->__instructionbuf_elementv[0]);

                        /* Fail if memory could not be alloc'd for opcode */
                        if (parsed_instruction->opcode == NULL) {
                            guac_error = GUAC_STATUS_NO_MEMORY;
                            guac_error_message = "Could not allocate memory for opcode of parsed instruction";
                            free(parsed_instruction->argv);
                            free(parsed_instruction);
                            return NULL;
                        }


                        /* Copy element values to parsed instruction */
                        for (j=0; j<parsed_instruction->argc; j++) {
                            parsed_instruction->argv[j] = strdup(socket->__instructionbuf_elementv[j+1]);

                            /* Free memory and fail if out of mem */
                            if (parsed_instruction->argv[j] == NULL) {
                                guac_error = GUAC_STATUS_NO_MEMORY;
                                guac_error_message = "Could not allocate memory for single argument of parsed instruction";

                                /* 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(socket->__instructionbuf, socket->__instructionbuf + i, socket->__instructionbuf_used_length - i);
                        socket->__instructionbuf_used_length -= i;
                        socket->__instructionbuf_parse_start = 0;
                        socket->__instructionbuf_elementc = 0;

                        /* Done */
                        return parsed_instruction;

                    } /* end if terminator */

                    /* Error if expected comma is not present */
                    else if (terminator != ',') {
                        guac_error = GUAC_STATUS_BAD_ARGUMENT;
                        guac_error_message = "Element terminator of instruction was not ';' nor ','";
                        return NULL;
                    }

                } /* end if element fully read */

                /* Otherwise, read more data */
                else
                    break;

            }

            /* Error if length is non-numeric or does not end in a period */
            else {
                guac_error = GUAC_STATUS_BAD_ARGUMENT;
                guac_error_message = "Non-numeric character in element length";
                return NULL;
            }

        }

        /* No instruction yet? Get more data ... */
        retval = guac_socket_select(socket, usec_timeout);
        if (retval <= 0)
            return NULL;

        /* If more data is available, fill into buffer */
        retval = __guac_fill_instructionbuf(socket);

        /* Error, guac_error already set */
        if (retval < 0)
            return NULL;

        /* EOF */
        if (retval == 0) {
            guac_error = GUAC_STATUS_NO_INPUT;
            guac_error_message = "End of stream reached while reading instruction";
            return NULL;
        }

    }

}
Пример #5
0
/* Returns new instruction if one exists, or NULL if no more instructions. */
guac_instruction* guac_instruction_read(guac_socket* socket,
        int usec_timeout) {

    char* unparsed_end = socket->__instructionbuf_unparsed_end;
    char* unparsed_start = socket->__instructionbuf_unparsed_start;
    char* instr_start = socket->__instructionbuf_unparsed_start;
    char* buffer_end = socket->__instructionbuf
                            + sizeof(socket->__instructionbuf);

    guac_instruction* instruction = guac_instruction_alloc();

    while (instruction->state != GUAC_INSTRUCTION_PARSE_COMPLETE
        && instruction->state != GUAC_INSTRUCTION_PARSE_ERROR) {

        /* Add any available data to buffer */
        int parsed = guac_instruction_append(instruction, unparsed_start,
                unparsed_end - unparsed_start);

        /* Read more data if not enough data to parse */
        if (parsed == 0) {

            int retval;

            /* If no space left to read, fail */
            if (unparsed_end == buffer_end) {

                /* Shift backward if possible */
                if (instr_start != socket->__instructionbuf) {

                    int i;

                    /* Shift buffer */
                    int offset = instr_start - socket->__instructionbuf;
                    memmove(socket->__instructionbuf, instr_start,
                            unparsed_end - instr_start);

                    /* Update tracking pointers */
                    unparsed_end -= offset;
                    unparsed_start -= offset;
                    instr_start = socket->__instructionbuf;

                    /* Update parsed elements, if any */
                    for (i=0; i<instruction->__elementc; i++)
                        instruction->__elementv[i] -= offset;

                }

                /* Otherwise, no memory to read */
                else {
                    guac_error = GUAC_STATUS_NO_MEMORY;
                    guac_error_message = "Instruction too long";
                    return NULL;
                }

            }

            /* No instruction yet? Get more data ... */
            retval = guac_socket_select(socket, usec_timeout);
            if (retval <= 0)
                return NULL;
           
            /* Attempt to fill buffer */
            retval = guac_socket_read(socket, unparsed_end,
                    buffer_end - unparsed_end);

            /* Set guac_error if read unsuccessful */
            if (retval < 0) {
                guac_error = GUAC_STATUS_SEE_ERRNO;
                guac_error_message = "Error filling instruction buffer";
                return NULL;
            }

            /* EOF */
            if (retval == 0) {
                guac_error = GUAC_STATUS_NO_INPUT;
                guac_error_message = "End of stream reached while "
                                     "reading instruction";
                return NULL;
            }

            /* Update internal buffer */
            unparsed_end += retval;

        }

        /* If data was parsed, advance buffer */
        else
            unparsed_start += parsed;

    } /* end while parsing data */

    /* Fail on error */
    if (instruction->state == GUAC_INSTRUCTION_PARSE_ERROR) {
        guac_error = GUAC_STATUS_BAD_ARGUMENT;
        guac_error_message = "Instruction parse error";
        return NULL;
    }

    socket->__instructionbuf_unparsed_start = unparsed_start;
    socket->__instructionbuf_unparsed_end = unparsed_end;
    return instruction;

}