diff --git a/main/iostream.c b/main/iostream.c index 819616a15c3a8dacd2143483e8bb68434a941dc4..15131c09ffd113ffebacf256d1faf2779afad148 100644 --- a/main/iostream.c +++ b/main/iostream.c @@ -285,46 +285,59 @@ ssize_t ast_iostream_read(struct ast_iostream *stream, void *buffer, size_t coun ssize_t ast_iostream_gets(struct ast_iostream *stream, char *buffer, size_t size) { - ssize_t r; + size_t remaining = size; + ssize_t accum_size = 0; + ssize_t len; char *newline; - do { + for (;;) { /* Search for newline */ newline = memchr(stream->rbufhead, '\n', stream->rbuflen); if (newline) { - r = newline - stream->rbufhead + 1; - if (r > size-1) { - r = size-1; + len = newline - stream->rbufhead + 1; + if (len > remaining - 1) { + len = remaining - 1; } break; } - /* Enough data? */ - if (stream->rbuflen >= size - 1) { - r = size - 1; + /* Enough buffered line data to fill request buffer? */ + if (stream->rbuflen >= remaining - 1) { + len = remaining - 1; break; } - - /* Try to fill in line buffer */ - if (stream->rbuflen && stream->rbuf != stream->rbufhead) { - memmove(&stream->rbuf, stream->rbufhead, stream->rbuflen); + if (stream->rbuflen) { + /* Put leftover buffered line data into request buffer */ + memcpy(buffer + accum_size, stream->rbufhead, stream->rbuflen); + remaining -= stream->rbuflen; + accum_size += stream->rbuflen; + stream->rbuflen = 0; } stream->rbufhead = stream->rbuf; - r = iostream_read(stream, stream->rbufhead + stream->rbuflen, sizeof(stream->rbuf) - stream->rbuflen); - if (r <= 0) { - return r; + len = iostream_read(stream, stream->rbuf, sizeof(stream->rbuf)); + if (len == 0) { + /* Nothing new was read. Return whatever we have accumulated. */ + break; } - stream->rbuflen += r; - } while (1); + if (len < 0) { + if (accum_size) { + /* We have an accumulated buffer so return that instead. */ + len = 0; + break; + } + return len; + } + stream->rbuflen += len; + } - /* Return r bytes with termination byte */ - memcpy(buffer, stream->rbufhead, r); - buffer[r] = 0; - stream->rbuflen -= r; - stream->rbufhead += r; + /* Return read buffer string length */ + memcpy(buffer + accum_size, stream->rbufhead, len); + buffer[accum_size + len] = 0; + stream->rbuflen -= len; + stream->rbufhead += len; - return r; + return accum_size + len; } ssize_t ast_iostream_discard(struct ast_iostream *stream, size_t size)