in src/libguac/parser.c [167:268]
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;
}