From 567b81d9dd3bd0a0cd8df4a3d464b3273576fe73 Mon Sep 17 00:00:00 2001 From: asterix Date: Wed, 28 Sep 2011 16:53:31 +0000 Subject: [PATCH] Add first implementation of http server module. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@5117 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cfg/cfg_http.h | 64 ++++++ bertos/hw/hw_http.c | 56 +++++ bertos/hw/hw_http.h | 49 +++++ bertos/net/http.c | 198 ++++++++++++++++++ bertos/net/http.h | 67 ++++++ .../sam3x-ek_http_server/cfg/cfg_http.h | 64 ++++++ boards/sam3x-ek/hw/hw_http.c | 56 +++++ boards/sam3x-ek/hw/hw_http.h | 49 +++++ 8 files changed, 603 insertions(+) create mode 100644 bertos/cfg/cfg_http.h create mode 100644 bertos/hw/hw_http.c create mode 100644 bertos/hw/hw_http.h create mode 100644 bertos/net/http.c create mode 100644 bertos/net/http.h create mode 100644 boards/sam3x-ek/examples/sam3x-ek_http_server/cfg/cfg_http.h create mode 100644 boards/sam3x-ek/hw/hw_http.c create mode 100644 boards/sam3x-ek/hw/hw_http.h diff --git a/bertos/cfg/cfg_http.h b/bertos/cfg/cfg_http.h new file mode 100644 index 00000000..0aba5f02 --- /dev/null +++ b/bertos/cfg/cfg_http.h @@ -0,0 +1,64 @@ +/** + * \file + * + * + * \brief Configuration file for the HTTP module. + * + * \author Daniele Basile + */ + +#ifndef CFG_HTTP_H +#define CFG_HTTP_H + +/** + * Module logging level. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_level" + */ +#define HTTP_LOG_LEVEL LOG_LVL_INFO + +/** + * Module logging format. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_format" + */ +#define HTTP_LOG_FORMAT LOG_FMT_VERBOSE + +/** + * Default start page to load + * + * $WIZ$ type = "str" + */ +#define HTTP_DEFAULT_PAGE "index.htm" + +#endif /* CFG_HTTP_H */ diff --git a/bertos/hw/hw_http.c b/bertos/hw/hw_http.c new file mode 100644 index 00000000..7d9ba7b3 --- /dev/null +++ b/bertos/hw/hw_http.c @@ -0,0 +1,56 @@ +/** + * \file + * + * + * \brief Simple Http server error pages. + * + * \author Daniele Basile + */ + +#include "hw_http.h" + +const char http_file_not_found[] = "\ + \ + \ +404 Not Found

404 Not Found

\ +

The requested URL was not found on this server.


\ +
BeRTOS simple HTTP server
"; + +const size_t http_file_not_found_len = sizeof(http_file_not_found); + +const char http_sd_not_present[] = " \ + \ + \ +BeRTOS simple HTTP Server \ +

BeRTOS simple HTTP Server

Simple Http server, the site's pages are stored on SD card, check it if is present.


\ +www.BeRTOS.org \ +"; +const size_t http_sd_not_present_len = sizeof(http_sd_not_present); diff --git a/bertos/hw/hw_http.h b/bertos/hw/hw_http.h new file mode 100644 index 00000000..88ec1bf7 --- /dev/null +++ b/bertos/hw/hw_http.h @@ -0,0 +1,49 @@ +/** + * \file + * + * + * \brief Simple Http server error pages. + * + * \author Daniele Basile + */ + +#ifndef HW_HTTP_H +#define HW_HTTP_H + +#include + +extern const char http_file_not_found[]; +extern const size_t http_file_not_found_len; + +extern const char http_sd_not_present[]; +extern const size_t http_sd_not_present_len; + +#endif /* HW_HTTP_H */ diff --git a/bertos/net/http.c b/bertos/net/http.c new file mode 100644 index 00000000..235401cd --- /dev/null +++ b/bertos/net/http.c @@ -0,0 +1,198 @@ +/** + * \file + * + * + * \author Daniele Basile + * + * \brief Simple Http server. + * + * This simple web server read the site's pages from SD card, and manage + * the cases where SD is not present or page not found, using embedded pages. + * Quering from browser the /status page, the server return a json dictionary where are store + * some board status info, like board temperature, up-time, etc. + */ + +#include "http.h" + +#include "hw/hw_sd.h" +#include "hw/hw_http.h" + +#include "cfg/cfg_http.h" + +// Define logging setting (for cfg/log.h module). +#define LOG_LEVEL HTTP_LOG_LEVEL +#define LOG_VERBOSITY HTTP_LOG_FORMAT +#include + +#include + +#include + +#include +#include + + +static const char http_html_hdr_200[] = "HTTP/1.1 200 OK\r\nContent-type: text/html\r\n\r\n"; +static const char http_html_hdr_404[] = "HTTP/1.1 404 Not Found\r\nContent-type: text/html\r\n\r\n"; + +void http_sendOk(struct netconn *client) +{ + netconn_write(client, http_html_hdr_200, sizeof(http_html_hdr_200) - 1, NETCONN_NOCOPY); +} + +void http_sendFileNotFound(struct netconn *client) +{ + netconn_write(client, http_html_hdr_404, sizeof(http_html_hdr_404) - 1, NETCONN_NOCOPY); +} + + +static void get_fileName(char *revc_buf, char *name, size_t len) +{ + char *p = strstr(revc_buf, "GET"); + if (p) + { + //skip the "/" in get string request + p += sizeof("GET") + 1; + for (size_t i = 0; *p != ' '; i++,p++) + { + if (i > len) + break; + name[i] = *p; + } + } +} + +static http_gci_handler_t cgi_search(const char *name, HttpCGI *table) +{ + for (int i = 0; table[i].name; i++) + { + if (!strcmp(table[i].name, name)) + return table[i].handler; + } + return NULL; +} + +static uint8_t tx_buf[2048]; +static char file_name[80]; + +void http_server(struct netconn *server, struct HttpCGI *table) +{ + // SD fat filesystem context + Sd sd; + FATFS fs; + FatFile in_file; + struct netconn *client; + struct netbuf *rx_buf_conn; + char *rx_buf; + u16_t len; + FRESULT result; + + client = netconn_accept(server); + if (!client) + return; + + rx_buf_conn = netconn_recv(client); + if (rx_buf_conn) + { + netbuf_data(rx_buf_conn, (void **)&rx_buf, &len); + if (rx_buf) + { + memset(file_name, 0, sizeof(file_name)); + get_fileName(rx_buf, file_name, sizeof(file_name)); + + LOG_INFO("Search %s\n", file_name); + if (strlen(file_name) == 0) + strcpy(file_name, HTTP_DEFAULT_PAGE); + + http_gci_handler_t cgi = cgi_search(file_name, table); + if (cgi) + { + cgi(rx_buf, client); + } + else if (SD_CARD_PRESENT()) + { + bool sd_ok = sd_init(&sd, NULL, 0); + if (sd_ok) + { + LOG_INFO("Mount FAT filesystem.\n"); + result = f_mount(0, &fs); + if (result != FR_OK) + { + LOG_ERR("Mounting FAT volumes error[%d]\n", result); + sd_ok = false; + f_mount(0, NULL); + } + + if (sd_ok) + { + result = fatfile_open(&in_file, file_name, FA_OPEN_EXISTING | FA_READ); + + size_t count = 0; + if (result == FR_OK) + { + LOG_INFO("Opened file '%s' size %ld\n", file_name, in_file.fat_file.fsize); + + http_sendOk(client); + + while (count < in_file.fat_file.fsize) + { + int len = kfile_read(&in_file.fd, tx_buf, sizeof(tx_buf)); + netconn_write(client, tx_buf, len, NETCONN_COPY); + count += len; + } + + kfile_flush(&in_file.fd); + kfile_close(&in_file.fd); + + LOG_INFO("Sent: %d\n", count); + } + else + { + LOG_ERR("Unable to open file: '%s' error[%d]\n", file_name, result); + http_sendFileNotFound(client); + netconn_write(client, http_file_not_found, http_file_not_found_len - 1, NETCONN_NOCOPY); + } + } + } + f_mount(0, NULL); + LOG_INFO("Umount FAT filesystem.\n"); + } + else + { + http_sendFileNotFound(client); + netconn_write(client, http_sd_not_present, http_sd_not_present_len, NETCONN_NOCOPY); + } + } + netconn_close(client); + netbuf_delete(rx_buf_conn); + } + netconn_delete(client); +} diff --git a/bertos/net/http.h b/bertos/net/http.h new file mode 100644 index 00000000..6b5b3bc1 --- /dev/null +++ b/bertos/net/http.h @@ -0,0 +1,67 @@ +/** + * \file + * + * + * \brief Simple HTTP server + * + * \author Daniele Basile + * + * $WIZ$ module_name = "http" + * $WIZ$ module_configuration = "bertos/cfg/cfg_http.h" + * $WIZ$ module_depends = "lwip", "kfile", "sd" + * $WIZ$ module_hw = "bertos/hw/hw_http.h", "bertos/hw/hw_http.c" + */ + +#ifndef NET_HTTP_H +#define NET_HTTP_H + + +#include + +#include +#include +#include +#include +#include + +typedef int (*http_gci_handler_t)(char *revc_buf, struct netconn *client); + +typedef struct HttpCGI +{ + const char *name; + http_gci_handler_t handler; +} HttpCGI; + +void http_sendOk(struct netconn *client); +void http_sendFileNotFound(struct netconn *client); +void http_server(struct netconn *server, struct HttpCGI *gci); + +#endif /* NET_HTTP_H */ diff --git a/boards/sam3x-ek/examples/sam3x-ek_http_server/cfg/cfg_http.h b/boards/sam3x-ek/examples/sam3x-ek_http_server/cfg/cfg_http.h new file mode 100644 index 00000000..0aba5f02 --- /dev/null +++ b/boards/sam3x-ek/examples/sam3x-ek_http_server/cfg/cfg_http.h @@ -0,0 +1,64 @@ +/** + * \file + * + * + * \brief Configuration file for the HTTP module. + * + * \author Daniele Basile + */ + +#ifndef CFG_HTTP_H +#define CFG_HTTP_H + +/** + * Module logging level. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_level" + */ +#define HTTP_LOG_LEVEL LOG_LVL_INFO + +/** + * Module logging format. + * + * $WIZ$ type = "enum" + * $WIZ$ value_list = "log_format" + */ +#define HTTP_LOG_FORMAT LOG_FMT_VERBOSE + +/** + * Default start page to load + * + * $WIZ$ type = "str" + */ +#define HTTP_DEFAULT_PAGE "index.htm" + +#endif /* CFG_HTTP_H */ diff --git a/boards/sam3x-ek/hw/hw_http.c b/boards/sam3x-ek/hw/hw_http.c new file mode 100644 index 00000000..7d9ba7b3 --- /dev/null +++ b/boards/sam3x-ek/hw/hw_http.c @@ -0,0 +1,56 @@ +/** + * \file + * + * + * \brief Simple Http server error pages. + * + * \author Daniele Basile + */ + +#include "hw_http.h" + +const char http_file_not_found[] = "\ + \ + \ +404 Not Found

404 Not Found

\ +

The requested URL was not found on this server.


\ +
BeRTOS simple HTTP server
"; + +const size_t http_file_not_found_len = sizeof(http_file_not_found); + +const char http_sd_not_present[] = " \ + \ + \ +BeRTOS simple HTTP Server \ +

BeRTOS simple HTTP Server

Simple Http server, the site's pages are stored on SD card, check it if is present.


\ +www.BeRTOS.org \ +"; +const size_t http_sd_not_present_len = sizeof(http_sd_not_present); diff --git a/boards/sam3x-ek/hw/hw_http.h b/boards/sam3x-ek/hw/hw_http.h new file mode 100644 index 00000000..88ec1bf7 --- /dev/null +++ b/boards/sam3x-ek/hw/hw_http.h @@ -0,0 +1,49 @@ +/** + * \file + * + * + * \brief Simple Http server error pages. + * + * \author Daniele Basile + */ + +#ifndef HW_HTTP_H +#define HW_HTTP_H + +#include + +extern const char http_file_not_found[]; +extern const size_t http_file_not_found_len; + +extern const char http_sd_not_present[]; +extern const size_t http_sd_not_present_len; + +#endif /* HW_HTTP_H */ -- 2.25.1