summaryrefslogtreecommitdiffstats
path: root/hw4/chttpd/chttpd-conn.c
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2014-01-14 22:27:34 +0800
committerLAN-TW <lantw44@gmail.com>2014-01-14 22:27:34 +0800
commit562b3936c0140c215bc01ecd7ebc40e004f5b3ba (patch)
tree45eadcc6507d5b4e6a4d8ad2fbb25867c8ba37b9 /hw4/chttpd/chttpd-conn.c
parent08b63dcd438ee4ec68fe9eb61b6cd42ee6684963 (diff)
downloadsp2013-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.c87
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) {