Add [16_m1284p_WIZNET_HTTPD_FTPD_FATFS_SDCARD] prj

This commit is contained in:
maxxir_w
2019-01-18 15:34:25 +04:00
parent 9aad70f01b
commit 216efc6cd0
50 changed files with 18267 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,156 @@
#ifndef _FTPD_H_
#define _FTPD_H_
#ifdef __cplusplus
extern "C" {
#endif
/*
* Wiznet.
* (c) Copyright 2002, Wiznet.
*
* Filename : ftpd.h
* Version : 1.0
* Programmer(s) :
* Created : 2003/01/28
* Description : Header file of FTP daemon. (AVR-GCC Compiler)
*/
#include <stdint.h>
#include "../../globals.h" //add AVR specific useful headers
#define F_FILESYSTEM // If your target support a file system, you have to activate this feature and implement.
#if defined(F_FILESYSTEM)
#include "ff.h"
#endif
#define F_APP_FTP
//#define _FTP_DEBUG_
#define LINELEN 100
//#define DATA_BUF_SIZE 100
#if !defined(F_FILESYSTEM)
#define _MAX_SS 512
#endif
#define CTRL_SOCK 2
#define DATA_SOCK 3
#define IPPORT_FTPD 20 /* FTP Data port */
#define IPPORT_FTP 21 /* FTP Control port */
#define HOSTNAME "iinChip"
#define VERSION "1.0"
#define FILENAME "a.txt"
/* FTP commands */
enum ftp_cmd {
USER_CMD,
ACCT_CMD,
PASS_CMD,
TYPE_CMD,
LIST_CMD,
CWD_CMD,
DELE_CMD,
NAME_CMD,
QUIT_CMD,
RETR_CMD,
STOR_CMD,
PORT_CMD,
NLST_CMD,
PWD_CMD,
XPWD_CMD,
MKD_CMD,
XMKD_CMD,
XRMD_CMD,
RMD_CMD,
STRU_CMD,
MODE_CMD,
SYST_CMD,
XMD5_CMD,
XCWD_CMD,
FEAT_CMD,
PASV_CMD,
SIZE_CMD,
MLSD_CMD,
APPE_CMD,
NO_CMD,
};
enum ftp_type {
ASCII_TYPE,
IMAGE_TYPE,
LOGICAL_TYPE
};
enum ftp_state {
FTPS_NOT_LOGIN,
FTPS_LOGIN
};
enum datasock_state{
DATASOCK_IDLE,
DATASOCK_READY,
DATASOCK_START
};
enum datasock_mode{
PASSIVE_MODE,
ACTIVE_MODE
};
struct ftpd {
uint8_t control; /* Control stream */
uint8_t data; /* Data stream */
enum ftp_type type; /* Transfer type */
enum ftp_state state;
enum ftp_cmd current_cmd;
enum datasock_state dsock_state;
enum datasock_mode dsock_mode;
char username[LINELEN]; /* Arg to USER command */
char workingdir[LINELEN];
char filename[LINELEN];
#if defined(F_FILESYSTEM)
FIL fil; // FatFs File objects
FRESULT fr; // FatFs function common result code
#endif
};
#ifndef un_I2cval
typedef union _un_l2cval {
uint32_t lVal;
uint8_t cVal[4];
}un_l2cval;
#endif
void ftpd_init(uint8_t * src_ip);
uint8_t ftpd_run(uint8_t * dbuf);
char proc_ftpd(char * buf);
char ftplogin(char * pass);
int pport(char * arg);
int sendit(char * command);
int recvit(char * command);
long sendfile(uint8_t s, char * command);
long recvfile(uint8_t s);
#if defined(F_FILESYSTEM)
void print_filedsc(FIL *fil);
#endif
#ifdef __cplusplus
}
#endif
#endif // _FTPD_H_

View File

@@ -0,0 +1,75 @@
/* Copyright (c) 2002, Joerg Wunsch
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* 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.
* Neither the name of the copyright holders nor the names of
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
*/
/* $Id: stdio_private.h,v 1.6 2003/01/07 22:17:24 joerg_wunsch Exp $ */
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdio.h>
//struct __file {
// char *buf; /* buffer pointer */
// unsigned char unget; /* ungetc() buffer */
// uint8_t flags; /* flags, see below */
//#define __SRD 0x0001 /* OK to read */
//#define __SWR 0x0002 /* OK to write */
//#define __SSTR 0x0004 /* this is an sprintf/snprintf string */
//#define __SPGM 0x0008 /* fmt string is in progmem */
//#define __SERR 0x0010 /* found error */
//#define __SEOF 0x0020 /* found EOF */
//#define __SUNGET 0x040 /* ungetc() happened */
//#if 0
///* possible future extensions, will require uint16_t flags */
//#define __SRW 0x0080 /* open for reading & writing */
//#define __SLBF 0x0100 /* line buffered */
//#define __SNBF 0x0200 /* unbuffered */
//#define __SMBF 0x0400 /* buf is from malloc */
//#endif
// int size; /* size of buffer */
// int len; /* characters read or written so far */
// int (*put)(char); /* function to write one char to device */
// int (*get)(void); /* function to read one char from device */
//};
/* values for PRINTF_LEVEL */
#define PRINTF_MIN 1
#define PRINTF_STD 2
#define PRINTF_FLT 3
/* values for SCANF_LEVEL */
#define SCANF_MIN 1
#define SCANF_STD 2
#define SCANF_FLT 3
#ifdef __cplusplus
}
#endif

View File

@@ -0,0 +1,402 @@
/**
@file httpd.c
@brief functions associated http processing
*/
#include <stdio.h>
#include <string.h>
#include "socket.h"
#include "httpParser.h"
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
//uint8_t BUFPUB[2048];
uint8_t BUFPUB[256];
/*****************************************************************************
* Private functions
****************************************************************************/
static void replacetochar(uint8_t * str, uint8_t oldchar, uint8_t newchar); /* Replace old character with new character in the string */
static uint8_t C2D(uint8_t c); /* Convert a character to HEX */
/**
@brief convert escape characters(%XX) to ASCII character
*/
void unescape_http_url(
char * url /**< pointer to be converted ( escape characters )*/
)
{
int x, y;
for (x = 0, y = 0; url[y]; ++x, ++y) {
if ((url[x] = url[y]) == '%') {
url[x] = C2D(url[y+1])*0x10+C2D(url[y+2]);
y+=2;
}
}
url[x] = '\0';
}
/**
@brief make response header such as html, gif, jpeg,etc.
*/
void make_http_response_head(
char * buf, /**< pointer to response header to be made */
char type, /**< response type */
uint32_t len /**< size of response header */
)
{
const char * head;
char tmp[10];
/* file type*/
if (type == PTYPE_HTML) head = PSTR(RES_HTMLHEAD_OK);
else if (type == PTYPE_GIF) head = PSTR(RES_GIFHEAD_OK);
else if (type == PTYPE_TEXT) head = PSTR(RES_TEXTHEAD_OK);
else if (type == PTYPE_JPEG) head = PSTR(RES_JPEGHEAD_OK);
else if (type == PTYPE_FLASH) head = PSTR(RES_FLASHHEAD_OK);
else if (type == PTYPE_XML) head = PSTR(RES_XMLHEAD_OK);
else if (type == PTYPE_CSS) head = PSTR(RES_CSSHEAD_OK);
else if (type == PTYPE_JSON) head = PSTR(RES_JSONHEAD_OK);
else if (type == PTYPE_JS) head = PSTR(RES_JSHEAD_OK);
else if (type == PTYPE_CGI) head = PSTR(RES_CGIHEAD_OK);
else if (type == PTYPE_PNG) head = PSTR(RES_PNGHEAD_OK);
else if (type == PTYPE_ICO) head = PSTR(RES_ICOHEAD_OK);
else if (type == PTYPE_TTF) head = PSTR(RES_TTFHEAD_OK);
else if (type == PTYPE_OTF) head = PSTR(RES_OTFHEAD_OK);
else if (type == PTYPE_WOFF) head = PSTR(RES_WOFFHEAD_OK);
else if (type == PTYPE_EOT) head = PSTR(RES_EOTHEAD_OK);
else if (type == PTYPE_SVG) head = PSTR(RES_SVGHEAD_OK);
#ifdef _HTTPPARSER_DEBUG_
else
{
head = NULL;
PRINTF("\r\n\r\n-MAKE HEAD UNKNOWN-\r\n");
}
#else
else head = NULL;
#endif
sprintf(tmp, "%ld", len);
strcpy_P(buf, head);
strcat(buf, tmp);
strcat(buf, "\r\n\r\n");
}
/**
@brief find MIME type of a file
*/
void find_http_uri_type(
uint8_t * type, /**< type to be returned */
uint8_t * buff /**< file name */
)
{
/* Decide type according to extension*/
char * buf;
buf = (char *)buff;
if (strcasestr_P(buf, PSTR(".htm")) || strcasestr_P(buf, PSTR(".html"))) *type = PTYPE_HTML;
else if (strcasestr_P(buf, PSTR(".gif"))) *type = PTYPE_GIF;
else if (strcasestr_P(buf, PSTR(".text")) || strstr_P(buf,PSTR(".txt"))) *type = PTYPE_TEXT;
else if (strcasestr_P(buf, PSTR(".jpeg")) || strstr_P(buf,PSTR(".jpg"))) *type = PTYPE_JPEG;
else if (strcasestr_P(buf, PSTR(".swf"))) *type = PTYPE_FLASH;
else if (strstr_P(buf, PSTR(".cgi")) || strstr_P(buf,PSTR(".CGI"))) *type = PTYPE_CGI;
else if (strstr_P(buf, PSTR(".json")) || strstr_P(buf,PSTR(".JSON"))) *type = PTYPE_JSON;
else if (strstr_P(buf, PSTR(".js")) || strstr_P(buf,PSTR(".JS"))) *type = PTYPE_JS;
else if (strstr_P(buf, PSTR(".CGI")) || strstr_P(buf,PSTR(".cgi"))) *type = PTYPE_CGI;
else if (strstr_P(buf, PSTR(".xml")) || strstr_P(buf,PSTR(".XML"))) *type = PTYPE_XML;
else if (strstr_P(buf, PSTR(".css")) || strstr_P(buf,PSTR(".CSS"))) *type = PTYPE_CSS;
else if (strstr_P(buf, PSTR(".png")) || strstr_P(buf,PSTR(".PNG"))) *type = PTYPE_PNG;
else if (strstr_P(buf, PSTR(".ico")) || strstr_P(buf,PSTR(".ICO"))) *type = PTYPE_ICO;
else if (strstr_P(buf, PSTR(".ttf")) || strstr_P(buf,PSTR(".TTF"))) *type = PTYPE_TTF;
else if (strstr_P(buf, PSTR(".otf")) || strstr_P(buf,PSTR(".OTF"))) *type = PTYPE_OTF;
else if (strstr_P(buf, PSTR(".woff")) || strstr_P(buf,PSTR(".WOFF"))) *type = PTYPE_WOFF;
else if (strstr_P(buf, PSTR(".eot")) || strstr_P(buf,PSTR(".EOT"))) *type = PTYPE_EOT;
else if (strstr_P(buf, PSTR(".svg")) || strstr_P(buf,PSTR(".SVG"))) *type = PTYPE_SVG;
else *type = PTYPE_ERR;
}
/**
@brief parse http request from a peer
*/
void parse_http_request(
st_http_request * request, /**< request to be returned */
uint8_t * buf /**< pointer to be parsed */
)
{
char * nexttok;
nexttok = strtok((char*)buf," ");
if(!nexttok)
{
request->METHOD = METHOD_ERR;
return;
}
if(!strcmp_P(nexttok, PSTR("GET")) || !strcmp_P(nexttok,PSTR("get")))
{
request->METHOD = METHOD_GET;
nexttok = strtok(NULL," ");
}
else if (!strcmp_P(nexttok, PSTR("HEAD")) || !strcmp_P(nexttok,PSTR("head")))
{
request->METHOD = METHOD_HEAD;
nexttok = strtok(NULL," ");
}
else if (!strcmp_P(nexttok, PSTR("POST")) || !strcmp_P(nexttok,PSTR("post")))
{
nexttok = strtok(NULL,"\0");
request->METHOD = METHOD_POST;
}
else
{
request->METHOD = METHOD_ERR;
}
if(!nexttok)
{
request->METHOD = METHOD_ERR;
return;
}
strcpy((char *)request->URI, nexttok);
}
#ifdef _OLD_
/**
@brief get next parameter value in the request
*/
uint8_t * get_http_param_value(
char* uri,
char* param_name
)
{
char tempURI[MAX_URI_SIZE];
uint8_t * name = 0;
if(!uri || !param_name) return 0;
strcpy((char*)tempURI,uri);
if((name = (uint8_t*)strstr(tempURI, param_name)))
{
name += strlen(param_name) + 1; // strlen(para_name) + strlen("=")
if((name = (uint8_t*)strtok((char *)name,"& \r\n\t\0")))
{
unescape_http_url((char *)name);
replacetochar(name, '+', ' ');
}
}
#ifdef _HTTPPARSER_DEBUG_
printf(" %s=%s",param_name,name);
#endif
return name;
}
#else
/**
@brief get next parameter value in the request
*/
uint8_t * get_http_param_value(char* uri, char* param_name)
{
uint8_t * name = 0;
uint8_t * ret = BUFPUB;
uint8_t * pos2;
uint16_t len = 0, content_len = 0;
uint8_t tmp_buf[10]={0x00, };
if(!uri || !param_name) return 0;
/***************/
mid(uri, "Content-Length: ", "\r\n", (char *)tmp_buf);
content_len = ATOI(tmp_buf, 10);
uri = strstr(uri, "\r\n\r\n");
uri += 4;
uri[content_len] = 0;
/***************/
if((name = (uint8_t *)strstr(uri, param_name)))
{
name += strlen(param_name) + 1;
pos2 = (uint8_t*)strstr((char*)name, "&");
if(!pos2)
{
pos2 = name + strlen((char*)name);
}
len = pos2 - name;
if(len)
{
ret[len] = 0;
strncpy((char*)ret,(char*)name, len);
unescape_http_url((char *)ret);
replacetochar(ret, '+' ,' ');
//ret[len] = 0;
//ret[strlen((int8*)ret)] = 0;
//printf("len=%d\r\n",len);
}
else
{
ret[0] = 0;
}
}
else
{
return 0;
}
#ifdef _HTTPPARSER_DEBUG_
printf(" %s=%s\r\n", param_name, ret);
#endif
return ret;
}
#endif
#ifdef _OLD_
uint8_t * get_http_uri_name(uint8_t * uri)
{
char tempURI[MAX_URI_SIZE];
uint8_t * uri_name;
if(!uri) return 0;
strcpy(tempURI, (char *)uri);
uri_name = (uint8_t *)strtok(tempURI, " ?");
if(strcmp((char *)uri_name,"/")) uri_name++;
#ifdef _HTTPPARSER_DEBUG_
printf(" uri_name = %s\r\n", uri_name);
#endif
return uri_name;
}
#else
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf)
{
uint8_t * uri_ptr;
if(!uri) return 0;
strcpy((char *)uri_buf, (char *)uri);
uri_ptr = (uint8_t *)strtok((char *)uri_buf, " ?");
if(strcmp((char *)uri_ptr,"/")) uri_ptr++;
strcpy((char *)uri_buf, (char *)uri_ptr);
#ifdef _HTTPPARSER_DEBUG_
PRINTF(" uri_name = %s\r\n", uri_buf);
#endif
return 1;
}
#endif
void inet_addr_(uint8_t * addr, uint8_t *ip)
{
uint8_t i;
uint8_t taddr[30];
uint8_t * nexttok;
uint8_t num;
strcpy((char *)taddr, (char *)addr);
nexttok = taddr;
for(i = 0; i < 4 ; i++)
{
nexttok = (uint8_t *)strtok((char *)nexttok, ".");
if(nexttok[0] == '0' && nexttok[1] == 'x') num = ATOI(nexttok+2,0x10);
else num = ATOI(nexttok,10);
ip[i] = num;
nexttok = NULL;
}
}
/**
@brief CONVERT STRING INTO INTEGER
@return a integer number
*/
uint16_t ATOI(
uint8_t * str, /**< is a pointer to convert */
uint8_t base /**< is a base value (must be in the range 2 - 16) */
)
{
unsigned int num = 0;
// debug_2013_11_25
// while (*str !=0)
while ((*str !=0) && (*str != 0x20)) // not include the space(0x020)
num = num * base + C2D(*str++);
return num;
}
/**
* @brief Check strings and then execute callback function by each string.
* @param src The information of URI
* @param s1 The start string to be researched
* @param s2 The end string to be researched
* @param sub The string between s1 and s2
* @return The length value atfer working
*/
void mid(char* src, char* s1, char* s2, char* sub)
{
char* sub1;
char* sub2;
uint16_t n;
sub1=strstr((char*)src,(char*)s1);
sub1+=strlen((char*)s1);
sub2=strstr((char*)sub1,(char*)s2);
n=sub2-sub1;
strncpy((char*)sub,(char*)sub1,n);
sub[n]='\0';
}
////////////////////////////////////////////////////////////////////
// Static functions
////////////////////////////////////////////////////////////////////
/**
@brief replace the specified character in a string with new character
*/
static void replacetochar(
uint8_t * str, /**< pointer to be replaced */
uint8_t oldchar, /**< old character */
uint8_t newchar /**< new character */
)
{
int x;
for (x = 0; str[x]; x++)
if (str[x] == oldchar) str[x] = newchar;
}
/**
@brief CONVERT CHAR INTO HEX
@return HEX
This function converts HEX(0-F) to a character
*/
static uint8_t C2D(
uint8_t c /**< is a character('0'-'F') to convert to HEX */
)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return 10 + c -'a';
if (c >= 'A' && c <= 'F')
return 10 + c -'A';
return (char)c;
}

View File

@@ -0,0 +1,159 @@
/**
@file httpd.h
@brief Define Constants and fucntions associated with HTTP protocol.
*/
#include <stdint.h>
#include "../../globals.h"
#ifndef __HTTPPARSER_H__
#define __HTTPPARSER_H__
#ifdef __cplusplus
extern "C" {
#endif
//#define _HTTPPARSER_DEBUG_
#define HTTP_SERVER_PORT 80 /**< HTTP server well-known port number */
/* HTTP Method */
#define METHOD_ERR 0 /**< Error Method. */
#define METHOD_GET 1 /**< GET Method. */
#define METHOD_HEAD 2 /**< HEAD Method. */
#define METHOD_POST 3 /**< POST Method. */
/* HTTP GET Method */
#define PTYPE_ERR 0 /**< Error file. */
#define PTYPE_HTML 1 /**< HTML file. */
#define PTYPE_GIF 2 /**< GIF file. */
#define PTYPE_TEXT 3 /**< TEXT file. */
#define PTYPE_JPEG 4 /**< JPEG file. */
#define PTYPE_FLASH 5 /**< FLASH file. */
#define PTYPE_MPEG 6 /**< MPEG file. */
#define PTYPE_PDF 7 /**< PDF file. */
#define PTYPE_CGI 8 /**< CGI file. */
#define PTYPE_XML 9 /**< XML file. */
#define PTYPE_CSS 10 /**< CSS file. */
#define PTYPE_JS 11 /**< JavaScript file. */
#define PTYPE_JSON 12 /**< JSON (JavaScript Standard Object Notation) file. */
#define PTYPE_PNG 13 /**< PNG file. */
#define PTYPE_ICO 14 /**< ICON file. */
#define PTYPE_TTF 20 /**< Font type: TTF file. */
#define PTYPE_OTF 21 /**< Font type: OTF file. */
#define PTYPE_WOFF 22 /**< Font type: WOFF file. */
#define PTYPE_EOT 23 /**< Font type: EOT file. */
#define PTYPE_SVG 24 /**< Font type: SVG file. */
/* HTTP response */
#define STATUS_OK 200
#define STATUS_CREATED 201
#define STATUS_ACCEPTED 202
#define STATUS_NO_CONTENT 204
#define STATUS_MV_PERM 301
#define STATUS_MV_TEMP 302
#define STATUS_NOT_MODIF 304
#define STATUS_BAD_REQ 400
#define STATUS_UNAUTH 401
#define STATUS_FORBIDDEN 403
#define STATUS_NOT_FOUND 404
#define STATUS_INT_SERR 500
#define STATUS_NOT_IMPL 501
#define STATUS_BAD_GATEWAY 502
#define STATUS_SERV_UNAVAIL 503
/* HTML Doc. for ERROR */
static const char PROGMEM ERROR_HTML_PAGE[] = "HTTP/1.1 404 Not Found\r\nContent-Type: text/html\r\nContent-Length: 78\r\n\r\n<HTML>\r\n<BODY>\r\nSorry, the page you requested was not found.\r\n</BODY>\r\n</HTML>\r\n\0";
static const char PROGMEM ERROR_REQUEST_PAGE[] = "HTTP/1.1 400 OK\r\nContent-Type: text/html\r\nContent-Length: 50\r\n\r\n<HTML>\r\n<BODY>\r\nInvalid request.\r\n</BODY>\r\n</HTML>\r\n\0";
/* HTML Doc. for CGI result */
#define HTML_HEADER "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
/* Response header for HTML*/
#define RES_HTMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nConnection: keep-alive\r\nContent-Length: "
/* Response head for TEXT */
#define RES_TEXTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\nContent-Length: "
/* Response head for GIF */
#define RES_GIFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/gif\r\nContent-Length: "
/* Response head for JPEG */
#define RES_JPEGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/jpeg\r\nContent-Length: "
/* Response head for PNG */
#define RES_PNGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/png\r\nContent-Length: "
/* Response head for FLASH */
#define RES_FLASHHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-shockwave-flash\r\nContent-Length: "
/* Response head for XML */
#define RES_XMLHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/xml\r\nConnection: keep-alive\r\nContent-Length: "
/* Response head for CSS */
#define RES_CSSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/css\r\nContent-Length: "
/* Response head for JavaScript */
#define RES_JSHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/javascript\r\nContent-Length: "
/* Response head for JSON */
#define RES_JSONHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: "
/* Response head for ICO */
#define RES_ICOHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/x-icon\r\nContent-Length: "
/* Response head for CGI */
#define RES_CGIHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\nContent-Length: "
/* Response head for TTF, Font */
#define RES_TTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-truetype\r\nContent-Length: "
/* Response head for OTF, Font */
#define RES_OTFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/x-font-opentype\r\nContent-Length: "
/* Response head for WOFF, Font */
#define RES_WOFFHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/font-woff\r\nContent-Length: "
/* Response head for EOT, Font */
#define RES_EOTHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.ms-fontobject\r\nContent-Length: "
/* Response head for SVG, Font */
#define RES_SVGHEAD_OK "HTTP/1.1 200 OK\r\nContent-Type: image/svg+xml\r\nContent-Length: "
/**
@brief Structure of HTTP REQUEST
*/
//#define MAX_URI_SIZE 1461
#define MAX_URI_SIZE 512
typedef struct _st_http_request
{
uint8_t METHOD; /**< request method(METHOD_GET...). */
uint8_t TYPE; /**< request type(PTYPE_HTML...). */
uint8_t URI[MAX_URI_SIZE]; /**< request file name. */
}st_http_request;
// HTTP Parsing functions
void unescape_http_url(char * url); /* convert escape character to ascii */
void parse_http_request(st_http_request *, uint8_t *); /* parse request from peer */
void find_http_uri_type(uint8_t *, uint8_t *); /* find MIME type of a file */
void make_http_response_head(char *, char, uint32_t); /* make response header */
uint8_t * get_http_param_value(char* uri, char* param_name); /* get the user-specific parameter value */
uint8_t get_http_uri_name(uint8_t * uri, uint8_t * uri_buf); /* get the requested URI name */
#ifdef _OLD_
uint8_t * get_http_uri_name(uint8_t * uri);
#endif
// Utility functions
uint16_t ATOI(uint8_t * str, uint8_t base);
void mid(char* src, char* s1, char* s2, char* sub);
void inet_addr_(uint8_t * addr, uint8_t * ip);
#ifdef __cplusplus
}
#endif
#endif /* end of __HTTPPARSER_H__ */

View File

@@ -0,0 +1,878 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "socket.h"
#include "wizchip_conf.h"
#include "httpServer.h"
#include "httpParser.h"
#include "httpUtil.h"
#include "../../globals.h" //add AVR specific useful headers
#define DATA_BUF_SIZE HTTPD_MAX_BUF_SIZE
/*****************************************************************************
* Private types/enumerations/variables
****************************************************************************/
static uint8_t HTTPSock_Num[_WIZCHIP_SOCK_NUM_] = {0, };
static st_http_request * http_request; /**< Pointer to received HTTP request */
static st_http_request * parsed_http_request; /**< Pointer to parsed HTTP request */
static uint8_t * http_response; /**< Pointer to HTTP response */
// ## For Debugging
//static uint8_t uri_buf[128];
// Number of registered web content in code flash memory
static uint16_t total_content_cnt = 0;
/*****************************************************************************
* Public types/enumerations/variables
****************************************************************************/
uint8_t * pHTTP_TX;
uint8_t * pHTTP_RX;
volatile uint32_t httpServer_tick_1s = 0;
st_http_socket HTTPSock_Status[_WIZCHIP_SOCK_NUM_] = { {STATE_HTTP_IDLE, }, };
httpServer_webContent web_content[MAX_CONTENT_CALLBACK];
#ifdef _USE_SDCARD_
//static FIL fs; // FatFs: File object
static FRESULT fr; // FatFs: File function return code
#endif
/*****************************************************************************
* Private functions
****************************************************************************/
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist);
static uint8_t getHTTPSocketNum(uint8_t seqnum);
static int8_t getHTTPSequenceNum(uint8_t socket);
static int8_t http_disconnect(uint8_t sn);
static void http_process_handler_avr(uint8_t s, st_http_request * p_http_request);
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status);
static void send_http_response_body_avr(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len);
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len);
/*****************************************************************************
* Public functions
****************************************************************************/
// Callback functions definition: MCU Reset / WDT Reset
void default_mcu_reset(void) {;}
void default_wdt_reset(void) {;}
void (*HTTPServer_ReStart)(void) = default_mcu_reset;
void (*HTTPServer_WDT_Reset)(void) = default_wdt_reset;
void httpServer_Sockinit(uint8_t cnt, uint8_t * socklist)
{
uint8_t i;
for(i = 0; i < cnt; i++)
{
// Mapping the H/W socket numbers to the sequential index numbers
HTTPSock_Num[i] = socklist[i];
}
}
static uint8_t getHTTPSocketNum(uint8_t seqnum)
{
// Return the 'H/W socket number' corresponding to the index number
return HTTPSock_Num[seqnum];
}
static int8_t getHTTPSequenceNum(uint8_t socket)
{
uint8_t i;
for(i = 0; i < _WIZCHIP_SOCK_NUM_; i++)
if(HTTPSock_Num[i] == socket) return i;
return -1;
}
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist)
{
// User's shared buffer
pHTTP_TX = tx_buf;
pHTTP_RX = rx_buf;
// H/W Socket number mapping
httpServer_Sockinit(cnt, socklist);
}
/* Register the call back functions for HTTP Server */
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void))
{
// Callback: HW Reset and WDT reset function for each MCU platforms
if(mcu_reset) HTTPServer_ReStart = mcu_reset;
if(wdt_reset) HTTPServer_WDT_Reset = wdt_reset;
}
void httpServer_run_avr(uint8_t seqnum)
{
uint8_t s; // socket number
uint16_t len;
uint32_t gettime = 0;
#ifdef _HTTPSERVER_DEBUG_
uint8_t destip[4] = {0, };
uint16_t destport = 0;
#endif
http_request = (st_http_request *)pHTTP_RX; // Structure of HTTP Request
parsed_http_request = (st_http_request *)pHTTP_TX;
// Get the H/W socket number
s = getHTTPSocketNum(seqnum);
/* HTTP Service Start */
switch(getSn_SR(s))
{
case SOCK_ESTABLISHED:
// Interrupt clear
if(getSn_IR(s) & Sn_IR_CON)
{
setSn_IR(s, Sn_IR_CON);
}
// HTTP Process states
switch(HTTPSock_Status[seqnum].sock_status)
{
case STATE_HTTP_IDLE :
if ((len = getSn_RX_RSR(s)) > 0)
{
if (len > DATA_BUF_SIZE) len = DATA_BUF_SIZE;
len = recv(s, (uint8_t *)http_request, len);
*(((uint8_t *)http_request) + len) = '\0';
parse_http_request(parsed_http_request, (uint8_t *)http_request);
#ifdef _HTTPSERVER_DEBUG_
getSn_DIPR(s, destip);
destport = getSn_DPORT(s);
PRINTF("\r\n");
PRINTF("> HTTPSocket[%d] : HTTP Request received ", s);
PRINTF("from %d.%d.%d.%d : %u\r\n", destip[0], destip[1], destip[2], destip[3], destport);
#endif
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE\r\n", s);
#endif
// HTTP 'response' handler; includes send_http_response_header / body function
http_process_handler_avr(s, parsed_http_request);
gettime = get_httpServer_timecount();
// Check the TX socket buffer for End of HTTP response sends
while(getSn_TX_FSR(s) != (getSn_TXBUF_SIZE(s)*1024))
{
if((get_httpServer_timecount() - gettime) > 3)
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [State] STATE_HTTP_REQ_DONE: TX Buffer clear timeout\r\n", s);
#endif
break;
}
}
if(HTTPSock_Status[seqnum].file_len > 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_INPROC;
else HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE; // Send the 'HTTP response' end
}
break;
case STATE_HTTP_RES_INPROC :
/* Repeat: Send the remain parts of HTTP responses */
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [State] STATE_HTTP_RES_INPROC\r\n", s);
PRINTF("\r\n> HTTPSocket[%d] : Re-Open the requested content\r\n", s); //_delay_ms(200);
#endif
/*
#ifdef _USE_SDCARD_
#ifdef _HTTPSERVER_DEBUG_
//PRINTF("++SDFLASH FIND..\r\n"); //_delay_ms(200);
#endif
if((fr = f_open(&fs, (const char *)HTTPSock_Status[seqnum].file_name, FA_READ)) == 0)
{
#ifdef _HTTPSERVER_DEBUG_
//PRINTF("++Content found on SDCARD\r\n");
if((fr = f_lseek(&fs, HTTPSock_Status[seqnum].file_offset)) != 0)
{
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
break;
}
#endif
}
else
{
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
break;
}
#endif
*/
// Repeatedly send remaining data to client
send_http_response_body_avr(s, 0, http_response, 0, 0);
if(HTTPSock_Status[seqnum].file_len == 0) HTTPSock_Status[seqnum].sock_status = STATE_HTTP_RES_DONE;
break;
case STATE_HTTP_RES_DONE :
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [State] STATE_HTTP_RES_DONE\r\n", s);
#endif
// Socket file info structure re-initialize
HTTPSock_Status[seqnum].file_len = 0;
HTTPSock_Status[seqnum].file_offset = 0;
HTTPSock_Status[seqnum].file_start = 0;
HTTPSock_Status[seqnum].sock_status = STATE_HTTP_IDLE;
#ifdef _USE_SDCARD_
f_close(&HTTPSock_Status[seqnum].fs);
#endif
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
http_disconnect(s);
break;
default :
break;
}
break;
case SOCK_CLOSE_WAIT:
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : ClOSE_WAIT\r\n", s); // if a peer requests to close the current connection
#endif
disconnect(s);
break;
case SOCK_CLOSED:
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : CLOSED\r\n", s);
#endif
if(socket(s, Sn_MR_TCP, HTTP_SERVER_PORT, 0x00) == s) /* Reinitialize the socket */
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : OPEN\r\n", s);
#endif
}
break;
case SOCK_INIT:
listen(s);
break;
case SOCK_LISTEN:
break;
default :
break;
} // end of switch
#ifdef _USE_WATCHDOG_
HTTPServer_WDT_Reset();
#endif
}
////////////////////////////////////////////
// Private Functions
////////////////////////////////////////////
static void send_http_response_header(uint8_t s, uint8_t content_type, uint32_t body_len, uint16_t http_status)
{
switch(http_status)
{
case STATUS_OK: // HTTP/1.1 200 OK
if((content_type != PTYPE_CGI) && (content_type != PTYPE_XML)) // CGI/XML type request does not respond HTTP header
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header - STATUS_OK\r\n", s);
#endif
make_http_response_head((char*)http_response, content_type, body_len);
}
else
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header - NONE / CGI or XML\r\n", s);
#endif
// CGI/XML type request does not respond HTTP header to client
http_status = 0;
}
break;
case STATUS_BAD_REQ: // HTTP/1.1 400 OK
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header - STATUS_BAD_REQ\r\n", s);
#endif
memcpy_P(http_response, ERROR_REQUEST_PAGE, sizeof(ERROR_REQUEST_PAGE));
break;
case STATUS_NOT_FOUND: // HTTP/1.1 404 Not Found
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header - STATUS_NOT_FOUND\r\n", s);
#endif
memcpy_P(http_response, ERROR_HTML_PAGE, sizeof(ERROR_HTML_PAGE));
break;
default:
break;
}
// Send the HTTP Response 'header'
if(http_status)
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [Send] HTTP Response Header [ %d ]byte\r\n", s, (uint16_t)strlen((char *)http_response));
#endif
send(s, http_response, strlen((char *)http_response));
}
}
static void send_http_response_body_avr(uint8_t s, uint8_t * uri_name, uint8_t * buf, uint32_t start_addr, uint32_t file_len)
{
int8_t get_seqnum;
uint32_t send_len;
uint8_t flag_datasend_end = 0;
#ifdef _USE_SDCARD_
uint16_t blocklen;
#endif
#ifdef _USE_FLASH_
uint32_t addr = 0;
#endif
if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
// Send the HTTP Response 'body'; requested file
if(!HTTPSock_Status[get_seqnum].file_len) // ### Send HTTP response body: First part ###
{
if (file_len > DATA_BUF_SIZE - 1)
{
HTTPSock_Status[get_seqnum].file_start = start_addr;
HTTPSock_Status[get_seqnum].file_len = file_len;
send_len = DATA_BUF_SIZE - 1;
/////////////////////////////////////////////////////////////////////////////////////////////////
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
memset(HTTPSock_Status[get_seqnum].file_name, 0x00, MAX_CONTENT_NAME_LEN);
strcpy((char *)HTTPSock_Status[get_seqnum].file_name, (char *)uri_name);
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response body - file name [ %s ]\r\n", s, HTTPSock_Status[get_seqnum].file_name);
#endif
/////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response body - file len [ %ld ]byte\r\n", s, file_len);
#endif
}
else
{
// Send process end
send_len = file_len;
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : (1)HTTP Response end - file len [ %ld ]byte\r\n", s, send_len);
#endif
}
#ifdef _USE_FLASH_
if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH) addr = start_addr;
#endif
}
else // remained parts
{
#ifdef _USE_FLASH_
if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
{
addr = HTTPSock_Status[get_seqnum].file_start + HTTPSock_Status[get_seqnum].file_offset;
}
#endif
send_len = HTTPSock_Status[get_seqnum].file_len - HTTPSock_Status[get_seqnum].file_offset;
if(send_len > DATA_BUF_SIZE - 1)
{
send_len = DATA_BUF_SIZE - 1;
//HTTPSock_Status[get_seqnum]->file_offset += send_len;
}
else
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : (2)HTTP Response end - file len [ %ld ]byte\r\n", s, HTTPSock_Status[get_seqnum].file_len);
#endif
// Send process end
flag_datasend_end = 1;
}
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response body - send len [ %ld ]byte\r\n", s, send_len);
#endif
}
/*****************************************************/
//HTTPSock_Status[get_seqnum]->storage_type == NONE
//HTTPSock_Status[get_seqnum]->storage_type == CODEFLASH
//HTTPSock_Status[get_seqnum]->storage_type == SDCARD
//HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH
/*****************************************************/
if(HTTPSock_Status[get_seqnum].storage_type == CODEFLASH)
{
if(HTTPSock_Status[get_seqnum].file_len) start_addr = HTTPSock_Status[get_seqnum].file_start;
read_userReg_webContent_avr(start_addr, &buf[0], HTTPSock_Status[get_seqnum].file_offset, send_len);
}
#ifdef _USE_SDCARD_
else if(HTTPSock_Status[get_seqnum].storage_type == SDCARD)
{
// Data read from SD Card
//PRINTF("++SDCARD f_read(..)\r\n");
fr = f_read(&HTTPSock_Status[get_seqnum].fs, &buf[0], send_len, (void *)&blocklen);
if(fr != FR_OK)
{
send_len = 0;
#ifdef _HTTPSERVER_DEBUG_
printf("> HTTPSocket[%d] : [FatFs] Error code return: %d (File Read) / HTTP Send Failed - %s\r\n", s, fr, HTTPSock_Status[get_seqnum].file_name);
#endif
}
else
{
*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
}
}
#endif
#ifdef _USE_FLASH_
else if(HTTPSock_Status[get_seqnum]->storage_type == DATAFLASH)
{
// Data read from external data flash memory
read_from_flashbuf(addr, &buf[0], send_len);
*(buf+send_len+1) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
}
#endif
else
{
send_len = 0;
}
// Requested content send to HTTP client
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [Send] HTTP Response body [ %ld ]byte\r\n", s, send_len);
#endif
if(send_len) send(s, buf, send_len);
else flag_datasend_end = 1;
if(flag_datasend_end)
{
HTTPSock_Status[get_seqnum].file_start = 0;
HTTPSock_Status[get_seqnum].file_len = 0;
HTTPSock_Status[get_seqnum].file_offset = 0;
flag_datasend_end = 0;
}
else
{
HTTPSock_Status[get_seqnum].file_offset += send_len;
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response body - offset [ %ld ]\r\n", s, HTTPSock_Status[get_seqnum].file_offset);
#endif
}
// ## 20141219 Eric added, for 'File object structure' (fs) allocation reduced (8 -> 1)
#ifdef _USE_SDCARD_
//Should not close here
//f_close(&fs);
#endif
// ## 20141219 added end
}
static void send_http_response_cgi(uint8_t s, uint8_t * buf, uint8_t * http_body, uint16_t file_len)
{
uint16_t send_len = 0;
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header + Body - CGI\r\n", s);
#endif
//send_len = sprintf((char *)buf, "%s%d\r\n\r\n%s", RES_CGIHEAD_OK, file_len, http_body);
send_len = sprintf_P((char *)buf, PSTR("%S%d\r\n\r\n%s"), PSTR(RES_CGIHEAD_OK), file_len, http_body);
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : HTTP Response Header + Body - send len [ %d ]byte\r\n", s, send_len);
#endif
send(s, buf, send_len);
}
static int8_t http_disconnect(uint8_t sn)
{
setSn_CR(sn,Sn_CR_DISCON);
/* wait to process the command... */
while(getSn_CR(sn));
return SOCK_OK;
}
static void http_process_handler_avr(uint8_t s, st_http_request * p_http_request)
{
uint8_t * uri_name;
uint32_t content_addr = 0;
uint16_t content_num = 0;
uint32_t file_len = 0;
uint8_t uri_buf[MAX_URI_SIZE]={0x00, };
uint16_t http_status;
int8_t get_seqnum;
uint8_t content_found;
if((get_seqnum = getHTTPSequenceNum(s)) == -1) return; // exception handling; invalid number
http_status = 0;
http_response = pHTTP_RX;
file_len = 0;
//method Analyze
switch (p_http_request->METHOD)
{
case METHOD_ERR :
http_status = STATUS_BAD_REQ;
send_http_response_header(s, 0, 0, http_status);
break;
case METHOD_HEAD :
case METHOD_GET :
get_http_uri_name(p_http_request->URI, uri_buf);
uri_name = uri_buf;
if (!strcmp((char *)uri_name, "/")) strcpy((char *)uri_name, INITIAL_WEBPAGE); // If URI is "/", respond by index.html
if (!strcmp((char *)uri_name, "m")) strcpy((char *)uri_name, M_INITIAL_WEBPAGE);
if (!strcmp((char *)uri_name, "mobile")) strcpy((char *)uri_name, MOBILE_INITIAL_WEBPAGE);
find_http_uri_type(&p_http_request->TYPE, uri_name); // Checking requested file types (HTML, TEXT, GIF, JPEG and Etc. are included)
#ifdef _HTTPSERVER_DEBUG_
PRINTF("\r\n> HTTPSocket[%d] : HTTP Method GET\r\n", s);
PRINTF("> HTTPSocket[%d] : Request Type = %d\r\n", s, p_http_request->TYPE);
PRINTF("> HTTPSocket[%d] : Request URI = %s\r\n", s, uri_name);
#endif
if (p_http_request->TYPE == PTYPE_ERR)
{
http_status = STATUS_BAD_REQ;
send_http_response_header(s, 0, 0, http_status);
return;
}
else if(p_http_request->TYPE == PTYPE_CGI)
{
content_found = http_get_cgi_handler(uri_name, pHTTP_TX, &file_len);
if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
{
send_http_response_cgi(s, http_response, pHTTP_TX, (uint16_t)file_len);
}
else
{
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
}
}
else
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("\r\n> HTTPSocket[%d] : Searching the requested content\r\n", s); //_delay_ms(200);
//PRINTF("++CODEFLASH FIND..\r\n"); //_delay_ms(200);
#endif
// Find the User registered index for web content
if(find_userReg_webContent_avr(uri_buf, &content_num, &file_len))
{
content_found = 1; // Web content found in code flash memory
content_addr = (uint32_t)content_num;
HTTPSock_Status[get_seqnum].storage_type = CODEFLASH;
#ifdef _HTTPSERVER_DEBUG_
//PRINTF("++Content found on CODEFLASH\r\n");
#endif
}
// Not CGI request, Web content in 'SD card' or 'Data flash' requested
#ifdef _USE_SDCARD_
#ifdef _HTTPSERVER_DEBUG_
PRINTF("\r\n> HTTPSocket[%d] : Searching the requested content\r\n", s); //_delay_ms(200);
//PRINTF("++SDFLASH FIND..\r\n"); //_delay_ms(200);
#endif
if((fr = f_open(&HTTPSock_Status[get_seqnum].fs, (const char *)uri_name, FA_READ)) == 0)
{
content_found = 1; // file open succeed
file_len = HTTPSock_Status[get_seqnum].fs.fsize;
//content_addr = fs.sclust; //?
content_addr = HTTPSock_Status[get_seqnum].fs.fptr; //much better
HTTPSock_Status[get_seqnum].storage_type = SDCARD;
#ifdef _HTTPSERVER_DEBUG_
//PRINTF("++Content found on SDCARD\r\n");
#endif
}
#elif _USE_FLASH_
else if(/* Read content from Dataflash */)
{
content_found = 1;
HTTPSock_Status[get_seqnum]->storage_type = DATAFLASH;
; // To do
}
#endif
else
{
content_found = 0; // fail to find content
}
if(!content_found)
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : Unknown Page Request\r\n", s);
#endif
http_status = STATUS_NOT_FOUND;
}
else
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : Find Content [%s] ok - Start [%ld] len [ %ld ]byte\r\n", s, uri_name, content_addr, file_len);
#endif
http_status = STATUS_OK;
}
// Send HTTP header
if(http_status)
{
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : Requested content len = [ %ld ]byte\r\n", s, file_len);
#endif
send_http_response_header(s, p_http_request->TYPE, file_len, http_status);
}
// Send HTTP body (content)
if(http_status == STATUS_OK)
{
send_http_response_body_avr(s, uri_name, http_response, content_addr, file_len);
}
}
break;
case METHOD_POST :
mid((char *)p_http_request->URI, "/", " HTTP", (char *)uri_buf);
uri_name = uri_buf;
find_http_uri_type(&p_http_request->TYPE, uri_name); // Check file type (HTML, TEXT, GIF, JPEG are included)
#ifdef _HTTPSERVER_DEBUG_
PRINTF("\r\n> HTTPSocket[%d] : HTTP Method POST\r\n", s);
PRINTF("> HTTPSocket[%d] : Request URI = %s ", s, uri_name);
PRINTF("Type = %d\r\n", p_http_request->TYPE);
#endif
if(p_http_request->TYPE == PTYPE_CGI) // HTTP POST Method; CGI Process
{
content_found = http_post_cgi_handler(uri_name, p_http_request, http_response, &file_len);
#ifdef _HTTPSERVER_DEBUG_
PRINTF("> HTTPSocket[%d] : [CGI: %s] / Response len [ %ld ]byte\r\n", s, content_found?"Content found":"Content not found", file_len);
#endif
if(content_found && (file_len <= (DATA_BUF_SIZE-(strlen(RES_CGIHEAD_OK)+8))))
{
send_http_response_cgi(s, pHTTP_TX, http_response, (uint16_t)file_len);
// Reset the H/W for apply to the change configuration information
if(content_found == HTTP_RESET) HTTPServer_ReStart();
}
else
{
send_http_response_header(s, PTYPE_CGI, 0, STATUS_NOT_FOUND);
}
}
else // HTTP POST Method; Content not found
{
send_http_response_header(s, 0, 0, STATUS_NOT_FOUND);
}
break;
default :
http_status = STATUS_BAD_REQ;
send_http_response_header(s, 0, 0, http_status);
break;
}
}
void httpServer_time_handler(void)
{
httpServer_tick_1s++;
}
uint32_t get_httpServer_timecount(void)
{
return httpServer_tick_1s;
}
void reg_httpServer_webContent_avr(const uint8_t * content_name,const uint8_t * content)
{
uint16_t name_len;
uint32_t content_len;
if(content_name == NULL || content == NULL)
{
return;
}
else if(total_content_cnt >= MAX_CONTENT_CALLBACK)
{
return;
}
name_len = strlen_P((const char *)content_name);
content_len = strlen_P((const char *)content);
web_content[total_content_cnt].content_name = malloc(name_len+1);
strcpy_P((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
web_content[total_content_cnt].content_len = content_len;
web_content[total_content_cnt].content = content;
total_content_cnt++;
}
void reg_httpServer_binContent_avr(const uint8_t * content_name,const uint8_t * content, const uint32_t content_len)
{
uint16_t name_len;
//uint32_t content_len;
if(content_name == NULL || content == NULL)
{
return;
}
else if(total_content_cnt >= MAX_CONTENT_CALLBACK)
{
return;
}
name_len = strlen_P((const char *)content_name);
//content_len = (uint32_t) sizeof(content);
web_content[total_content_cnt].content_name = malloc(name_len+1);
strcpy_P((char *)web_content[total_content_cnt].content_name, (const char *)content_name);
web_content[total_content_cnt].content_len = content_len;
web_content[total_content_cnt].content = content;
total_content_cnt++;
}
uint8_t display_reg_webContent_list_avr(void)
{
uint16_t i;
uint8_t ret;
if(total_content_cnt == 0)
{
PRINTF(">> Web content file not found\r\n");
ret = 0;
}
else
{
PRINTF("\r\n=== List of Web content in code flash ===\r\n");
for(i = 0; i < total_content_cnt; i++)
{
PRINTF(" [%d] ", i+1);
PRINTF("%s, ", web_content[i].content_name);
PRINTF("%ld byte\r\n", web_content[i].content_len);
if(web_content[i].content_len < 30)
{
PRINTF("[%s]\r\n", web_content[i].content);
}
else
{
PRINTF("[ ... ]\r\n");
}
//Dump head 16 bytes every file..
/*
else
{
const char PROGMEM * tst_char = web_content[i].content;
if(strstr_P(web_content[i].content_name,PSTR("favicon.ico"))==NULL)
{
//ASCII Dump first 0x10 symbols, for all files without <favicon.ico>
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:%c]\r\n",tst_char, pgm_read_byte(tst_char++));
}
else
{
//HEX dump first 0x10 symbols, for <favicon.ico>
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
PRINTF("[0x%04X:0x%02X]\r\n",tst_char, pgm_read_byte(tst_char++));
}
}
*/
wdt_reset(); // WDT reset at least every sec
}
PRINTF("=========================================\r\n\r\n");
ret = 1;
}
return ret;
}
uint8_t find_userReg_webContent_avr(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len)
{
uint16_t i;
uint8_t ret = 0; // '0' means 'File Not Found'
for(i = 0; i < total_content_cnt; i++)
{
if(!strcmp((const char *)content_name, (const char *)web_content[i].content_name))
{
*file_len = web_content[i].content_len;
*content_num = i;
ret = 1; // If the requested content found, ret set to '1' (Found)
break;
}
}
return ret;
}
uint16_t read_userReg_webContent_avr(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size)
{
uint16_t ret = 0;
uint8_t * ptr;
if(content_num > total_content_cnt) return 0;
ptr = web_content[content_num].content;
if(offset) ptr += offset;
//strncpy_P((char *)buf, (const char *)ptr, size); //not suit for case binary data
memcpy_P((char *)buf, (const char *)ptr, size);
*(buf+size) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
//ret = strlen((void *)buf); //Useless for memcpy_P
ret = 0; //All ok
return ret;
}

View File

@@ -0,0 +1,125 @@
/**
@file httpServer.h
@brief Define constants and functions related HTTP Web server.
*/
#include <stdint.h>
#ifndef __HTTPSERVER_H__
#define __HTTPSERVER_H__
#ifdef __cplusplus
extern "C" {
#endif
// HTTP Server debug message enable
//#define _HTTPSERVER_DEBUG_
//#define INITIAL_WEBPAGE "index.html"
#define INITIAL_WEBPAGE "index.htm"
#define M_INITIAL_WEBPAGE "m/index.html"
#define MOBILE_INITIAL_WEBPAGE "mobile/index.html"
/* Web Server Content Storage Select */
#define _USE_SDCARD_
#ifndef _USE_SDCARD_
//#define _USE_FLASH_
#endif
#ifdef _USE_SDCARD_
#include "ff.h" // header file for FatFs library (FAT file system)
#endif
#if !defined(_USE_SDCARD_) && !defined(_USE_FLASH_)
#define _NOTUSED_STORAGE_
#endif
/* Watchdog timer */
//#define _USE_WATCHDOG_
/*********************************************
* HTTP Process states list
*********************************************/
#define STATE_HTTP_IDLE 0 /* IDLE, Waiting for data received (TCP established) */
#define STATE_HTTP_REQ_INPROC 1 /* Received HTTP request from HTTP client */
#define STATE_HTTP_REQ_DONE 2 /* The end of HTTP request parse */
#define STATE_HTTP_RES_INPROC 3 /* Sending the HTTP response to HTTP client (in progress) */
#define STATE_HTTP_RES_DONE 4 /* The end of HTTP response send (HTTP transaction ended) */
/*********************************************
* HTTP Simple Return Value
*********************************************/
#define HTTP_FAILED 0
#define HTTP_OK 1
#define HTTP_RESET 2
/*********************************************
* HTTP Content NAME length
*********************************************/
//#define MAX_CONTENT_NAME_LEN 128 ? Wasteful
#define MAX_CONTENT_NAME_LEN 16
/*********************************************
* HTTP Timeout
*********************************************/
#define HTTP_MAX_TIMEOUT_SEC 3 // Sec.
typedef enum
{
NONE, ///< Web storage none
CODEFLASH, ///< Code flash memory
SDCARD, ///< SD card
DATAFLASH ///< External data flash memory
}StorageType;
typedef struct _st_http_socket
{
uint8_t sock_status;
uint8_t file_name[MAX_CONTENT_NAME_LEN];
uint32_t file_start;
uint32_t file_len;
uint32_t file_offset; // (start addr + sent size...)
uint8_t storage_type; // Storage type; Code flash, SDcard, Data flash ...
FIL fs; // FatFs: File object
}st_http_socket;
// Web content structure for file in code flash memory
#define MAX_CONTENT_CALLBACK 20
typedef struct _httpServer_webContent
{
uint8_t * content_name;
uint32_t content_len;
uint8_t * content;
}httpServer_webContent;
void httpServer_init(uint8_t * tx_buf, uint8_t * rx_buf, uint8_t cnt, uint8_t * socklist);
void reg_httpServer_cbfunc(void(*mcu_reset)(void), void(*wdt_reset)(void));
void httpServer_run_avr(uint8_t seqnum);
void reg_httpServer_webContent_avr(const uint8_t * content_name,const uint8_t * content);
void reg_httpServer_binContent_avr(const uint8_t * content_name,const uint8_t * content, const uint32_t content_len);
uint8_t find_userReg_webContent_avr(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len);
uint16_t read_userReg_webContent_avr(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size);
uint8_t display_reg_webContent_list_avr(void);
/*
* @brief HTTP Server 1sec Tick Timer handler
* @note SHOULD BE register to your system 1s Tick timer handler
*/
void httpServer_time_handler(void);
uint32_t get_httpServer_timecount(void);
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,65 @@
/**
* @file httpUtil.c
* @brief HTTP Server Utilities
* @version 1.0
* @date 2014/07/15
* @par Revision
* 2014/07/15 - 1.0 Release
* @author
* \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "httpUtil.h"
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len)
{
uint8_t ret = HTTP_OK;
uint16_t len = 0;
if(predefined_get_cgi_processor(uri_name, buf, &len))
{
;
}
else if(strcmp((const char *)uri_name, "example.cgi") == 0)
{
// To do
;
}
else
{
// CGI file not found
ret = HTTP_FAILED;
}
if(ret) *file_len = len;
return ret;
}
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len)
{
uint8_t ret = HTTP_OK;
uint16_t len = 0;
uint8_t val = 0;
if(predefined_set_cgi_processor(uri_name, p_http_request->URI, buf, &len))
{
;
}
else if(strcmp((const char *)uri_name, "example.cgi") == 0)
{
// To do
val = 1;
len = sprintf((char *)buf, "%d", val);
}
else
{
// CGI file not found
ret = HTTP_FAILED;
}
if(ret) *file_len = len;
return ret;
}

View File

@@ -0,0 +1,32 @@
/**
* @file httpUtil.h
* @brief Header File for HTTP Server Utilities
* @version 1.0
* @date 2014/07/15
* @par Revision
* 2014/07/15 - 1.0 Release
* @author
* \n\n @par Copyright (C) 1998 - 2014 WIZnet. All rights reserved.
*/
#ifndef __HTTPUTIL_H__
#define __HTTPUTIL_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "httpServer.h"
#include "httpParser.h"
uint8_t http_get_cgi_handler(uint8_t * uri_name, uint8_t * buf, uint32_t * file_len);
uint8_t http_post_cgi_handler(uint8_t * uri_name, st_http_request * p_http_request, uint8_t * buf, uint32_t * file_len);
uint8_t predefined_get_cgi_processor(uint8_t * uri_name, uint8_t * buf, uint16_t * len);
uint8_t predefined_set_cgi_processor(uint8_t * uri_name, uint8_t * uri, uint8_t * buf, uint16_t * len);
#ifdef __cplusplus
}
#endif
#endif