diff options
author | LAN-TW <lantw44@gmail.com> | 2014-01-14 22:27:34 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2014-01-14 22:27:34 +0800 |
commit | 562b3936c0140c215bc01ecd7ebc40e004f5b3ba (patch) | |
tree | 45eadcc6507d5b4e6a4d8ad2fbb25867c8ba37b9 /hw4/chttpd/chttpd-conn.c | |
parent | 08b63dcd438ee4ec68fe9eb61b6cd42ee6684963 (diff) | |
download | sp2013-562b3936c0140c215bc01ecd7ebc40e004f5b3ba.tar.gz sp2013-562b3936c0140c215bc01ecd7ebc40e004f5b3ba.tar.zst sp2013-562b3936c0140c215bc01ecd7ebc40e004f5b3ba.zip |
HW4: 基本的 HTTP header 解析
Diffstat (limited to 'hw4/chttpd/chttpd-conn.c')
-rw-r--r-- | hw4/chttpd/chttpd-conn.c | 87 |
1 files changed, 86 insertions, 1 deletions
diff --git a/hw4/chttpd/chttpd-conn.c b/hw4/chttpd/chttpd-conn.c index 494742d..893661d 100644 --- a/hw4/chttpd/chttpd-conn.c +++ b/hw4/chttpd/chttpd-conn.c @@ -3,18 +3,28 @@ # include "config.h" #endif +#define CHTTPD_SERVER_ENABLE_ERRMSG + #include "chttpd-conn.h" #include "chttpd-log.h" #include "chttpd-server.h" +#include <l4array.h> #include <l4list.h> +#include <l4str.h> +#include <errno.h> +#include <pthread.h> +#include <signal.h> #include <stdlib.h> +#include <stdio.h> #include <unistd.h> #define CHTTPD_CONN_THREAD_INIT \ ChttpdConn* conn = ptr_to_ChttpdConn; \ ChttpdServer* server = conn->server; \ - ChttpdLog* hlog = conn->hlog + ChttpdLog* hlog = conn->hlog; \ + unsigned long long id = conn->id; \ + pthread_sigmask (SIG_SETMASK, &server->conn_mask, NULL); #define CHTTPD_CONN_THREAD_DESTROY \ chttpd_log_write (hlog, "[%4llu] terminated", conn->id); \ @@ -23,18 +33,93 @@ pthread_rwlock_unlock (&server->lock); \ return NULL +static inline char* internal_memstr (const void* haystack, + size_t haystacklen, const char* needle) { + + const char* haychar = haystack; + bool matched; + + for (size_t i = 0; i < haystacklen; i++, haychar++) { + matched = true; + for (size_t j = 0; needle[j] != '\0'; j++) { + if (i + j >= haystacklen || haychar[j] != needle[j]) { + matched = false; + break; + } + } + if (matched) { + return (char*)haychar; + } + } + return NULL; +} + +#define ERRLEN 256 void* chttpd_conn_admin (void* ptr_to_ChttpdConn) { CHTTPD_CONN_THREAD_INIT; + chttpd_log_write (hlog, "[%4llu] sorry, function not implemented", id); + CHTTPD_CONN_THREAD_DESTROY; } void* chttpd_conn_http (void* ptr_to_ChttpdConn) { CHTTPD_CONN_THREAD_INIT; + const char hdr_delim[] = "\015\012\015\012"; + _Static_assert (LBS_STR_STATIC_STRLEN (hdr_delim) == 4, + "HTTP header delimiter length must be 4 bytes!"); + + const char line_delim[] = "\015\012"; + _Static_assert (LBS_STR_STATIC_STRLEN (line_delim) == 2, + "HTTP line delimiter length must be 2bytes!"); + + char errmsg[ERRLEN]; + LbsArray* hdr_buf = lbs_array_new (sizeof (char)); + LbsArray* out_buf = lbs_array_new (sizeof (char)); + size_t data_offset; + + while (true) { + ssize_t r = read (conn->connfd, conn->buf, CHTTPD_CONN_BUF_SIZE); + if (r < 0) { + if (errno == EINTR || errno == EAGAIN) { + continue; + } + chttpd_log_write (hlog, "[%4llu] incomplete header: read: %s", + id, get_errmsg (errno, errmsg, ERRLEN)); + goto http_exit; + } else if (r == 0) { + chttpd_log_write (hlog, "[%4llu] incomplete header: premature EOF", + id); + goto http_exit; + } + + const char* hdr_end = internal_memstr (conn->buf, r, hdr_delim); + if (hdr_end != NULL) { + data_offset = hdr_end - conn->buf; + lbs_array_append_mass (hdr_buf, conn->buf, data_offset); + lbs_array_append_data (hdr_buf, &(char){ '\0' }); + data_offset += 4; + break; + } else { + lbs_array_append_mass (hdr_buf, conn->buf, r); + } + } + + char* method_start = hdr_buf->data; + char* hdr_start = internal_memstr (hdr_buf->data, hdr_buf->len, line_delim); + if (hdr_start != NULL) { + *hdr_start = '\0'; + hdr_start += 2; + } + +http_exit: + lbs_array_unref (hdr_buf); + lbs_array_unref (out_buf); CHTTPD_CONN_THREAD_DESTROY; } +#undef ERRLEN void chttpd_conn_ctor (void* conn_generic, unsigned long long id, int connfd, ChttpdLog* hlog, ChttpdServer* server, LbsListMeta* slist) { |