Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Committer:
Michael J. Spencer
Date:
Fri Feb 28 18:52:52 2014 -0800
Revision:
2:1df0b61d3b5a
Update to latest Smoothie.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Michael J. Spencer 2:1df0b61d3b5a 1 #pragma GCC diagnostic ignored "-Wredundant-decls"
Michael J. Spencer 2:1df0b61d3b5a 2 #pragma GCC diagnostic ignored "-Wstrict-aliasing"
Michael J. Spencer 2:1df0b61d3b5a 3 #pragma GCC diagnostic ignored "-Wcast-align"
Michael J. Spencer 2:1df0b61d3b5a 4 #pragma GCC diagnostic ignored "-Wcast-qual"
Michael J. Spencer 2:1df0b61d3b5a 5 #pragma GCC diagnostic ignored "-Wunused-but-set-variable"
Michael J. Spencer 2:1df0b61d3b5a 6
Michael J. Spencer 2:1df0b61d3b5a 7 /**
Michael J. Spencer 2:1df0b61d3b5a 8 * \addtogroup apps
Michael J. Spencer 2:1df0b61d3b5a 9 * @{
Michael J. Spencer 2:1df0b61d3b5a 10 */
Michael J. Spencer 2:1df0b61d3b5a 11
Michael J. Spencer 2:1df0b61d3b5a 12 /**
Michael J. Spencer 2:1df0b61d3b5a 13 * \defgroup httpd Web server
Michael J. Spencer 2:1df0b61d3b5a 14 * @{
Michael J. Spencer 2:1df0b61d3b5a 15 * The uIP web server is a very simplistic implementation of an HTTP
Michael J. Spencer 2:1df0b61d3b5a 16 * server. It can serve web pages and files from a read-only ROM
Michael J. Spencer 2:1df0b61d3b5a 17 * filesystem, and provides a very small scripting language.
Michael J. Spencer 2:1df0b61d3b5a 18
Michael J. Spencer 2:1df0b61d3b5a 19 */
Michael J. Spencer 2:1df0b61d3b5a 20
Michael J. Spencer 2:1df0b61d3b5a 21 /**
Michael J. Spencer 2:1df0b61d3b5a 22 * \file
Michael J. Spencer 2:1df0b61d3b5a 23 * Web server
Michael J. Spencer 2:1df0b61d3b5a 24 * \author
Michael J. Spencer 2:1df0b61d3b5a 25 * Adam Dunkels <adam@sics.se>
Michael J. Spencer 2:1df0b61d3b5a 26 */
Michael J. Spencer 2:1df0b61d3b5a 27
Michael J. Spencer 2:1df0b61d3b5a 28
Michael J. Spencer 2:1df0b61d3b5a 29 /*
Michael J. Spencer 2:1df0b61d3b5a 30 * Copyright (c) 2004, Adam Dunkels.
Michael J. Spencer 2:1df0b61d3b5a 31 * All rights reserved.
Michael J. Spencer 2:1df0b61d3b5a 32 *
Michael J. Spencer 2:1df0b61d3b5a 33 * Redistribution and use in source and binary forms, with or without
Michael J. Spencer 2:1df0b61d3b5a 34 * modification, are permitted provided that the following conditions
Michael J. Spencer 2:1df0b61d3b5a 35 * are met:
Michael J. Spencer 2:1df0b61d3b5a 36 * 1. Redistributions of source code must retain the above copyright
Michael J. Spencer 2:1df0b61d3b5a 37 * notice, this list of conditions and the following disclaimer.
Michael J. Spencer 2:1df0b61d3b5a 38 * 2. Redistributions in binary form must reproduce the above copyright
Michael J. Spencer 2:1df0b61d3b5a 39 * notice, this list of conditions and the following disclaimer in the
Michael J. Spencer 2:1df0b61d3b5a 40 * documentation and/or other materials provided with the distribution.
Michael J. Spencer 2:1df0b61d3b5a 41 * 3. Neither the name of the Institute nor the names of its contributors
Michael J. Spencer 2:1df0b61d3b5a 42 * may be used to endorse or promote products derived from this software
Michael J. Spencer 2:1df0b61d3b5a 43 * without specific prior written permission.
Michael J. Spencer 2:1df0b61d3b5a 44 *
Michael J. Spencer 2:1df0b61d3b5a 45 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
Michael J. Spencer 2:1df0b61d3b5a 46 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Michael J. Spencer 2:1df0b61d3b5a 47 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Michael J. Spencer 2:1df0b61d3b5a 48 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
Michael J. Spencer 2:1df0b61d3b5a 49 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Michael J. Spencer 2:1df0b61d3b5a 50 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Michael J. Spencer 2:1df0b61d3b5a 51 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Michael J. Spencer 2:1df0b61d3b5a 52 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Michael J. Spencer 2:1df0b61d3b5a 53 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Michael J. Spencer 2:1df0b61d3b5a 54 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Michael J. Spencer 2:1df0b61d3b5a 55 * SUCH DAMAGE.
Michael J. Spencer 2:1df0b61d3b5a 56 *
Michael J. Spencer 2:1df0b61d3b5a 57 * This file is part of the uIP TCP/IP stack.
Michael J. Spencer 2:1df0b61d3b5a 58 *
Michael J. Spencer 2:1df0b61d3b5a 59 * Author: Adam Dunkels <adam@sics.se>
Michael J. Spencer 2:1df0b61d3b5a 60 *
Michael J. Spencer 2:1df0b61d3b5a 61 * $Id: httpd.c,v 1.2 2006/06/11 21:46:38 adam Exp $
Michael J. Spencer 2:1df0b61d3b5a 62 */
Michael J. Spencer 2:1df0b61d3b5a 63
Michael J. Spencer 2:1df0b61d3b5a 64 #include <stdio.h>
Michael J. Spencer 2:1df0b61d3b5a 65
Michael J. Spencer 2:1df0b61d3b5a 66 #include "uip.h"
Michael J. Spencer 2:1df0b61d3b5a 67 #include "httpd.h"
Michael J. Spencer 2:1df0b61d3b5a 68 #include "httpd-fs.h"
Michael J. Spencer 2:1df0b61d3b5a 69 #include "http-strings.h"
Michael J. Spencer 2:1df0b61d3b5a 70
Michael J. Spencer 2:1df0b61d3b5a 71 #include <string.h>
Michael J. Spencer 2:1df0b61d3b5a 72 #include "stdio.h"
Michael J. Spencer 2:1df0b61d3b5a 73 #include "stdlib.h"
Michael J. Spencer 2:1df0b61d3b5a 74
Michael J. Spencer 2:1df0b61d3b5a 75 #include "CommandQueue.h"
Michael J. Spencer 2:1df0b61d3b5a 76 #include "CallbackStream.h"
Michael J. Spencer 2:1df0b61d3b5a 77
Michael J. Spencer 2:1df0b61d3b5a 78 #include "c-fifo.h"
Michael J. Spencer 2:1df0b61d3b5a 79
Michael J. Spencer 2:1df0b61d3b5a 80 #define STATE_WAITING 0
Michael J. Spencer 2:1df0b61d3b5a 81 #define STATE_HEADERS 1
Michael J. Spencer 2:1df0b61d3b5a 82 #define STATE_BODY 2
Michael J. Spencer 2:1df0b61d3b5a 83 #define STATE_OUTPUT 3
Michael J. Spencer 2:1df0b61d3b5a 84 #define STATE_UPLOAD 4
Michael J. Spencer 2:1df0b61d3b5a 85
Michael J. Spencer 2:1df0b61d3b5a 86 #define GET 1
Michael J. Spencer 2:1df0b61d3b5a 87 #define POST 2
Michael J. Spencer 2:1df0b61d3b5a 88
Michael J. Spencer 2:1df0b61d3b5a 89 #define ISO_nl 0x0a
Michael J. Spencer 2:1df0b61d3b5a 90 #define ISO_space 0x20
Michael J. Spencer 2:1df0b61d3b5a 91 #define ISO_bang 0x21
Michael J. Spencer 2:1df0b61d3b5a 92 #define ISO_percent 0x25
Michael J. Spencer 2:1df0b61d3b5a 93 #define ISO_period 0x2e
Michael J. Spencer 2:1df0b61d3b5a 94 #define ISO_slash 0x2f
Michael J. Spencer 2:1df0b61d3b5a 95 #define ISO_colon 0x3a
Michael J. Spencer 2:1df0b61d3b5a 96
Michael J. Spencer 2:1df0b61d3b5a 97 #define DEBUG_PRINTF printf
Michael J. Spencer 2:1df0b61d3b5a 98 //#define DEBUG_PRINTF(...)
Michael J. Spencer 2:1df0b61d3b5a 99
Michael J. Spencer 2:1df0b61d3b5a 100
Michael J. Spencer 2:1df0b61d3b5a 101 // this callback gets the results of a command, line by line. need to check if
Michael J. Spencer 2:1df0b61d3b5a 102 // we need to stall the upstream sender return 0 if stalled 1 if ok to keep
Michael J. Spencer 2:1df0b61d3b5a 103 // providing more -1 if the connection has closed or is not in output state.
Michael J. Spencer 2:1df0b61d3b5a 104 // need to see which connection to send to based on state and add result to
Michael J. Spencer 2:1df0b61d3b5a 105 // that fifo for each connection. NOTE this will not get called if the
Michael J. Spencer 2:1df0b61d3b5a 106 // connection has been closed and the stream will get deleted when the last
Michael J. Spencer 2:1df0b61d3b5a 107 // command has been executed
Michael J. Spencer 2:1df0b61d3b5a 108 static int command_result(const char *str, void *state)
Michael J. Spencer 2:1df0b61d3b5a 109 {
Michael J. Spencer 2:1df0b61d3b5a 110 struct httpd_state *s = (struct httpd_state *)state;
Michael J. Spencer 2:1df0b61d3b5a 111 if (s == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 112 // connection was closed so discard, this should never happen
Michael J. Spencer 2:1df0b61d3b5a 113 DEBUG_PRINTF("ERROR: command result for closed state %d\n", (int)state);
Michael J. Spencer 2:1df0b61d3b5a 114 return -1;
Michael J. Spencer 2:1df0b61d3b5a 115 }
Michael J. Spencer 2:1df0b61d3b5a 116
Michael J. Spencer 2:1df0b61d3b5a 117 if (str == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 118 DEBUG_PRINTF("End of command (%p)\n", state);
Michael J. Spencer 2:1df0b61d3b5a 119 fifo_push(s->fifo, NULL);
Michael J. Spencer 2:1df0b61d3b5a 120
Michael J. Spencer 2:1df0b61d3b5a 121 } else {
Michael J. Spencer 2:1df0b61d3b5a 122 if (fifo_size(s->fifo) < 10) {
Michael J. Spencer 2:1df0b61d3b5a 123 DEBUG_PRINTF("Got command result (%p): %s", state, str);
Michael J. Spencer 2:1df0b61d3b5a 124 fifo_push(s->fifo, strdup(str));
Michael J. Spencer 2:1df0b61d3b5a 125 return 1;
Michael J. Spencer 2:1df0b61d3b5a 126 } else {
Michael J. Spencer 2:1df0b61d3b5a 127 DEBUG_PRINTF("command result fifo is full (%p)\n", state);
Michael J. Spencer 2:1df0b61d3b5a 128 return 0;
Michael J. Spencer 2:1df0b61d3b5a 129 }
Michael J. Spencer 2:1df0b61d3b5a 130 }
Michael J. Spencer 2:1df0b61d3b5a 131 return 1;
Michael J. Spencer 2:1df0b61d3b5a 132 }
Michael J. Spencer 2:1df0b61d3b5a 133
Michael J. Spencer 2:1df0b61d3b5a 134 static void create_callback_stream(struct httpd_state *s)
Michael J. Spencer 2:1df0b61d3b5a 135 {
Michael J. Spencer 2:1df0b61d3b5a 136 // need to create a callback stream here, but do one per connection pass
Michael J. Spencer 2:1df0b61d3b5a 137 // the state to the callback, also create the fifo for the command results
Michael J. Spencer 2:1df0b61d3b5a 138 s->fifo = new_fifo();
Michael J. Spencer 2:1df0b61d3b5a 139 s->pstream = new_callback_stream(command_result, s);
Michael J. Spencer 2:1df0b61d3b5a 140 }
Michael J. Spencer 2:1df0b61d3b5a 141
Michael J. Spencer 2:1df0b61d3b5a 142 // Used to save files to SDCARD during upload
Michael J. Spencer 2:1df0b61d3b5a 143 static FILE *fd;
Michael J. Spencer 2:1df0b61d3b5a 144 static char *output_filename = NULL;
Michael J. Spencer 2:1df0b61d3b5a 145 static int file_cnt = 0;
Michael J. Spencer 2:1df0b61d3b5a 146 static int open_file(const char *fn)
Michael J. Spencer 2:1df0b61d3b5a 147 {
Michael J. Spencer 2:1df0b61d3b5a 148 if (output_filename != NULL) free(output_filename);
Michael J. Spencer 2:1df0b61d3b5a 149 output_filename = malloc(strlen(fn) + 5);
Michael J. Spencer 2:1df0b61d3b5a 150 strcpy(output_filename, "/sd/");
Michael J. Spencer 2:1df0b61d3b5a 151 strcat(output_filename, fn);
Michael J. Spencer 2:1df0b61d3b5a 152 fd = fopen(output_filename, "w");
Michael J. Spencer 2:1df0b61d3b5a 153 if (fd == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 154 free(output_filename);
Michael J. Spencer 2:1df0b61d3b5a 155 output_filename = NULL;
Michael J. Spencer 2:1df0b61d3b5a 156 return 0;
Michael J. Spencer 2:1df0b61d3b5a 157 }
Michael J. Spencer 2:1df0b61d3b5a 158 return 1;
Michael J. Spencer 2:1df0b61d3b5a 159 }
Michael J. Spencer 2:1df0b61d3b5a 160
Michael J. Spencer 2:1df0b61d3b5a 161 static int close_file()
Michael J. Spencer 2:1df0b61d3b5a 162 {
Michael J. Spencer 2:1df0b61d3b5a 163 free(output_filename);
Michael J. Spencer 2:1df0b61d3b5a 164 output_filename = NULL;
Michael J. Spencer 2:1df0b61d3b5a 165 fclose(fd);
Michael J. Spencer 2:1df0b61d3b5a 166 return 1;
Michael J. Spencer 2:1df0b61d3b5a 167 }
Michael J. Spencer 2:1df0b61d3b5a 168
Michael J. Spencer 2:1df0b61d3b5a 169 static int save_file(uint8_t *buf, unsigned int len)
Michael J. Spencer 2:1df0b61d3b5a 170 {
Michael J. Spencer 2:1df0b61d3b5a 171 if (fwrite(buf, 1, len, fd) == len) {
Michael J. Spencer 2:1df0b61d3b5a 172 file_cnt += len;
Michael J. Spencer 2:1df0b61d3b5a 173 // HACK alert work around bug causing file corruption when writing large amounts of data
Michael J. Spencer 2:1df0b61d3b5a 174 if (file_cnt >= 400) {
Michael J. Spencer 2:1df0b61d3b5a 175 file_cnt = 0;
Michael J. Spencer 2:1df0b61d3b5a 176 fclose(fd);
Michael J. Spencer 2:1df0b61d3b5a 177 fd = fopen(output_filename, "a");
Michael J. Spencer 2:1df0b61d3b5a 178 }
Michael J. Spencer 2:1df0b61d3b5a 179 return 1;
Michael J. Spencer 2:1df0b61d3b5a 180
Michael J. Spencer 2:1df0b61d3b5a 181 } else {
Michael J. Spencer 2:1df0b61d3b5a 182 close_file();
Michael J. Spencer 2:1df0b61d3b5a 183 return 0;
Michael J. Spencer 2:1df0b61d3b5a 184 }
Michael J. Spencer 2:1df0b61d3b5a 185 }
Michael J. Spencer 2:1df0b61d3b5a 186
Michael J. Spencer 2:1df0b61d3b5a 187 static int fs_open(struct httpd_state *s)
Michael J. Spencer 2:1df0b61d3b5a 188 {
Michael J. Spencer 2:1df0b61d3b5a 189 if (strncmp(s->filename, "/sd/", 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 190 DEBUG_PRINTF("Opening file %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 191 s->fd = fopen(s->filename, "r");
Michael J. Spencer 2:1df0b61d3b5a 192 if (s->fd == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 193 DEBUG_PRINTF("Failed to open: %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 194 return 0;
Michael J. Spencer 2:1df0b61d3b5a 195 }
Michael J. Spencer 2:1df0b61d3b5a 196 return 1;
Michael J. Spencer 2:1df0b61d3b5a 197
Michael J. Spencer 2:1df0b61d3b5a 198 } else {
Michael J. Spencer 2:1df0b61d3b5a 199 s->fd = NULL;
Michael J. Spencer 2:1df0b61d3b5a 200 return httpd_fs_open(s->filename, &s->file);
Michael J. Spencer 2:1df0b61d3b5a 201 }
Michael J. Spencer 2:1df0b61d3b5a 202 }
Michael J. Spencer 2:1df0b61d3b5a 203
Michael J. Spencer 2:1df0b61d3b5a 204 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 205 static PT_THREAD(send_command_response(struct httpd_state *s))
Michael J. Spencer 2:1df0b61d3b5a 206 {
Michael J. Spencer 2:1df0b61d3b5a 207 PSOCK_BEGIN(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 208
Michael J. Spencer 2:1df0b61d3b5a 209 do {
Michael J. Spencer 2:1df0b61d3b5a 210 PSOCK_WAIT_UNTIL( &s->sout, fifo_size(s->fifo) > 0 );
Michael J. Spencer 2:1df0b61d3b5a 211 s->strbuf = fifo_pop(s->fifo);
Michael J. Spencer 2:1df0b61d3b5a 212 if (s->strbuf != NULL) {
Michael J. Spencer 2:1df0b61d3b5a 213 // send it
Michael J. Spencer 2:1df0b61d3b5a 214 DEBUG_PRINTF("Sending response: %s", s->strbuf);
Michael J. Spencer 2:1df0b61d3b5a 215 // TODO send as much as we can in one packet
Michael J. Spencer 2:1df0b61d3b5a 216 PSOCK_SEND_STR(&s->sout, s->strbuf);
Michael J. Spencer 2:1df0b61d3b5a 217 // free the strdup
Michael J. Spencer 2:1df0b61d3b5a 218 free(s->strbuf);
Michael J. Spencer 2:1df0b61d3b5a 219 }else if(--s->command_count <= 0) {
Michael J. Spencer 2:1df0b61d3b5a 220 // when all commands have completed exit
Michael J. Spencer 2:1df0b61d3b5a 221 break;
Michael J. Spencer 2:1df0b61d3b5a 222 }
Michael J. Spencer 2:1df0b61d3b5a 223 } while (1);
Michael J. Spencer 2:1df0b61d3b5a 224
Michael J. Spencer 2:1df0b61d3b5a 225 PSOCK_END(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 226 }
Michael J. Spencer 2:1df0b61d3b5a 227
Michael J. Spencer 2:1df0b61d3b5a 228 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 229 static unsigned short generate_part_of_file(void *state)
Michael J. Spencer 2:1df0b61d3b5a 230 {
Michael J. Spencer 2:1df0b61d3b5a 231 struct httpd_state *s = (struct httpd_state *)state;
Michael J. Spencer 2:1df0b61d3b5a 232
Michael J. Spencer 2:1df0b61d3b5a 233 if (s->file.len > uip_mss()) {
Michael J. Spencer 2:1df0b61d3b5a 234 s->len = uip_mss();
Michael J. Spencer 2:1df0b61d3b5a 235 } else {
Michael J. Spencer 2:1df0b61d3b5a 236 s->len = s->file.len;
Michael J. Spencer 2:1df0b61d3b5a 237 }
Michael J. Spencer 2:1df0b61d3b5a 238 memcpy(uip_appdata, s->file.data, s->len);
Michael J. Spencer 2:1df0b61d3b5a 239
Michael J. Spencer 2:1df0b61d3b5a 240 return s->len;
Michael J. Spencer 2:1df0b61d3b5a 241 }
Michael J. Spencer 2:1df0b61d3b5a 242 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 243 static unsigned short generate_part_of_sd_file(void *state)
Michael J. Spencer 2:1df0b61d3b5a 244 {
Michael J. Spencer 2:1df0b61d3b5a 245 struct httpd_state *s = (struct httpd_state *)state;
Michael J. Spencer 2:1df0b61d3b5a 246
Michael J. Spencer 2:1df0b61d3b5a 247 int len = fread(uip_appdata, 1, uip_mss(), s->fd);
Michael J. Spencer 2:1df0b61d3b5a 248 if (len <= 0) {
Michael J. Spencer 2:1df0b61d3b5a 249 // we need to send something
Michael J. Spencer 2:1df0b61d3b5a 250 strcpy(uip_appdata, "\r\n");
Michael J. Spencer 2:1df0b61d3b5a 251 len = 2;
Michael J. Spencer 2:1df0b61d3b5a 252 s->len = 0;
Michael J. Spencer 2:1df0b61d3b5a 253 } else {
Michael J. Spencer 2:1df0b61d3b5a 254 s->len = len;
Michael J. Spencer 2:1df0b61d3b5a 255 }
Michael J. Spencer 2:1df0b61d3b5a 256 return len;
Michael J. Spencer 2:1df0b61d3b5a 257 }
Michael J. Spencer 2:1df0b61d3b5a 258 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 259 static
Michael J. Spencer 2:1df0b61d3b5a 260 PT_THREAD(send_file(struct httpd_state *s))
Michael J. Spencer 2:1df0b61d3b5a 261 {
Michael J. Spencer 2:1df0b61d3b5a 262 PSOCK_BEGIN(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 263
Michael J. Spencer 2:1df0b61d3b5a 264 do {
Michael J. Spencer 2:1df0b61d3b5a 265 PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_file, s);
Michael J. Spencer 2:1df0b61d3b5a 266 s->file.len -= s->len;
Michael J. Spencer 2:1df0b61d3b5a 267 s->file.data += s->len;
Michael J. Spencer 2:1df0b61d3b5a 268 } while (s->file.len > 0);
Michael J. Spencer 2:1df0b61d3b5a 269
Michael J. Spencer 2:1df0b61d3b5a 270 PSOCK_END(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 271 }
Michael J. Spencer 2:1df0b61d3b5a 272
Michael J. Spencer 2:1df0b61d3b5a 273 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 274 static PT_THREAD(send_sd_file(struct httpd_state *s))
Michael J. Spencer 2:1df0b61d3b5a 275 {
Michael J. Spencer 2:1df0b61d3b5a 276 PSOCK_BEGIN(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 277
Michael J. Spencer 2:1df0b61d3b5a 278 do {
Michael J. Spencer 2:1df0b61d3b5a 279 PSOCK_GENERATOR_SEND(&s->sout, generate_part_of_sd_file, s);
Michael J. Spencer 2:1df0b61d3b5a 280 } while (s->len > 0);
Michael J. Spencer 2:1df0b61d3b5a 281
Michael J. Spencer 2:1df0b61d3b5a 282 fclose(s->fd);
Michael J. Spencer 2:1df0b61d3b5a 283 s->fd = NULL;
Michael J. Spencer 2:1df0b61d3b5a 284
Michael J. Spencer 2:1df0b61d3b5a 285 PSOCK_END(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 286 }
Michael J. Spencer 2:1df0b61d3b5a 287
Michael J. Spencer 2:1df0b61d3b5a 288 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 289 static PT_THREAD(send_headers_3(struct httpd_state *s, const char *statushdr, char send_content_type))
Michael J. Spencer 2:1df0b61d3b5a 290 {
Michael J. Spencer 2:1df0b61d3b5a 291 char *ptr;
Michael J. Spencer 2:1df0b61d3b5a 292
Michael J. Spencer 2:1df0b61d3b5a 293 PSOCK_BEGIN(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 294
Michael J. Spencer 2:1df0b61d3b5a 295 PSOCK_SEND_STR(&s->sout, statushdr);
Michael J. Spencer 2:1df0b61d3b5a 296
Michael J. Spencer 2:1df0b61d3b5a 297 if (send_content_type) {
Michael J. Spencer 2:1df0b61d3b5a 298 ptr = strrchr(s->filename, ISO_period);
Michael J. Spencer 2:1df0b61d3b5a 299 if (ptr == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 300 PSOCK_SEND_STR(&s->sout, http_content_type_plain); // http_content_type_binary);
Michael J. Spencer 2:1df0b61d3b5a 301 } else if (strncmp(http_html, ptr, 5) == 0 || strncmp(http_shtml, ptr, 6) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 302 PSOCK_SEND_STR(&s->sout, http_content_type_html);
Michael J. Spencer 2:1df0b61d3b5a 303 } else if (strncmp(http_css, ptr, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 304 PSOCK_SEND_STR(&s->sout, http_content_type_css);
Michael J. Spencer 2:1df0b61d3b5a 305 } else if (strncmp(http_png, ptr, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 306 PSOCK_SEND_STR(&s->sout, http_content_type_png);
Michael J. Spencer 2:1df0b61d3b5a 307 } else if (strncmp(http_gif, ptr, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 308 PSOCK_SEND_STR(&s->sout, http_content_type_gif);
Michael J. Spencer 2:1df0b61d3b5a 309 } else if (strncmp(http_jpg, ptr, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 310 PSOCK_SEND_STR(&s->sout, http_content_type_jpg);
Michael J. Spencer 2:1df0b61d3b5a 311 } else {
Michael J. Spencer 2:1df0b61d3b5a 312 PSOCK_SEND_STR(&s->sout, http_content_type_plain);
Michael J. Spencer 2:1df0b61d3b5a 313 }
Michael J. Spencer 2:1df0b61d3b5a 314 }
Michael J. Spencer 2:1df0b61d3b5a 315 PSOCK_END(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 316 }
Michael J. Spencer 2:1df0b61d3b5a 317 static PT_THREAD(send_headers(struct httpd_state *s, const char *statushdr))
Michael J. Spencer 2:1df0b61d3b5a 318 {
Michael J. Spencer 2:1df0b61d3b5a 319 return send_headers_3(s, statushdr, 1);
Michael J. Spencer 2:1df0b61d3b5a 320 }
Michael J. Spencer 2:1df0b61d3b5a 321 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 322 static
Michael J. Spencer 2:1df0b61d3b5a 323 PT_THREAD(handle_output(struct httpd_state *s))
Michael J. Spencer 2:1df0b61d3b5a 324 {
Michael J. Spencer 2:1df0b61d3b5a 325 PT_BEGIN(&s->outputpt);
Michael J. Spencer 2:1df0b61d3b5a 326
Michael J. Spencer 2:1df0b61d3b5a 327 if (s->method == POST) {
Michael J. Spencer 2:1df0b61d3b5a 328 if (strcmp(s->filename, "/command") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 329 DEBUG_PRINTF("Executed command post\n");
Michael J. Spencer 2:1df0b61d3b5a 330 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200));
Michael J. Spencer 2:1df0b61d3b5a 331 // send response as we get it
Michael J. Spencer 2:1df0b61d3b5a 332 PT_WAIT_THREAD(&s->outputpt, send_command_response(s));
Michael J. Spencer 2:1df0b61d3b5a 333
Michael J. Spencer 2:1df0b61d3b5a 334 } else if (strcmp(s->filename, "/command_silent") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 335 DEBUG_PRINTF("Executed silent command post\n");
Michael J. Spencer 2:1df0b61d3b5a 336 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200));
Michael J. Spencer 2:1df0b61d3b5a 337
Michael J. Spencer 2:1df0b61d3b5a 338 } else if (strcmp(s->filename, "/upload") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 339 DEBUG_PRINTF("upload output: %d\n", s->uploadok);
Michael J. Spencer 2:1df0b61d3b5a 340 if (s->uploadok == 0) {
Michael J. Spencer 2:1df0b61d3b5a 341 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_503));
Michael J. Spencer 2:1df0b61d3b5a 342 PSOCK_SEND_STR(&s->sout, "FAILED\r\n");
Michael J. Spencer 2:1df0b61d3b5a 343 } else {
Michael J. Spencer 2:1df0b61d3b5a 344 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200));
Michael J. Spencer 2:1df0b61d3b5a 345 PSOCK_SEND_STR(&s->sout, "OK\r\n");
Michael J. Spencer 2:1df0b61d3b5a 346 }
Michael J. Spencer 2:1df0b61d3b5a 347
Michael J. Spencer 2:1df0b61d3b5a 348 } else {
Michael J. Spencer 2:1df0b61d3b5a 349 DEBUG_PRINTF("Unknown POST: %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 350 httpd_fs_open(http_404_html, &s->file);
Michael J. Spencer 2:1df0b61d3b5a 351 strcpy(s->filename, http_404_html);
Michael J. Spencer 2:1df0b61d3b5a 352 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404));
Michael J. Spencer 2:1df0b61d3b5a 353 PT_WAIT_THREAD(&s->outputpt, send_file(s));
Michael J. Spencer 2:1df0b61d3b5a 354 }
Michael J. Spencer 2:1df0b61d3b5a 355
Michael J. Spencer 2:1df0b61d3b5a 356 } else {
Michael J. Spencer 2:1df0b61d3b5a 357 // Presume method GET
Michael J. Spencer 2:1df0b61d3b5a 358 if (!fs_open(s)) { // Note this has the side effect of opening the file
Michael J. Spencer 2:1df0b61d3b5a 359 DEBUG_PRINTF("404 file not found\n");
Michael J. Spencer 2:1df0b61d3b5a 360 httpd_fs_open(http_404_html, &s->file);
Michael J. Spencer 2:1df0b61d3b5a 361 strcpy(s->filename, http_404_html);
Michael J. Spencer 2:1df0b61d3b5a 362 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_404));
Michael J. Spencer 2:1df0b61d3b5a 363 PT_WAIT_THREAD(&s->outputpt, send_file(s));
Michael J. Spencer 2:1df0b61d3b5a 364
Michael J. Spencer 2:1df0b61d3b5a 365 } else if (s->cache_page) {
Michael J. Spencer 2:1df0b61d3b5a 366 if (s->fd != NULL) {
Michael J. Spencer 2:1df0b61d3b5a 367 // if it was an sd file then we need to close it
Michael J. Spencer 2:1df0b61d3b5a 368 fclose(s->fd);
Michael J. Spencer 2:1df0b61d3b5a 369 s->fd = NULL;
Michael J. Spencer 2:1df0b61d3b5a 370 }
Michael J. Spencer 2:1df0b61d3b5a 371 // tell it it has not changed
Michael J. Spencer 2:1df0b61d3b5a 372 DEBUG_PRINTF("304 Not Modified\n");
Michael J. Spencer 2:1df0b61d3b5a 373 PT_WAIT_THREAD(&s->outputpt, send_headers_3(s, http_header_304, 0));
Michael J. Spencer 2:1df0b61d3b5a 374
Michael J. Spencer 2:1df0b61d3b5a 375 } else {
Michael J. Spencer 2:1df0b61d3b5a 376 DEBUG_PRINTF("sending file %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 377 PT_WAIT_THREAD(&s->outputpt, send_headers(s, http_header_200));
Michael J. Spencer 2:1df0b61d3b5a 378 if (s->fd != NULL) {
Michael J. Spencer 2:1df0b61d3b5a 379 // send from sd card
Michael J. Spencer 2:1df0b61d3b5a 380 PT_WAIT_THREAD(&s->outputpt, send_sd_file(s));
Michael J. Spencer 2:1df0b61d3b5a 381
Michael J. Spencer 2:1df0b61d3b5a 382 } else {
Michael J. Spencer 2:1df0b61d3b5a 383 // send from FLASH
Michael J. Spencer 2:1df0b61d3b5a 384 PT_WAIT_THREAD(&s->outputpt, send_file(s));
Michael J. Spencer 2:1df0b61d3b5a 385 }
Michael J. Spencer 2:1df0b61d3b5a 386 }
Michael J. Spencer 2:1df0b61d3b5a 387 }
Michael J. Spencer 2:1df0b61d3b5a 388
Michael J. Spencer 2:1df0b61d3b5a 389 PSOCK_CLOSE(&s->sout);
Michael J. Spencer 2:1df0b61d3b5a 390 PT_END(&s->outputpt);
Michael J. Spencer 2:1df0b61d3b5a 391 }
Michael J. Spencer 2:1df0b61d3b5a 392
Michael J. Spencer 2:1df0b61d3b5a 393 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 394 // this forces us to yield every other call as we read all data everytime
Michael J. Spencer 2:1df0b61d3b5a 395 static char has_newdata(struct httpd_state *s)
Michael J. Spencer 2:1df0b61d3b5a 396 {
Michael J. Spencer 2:1df0b61d3b5a 397 if (s->upload_state == 1) {
Michael J. Spencer 2:1df0b61d3b5a 398 /* All data in uip_appdata buffer already consumed. */
Michael J. Spencer 2:1df0b61d3b5a 399 s->upload_state = 0;
Michael J. Spencer 2:1df0b61d3b5a 400 return 0;
Michael J. Spencer 2:1df0b61d3b5a 401 } else if (uip_newdata()) {
Michael J. Spencer 2:1df0b61d3b5a 402 /* There is new data that has not been consumed. */
Michael J. Spencer 2:1df0b61d3b5a 403 return 1;
Michael J. Spencer 2:1df0b61d3b5a 404 } else {
Michael J. Spencer 2:1df0b61d3b5a 405 /* There is no new data. */
Michael J. Spencer 2:1df0b61d3b5a 406 return 0;
Michael J. Spencer 2:1df0b61d3b5a 407 }
Michael J. Spencer 2:1df0b61d3b5a 408 }
Michael J. Spencer 2:1df0b61d3b5a 409
Michael J. Spencer 2:1df0b61d3b5a 410 /*
Michael J. Spencer 2:1df0b61d3b5a 411 * handle trhe uploaded data, as there may be part of that buffer still in the last packet buffer
Michael J. Spencer 2:1df0b61d3b5a 412 * write that first from the buf/len parameters
Michael J. Spencer 2:1df0b61d3b5a 413 */
Michael J. Spencer 2:1df0b61d3b5a 414 static PT_THREAD(handle_uploaded_data(struct httpd_state *s, uint8_t *buf, int len))
Michael J. Spencer 2:1df0b61d3b5a 415 {
Michael J. Spencer 2:1df0b61d3b5a 416 PT_BEGIN(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 417
Michael J. Spencer 2:1df0b61d3b5a 418 DEBUG_PRINTF("Uploading file: %s, %d\n", s->upload_name, s->content_length);
Michael J. Spencer 2:1df0b61d3b5a 419
Michael J. Spencer 2:1df0b61d3b5a 420 // The body is the raw data to be stored to the file
Michael J. Spencer 2:1df0b61d3b5a 421 if (!open_file(s->upload_name)) {
Michael J. Spencer 2:1df0b61d3b5a 422 DEBUG_PRINTF("failed to open file\n");
Michael J. Spencer 2:1df0b61d3b5a 423 s->uploadok = 0;
Michael J. Spencer 2:1df0b61d3b5a 424 PT_EXIT(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 425 }
Michael J. Spencer 2:1df0b61d3b5a 426
Michael J. Spencer 2:1df0b61d3b5a 427 DEBUG_PRINTF("opened file: %s\n", s->upload_name);
Michael J. Spencer 2:1df0b61d3b5a 428
Michael J. Spencer 2:1df0b61d3b5a 429 if (len > 0) {
Michael J. Spencer 2:1df0b61d3b5a 430 // write the first part of the buffer
Michael J. Spencer 2:1df0b61d3b5a 431 if (!save_file(buf, len)) {
Michael J. Spencer 2:1df0b61d3b5a 432 DEBUG_PRINTF("initial write failed\n");
Michael J. Spencer 2:1df0b61d3b5a 433 s->uploadok = 0;
Michael J. Spencer 2:1df0b61d3b5a 434 PT_EXIT(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 435 }
Michael J. Spencer 2:1df0b61d3b5a 436 s->content_length -= len;
Michael J. Spencer 2:1df0b61d3b5a 437 }
Michael J. Spencer 2:1df0b61d3b5a 438
Michael J. Spencer 2:1df0b61d3b5a 439 s->upload_state = 1; // first time through we need to yield to get new data
Michael J. Spencer 2:1df0b61d3b5a 440
Michael J. Spencer 2:1df0b61d3b5a 441 // save the entire input buffer
Michael J. Spencer 2:1df0b61d3b5a 442 while (s->content_length > 0) {
Michael J. Spencer 2:1df0b61d3b5a 443 PT_WAIT_UNTIL(&s->inputpt, has_newdata(s));
Michael J. Spencer 2:1df0b61d3b5a 444 s->upload_state = 1;
Michael J. Spencer 2:1df0b61d3b5a 445
Michael J. Spencer 2:1df0b61d3b5a 446 u8_t *readptr = (u8_t *)uip_appdata;
Michael J. Spencer 2:1df0b61d3b5a 447 int readlen = uip_datalen();
Michael J. Spencer 2:1df0b61d3b5a 448 //DEBUG_PRINTF("read %d bytes of data\n", readlen);
Michael J. Spencer 2:1df0b61d3b5a 449
Michael J. Spencer 2:1df0b61d3b5a 450 if (readlen > 0) {
Michael J. Spencer 2:1df0b61d3b5a 451 if (!save_file(readptr, readlen)) {
Michael J. Spencer 2:1df0b61d3b5a 452 DEBUG_PRINTF("write failed\n");
Michael J. Spencer 2:1df0b61d3b5a 453 s->uploadok = 0;
Michael J. Spencer 2:1df0b61d3b5a 454 PT_EXIT(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 455 }
Michael J. Spencer 2:1df0b61d3b5a 456 s->content_length -= readlen;
Michael J. Spencer 2:1df0b61d3b5a 457 }
Michael J. Spencer 2:1df0b61d3b5a 458 }
Michael J. Spencer 2:1df0b61d3b5a 459
Michael J. Spencer 2:1df0b61d3b5a 460 close_file();
Michael J. Spencer 2:1df0b61d3b5a 461 s->uploadok = 1;
Michael J. Spencer 2:1df0b61d3b5a 462 DEBUG_PRINTF("finished upload\n");
Michael J. Spencer 2:1df0b61d3b5a 463
Michael J. Spencer 2:1df0b61d3b5a 464 PT_END(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 465 }
Michael J. Spencer 2:1df0b61d3b5a 466 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 467 static
Michael J. Spencer 2:1df0b61d3b5a 468 PT_THREAD(handle_input(struct httpd_state *s))
Michael J. Spencer 2:1df0b61d3b5a 469 {
Michael J. Spencer 2:1df0b61d3b5a 470 PSOCK_BEGIN(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 471
Michael J. Spencer 2:1df0b61d3b5a 472 PSOCK_READTO(&s->sin, ISO_space);
Michael J. Spencer 2:1df0b61d3b5a 473
Michael J. Spencer 2:1df0b61d3b5a 474 if (strncmp(s->inputbuf, http_get, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 475 s->method = GET;
Michael J. Spencer 2:1df0b61d3b5a 476 } else if (strncmp(s->inputbuf, http_post, 4) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 477 s->method = POST;
Michael J. Spencer 2:1df0b61d3b5a 478 } else {
Michael J. Spencer 2:1df0b61d3b5a 479 DEBUG_PRINTF("Unexpected method: %s\n", s->inputbuf);
Michael J. Spencer 2:1df0b61d3b5a 480 PSOCK_CLOSE_EXIT(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 481 }
Michael J. Spencer 2:1df0b61d3b5a 482
Michael J. Spencer 2:1df0b61d3b5a 483 DEBUG_PRINTF("Method: %s\n", s->method == POST ? "POST" : "GET");
Michael J. Spencer 2:1df0b61d3b5a 484
Michael J. Spencer 2:1df0b61d3b5a 485 PSOCK_READTO(&s->sin, ISO_space);
Michael J. Spencer 2:1df0b61d3b5a 486
Michael J. Spencer 2:1df0b61d3b5a 487 if (s->inputbuf[0] != ISO_slash) {
Michael J. Spencer 2:1df0b61d3b5a 488 PSOCK_CLOSE_EXIT(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 489 }
Michael J. Spencer 2:1df0b61d3b5a 490
Michael J. Spencer 2:1df0b61d3b5a 491 if (s->inputbuf[1] == ISO_space) {
Michael J. Spencer 2:1df0b61d3b5a 492 strncpy(s->filename, http_index_html, sizeof(s->filename));
Michael J. Spencer 2:1df0b61d3b5a 493 } else {
Michael J. Spencer 2:1df0b61d3b5a 494 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
Michael J. Spencer 2:1df0b61d3b5a 495 strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename));
Michael J. Spencer 2:1df0b61d3b5a 496 }
Michael J. Spencer 2:1df0b61d3b5a 497
Michael J. Spencer 2:1df0b61d3b5a 498 DEBUG_PRINTF("filename: %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 499
Michael J. Spencer 2:1df0b61d3b5a 500 /* httpd_log_file(uip_conn->ripaddr, s->filename);*/
Michael J. Spencer 2:1df0b61d3b5a 501
Michael J. Spencer 2:1df0b61d3b5a 502 s->state = STATE_HEADERS;
Michael J. Spencer 2:1df0b61d3b5a 503 s->content_length = 0;
Michael J. Spencer 2:1df0b61d3b5a 504 s->cache_page = 0;
Michael J. Spencer 2:1df0b61d3b5a 505 while (1) {
Michael J. Spencer 2:1df0b61d3b5a 506 if (s->state == STATE_HEADERS) {
Michael J. Spencer 2:1df0b61d3b5a 507 // read the headers of the request
Michael J. Spencer 2:1df0b61d3b5a 508 PSOCK_READTO(&s->sin, ISO_nl);
Michael J. Spencer 2:1df0b61d3b5a 509 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
Michael J. Spencer 2:1df0b61d3b5a 510 if (s->inputbuf[0] == '\r') {
Michael J. Spencer 2:1df0b61d3b5a 511 DEBUG_PRINTF("end of headers\n");
Michael J. Spencer 2:1df0b61d3b5a 512 if (s->method == GET) {
Michael J. Spencer 2:1df0b61d3b5a 513 s->state = STATE_OUTPUT;
Michael J. Spencer 2:1df0b61d3b5a 514 break;
Michael J. Spencer 2:1df0b61d3b5a 515 } else if (s->method == POST) {
Michael J. Spencer 2:1df0b61d3b5a 516 if (strcmp(s->filename, "/upload") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 517 s->state = STATE_UPLOAD;
Michael J. Spencer 2:1df0b61d3b5a 518 } else {
Michael J. Spencer 2:1df0b61d3b5a 519 s->state = STATE_BODY;
Michael J. Spencer 2:1df0b61d3b5a 520 }
Michael J. Spencer 2:1df0b61d3b5a 521 }
Michael J. Spencer 2:1df0b61d3b5a 522 } else {
Michael J. Spencer 2:1df0b61d3b5a 523 DEBUG_PRINTF("reading header: %s\n", s->inputbuf);
Michael J. Spencer 2:1df0b61d3b5a 524 // handle headers here
Michael J. Spencer 2:1df0b61d3b5a 525 if (strncmp(s->inputbuf, http_content_length, sizeof(http_content_length) - 1) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 526 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
Michael J. Spencer 2:1df0b61d3b5a 527 s->content_length = atoi(&s->inputbuf[sizeof(http_content_length) - 1]);
Michael J. Spencer 2:1df0b61d3b5a 528 DEBUG_PRINTF("Content length= %s, %d\n", &s->inputbuf[sizeof(http_content_length) - 1], s->content_length);
Michael J. Spencer 2:1df0b61d3b5a 529
Michael J. Spencer 2:1df0b61d3b5a 530 } else if (strncmp(s->inputbuf, "X-Filename: ", 11) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 531 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
Michael J. Spencer 2:1df0b61d3b5a 532 strncpy(s->upload_name, &s->inputbuf[12], sizeof(s->upload_name) - 1);
Michael J. Spencer 2:1df0b61d3b5a 533 DEBUG_PRINTF("Upload name= %s\n", s->upload_name);
Michael J. Spencer 2:1df0b61d3b5a 534
Michael J. Spencer 2:1df0b61d3b5a 535 } else if (strncmp(s->inputbuf, http_cache_control, sizeof(http_cache_control) - 1) == 0) {
Michael J. Spencer 2:1df0b61d3b5a 536 s->inputbuf[PSOCK_DATALEN(&s->sin) - 2] = 0;
Michael J. Spencer 2:1df0b61d3b5a 537 s->cache_page = strncmp(http_no_cache, &s->inputbuf[sizeof(http_cache_control) - 1], sizeof(http_no_cache) - 1) != 0;
Michael J. Spencer 2:1df0b61d3b5a 538 DEBUG_PRINTF("cache page= %d\n", s->cache_page);
Michael J. Spencer 2:1df0b61d3b5a 539 }
Michael J. Spencer 2:1df0b61d3b5a 540 }
Michael J. Spencer 2:1df0b61d3b5a 541
Michael J. Spencer 2:1df0b61d3b5a 542 } else if (s->state == STATE_BODY) {
Michael J. Spencer 2:1df0b61d3b5a 543 if (s->method == POST && strcmp(s->filename, "/command") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 544 // create a callback stream and fifo for the results as it is a command
Michael J. Spencer 2:1df0b61d3b5a 545 create_callback_stream(s);
Michael J. Spencer 2:1df0b61d3b5a 546
Michael J. Spencer 2:1df0b61d3b5a 547 } else if (s->method == POST && strcmp(s->filename, "/command_silent") == 0) {
Michael J. Spencer 2:1df0b61d3b5a 548 // stick the command on the command queue specifying null output stream
Michael J. Spencer 2:1df0b61d3b5a 549 s->pstream = NULL;
Michael J. Spencer 2:1df0b61d3b5a 550
Michael J. Spencer 2:1df0b61d3b5a 551 } else { // unknown POST
Michael J. Spencer 2:1df0b61d3b5a 552 DEBUG_PRINTF("Unknown Post URL: %s\n", s->filename);
Michael J. Spencer 2:1df0b61d3b5a 553 s->state = STATE_OUTPUT;
Michael J. Spencer 2:1df0b61d3b5a 554 break;
Michael J. Spencer 2:1df0b61d3b5a 555 }
Michael J. Spencer 2:1df0b61d3b5a 556 s->command_count= 0;
Michael J. Spencer 2:1df0b61d3b5a 557 // read the Body of the request, each line is a command
Michael J. Spencer 2:1df0b61d3b5a 558 if (s->content_length > 0) {
Michael J. Spencer 2:1df0b61d3b5a 559 DEBUG_PRINTF("start reading body %d...\n", s->content_length);
Michael J. Spencer 2:1df0b61d3b5a 560 while (s->content_length > 2) {
Michael J. Spencer 2:1df0b61d3b5a 561 PSOCK_READTO(&s->sin, ISO_nl);
Michael J. Spencer 2:1df0b61d3b5a 562 s->inputbuf[PSOCK_DATALEN(&s->sin) - 1] = 0;
Michael J. Spencer 2:1df0b61d3b5a 563 s->content_length -= PSOCK_DATALEN(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 564 // stick the command on the command queue, with this connections stream output
Michael J. Spencer 2:1df0b61d3b5a 565 DEBUG_PRINTF("Adding command: %s, left: %d\n", s->inputbuf, s->content_length);
Michael J. Spencer 2:1df0b61d3b5a 566 network_add_command(s->inputbuf, s->pstream);
Michael J. Spencer 2:1df0b61d3b5a 567 s->command_count++; // count number of command lines we submit
Michael J. Spencer 2:1df0b61d3b5a 568 }
Michael J. Spencer 2:1df0b61d3b5a 569 DEBUG_PRINTF("Read body done\n");
Michael J. Spencer 2:1df0b61d3b5a 570 s->state = STATE_OUTPUT;
Michael J. Spencer 2:1df0b61d3b5a 571
Michael J. Spencer 2:1df0b61d3b5a 572 } else {
Michael J. Spencer 2:1df0b61d3b5a 573 s->state = STATE_OUTPUT;
Michael J. Spencer 2:1df0b61d3b5a 574 }
Michael J. Spencer 2:1df0b61d3b5a 575 break;
Michael J. Spencer 2:1df0b61d3b5a 576
Michael J. Spencer 2:1df0b61d3b5a 577 } else if (s->state == STATE_UPLOAD) {
Michael J. Spencer 2:1df0b61d3b5a 578 PSOCK_WAIT_THREAD(&s->sin, handle_uploaded_data(s, PSOCK_GET_START_OF_REST_OF_BUFFER(&s->sin), PSOCK_GET_LENGTH_OF_REST_OF_BUFFER(&s->sin)));
Michael J. Spencer 2:1df0b61d3b5a 579 PSOCK_MARK_BUFFER_READ(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 580 s->state = STATE_OUTPUT;
Michael J. Spencer 2:1df0b61d3b5a 581 break;
Michael J. Spencer 2:1df0b61d3b5a 582
Michael J. Spencer 2:1df0b61d3b5a 583 } else {
Michael J. Spencer 2:1df0b61d3b5a 584 DEBUG_PRINTF("WTF State: %d", s->state);
Michael J. Spencer 2:1df0b61d3b5a 585 break;
Michael J. Spencer 2:1df0b61d3b5a 586 }
Michael J. Spencer 2:1df0b61d3b5a 587 }
Michael J. Spencer 2:1df0b61d3b5a 588
Michael J. Spencer 2:1df0b61d3b5a 589 PSOCK_END(&s->sin);
Michael J. Spencer 2:1df0b61d3b5a 590 }
Michael J. Spencer 2:1df0b61d3b5a 591 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 592 static void
Michael J. Spencer 2:1df0b61d3b5a 593 handle_connection(struct httpd_state *s)
Michael J. Spencer 2:1df0b61d3b5a 594 {
Michael J. Spencer 2:1df0b61d3b5a 595 if (s->state != STATE_OUTPUT) {
Michael J. Spencer 2:1df0b61d3b5a 596 handle_input(s);
Michael J. Spencer 2:1df0b61d3b5a 597 }
Michael J. Spencer 2:1df0b61d3b5a 598 if (s->state == STATE_OUTPUT) {
Michael J. Spencer 2:1df0b61d3b5a 599 handle_output(s);
Michael J. Spencer 2:1df0b61d3b5a 600 }
Michael J. Spencer 2:1df0b61d3b5a 601 }
Michael J. Spencer 2:1df0b61d3b5a 602 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 603 void
Michael J. Spencer 2:1df0b61d3b5a 604 httpd_appcall(void)
Michael J. Spencer 2:1df0b61d3b5a 605 {
Michael J. Spencer 2:1df0b61d3b5a 606 struct httpd_state *s = (struct httpd_state *)(uip_conn->appstate);
Michael J. Spencer 2:1df0b61d3b5a 607
Michael J. Spencer 2:1df0b61d3b5a 608 if (uip_connected()) {
Michael J. Spencer 2:1df0b61d3b5a 609 s = malloc(sizeof(struct httpd_state));
Michael J. Spencer 2:1df0b61d3b5a 610 if (s == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 611 DEBUG_PRINTF("Connection: Out of memory\n");
Michael J. Spencer 2:1df0b61d3b5a 612 uip_abort();
Michael J. Spencer 2:1df0b61d3b5a 613 return;
Michael J. Spencer 2:1df0b61d3b5a 614 }
Michael J. Spencer 2:1df0b61d3b5a 615 uip_conn->appstate = s;
Michael J. Spencer 2:1df0b61d3b5a 616 DEBUG_PRINTF("Connection: %d.%d.%d.%d:%d\n",
Michael J. Spencer 2:1df0b61d3b5a 617 uip_ipaddr1(uip_conn->ripaddr), uip_ipaddr2(uip_conn->ripaddr),
Michael J. Spencer 2:1df0b61d3b5a 618 uip_ipaddr3(uip_conn->ripaddr), uip_ipaddr4(uip_conn->ripaddr),
Michael J. Spencer 2:1df0b61d3b5a 619 HTONS(uip_conn->rport));
Michael J. Spencer 2:1df0b61d3b5a 620
Michael J. Spencer 2:1df0b61d3b5a 621 PSOCK_INIT(&s->sin, s->inputbuf, sizeof(s->inputbuf) - 1);
Michael J. Spencer 2:1df0b61d3b5a 622 PSOCK_INIT(&s->sout, s->inputbuf, sizeof(s->inputbuf) - 1);
Michael J. Spencer 2:1df0b61d3b5a 623 PT_INIT(&s->outputpt);
Michael J. Spencer 2:1df0b61d3b5a 624 PT_INIT(&s->inputpt);
Michael J. Spencer 2:1df0b61d3b5a 625 s->state = STATE_WAITING;
Michael J. Spencer 2:1df0b61d3b5a 626 /* timer_set(&s->timer, CLOCK_SECOND * 100);*/
Michael J. Spencer 2:1df0b61d3b5a 627 s->timer = 0;
Michael J. Spencer 2:1df0b61d3b5a 628 s->fd = NULL;
Michael J. Spencer 2:1df0b61d3b5a 629 s->strbuf = NULL;
Michael J. Spencer 2:1df0b61d3b5a 630 s->fifo = NULL;
Michael J. Spencer 2:1df0b61d3b5a 631 s->pstream = NULL;
Michael J. Spencer 2:1df0b61d3b5a 632 }
Michael J. Spencer 2:1df0b61d3b5a 633
Michael J. Spencer 2:1df0b61d3b5a 634 if (s == NULL) {
Michael J. Spencer 2:1df0b61d3b5a 635 DEBUG_PRINTF("ERROR no state context: %d\n", uip_flags);
Michael J. Spencer 2:1df0b61d3b5a 636 uip_abort();
Michael J. Spencer 2:1df0b61d3b5a 637 return;
Michael J. Spencer 2:1df0b61d3b5a 638 }
Michael J. Spencer 2:1df0b61d3b5a 639
Michael J. Spencer 2:1df0b61d3b5a 640 // check for timeout on connection here so we can cleanup if we abort
Michael J. Spencer 2:1df0b61d3b5a 641 if (uip_poll()) {
Michael J. Spencer 2:1df0b61d3b5a 642 ++s->timer;
Michael J. Spencer 2:1df0b61d3b5a 643 if (s->timer >= 20 * 2) { // we have a 0.5 second poll and we want 20 second timeout
Michael J. Spencer 2:1df0b61d3b5a 644 DEBUG_PRINTF("Timer expired, aborting\n");
Michael J. Spencer 2:1df0b61d3b5a 645 uip_abort();
Michael J. Spencer 2:1df0b61d3b5a 646 }
Michael J. Spencer 2:1df0b61d3b5a 647 } else {
Michael J. Spencer 2:1df0b61d3b5a 648 s->timer = 0;
Michael J. Spencer 2:1df0b61d3b5a 649 }
Michael J. Spencer 2:1df0b61d3b5a 650
Michael J. Spencer 2:1df0b61d3b5a 651 if (uip_closed() || uip_aborted() || uip_timedout()) {
Michael J. Spencer 2:1df0b61d3b5a 652 DEBUG_PRINTF("Closing connection: %d\n", HTONS(uip_conn->rport));
Michael J. Spencer 2:1df0b61d3b5a 653 if (s->fd != NULL) fclose(fd); // clean up
Michael J. Spencer 2:1df0b61d3b5a 654 if (s->strbuf != NULL) free(s->strbuf);
Michael J. Spencer 2:1df0b61d3b5a 655 if (s->pstream != NULL) {
Michael J. Spencer 2:1df0b61d3b5a 656 // free these if they were allocated
Michael J. Spencer 2:1df0b61d3b5a 657 delete_fifo(s->fifo);
Michael J. Spencer 2:1df0b61d3b5a 658 delete_callback_stream(s->pstream); // this will mark it as closed and will get deleted when no longer needed
Michael J. Spencer 2:1df0b61d3b5a 659 }
Michael J. Spencer 2:1df0b61d3b5a 660 free(s) ;
Michael J. Spencer 2:1df0b61d3b5a 661 uip_conn->appstate = NULL;
Michael J. Spencer 2:1df0b61d3b5a 662
Michael J. Spencer 2:1df0b61d3b5a 663 } else {
Michael J. Spencer 2:1df0b61d3b5a 664 handle_connection(s);
Michael J. Spencer 2:1df0b61d3b5a 665 }
Michael J. Spencer 2:1df0b61d3b5a 666 }
Michael J. Spencer 2:1df0b61d3b5a 667
Michael J. Spencer 2:1df0b61d3b5a 668 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 669 /**
Michael J. Spencer 2:1df0b61d3b5a 670 * \brief Initialize the web server
Michael J. Spencer 2:1df0b61d3b5a 671 *
Michael J. Spencer 2:1df0b61d3b5a 672 * This function initializes the web server and should be
Michael J. Spencer 2:1df0b61d3b5a 673 * called at system boot-up.
Michael J. Spencer 2:1df0b61d3b5a 674 */
Michael J. Spencer 2:1df0b61d3b5a 675 void httpd_init(void)
Michael J. Spencer 2:1df0b61d3b5a 676 {
Michael J. Spencer 2:1df0b61d3b5a 677 uip_listen(HTONS(80));
Michael J. Spencer 2:1df0b61d3b5a 678 }
Michael J. Spencer 2:1df0b61d3b5a 679 /*---------------------------------------------------------------------------*/
Michael J. Spencer 2:1df0b61d3b5a 680 /** @} */