From 3f65a4ed2ee00e45072bf69ad6ed272d99096263 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sun, 29 Apr 2012 22:46:22 -0400 Subject: [PATCH] http parsing --- htest.c | 56 ++++++++++++++++++ http.utils.c | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++ http.utils.h | 11 ++++ 3 files changed, 223 insertions(+) create mode 100644 htest.c create mode 100644 http.utils.c create mode 100644 http.utils.h diff --git a/htest.c b/htest.c new file mode 100644 index 0000000..0635398 --- /dev/null +++ b/htest.c @@ -0,0 +1,56 @@ +#include +#include + +#include "http.utils.h" + +int main(int argc, char **argv) +{ + + int version; + int status; + int ok; + char *cp; + + URLRange k, v; + + cp = "HTTP/1.0 200 OK"; + ok = parseStatusLine(cp, strlen(cp), &version, &status); + if (!ok || version != 0x0100 || status != 200) + { + fprintf(stderr, "%s: %x %d\n", cp, version, status); + } + + cp = "HTTP/1.1 404 bleh"; + ok = parseStatusLine(cp, strlen(cp), &version, &status); + if (!ok || version != 0x0101 || status != 404) + { + fprintf(stderr, "%s: %x %d\n", cp, version, status); + } + + + cp = "http/1.10 200 asdasd as dsad asd"; + ok = parseStatusLine(cp, strlen(cp), &version, &status); + if (!ok || version != 0x010a || status != 200) + { + fprintf(stderr, "%s: %x %d\n", cp, version, status); + } + + + cp = "key: value"; + ok = parseHeaderLine(cp, strlen(cp), &k, &v); + if (!ok + || k.location != 0 + || k.length != 3 + || v.location != 5 + || v.length != 5) + { + fprintf(stderr, "%s: %.*s, %.*s\n", cp, + k.length, cp + k.location, + v.length, cp + v.location); + } + + + return 0; +} + + diff --git a/http.utils.c b/http.utils.c new file mode 100644 index 0000000..816de8f --- /dev/null +++ b/http.utils.c @@ -0,0 +1,156 @@ +#ifdef __ORCAC__ +#pragma optimize 79 +#pragma noroot +#endif + +#include +#include "url.h" + + +int parseHeaderLine(const char *cp, unsigned length, URLRange *key, URLRange *value) +{ + unsigned i, l; + + key->location = 0; + key->length = 0; + value->location = 0; + value->length = 0; + + // trim any trailing whitespace. + + while (length) + { + if (isspace(cp[length - 1])) + --length; + else break; + } + if (!length) return 0; + + /* format: + * key: value + * /^([^:]+):\s+(.*)$/ + * -or- + * value [continuation of previous line] + * /^\s+(.*)$/ + */ + + for (i = 0; i < length; ++i) + { + if (cp[i] == ':') break; + } + + if (i == length) + { + // try as value only + i = 0; + } + else + { + key->length = i; + i = i + 1; + } + + // now gobble up all the whitespace... + + for ( ; i < length; ++i) + { + if (!isspace(cp[i])) break; + } + + // no value? no problem! + if (i == length) return 1; + + value->location = i; + value->length = length - i; + + return 1; +} + + +int parseStatusLine(const char *cp, unsigned length, int *version, int *status) +{ + /* + * HTTP/1.1 200 OK etc. + * + */ + + unsigned short *wp; + int i; + char c; + int x; + + *version = 0; + *status = 0; + + wp = (unsigned short *)cp; + + + // HTTP/ + if (length <= 5) return 0; + if ((wp[0] | 0x2020) != 0x7468) return 0; // 'ht' + if ((wp[1] | 0x2020) != 0x7074) return 0; // 'tp' + if (cp[4] != '/') return 0; + + // version string. + // \d+ . \d+ + i = 5; + + c = cp[i]; + if (!isdigit(c)) return 0; + x = c - '0'; + + for (i = i + 1; i < length; ++i) + { + c = cp[i]; + if (!isdigit(c)) break; + x = (x << 1) + (x << 3) + (c - '0'); + } + + *version = x << 8; + + if (i == length) return 0; + if (cp[i++] != '.') return 0; + + c = cp[i]; + if (!isdigit(c)) return 0; + x = c - '0'; + + for (i = i + 1; i < length; ++i) + { + c = cp[i]; + if (!isdigit(c)) break; + x = (x << 1) + (x << 3) + (c - '0'); + } + + *version |= x; + + // 1+ space + if (i == length) return 0; + c = cp[i]; + if (!isspace(c)) return 0; + + for (i = i + 1; i < length; ++i) + { + c = cp[i]; + if (!isspace(c)) break; + } + + if (i == length) return 0; + + c = cp[i]; + if (!isdigit(c)) return 0; + x = c - '0'; + + for (i = i + 1; i < length; ++i) + { + c = cp[i]; + if (!isdigit(c)) break; + x = (x << 1) + (x << 3) + (c - '0'); + } + + *status = x; + + // rest of status line unimportant. + + return 1; +} diff --git a/http.utils.h b/http.utils.h new file mode 100644 index 0000000..1a00b5d --- /dev/null +++ b/http.utils.h @@ -0,0 +1,11 @@ +#ifndef __HTTP_UTILS_H__ +#define __HTTP_UTILS_H__ + +#include "url.h" + + +int parseHeaderLine(const char *line, unsigned length, URLRange *key, URLRange *value); + +int parseStatusLine(const char *cp, unsigned length, int *version, int *status); + +#endif \ No newline at end of file