X-Git-Url: https://git.sesse.net/?p=cubemap;a=blobdiff_plain;f=parse.h;h=a2e35802d38d31e804e4b16dcf1f948df6f7cfa7;hp=83c5d2a8998dff2832b879b78db04c4467608696;hb=fa431bfab848624c2490a1134e084e6c1dd0dbfa;hpb=17d773d2d45d495704e974b9246eccb21faa8635 diff --git a/parse.h b/parse.h index 83c5d2a..a2e3580 100644 --- a/parse.h +++ b/parse.h @@ -1,17 +1,45 @@ #ifndef _PARSE_H #define _PARSE_H -// Various routines that deal with parsing; both configuration files and HTTP requests. +// Various routines that deal with parsing; both HTTP requests and more generic text. -#include -#include +#include +#include +#include #include +#include +#include -struct ConfigLine { - std::string keyword; - std::vector arguments; - std::map parameters; +// Locale-unaware tolower(); matches RFC 2616 no matter what the locale is set to. +static inline char ascii_tolower(const char ch) +{ + if (ch >= 'A' && ch <= 'Z') { + return ch + 'a' - 'A'; + } else { + return ch; + } +} + +// Case-insensitive header comparison and hashing. +struct HTTPLess { + bool operator() (const std::string &a, const std::string &b) const + { + return std::lexicographical_compare( + begin(a), end(a), begin(b), end(b), + [](char a, char b) { + return ascii_tolower(a) < ascii_tolower(b); + }); + } +}; +struct HTTPHash { + size_t operator() (const std::string &s) const + { + std::string s_low = s; + for (char &ch : s_low) { ch = ascii_tolower(ch); } + return std::hash() (s_low); + } }; +using HTTPHeaderMultimap = std::unordered_multimap; // Split a line on whitespace, e.g. "foo bar baz" -> {"foo", "bar", "baz"}. std::vector split_tokens(const std::string &line); @@ -19,10 +47,23 @@ std::vector split_tokens(const std::string &line); // Split a string on \n or \r\n, e.g. "foo\nbar\r\n\nbaz\r\n\r\n" -> {"foo", "bar", "baz"}. std::vector split_lines(const std::string &str); -// Parse the configuration file. -std::vector parse_config(const std::string &filename); +// Extract HTTP headers from a request or response. Ignores the first line, +// where the verb or the return code is. +HTTPHeaderMultimap extract_headers(const std::vector &lines, const std::string &log_context); -// Note: Limits are inclusive. -int fetch_config_int(const std::vector &config, const std::string &keyword, int min_limit, int max_limit); +// Add the new data to an existing string, looking for \r\n\r\n +// (typical of HTTP requests and/or responses). Will return one +// of the given statuses. +// +// Note that if you give too much data in new_data_size, you could +// get an RP_OUT_OF_SPACE even if you expected RP_EXTRA_DATA. +// Be careful about how large reads you give in. +enum RequestParseStatus { + RP_OUT_OF_SPACE, // If larger than 16 kB. + RP_NOT_FINISHED_YET, // Did not get \r\n\r\n yet. + RP_EXTRA_DATA, // Got \r\n\r\n, but there was extra data behind it. + RP_FINISHED, // Ended exactly in \r\n\r\n. +}; +RequestParseStatus wait_for_double_newline(std::string *existing_data, const char *new_data, size_t new_data_size); #endif // !defined(_PARSE_H)