summaryrefslogtreecommitdiff
path: root/httpd/httpd.c
diff options
context:
space:
mode:
authorJeffrey Armstrong <jeffrey.armstrong@approximatrix.com>2016-08-25 15:14:24 -0400
committerJeffrey Armstrong <jeffrey.armstrong@approximatrix.com>2016-08-25 15:14:24 -0400
commit84de937689bcb35ea3ddae55d9c74dc23463f79c (patch)
treecddc948933f9e0ee0a3f1b4caeaea5eb93bfcc98 /httpd/httpd.c
downloaduIP-FOSSIL-84de937689bcb35ea3ddae55d9c74dc23463f79c.tar.gz
uIP-FOSSIL-84de937689bcb35ea3ddae55d9c74dc23463f79c.zip
Initial commit of original code
Diffstat (limited to 'httpd/httpd.c')
-rw-r--r--httpd/httpd.c231
1 files changed, 231 insertions, 0 deletions
diff --git a/httpd/httpd.c b/httpd/httpd.c
new file mode 100644
index 0000000..c7cc49c
--- /dev/null
+++ b/httpd/httpd.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2009 Jeffrey Armstrong
+ * Copyright (c) 2001-2005, Adam Dunkels.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * This file is part of the uIP TCP/IP stack.
+ *
+ */
+
+#include "httpd.h"
+#include "uip.h"
+#include "httpd-fs.h"
+#include "http-str.h"
+
+#include <string.h>
+
+#define STATE_WAITING 0
+#define STATE_OUTPUT 1
+
+#define ISO_nl 0x0a
+#define ISO_space 0x20
+#define ISO_bang 0x21
+#define ISO_percent 0x25
+#define ISO_period 0x2e
+#define ISO_slash 0x2f
+#define ISO_colon 0x3a
+
+
+static unsigned short generate_part_of_file(void *state)
+{
+ struct httpd_state *s = (struct httpd_state *)state;
+
+ if(s->file.len > uip_mss()) {
+ s->len = uip_mss();
+ } else {
+ s->len = s->file.len;
+ }
+
+ fread(uip_appdata,sizeof(char),s->len,s->file.fp);
+
+ if(s->len == s->file.len)
+ fclose(s->file.fp);
+
+ return s->len;
+}
+
+static PT_THREAD(send_file(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sout);
+
+ do {
+ PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s);
+ s->file.len -= s->len;
+ } while(s->file.len > 0);
+
+ PSOCK_END(&s->sout);
+}
+
+
+static PT_THREAD(send_part_of_file(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sout);
+
+ PSOCK_SEND(&s->sout, uip_appdata, s->len);
+
+ PSOCK_END(&s->sout);
+}
+
+static PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
+{
+ char *ptr;
+
+ PSOCK_BEGIN(&s->sout);
+
+ PSOCK_SEND_STR(&s->sout, statushdr);
+
+ ptr = strrchr(s->filename, ISO_period);
+ if(ptr == NULL) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_binary);
+ } else if(strncmp(http_html, ptr, 5) == 0 ||
+ strncmp(http_shtml, ptr, 6) == 0 ||
+ strncmp(http_htm, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_html);
+ } else if(strncmp(http_css, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_css);
+ } else if(strncmp(http_png, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_png);
+ } else if(strncmp(http_gif, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_gif);
+ } else if(strncmp(http_jpg, ptr, 4) == 0) {
+ PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
+ } else {
+ PSOCK_SEND_STR(&s->sout, http_content_type_plain);
+ }
+ PSOCK_END(&s->sout);
+}
+
+
+static PT_THREAD(handle_output(struct httpd_state *s))
+{
+ char *ptr;
+
+ PT_BEGIN(&s->outputpt);
+
+ if(httpd_fs_open(s->filename, &s->file) < 0) {
+
+ strcpy(s->filename, FILE_404);
+ PT_WAIT_THREAD(&s->outputpt,
+ send_headers(s,
+ http_header_404));
+
+ if(httpd_fs_open(s->filename, &s->file))
+ PT_WAIT_THREAD(&s->outputpt,
+ send_file(s));
+
+ } else {
+ PT_WAIT_THREAD(&s->outputpt,
+ send_headers(s,
+ http_header_200));
+ ptr = strchr(s->filename, ISO_period);
+ PT_WAIT_THREAD(&s->outputpt, send_file(s));
+ }
+ PSOCK_CLOSE(&s->sout);
+ PT_END(&s->outputpt);
+}
+
+static PT_THREAD(handle_input(struct httpd_state *s))
+{
+ PSOCK_BEGIN(&s->sin);
+
+ PSOCK_READTO(&s->sin, ISO_space);
+
+
+ if(strncmp(s->inputbuf, http_get, 4) != 0) {
+ PSOCK_CLOSE_EXIT(&s->sin);
+ }
+ PSOCK_READTO(&s->sin, ISO_space);
+
+ if(s->inputbuf[0] != ISO_slash) {
+ PSOCK_CLOSE_EXIT(&s->sin);
+ }
+
+ if(s->inputbuf[1] == ISO_space) {
+ strncpy(s->filename, http_index_html, sizeof(s->filename));
+ } else {
+ s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
+ strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
+ }
+
+ /* httpd_log_file(uip_conn->ripaddr, s->filename);*/
+
+ s->state = STATE_OUTPUT;
+
+ while(1) {
+ PSOCK_READTO(&s->sin, ISO_nl);
+
+ if(strncmp(s->inputbuf, http_referer, 8) == 0) {
+ s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
+ /* httpd_log(&s->inputbuf[9]);*/
+ }
+ }
+
+ PSOCK_END(&s->sin);
+}
+
+static void handle_connection(struct httpd_state *s)
+{
+ handle_input(s);
+ if(s->state == STATE_OUTPUT) {
+ handle_output(s);
+ }
+}
+
+void httpd_appcall(void)
+{
+ struct httpd_state *s = (struct httpd_state *)&(uip_conn->appstate);
+
+ if(uip_closed() || uip_aborted() || uip_timedout()) {
+ } else if(uip_connected()) {
+ PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
+ PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
+ PT_INIT(&s->outputpt);
+ s->state = STATE_WAITING;
+ /* timer_set(&s->timer, CLOCK_SECOND * 100);*/
+ s->timer = 0;
+ handle_connection(s);
+ } else if(s != NULL) {
+ if(uip_poll()) {
+ ++s->timer;
+ if(s->timer >= 20) {
+ uip_abort();
+ }
+ } else {
+ s->timer = 0;
+ }
+ handle_connection(s);
+ } else {
+ uip_abort();
+ }
+}
+
+void httpd_init(void)
+{
+ uip_listen(HTONS(80));
+}
+
+