return swrite(fd, string, strlen(string));
}
-/**
- * sreads:
- * @fd: the file descriptor
- * @buffer: the I/O buffer
- * @n_buffer: the size of the I/O buffer
- *
- * Internal routine to do a synchronous read of a line
- *
- * Returns the number of bytes read, or -1 in case of error
- */
-static ssize_t
-sreads(int fd, char *buffer, size_t n_buffer)
-{
- size_t offset;
-
- if (n_buffer < 1)
- return (-1);
-
- for (offset = 0; offset < (n_buffer - 1); offset++) {
- ssize_t ret;
-
- ret = sread(fd, buffer + offset, 1);
- if (ret == 0)
- break;
- else if (ret == -1)
- return ret;
-
- if (buffer[offset] == '\n') {
- offset++;
- break;
- }
- }
- buffer[offset] = 0;
-
- return offset;
-}
static int
istartswith(const char *haystack, const char *needle)
return (strncasecmp(haystack, needle, strlen(needle)) == 0);
}
+
/**
* xend_req:
* @fd: the file descriptor
xend_req(int fd, char *content, size_t n_content)
{
char buffer[4096];
+ int nbuf = -1;
int content_length = -1;
int retcode = 0;
+ /*
+ * Fill buffer with as much as possible to get
+ * process going
+ */
+ nbuf = sread(fd, buffer, sizeof(buffer));
+
+ /*
+ * Extract lines from the buffer, until the
+ * end of header is found
+ */
+ while (nbuf > -1) {
+ /* Seach for offset of first \r\n pair */
+ int i, offset = -1;
+
+ for (i = 0; i < (nbuf - 1); i++) {
+ if (buffer[i] == '\r' && buffer[i + 1] == '\n') {
+ offset = i;
+ break;
+ }
+ }
- while (sreads(fd, buffer, sizeof(buffer)) > 0) {
- if (strcmp(buffer, "\r\n") == 0)
- break;
+ if (offset == -1) { /* No newline found, so try to fill more data */
- if (istartswith(buffer, "Content-Length: "))
- content_length = atoi(buffer + 16);
- else if (istartswith(buffer, "HTTP/1.1 "))
- retcode = atoi(buffer + 9);
- }
+ if (nbuf == sizeof(buffer)) {
+ /* Already have 4096 bytes of data & no newline,
+ * get the hell out of this game */
+ break;
+ }
- if (content_length > -1) {
- ssize_t ret;
+ /* Fill remainder of buffer with more data */
+ int extra = sread(fd, buffer + nbuf, sizeof(buffer) - nbuf);
+ if (extra < 1) {
+ /* Couldn't get more, so quit trying */
+ break;
+ }
+ nbuf += extra;
+ } else if (!offset) { /* Immediate newline, indicates end of header */
+ /* Overwrite the \r\n pair */
+ offset += 2;
+ nbuf -= offset;
+ memmove(buffer, buffer + offset, nbuf);
+ break;
+ } else { /* We have a single line */
+ buffer[offset] = '\0';
+
+ if (istartswith(buffer, "Content-Length: "))
+ content_length = atoi(buffer + 16);
+ else if (istartswith(buffer, "HTTP/1.1 "))
+ retcode = atoi(buffer + 9);
+
+ /*
+ * Now move buffer, overwriting first line, to make room for
+ * more data on next iteration of loop (if needed)
+ */
+ offset += 2;
+ nbuf -= offset;
+ memmove(buffer, buffer + offset, nbuf);
+ }
+ }
+
+ if (content_length > -1) { /* Read the header, now get body */
if ((unsigned int) content_length > (n_content + 1))
content_length = n_content - 1;
- ret = sread(fd, content, content_length);
- if (ret < 0)
- return -1;
+ /*
+ * Copy across any data left in buffer after
+ * reading header
+ */
+ if (nbuf > content_length) {
+ nbuf = content_length;
+ }
+ memmove(content, buffer, nbuf);
+
+ if (nbuf < content_length) { /* Still need more data for body */
+ size_t ret = sread(fd, content + nbuf, content_length - nbuf);
- content[ret] = 0;
- } else {
+ if (0 > (int) ret)
+ return -1;
+
+ content[nbuf + ret + 1] = '\0';
+ } else {
+ content[nbuf + 1] = '\0';
+ }
+ } else { /* Unable to complete reading header */
content[0] = 0;
}