📄 http.c
字号:
/*********************************************************************
*
* HTTP Implementation for Microchip TCP/IP Stack
*
**********************************************************************
* FileName: Http.c
* Dependencies: string.h
* Stacktsk.h
* Http.h
* MPFS.h
* TCP.h
* Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F
* Complier: Microchip C18 v3.02 or higher
* Microchip C30 v2.01 or higher
* Company: Microchip Technology, Inc.
*
* Software License Agreement
*
* This software is owned by Microchip Technology Inc. ("Microchip")
* and is supplied to you for use exclusively as described in the
* associated software agreement. This software is protected by
* software and other intellectual property laws. Any use in
* violation of the software license may subject the user to criminal
* sanctions as well as civil liability. Copyright 2006 Microchip
* Technology Inc. All rights reserved.
*
* This software is provided "AS IS." MICROCHIP DISCLAIMS ALL
* WARRANTIES, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, NOT LIMITED
* TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND
* INFRINGEMENT. Microchip shall in no event be liable for special,
* incidental, or consequential damages.
*
*
* Author Date Comment
*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* Nilesh Rajbharti 8/14/01 Original
* Nilesh Rajbharti 9/12/01 Released (Rev. 1.0)
* Nilesh Rajbharti 2/9/02 Cleanup
* Nilesh Rajbharti 5/22/02 Rev 2.0 (See version.log for detail)
* Nilesh Rajbharti 7/9/02 Rev 2.1 (Fixed HTTPParse bug)
* Howard Schlunder 2/9/05 Fixed variable substitution
* parsing (uses hex now)
********************************************************************/
#define THIS_IS_HTTP_SERVER
#include <string.h>
#include "..\Include\StackTsk.h"
#include "..\Include\HTTP.h"
#include "..\Include\MPFS.h"
#include "..\Include\TCP.h"
#include "..\Include\Helpers.h"
#if defined(STACK_USE_HTTP_SERVER)
#if (MAC_TX_BUFFER_SIZE <= 130 || MAC_TX_BUFFER_SIZE > 1500 )
#error HTTP : Invalid MAC_TX_BUFFER_SIZE value specified.
#endif
// Each dynamic variable within a CGI file should be preceeded with this character.
#define HTTP_VAR_ESC_CHAR '%'
#define HTTP_DYNAMIC_FILE_TYPE (HTTP_CGI)
// HTTP File Types
#define HTTP_TXT (0u)
#define HTTP_HTML (1u)
#define HTTP_CGI (2u)
#define HTTP_XML (3u)
#define HTTP_GIF (4u)
#define HTTP_PNG (5u)
#define HTTP_JPG (6u)
#define HTTP_JAVA (7u)
#define HTTP_WAV (8u)
#define HTTP_UNKNOWN (9u)
#define FILE_EXT_LEN (3u)
typedef struct _FILE_TYPES
{
char fileExt[FILE_EXT_LEN+1];
} FILE_TYPES;
// Each entry in this structure must be in UPPER case.
// Order of these entries must match with those defined by "HTTP File Types" defines.
static ROM FILE_TYPES httpFiles[] =
{
{ "TXT" }, // HTTP_TXT
{ "HTM" }, // HTTP_HTML
{ "CGI" }, // HTTP_CGI
{ "XML" }, // HTTP_XML
{ "GIF" }, // HTTP_GIF
{ "PNG" }, // HTTP_PNG
{ "JPG" }, // HTTP_JPG
{ "CLA" }, // HTTP_JAVA
{ "WAV" }, // HTTP_WAV
{ "" } // HTTP_UNKNOWN
};
#define TOTAL_FILE_TYPES ( sizeof(httpFiles)/sizeof(httpFiles[0]) )
typedef struct _HTTP_CONTENT
{
ROM char typeString[20];
} HTTP_CONTENT;
// Content entry order must match with those "HTTP File Types" define's.
static ROM HTTP_CONTENT httpContents[] =
{
{ "text/plain" }, // HTTP_TXT
{ "text/html" }, // HTTP_HTML
{ "text/html" }, // HTTP_CGI
{ "text/xml" }, // HTTP_XML
{ "image/gif" }, // HTTP_GIF
{ "image/png" }, // HTTP_PNG
{ "image/jpeg" }, // HTTP_JPG
{ "application/java-vm" }, // HTTP_JAVA
{ "audio/x-wave" }, // HTTP_WAV
{ "" } // HTTP_UNKNOWN
};
#define TOTAL_HTTP_CONTENTS ( sizeof(httpContents)/sizeof(httpConetents[0]) )
// HTTP FSM states for each connection.
typedef enum _SM_HTTP
{
SM_HTTP_IDLE = 0,
SM_HTTP_GET,
SM_HTTP_NOT_FOUND,
SM_HTTP_GET_READ,
SM_HTTP_GET_PASS,
SM_HTTP_GET_DLE,
SM_HTTP_GET_HANDLE,
SM_HTTP_GET_HANDLE_NEXT,
SM_HTTP_GET_VAR,
SM_HTTP_DISCONNECT,
SM_HTTP_DISCONNECT_WAIT,
SM_HTTP_HEADER,
SM_HTTP_DISCARD
} SM_HTTP;
// Supported HTTP Commands
typedef enum _HTTP_COMMAND
{
HTTP_GET,
HTTP_POST,
HTTP_NOT_SUPPORTED,
HTTP_INVALID_COMMAND
} HTTP_COMMAND;
// HTTP Connection Info - one for each connection.
typedef struct _HTTP_INFO
{
TCP_SOCKET socket;
MPFS file;
SM_HTTP smHTTP;
BYTE smHTTPGet;
WORD VarRef;
BYTE bProcess;
BYTE Variable;
BYTE fileType;
} HTTP_INFO;
typedef BYTE HTTP_HANDLE;
typedef enum
{
HTTP_NOT_FOUND,
HTTP_NOT_AVAILABLE
} HTTP_MESSAGES;
// Following message order must match with that of HTTP_MESSAGES enum.
static ROM char *HTTPMessages[] =
{
"HTTP/1.0 404 Not found\r\n\r\nNot found.\r\n",
"HTTP/1.0 503 \r\n\r\nService Unavailable\r\n"
};
// Standard HTTP messages.
ROM BYTE HTTP_OK_STRING[] = "HTTP/1.0 200 OK\r\nContent-type: ";
ROM BYTE HTTP_OK_NO_CACHE_STRING[] = "HTTP/1.0 200 OK\r\nDate: Wed, 05 Apr 2006 02:53:05 GMT\r\nExpires: Wed, 05 Apr 2006 02:52:05 GMT\r\nCache-control: private\r\nContent-type: ";
#define HTTP_OK_STRING_LEN (sizeof(HTTP_OK_STRING)-1)
#define HTTP_OK_NO_CACHE_STRING_LEN (sizeof(HTTP_OK_NO_CACHE_STRING)-1)
ROM BYTE HTTP_HEADER_END_STRING[] = \
"\r\n\r\n";
#define HTTP_HEADER_END_STRING_LEN \
(sizeof(HTTP_HEADER_END_STRING)-1)
// HTTP Command Strings
ROM BYTE HTTP_GET_STRING[] = \
"GET";
#define HTTP_GET_STRING_LEN \
(sizeof(HTTP_GET_STRING)-1)
// Default HTML file.
ROM BYTE HTTP_DEFAULT_FILE_STRING[] = \
"INDEX.HTM";
#define HTTP_DEFAULT_FILE_STRING_LEN \
(sizeof(HTTP_DEFAULT_FILE_STRING)-1)
// Maximum nuber of arguments supported by this HTTP Server.
#define MAX_HTTP_ARGS (11)
// Maximum HTML Command String length.
#define MAX_HTML_CMD_LEN (100)
static HTTP_INFO HCB[MAX_HTTP_CONNECTIONS];
static void HTTPProcess(HTTP_HANDLE h);
static HTTP_COMMAND HTTPParse(BYTE *string,
BYTE** arg,
BYTE* argc,
BYTE* type);
static BOOL SendFile(HTTP_INFO* ph);
/*********************************************************************
* Function: void HTTPInit(void)
*
* PreCondition: TCP must already be initialized.
*
* Input: None
*
* Output: HTTP FSM and connections are initialized
*
* Side Effects: None
*
* Overview: Set all HTTP connections to Listening state.
* Initialize FSM for each connection.
*
* Note: This function is called only one during lifetime
* of the application.
********************************************************************/
void HTTPInit(void)
{
BYTE i;
for ( i = 0; i < MAX_HTTP_CONNECTIONS; i++ )
{
HCB[i].socket = TCPListen(HTTP_PORT);
HCB[i].smHTTP = SM_HTTP_IDLE;
}
}
/*********************************************************************
* Function: void HTTPServer(void)
*
* PreCondition: HTTPInit() must already be called.
*
* Input: None
*
* Output: Opened HTTP connections are served.
*
* Side Effects: None
*
* Overview: Browse through each connections and let it
* handle its connection.
* If a connection is not finished, do not process
* next connections. This must be done, all
* connections use some static variables that are
* common.
*
* Note: This function acts as a task (similar to one in
* RTOS). This function performs its task in
* co-operative manner. Main application must call
* this function repeatdly to ensure all open
* or new connections are served on time.
********************************************************************/
void HTTPServer(void)
{
BYTE conn;
for ( conn = 0; conn < MAX_HTTP_CONNECTIONS; conn++ )
HTTPProcess(conn);
}
/*********************************************************************
* Function: static BOOL HTTPProcess(HTTP_HANDLE h)
*
* PreCondition: HTTPInit() called.
*
* Input: h - Index to the handle which needs to be
* processed.
*
* Output: Connection referred by 'h' is served.
*
* Side Effects: None
*
* Overview:
*
* Note: None.
********************************************************************/
static void HTTPProcess(HTTP_HANDLE h)
{
BYTE httpData[MAX_HTML_CMD_LEN+1];
HTTP_COMMAND httpCommand;
WORD httpLength;
BOOL lbContinue;
BYTE *arg[MAX_HTTP_ARGS];
BYTE argc;
BYTE i;
HTTP_INFO* ph;
ROM char* romString;
ph = &HCB[h];
do
{
lbContinue = FALSE;
// If during handling of HTTP socket, it gets disconnected,
// forget about previous processing and return to idle state.
if(!TCPIsConnected(ph->socket))
{
ph->smHTTP = SM_HTTP_IDLE;
break;
}
switch(ph->smHTTP)
{
case SM_HTTP_IDLE:
if(TCPIsGetReady(ph->socket))
{
lbContinue = TRUE;
httpLength = 0;
while(httpLength < MAX_HTML_CMD_LEN &&
TCPGet(ph->socket, &httpData[httpLength++]) );
httpData[httpLength] = '\0';
TCPDiscard(ph->socket);
ph->smHTTP = SM_HTTP_NOT_FOUND;
argc = MAX_HTTP_ARGS;
httpCommand = HTTPParse(httpData, arg, &argc, &ph->fileType);
if ( httpCommand == HTTP_GET )
{
// If there are any arguments, this must be a remote command.
// Execute it and then send the file.
// The file name may be modified by command handler.
if ( argc > 1u )
{
// Let main application handle this remote command.
HTTPExecCmd(&arg[0], argc);
// Command handler must have modified arg[0] which now
// points to actual file that will be sent as a result of
// this remote command.
// Assume that Web author will only use CGI or HTML
// file for remote command.
ph->fileType = HTTP_CGI;
}
ph->file = MPFSOpen(arg[0]);
if ( ph->file == MPFS_INVALID )
{
ph->Variable = HTTP_NOT_FOUND;
ph->smHTTP = SM_HTTP_NOT_FOUND;
}
else if ( ph->file == MPFS_NOT_AVAILABLE )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -