diff --git a/TODO.txt b/TODO.txt index 98fa7b9..82410dd 100644 --- a/TODO.txt +++ b/TODO.txt @@ -15,6 +15,7 @@ Milestone: v0.3.0 [ ] TLS [ ] SOCKS [ ] Multi-output + [ ] Move UtilStreamCopy() [~] HTTP Client API [ ] Document HttpParseHeaders() [ ] HttpClient man page diff --git a/src/HttpClient.c b/src/HttpClient.c index a884d4f..00d64aa 100644 --- a/src/HttpClient.c +++ b/src/HttpClient.c @@ -182,6 +182,9 @@ HttpRequestSend(HttpClientContext * context) return 0; } + fflush(context->stream); + shutdown(fileno(context->stream), SHUT_WR); + lineLen = UtilGetLine(&line, &lineSize, context->stream); /* Line must contain at least "HTTP/x.x xxx" */ diff --git a/src/HttpServer.c b/src/HttpServer.c index fcdf2e9..10d76d0 100644 --- a/src/HttpServer.c +++ b/src/HttpServer.c @@ -444,7 +444,7 @@ HttpServerWorkerThread(void *args) * Every once in a while, we're too fast for the client. When this * happens, UtilGetLine() sets errno to EAGAIN. If we get * EAGAIN, then clear the error on the stream and try again - * after 1ms. This is typically more than enough time for the + * after a few ms. This is typically more than enough time for the * client to send data. */ firstRead = UtilServerTs(); while ((lineLen = UtilGetLine(&line, &lineSize, fp)) == -1 @@ -453,7 +453,7 @@ HttpServerWorkerThread(void *args) clearerr(fp); /* If the server is stopped, or it's been a while, just - * give up. */ + * give up so we aren't wasting a thread on this client. */ if (server->stop || (UtilServerTs() - firstRead) > 1000 * 30) { goto finish; diff --git a/src/Json.c b/src/Json.c index f0d1d36..4f6704d 100644 --- a/src/Json.c +++ b/src/Json.c @@ -31,6 +31,7 @@ #include #include #include +#include struct JsonValue { @@ -705,8 +706,33 @@ static int JsonConsumeWhitespace(JsonParserState * state) { int c; + while (1) + { + c = fgetc(state->stream); - while (isspace(c = fgetc(state->stream))); + if (feof(state->stream)) + { + break; + } + + if (ferror(state->stream)) + { + if (errno == EAGAIN) + { + clearerr(state->stream); + continue; + } + else + { + break; + } + } + + if (!isspace(c)) + { + break; + } + } return c; } diff --git a/src/Util.c b/src/Util.c index ed0239d..129a340 100644 --- a/src/Util.c +++ b/src/Util.c @@ -246,7 +246,7 @@ UtilGetDelim(char **linePtr, size_t * n, int delim, FILE * stream) while (1) { - c = getc(stream); + c = fgetc(stream); if (ferror(stream) || (c == EOF && curPos == *linePtr)) { @@ -300,3 +300,38 @@ UtilGetLine(char **linePtr, size_t * n, FILE * stream) { return UtilGetDelim(linePtr, n, '\n', stream); } + +size_t +UtilStreamCopy(FILE *in, FILE *out) +{ + size_t bytes = 0; + int c; + + while (1) + { + c = fgetc(in); + + if (feof(in)) + { + break; + } + + if (ferror(in)) + { + if (errno == EAGAIN) + { + clearerr(in); + continue; + } + else + { + break; + } + } + + fputc(c, out); + bytes++; + } + + return bytes; +} diff --git a/src/include/Util.h b/src/include/Util.h index ee03694..0476cd1 100644 --- a/src/include/Util.h +++ b/src/include/Util.h @@ -50,4 +50,7 @@ extern ssize_t extern ssize_t UtilGetLine(char **, size_t *, FILE *); +extern size_t +UtilStreamCopy(FILE *, FILE *); + #endif /* TELODENDRIA_UTIL_H */ diff --git a/tools/bin/td b/tools/bin/td index e818a13..9d7427a 100644 --- a/tools/bin/td +++ b/tools/bin/td @@ -126,7 +126,7 @@ recipe_build() { out=$(basename "$src" .c) out="build/tools/$out" - if [ $(mod_time "$src") -ge $(mod_time "$out") ]; then + if [ $(mod_time "$src") -ge $(mod_time "$out") ] || [ $do_rebuild -eq 1 ]; then echo "CC $(basename $out)" mkdir -p "$(dirname $out)" if ! $CC $CFLAGS $LDFLAGS -Isrc/include -o "$out" $objs "$src"; then diff --git a/tools/src/http.c b/tools/src/http.c index af1c1af..b87bb7a 100644 --- a/tools/src/http.c +++ b/tools/src/http.c @@ -32,22 +32,10 @@ #include #include #include +#include #define FLAG_HEADERS (1 << 0) -/* TODO: Will eventually be provided by the Stream API */ -static void -StreamCopy(FILE * in, FILE * out) -{ - int c; - - /* TODO: This should be buffered, not char-by-char */ - while ((c = fgetc(in)) != EOF) - { - fputc(c, out); - } -} - static void usage(char *prog) { @@ -170,7 +158,7 @@ main(int argc, char **argv) * from blocking if no pipe is provided */ if (!isatty(fileno(stdin))) { - StreamCopy(stdin, HttpClientStream(cx)); + UtilStreamCopy(stdin, HttpClientStream(cx)); } res = HttpRequestSend(cx); @@ -197,7 +185,7 @@ main(int argc, char **argv) printf("\n"); } - StreamCopy(HttpClientStream(cx), stdout); + UtilStreamCopy(HttpClientStream(cx), stdout); HttpClientContextFree(cx); UriFree(uri);