Internet protocol libraries and Application added
>> Internet \ FTPserver >> Internet \ httpServer (web server) >> Internet \ SNMP (SNMPv1 agent) >> Application \ loopback (loopback test)
This commit is contained in:
402
Internet/httpServer/httpParser.c
Normal file
402
Internet/httpServer/httpParser.c
Normal 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 */
|
||||
)
|
||||
{
|
||||
char * head;
|
||||
char tmp[10];
|
||||
|
||||
/* file type*/
|
||||
if (type == PTYPE_HTML) head = RES_HTMLHEAD_OK;
|
||||
else if (type == PTYPE_GIF) head = RES_GIFHEAD_OK;
|
||||
else if (type == PTYPE_TEXT) head = RES_TEXTHEAD_OK;
|
||||
else if (type == PTYPE_JPEG) head = RES_JPEGHEAD_OK;
|
||||
else if (type == PTYPE_FLASH) head = RES_FLASHHEAD_OK;
|
||||
else if (type == PTYPE_XML) head = RES_XMLHEAD_OK;
|
||||
else if (type == PTYPE_CSS) head = RES_CSSHEAD_OK;
|
||||
else if (type == PTYPE_JSON) head = RES_JSONHEAD_OK;
|
||||
else if (type == PTYPE_JS) head = RES_JSHEAD_OK;
|
||||
else if (type == PTYPE_CGI) head = RES_CGIHEAD_OK;
|
||||
else if (type == PTYPE_PNG) head = RES_PNGHEAD_OK;
|
||||
else if (type == PTYPE_ICO) head = RES_ICOHEAD_OK;
|
||||
else if (type == PTYPE_TTF) head = RES_TTFHEAD_OK;
|
||||
else if (type == PTYPE_OTF) head = RES_OTFHEAD_OK;
|
||||
else if (type == PTYPE_WOFF) head = RES_WOFFHEAD_OK;
|
||||
else if (type == PTYPE_EOT) head = RES_EOTHEAD_OK;
|
||||
else if (type == PTYPE_SVG) head = 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(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 (strstr(buf, ".htm") || strstr(buf, ".html")) *type = PTYPE_HTML;
|
||||
else if (strstr(buf, ".gif")) *type = PTYPE_GIF;
|
||||
else if (strstr(buf, ".text") || strstr(buf,".txt")) *type = PTYPE_TEXT;
|
||||
else if (strstr(buf, ".jpeg") || strstr(buf,".jpg")) *type = PTYPE_JPEG;
|
||||
else if (strstr(buf, ".swf")) *type = PTYPE_FLASH;
|
||||
else if (strstr(buf, ".cgi") || strstr(buf,".CGI")) *type = PTYPE_CGI;
|
||||
else if (strstr(buf, ".json") || strstr(buf,".JSON")) *type = PTYPE_JSON;
|
||||
else if (strstr(buf, ".js") || strstr(buf,".JS")) *type = PTYPE_JS;
|
||||
else if (strstr(buf, ".CGI") || strstr(buf,".cgi")) *type = PTYPE_CGI;
|
||||
else if (strstr(buf, ".xml") || strstr(buf,".XML")) *type = PTYPE_XML;
|
||||
else if (strstr(buf, ".css") || strstr(buf,".CSS")) *type = PTYPE_CSS;
|
||||
else if (strstr(buf, ".png") || strstr(buf,".PNG")) *type = PTYPE_PNG;
|
||||
else if (strstr(buf, ".ico") || strstr(buf,".ICO")) *type = PTYPE_ICO;
|
||||
else if (strstr(buf, ".ttf") || strstr(buf,".TTF")) *type = PTYPE_TTF;
|
||||
else if (strstr(buf, ".otf") || strstr(buf,".OTF")) *type = PTYPE_OTF;
|
||||
else if (strstr(buf, ".woff") || strstr(buf,".WOFF")) *type = PTYPE_WOFF;
|
||||
else if (strstr(buf, ".eot") || strstr(buf,".EOT")) *type = PTYPE_EOT;
|
||||
else if (strstr(buf, ".svg") || strstr(buf,".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(nexttok, "GET") || !strcmp(nexttok,"get"))
|
||||
{
|
||||
request->METHOD = METHOD_GET;
|
||||
nexttok = strtok(NULL," ");
|
||||
|
||||
}
|
||||
else if (!strcmp(nexttok, "HEAD") || !strcmp(nexttok,"head"))
|
||||
{
|
||||
request->METHOD = METHOD_HEAD;
|
||||
nexttok = strtok(NULL," ");
|
||||
|
||||
}
|
||||
else if (!strcmp(nexttok, "POST") || !strcmp(nexttok,"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;
|
||||
}
|
||||
|
||||
|
||||
|
150
Internet/httpServer/httpParser.h
Normal file
150
Internet/httpServer/httpParser.h
Normal file
@ -0,0 +1,150 @@
|
||||
/**
|
||||
@file httpd.h
|
||||
@brief Define Constants and fucntions associated with HTTP protocol.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __HTTPPARSER_H__
|
||||
#define __HTTPPARSER_H__
|
||||
|
||||
//#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 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 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);
|
||||
|
||||
#endif /* end of __HTTPPARSER_H__ */
|
751
Internet/httpServer/httpServer.c
Normal file
751
Internet/httpServer/httpServer.c
Normal file
@ -0,0 +1,751 @@
|
||||
#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 "common.h"
|
||||
|
||||
#ifdef _USE_SDCARD_
|
||||
#include "ff.h" // header file for FatFs library (FAT file system)
|
||||
#endif
|
||||
|
||||
#ifndef DATA_BUF_SIZE
|
||||
#define DATA_BUF_SIZE 2048
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* 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_
|
||||
FIL fs; // FatFs: File object
|
||||
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(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(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(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 : %d\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(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);
|
||||
#endif
|
||||
// Repeatedly send remaining data to client
|
||||
send_http_response_body(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(&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(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(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(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] : 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] : 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(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
|
||||
fr = f_read(&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_
|
||||
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);
|
||||
#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(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_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
|
||||
{
|
||||
// Find the User registered index for web content
|
||||
if(find_userReg_webContent(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;
|
||||
}
|
||||
// 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);
|
||||
#endif
|
||||
if((fr = f_open(&fs, (const char *)uri_name, FA_READ)) == 0)
|
||||
{
|
||||
content_found = 1; // file open succeed
|
||||
|
||||
file_len = fs.fsize;
|
||||
content_addr = fs.sclust;
|
||||
HTTPSock_Status[get_seqnum]->storage_type = SDCARD;
|
||||
}
|
||||
#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(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(uint8_t * content_name, 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((char *)content_name);
|
||||
content_len = strlen((char *)content);
|
||||
|
||||
web_content[total_content_cnt].content_name = malloc(name_len+1);
|
||||
strcpy((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(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, ", web_content[i].content_len);
|
||||
|
||||
if(web_content[i].content_len < 30) printf("[%s]\r\n", web_content[i].content);
|
||||
else printf("[ ... ]\r\n");
|
||||
}
|
||||
printf("=========================================\r\n\r\n");
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t find_userReg_webContent(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((char *)content_name, (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(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((char *)buf, (char *)ptr, size);
|
||||
*(buf+size) = 0; // Insert '/0' for indicates the 'End of String' (null terminated)
|
||||
|
||||
ret = strlen((void *)buf);
|
||||
return ret;
|
||||
}
|
103
Internet/httpServer/httpServer.h
Normal file
103
Internet/httpServer/httpServer.h
Normal file
@ -0,0 +1,103 @@
|
||||
/**
|
||||
@file httpServer.h
|
||||
@brief Define constants and functions related HTTP Web server.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef __HTTPSERVER_H__
|
||||
#define __HTTPSERVER_H__
|
||||
|
||||
// HTTP Server debug message enable
|
||||
#define _HTTPSERVER_DEBUG_
|
||||
|
||||
#define INITIAL_WEBPAGE "index.html"
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
/*********************************************
|
||||
* 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 ...
|
||||
}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(uint8_t seqnum);
|
||||
|
||||
void reg_httpServer_webContent(uint8_t * content_name, uint8_t * content);
|
||||
uint8_t find_userReg_webContent(uint8_t * content_name, uint16_t * content_num, uint32_t * file_len);
|
||||
uint16_t read_userReg_webContent(uint16_t content_num, uint8_t * buf, uint32_t offset, uint16_t size);
|
||||
uint8_t display_reg_webContent_list(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);
|
||||
|
||||
#endif
|
65
Internet/httpServer/httpUtil.c
Normal file
65
Internet/httpServer/httpUtil.c
Normal 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;
|
||||
}
|
24
Internet/httpServer/httpUtil.h
Normal file
24
Internet/httpServer/httpUtil.h
Normal file
@ -0,0 +1,24 @@
|
||||
/**
|
||||
* @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__
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user