mirror of
https://github.com/oopuuu/zTC1.git
synced 2025-12-16 06:58:14 +08:00
1192 lines
44 KiB
C
1192 lines
44 KiB
C
/**
|
|
******************************************************************************
|
|
* @file httpd.c
|
|
* @author QQ DING
|
|
* @version V1.0.0
|
|
* @date 1-September-2015
|
|
* @brief The main HTTPD server thread and its initialization.
|
|
******************************************************************************
|
|
*
|
|
* The MIT License
|
|
* Copyright (c) 2014 MXCHIP Inc.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
* of this software and associated documentation files (the "Software"), to deal
|
|
* in the Software without restriction, including without limitation the rights
|
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
* copies of the Software, and to permit persons to whom the Software is furnished
|
|
* to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in
|
|
* all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
|
* IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
******************************************************************************
|
|
*/
|
|
|
|
/*! \file httpd.h
|
|
* \brief HTTP Web Server
|
|
*
|
|
* HTTP Web Server can serve static pages from a file system, dynamic content
|
|
* using a server-side include (SSI) capability, and dynamic content using
|
|
* custom web service gateway interface (WSGI) handlers. This documentation
|
|
* describes:
|
|
* -# How to initialize, start, stop, and shutdown the server.
|
|
* -# How static files are served.
|
|
* -# How to implement WSGI handlers.
|
|
* -# How the SSI directives "file" and "virtual" are processed.
|
|
* Several limitations that may be unexpected by programmers accustomed to using
|
|
* more sophisticated web servers and frameworks are also discussed.
|
|
*
|
|
* \section httpd_usage Usage
|
|
*
|
|
* httpd must be initialized by calling \ref httpd_init. After \ref httpd_init
|
|
* returns WM_SUCESS, \ref httpd_start and \ref httpd_stop can be called to
|
|
* start and stop the server respectively. Finally, to perform a final cleanup,
|
|
* \ref httpd_shutdown should be called. After a successful call to
|
|
* httpd_start, the server is listening for connections on \ref HTTP_PORT or
|
|
* \ref HTTPS_PORT.
|
|
*
|
|
* The WSGI and SSI handlers can be registered by calling the functions
|
|
* httpd_register_wsgi_handler() and httpd_register_ssi().
|
|
*
|
|
* When a client request is made, httpd first checks if the requested URI
|
|
* matches any registered WSGI handlers (see below). If a matching handler is
|
|
* found it gets executed and the processing is terminated. If a file matching
|
|
* the requested URI is found, it is served. If that file is a .shtml file, it
|
|
* is processed for directives as described in the file handling section.
|
|
*
|
|
* \section wsgi Web Services Gateway Interface (WSGI)
|
|
*
|
|
* The Web Services Gateway Interface (WSGI) allows developers to take complete
|
|
* control over how HTTP requests are processed. When a request arrives, its
|
|
* request method (or type) and URI are parsed. A table of all registered WSGI
|
|
* handlers is queried for any matches. If an exact match is obtained, the
|
|
* control is transferred to the corresponding WSGI handler. If the
|
|
* WSGI handler returns WM_SUCCESS, no further processing is performed.
|
|
* In case
|
|
* A 500 Internal Server Error is returned to the client:
|
|
* -# When any other value than WM_SUCCESS is returned by the WSGI handler.
|
|
*
|
|
* A 404 Not Found Error is returned to the client:
|
|
* -# If no handler (including the file system) matches the incoming URI
|
|
* -# If incoming request type is not supported by that WSGI
|
|
*
|
|
* A WSGI handler typically is executed in response to a HTTP GET or
|
|
* HTTP POST operation. In case of HTTP GET, the handler fetches some
|
|
* data from the device, formats it as desired and sends it to the
|
|
* requester. In case of HTTP POST, the handler reads the data that is
|
|
* sent along with the POST request and takes some action on the
|
|
* device. The WSGI handlers can make use of some of the common httpd
|
|
* helper functions to perform tasks pertaining to the
|
|
* sending/receiving of the data.
|
|
*
|
|
* A simple WSGI HTTP GET handler is shown below:
|
|
* Example: JSON Time Get
|
|
*
|
|
* \code
|
|
* int sys_get_time(httpd_request_t *req)
|
|
* {
|
|
* char content[30];
|
|
* time_t time_val;
|
|
*
|
|
* some_api_to_fetch_time(&time_val)
|
|
* snprintf(content, sizeof(content), "{\"epoch\":%d}", time_val);
|
|
*
|
|
* return httpd_send_response(req, HTTP_RES_200
|
|
* , content, strlen(content), HTTP_CONTENT_JSON_STR);
|
|
* }
|
|
* \endcode
|
|
*
|
|
* A simple WSGI HTTP POST handler is shown below:
|
|
* Example: JSON Time Set
|
|
*
|
|
* \code
|
|
* int sys_set_time(httpd_request_t *req)
|
|
* {
|
|
* char sys_time_req[30];
|
|
* int ret;
|
|
* time_t time_val;
|
|
*
|
|
* ret = httpd_get_data_json(req, sys_time_req,
|
|
* sizeof(sys_time_req), &obj);
|
|
* if (ret < 0) {
|
|
* wmprintf("Failed to get post request data");
|
|
* return ret;
|
|
* }
|
|
* json_get_val_int(&obj, "epoch", (int *)&time_val);
|
|
*
|
|
* ret = Set the time using the value time_val func()
|
|
* if (ret == WM_SUCCESS)
|
|
* return httpd_send_response(req, HTTP_RES_200
|
|
* , HTTPD_JSON_SUCCESS, strlen(HTTPD_JSON_SUCCESS),
|
|
* HTTP_CONTENT_JSON_STR);
|
|
* else
|
|
* return httpd_send_response(req, HTTP_RES_200
|
|
* , HTTPD_JSON_ERROR, strlen(HTTPD_JSON_ERROR),
|
|
* HTTP_CONTENT_JSON_STR);
|
|
* }
|
|
* \endcode
|
|
*
|
|
* The above examples being simplest examples use the most convenient
|
|
* functions, namely httpd_send_response() and httpd_get_data_json()
|
|
* for most of their tasks. An advanced user may prefer to have more
|
|
* flexibility by using functions that provide a greater control. To
|
|
* enable this, the exact set of steps that are performed by both
|
|
* these functions is documented below.
|
|
*
|
|
* - httpd_send_response()
|
|
* -# Purge HTTP headers (valid only for GET request) : httpd_purge_headers()
|
|
* -# Send response status (200 OK/404 Not Found etc.): httpd_send()
|
|
* -# Send the default headers from \ref httpd_hdr_field_sel_t :
|
|
* httpd_send_default_headers()
|
|
* -# Send the Content-Type of the response : httpd_send_header()
|
|
* -# Send the header terminator : httpd_send_crlf()
|
|
* -# Send the chunked data : httpd_send_chunk()
|
|
* -# Send the last chunk : httpd_send_chunk() with length = 0
|
|
* .
|
|
* .
|
|
*
|
|
* - httpd_get_data_json()
|
|
* -# httpd_get_data()
|
|
* -# Parse the received headers : httpd_parse_hdr_tags()
|
|
* -# Receive the POST data : httpd_recv()
|
|
* .
|
|
* -# Initialize the JSON object : json_object_init()
|
|
* .
|
|
* .
|
|
*
|
|
* \section files Static File Handling
|
|
*
|
|
* Static files can be served from a filesystem. A WSGI handler can be
|
|
* registered at '/'. This handler can call httpd_handle_file() for dealing with
|
|
* file serving requests. If the fs contains a file called /404.html, this file
|
|
* will be returned when httpd receives a request for a URL that does not have a
|
|
* registered handler or page. The following table summarizes the Content-Types
|
|
* with which files of various file extensions are served:
|
|
*
|
|
| Extension | Content-Type |
|
|
| ----:---- | --------- |
|
|
| .html | text/html (with charset=iso8859-1) |
|
|
| .shtml | same as .html but with caching disabled |
|
|
| .css | text/css |
|
|
| .png | image/png |
|
|
| .gif | image/gif |
|
|
| .jpg | image/jpeg |
|
|
| [none] | application/octet-stream |
|
|
| [other] | text/plain |
|
|
*
|
|
* \subsection gzip_handling Compressed Files
|
|
*
|
|
* If the request for a file <em>abc.html</em> is received, the web server first
|
|
* tries to check if a compressed version of this file <em>abc.html.gz</em>
|
|
* exists. If found, this compressed version is served. The
|
|
* <em>Content-Encoding</em> field is set to \e gzip for these requests, so that
|
|
* the HTTP clients can handle it properly.
|
|
*
|
|
* \section ssi Server Side Include (SSI)
|
|
*
|
|
* Server Side Include (SSI) directives are mark-up snippets in .shtml files
|
|
* that are detected by HTTPD and replaced with some other content. Two SSI
|
|
* directives are supported: file and virtual.
|
|
*
|
|
* When the file directive is encountered, it is replaced by the contents of a
|
|
* file. For example, suppose you have the following .shtml files in your
|
|
* filesystem:
|
|
*
|
|
* index.shtml:
|
|
* \code
|
|
* Hello World
|
|
* <!--#include file=footer.html-->
|
|
* \endcode
|
|
*
|
|
* footer.html:
|
|
* \code
|
|
* <b>Copyright 2008-2013 your name here<\b>
|
|
* \endcode
|
|
*
|
|
* When index.shtml is requested, the SSI file directive will be replaced by
|
|
* the contents of footer.html, and the following will be served:
|
|
* index.shtml:
|
|
* \code
|
|
* Hello World
|
|
* <b>Copyright 2008-2013 your name here<\b>
|
|
* \endcode
|
|
*
|
|
* Much like a file SSI directive, a virtual SSI directive can also be used in
|
|
* .shtml files. They look something like this:
|
|
*
|
|
* \code
|
|
* <!--#include virtual=foo 1 2 3-->
|
|
* \endcode
|
|
*
|
|
* When a virtual SSI directive is encountered, control is passed to the SSI
|
|
* handler that is registered under the specified name ("foo" in this example).
|
|
* The foo handler would be passed the string "1 2 3" as its argument, along
|
|
* with the open socket to which the response is being sent, and an \ref
|
|
* httpd_request_t that can be queried for the request type (POST or GET) and
|
|
* any url-encoded form data (POST only). The handler is expected to send
|
|
* complete http chunks to the socket (see \ref httpd_send_chunk).
|
|
*
|
|
* When using .shtml files and SSI directives, keep the following tips and
|
|
* caveats in mind:
|
|
*
|
|
* - See \ref HTTPD_SSI_CALL, \ref httpd_register_ssi, struct \ref
|
|
* httpd_ssifunction for additional documentation and pointers.
|
|
*
|
|
* - Placing SSI directives in a file that does not have the .shtml extension
|
|
* has no effect; the file will be served as-is.
|
|
*
|
|
* - Each SSI directive should be on its own line with no other mark up. If
|
|
* there is any other markup, it will be ignored and will not be served to
|
|
* the client.
|
|
*
|
|
* - The SSI directives must start with either "<!--#include file=" or
|
|
* "<!--#include virtual=". They must not contain any extraneous spaces.
|
|
*
|
|
* - File names passed to the "file=" directive must not contain spaces.
|
|
*
|
|
* - If a virtual directive is encountered for which there is no registered
|
|
* handler, nothing will be output and the page processing will continue.
|
|
*
|
|
* \section other Other Considerations
|
|
*
|
|
* HTTPD operates in a highly memory constrained environment. Accordingly, it
|
|
* allocates a limited amount of memory for various elements such as the maximum
|
|
* URL length, maximum number of form elements, etc. Developers writing the
|
|
* handlers and web applications must consider these constraints. Details
|
|
* regarding these are discussed in the Defines section below. If necessary,
|
|
* these values can be changed and HTTPD can be rebuilt.
|
|
*
|
|
* \section httpd_call_graph HTTPD Call Graph
|
|
*
|
|
* The HTTPD library fundamentally uses the functions httpd_send() and
|
|
* httpd_recv() to send and receive data over the HTTP
|
|
* socket. Additional functionality is built on top of these functions
|
|
* in a hierarchical manner for the user's convenience. The following
|
|
* callgraph shows the layering of these calls.
|
|
*
|
|
* @cond uml_diag
|
|
*
|
|
* @startuml{httpd_wsgi.png}
|
|
* [*] --> WSGI_Handler_Function
|
|
* WSGI_Handler_Function --> httpd_send_response : GET/HEAD/POST Handler
|
|
* WSGI_Handler_Function --> httpd_get_data_json : POST Handler
|
|
* httpd_get_data_json --> httpd_get_data : Fetch the POST data
|
|
* httpd_get_data_json --> json_object_init : JSON object init
|
|
* httpd_get_data --> httpd_parse_hdr_tags : Parse the HTTP headers
|
|
* httpd_get_data --> httpd_recv : Receive the data
|
|
* httpd_parse_hdr_tags --> httpd_recv
|
|
* httpd_send_response --> httpd_purge_headers : Purge HTTP headers
|
|
* httpd_purge_headers --> httpd_recv : Receive the headers and purge them
|
|
* httpd_send_response --> httpd_send : Send response status
|
|
* httpd_send_response --> httpd_send_default_headers : Send default headers
|
|
* httpd_send_response --> httpd_send_header : Send the Content-Type header
|
|
* httpd_send_response --> httpd_send_crlf : Send header end indicator
|
|
* httpd_send_response --> httpd_send_chunk : Send chunked data
|
|
* httpd_send_response --> httpd_send_chunk : Send last chunk (len = 0)
|
|
* httpd_send_default_headers --> httpd_send
|
|
* httpd_send_header --> httpd_send
|
|
* httpd_send_crlf --> httpd_send
|
|
* httpd_send_chunk --> httpd_send_chunk_begin
|
|
* httpd_send_chunk --> httpd_send
|
|
* httpd_send_chunk --> httpd_send_crlf
|
|
* httpd_send_chunk_begin --> httpd_send
|
|
*
|
|
* @enduml
|
|
* @endcond
|
|
*
|
|
******************************************************************************/
|
|
|
|
|
|
/** @defgroup MICO_Middleware_Interface MiCO Middleware APIs
|
|
* @brief Provide MiCO Middleware Programming APIs.
|
|
* @{
|
|
*/
|
|
|
|
/** @addtogroup MICO_Middleware_Interface
|
|
* @{
|
|
*/
|
|
|
|
/** @defgroup MICO_HTTP_Web_Server MiCO HTTP Web Server
|
|
* @brief Provide MiCO HTTP Web Server APIs.
|
|
* @{
|
|
*/
|
|
|
|
|
|
#ifndef _HTTPD_H_
|
|
#define _HTTPD_H_
|
|
|
|
#include "common.h"
|
|
//#include <json.h>
|
|
|
|
/** Port on which the httpd listens for non secure connections. */
|
|
#define HTTP_PORT 80
|
|
|
|
/** Port on which the httpd listens for secure connections. */
|
|
#define HTTPS_PORT 443
|
|
|
|
/** Do not perform an exact match of the URI, but ensure that only the prefix is
|
|
* correct. This is required when the registered URI is /nodes/ while the
|
|
* handler wishes to match with /nodes/0/, /nodes/1/ etc.
|
|
*/
|
|
#define APP_HTTP_FLAGS_NO_EXACT_MATCH 1
|
|
|
|
/** This REQ_TYPE should not be used externally. */
|
|
#define HTTPD_REQ_TYPE_UNKNOWN 0
|
|
|
|
/** This request type indicates that incoming http request is of type POST. */
|
|
#define HTTPD_REQ_TYPE_POST 1
|
|
|
|
/** This request type indicates that incoming http request is of type GET.
|
|
*
|
|
* \note GET does not support URL-encoded tag/val pairs.
|
|
*/
|
|
#define HTTPD_REQ_TYPE_GET 2
|
|
|
|
/** This request type indicates that incoming http request is of type PUT. */
|
|
#define HTTPD_REQ_TYPE_PUT 4
|
|
|
|
/** This request type indicates that incoming http request is of type DELETE. */
|
|
#define HTTPD_REQ_TYPE_DELETE 8
|
|
|
|
/** This request type indicates that incoming http request is of type HEAD. */
|
|
#define HTTPD_REQ_TYPE_HEAD 16
|
|
|
|
/** HTTPD Error Codes */
|
|
enum wm_httpd_errno {
|
|
WM_E_HTTPD_ERRNO_BASE = 0,
|
|
/** Error parsing filename in HTTP Header */
|
|
WM_E_HTTPD_HDR_FNAME,
|
|
/** HTTPD doesn't support the http version */
|
|
WM_E_HTTPD_NOTSUPP,
|
|
/** Post data too long */
|
|
WM_E_HTTPD_TOOLONG,
|
|
/** Data read failed */
|
|
WM_E_HTTPD_DATA_RD,
|
|
/** SSI Table full */
|
|
WM_E_HTTPD_SSI_MAX,
|
|
/** Handler generated a HTTP 404 File Not Found error */
|
|
WM_E_HTTPD_HANDLER_404,
|
|
/** Handler generated a HTTP 400 Bad Request error */
|
|
WM_E_HTTPD_HANDLER_400,
|
|
/** Handler generated a HTTP 500 Internal Server error */
|
|
WM_E_HTTPD_HANDLER_500,
|
|
/** No handler was found */
|
|
WM_E_HTTPD_NO_HANDLER,
|
|
};
|
|
|
|
/** This value is returned when a WSGI handler is successful to indicate that
|
|
* all processing has been completed.
|
|
*/
|
|
#define HTTPD_DONE 1
|
|
|
|
/** Maximum received message length
|
|
*
|
|
* This value is essentially the longest single line that the HTTPD can
|
|
* handle. This limits programmers and users in some interesting ways. For
|
|
* example:
|
|
* -# This is the maximum length of any url-encoded data sent as the body of a
|
|
* POST request.
|
|
* If this limit is exceeded, the server will generate a 500 Internal
|
|
* Server Error response.
|
|
* Applications that require a higher capacity for form data must implement
|
|
* their own custom handler to process form data or tune this value.
|
|
* -# This is the maximum length of a header line that can be processed by
|
|
* \ref httpd_parse_hdr_tags. Header lines that exceed this
|
|
* length will be truncated before being analyzed. Applications that
|
|
* require more capacity must implement their own custom handler to process
|
|
* HTTP header data.
|
|
* -# This is the maximum length of a single line in a .shtml script.
|
|
*
|
|
* Developers must ensure that these limits are addressed to avoid unexpected
|
|
* errors in the field.
|
|
*
|
|
* \note This value does not include any NULL termination required internally
|
|
* by the httpd.
|
|
*/
|
|
#define HTTPD_MAX_MESSAGE 512
|
|
|
|
/** Maximum URI length
|
|
*
|
|
* This is the maximum supported URI length. For example, if a client sends a
|
|
* GET /foobar.html, the length of "/foobar.html" must be less than this value.
|
|
* Programmers are obliged to ensure that none of the URIs or HTTPD file names
|
|
* exceed this limit. If URIs do end up exceeding this limit, a 500 Internal
|
|
* Server Error response will be generated.
|
|
*
|
|
* \note This value does not include any NULL termination required internally
|
|
* by the HTTPD. However it does include the leading "/".
|
|
*/
|
|
#define HTTPD_MAX_URI_LENGTH 64
|
|
|
|
|
|
/** Maximum length of the value portion of a tag/value pair
|
|
*
|
|
* If this length is exceeded, the value will be truncated to this length and
|
|
* no error will be generated. If debugging is enabled, however, a warning
|
|
* will be written to the console.
|
|
*
|
|
* \note Truncating the user input passed by client may result in unexpected
|
|
* behavior depending on how a custom handler uses that data. Programmers
|
|
* should take steps to validate and/or limit user input using javascript,
|
|
* input tag properties, or other client-side means.
|
|
*
|
|
* \note This value does not include the NULL termination of the value.
|
|
*
|
|
*/
|
|
#define HTTPD_MAX_VAL_LENGTH 64
|
|
|
|
/** Maximum length of Content-Type
|
|
*
|
|
* httpd_parse_hdr_tags() will parse the headers and store the value of
|
|
* the Content-Type. The maximum value of this field has been arrived
|
|
* keeping in mind the need to support the following type of Content-Type
|
|
* header for working with multipart/form-data for file uploads:
|
|
* Content-Type: multipart/form-data; boundary=\<delimiter_max_length_70\>
|
|
* The length of this line is 104 bytes
|
|
*/
|
|
#define HTTPD_MAX_CONTENT_TYPE_LENGTH 128
|
|
|
|
#define ISO_nl 0x0a
|
|
#define ISO_cr 0x0d
|
|
#define ISO_tab 0x09
|
|
#define ISO_space 0x20
|
|
#define ISO_bang 0x21
|
|
#define ISO_quot 0x22
|
|
#define ISO_percent 0x25
|
|
#define ISO_period 0x2e
|
|
#define ISO_slash 0x2f
|
|
#define ISO_colon 0x3a
|
|
|
|
#define HTTPD_JSON_ERR_MSG "{\"error_msg\":\"%s\"}"
|
|
#define HTTPD_JSON_RETURN_MSG "{\"return_msg\":\"%s\"}"
|
|
#define HTTPD_JSON_ERROR "{\"error\": -1}"
|
|
#define HTTPD_JSON_SUCCESS "{\"success\": 0}"
|
|
#define HTTPD_TEXT_ERROR "error -1\r\n"
|
|
#define HTTPD_TEXT_SUCCESS "success\r\n"
|
|
|
|
/** Content-Type: application/json */
|
|
#define HTTP_CONTENT_JSON_STR "application/json"
|
|
/** Content-Type: text/xml */
|
|
#define HTTP_CONTENT_XML_STR "text/xml"
|
|
/** Content-Type: text/hxml */
|
|
#define HTTP_CONTENT_HTML_STR "text/html"
|
|
/** Content-Type: text/css */
|
|
#define HTTP_CONTENT_CSS_STR "text/css"
|
|
/** Content-Type: application/x-javascript */
|
|
#define HTTP_CONTENT_JS_STR "application/javascript"
|
|
/** Content-Type: image/png */
|
|
#define HTTP_CONTENT_PNG_STR "image/png"
|
|
/** Content-Type: text/plain */
|
|
#define HTTP_CONTENT_PLAIN_TEXT_STR "text/plain"
|
|
|
|
/** HTTP Response: 200 OK */
|
|
#define HTTP_RES_200 "HTTP/1.1 200 OK\r\n"
|
|
/** HTTP Response: 301 Moved Permanently */
|
|
#define HTTP_RES_301 "HTTP/1.1 301 Moved Permanently\r\n"
|
|
/** HTTP Response: 304 Not Modified */
|
|
#define HTTP_RES_304 "HTTP/1.1 304 Not Modified\r\n"
|
|
/** HTTP Response: 400 Bad Request */
|
|
#define HTTP_RES_400 "HTTP/1.1 400 Bad Request\r\n"
|
|
/** HTTP Response: 404 Not Found */
|
|
#define HTTP_RES_404 "HTTP/1.1 404 Not Found\r\n"
|
|
/** HTTP Response: 505 HTTP Version Not Supported */
|
|
#define HTTP_RES_505 "HTTP/1.1 505 HTTP Version Not Supported\r\n"
|
|
|
|
/* Are these \r\n required in here? The send chunk will append its own set of
|
|
* \r\n, thus making it two \r\n.
|
|
*/
|
|
|
|
#define HTTPD_XML_ERROR \
|
|
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?><error>%d</error>\r\n"
|
|
#define HTTPD_XML_SUCCESS \
|
|
"<?xml version=\"1.0\" encoding=\"US-ASCII\"?><success>0</success>\r\n"
|
|
|
|
/** Send carriage return and new line characters on the socket \_sock\_ */
|
|
#define httpd_send_crlf(_sock_) httpd_send(_sock_, "\r\n", 2);
|
|
|
|
/** httpd_useragent_t reports the product and version of the client accessing
|
|
* the httpd.
|
|
*/
|
|
typedef struct {
|
|
/** Product of the client */
|
|
char product[HTTPD_MAX_VAL_LENGTH + 1]; /* +1 for null termination */
|
|
/** Version of the client */
|
|
char version[HTTPD_MAX_VAL_LENGTH + 1]; /* +1 for null termination */
|
|
} httpd_useragent_t;
|
|
|
|
struct httpd_wsgi_call;
|
|
|
|
/** Request structure representing various properties of an HTTP request
|
|
*/
|
|
typedef struct {
|
|
/** HTTP Request type: GET, HEAD, POST, PUT, DELETE */
|
|
int type;
|
|
/** The incoming URI */
|
|
/* +1 is for null termination */
|
|
char filename[HTTPD_MAX_URI_LENGTH + 1];
|
|
/** The socket of the incoming HTTP Request */
|
|
int sock;
|
|
/** Indicator notifying whether the HTTP headers are parsed or not */
|
|
unsigned char hdr_parsed;
|
|
/** The number of data bytes not yet parsed */
|
|
int remaining_bytes;
|
|
/** The size of data in the incoming HTTP Request */
|
|
int body_nbytes;
|
|
/** Pointer to the corresponding wsgi structure */
|
|
const struct httpd_wsgi_call *wsgi;
|
|
/** Set to 1 if chunked data is used */
|
|
unsigned char chunked;
|
|
/** User-agent: Product and Version */
|
|
httpd_useragent_t agent;
|
|
/** The content type of the incoming HTTP Request */
|
|
char content_type[HTTPD_MAX_CONTENT_TYPE_LENGTH];
|
|
/** True if "If-None-Match" header is present in the incoming
|
|
* HTTP Request */
|
|
bool if_none_match;
|
|
/** Used for storing the etag of an URI */
|
|
unsigned etag_val;
|
|
} httpd_request_t;
|
|
|
|
/** @brief Initialize the httpd
|
|
*
|
|
* @note This function must be called before any of the other API functions. If any
|
|
* of the initialization steps fail, the function will fail.
|
|
*
|
|
* @return WM_SUCCESS if successful
|
|
* @return -WM_FAIL otherwise
|
|
*/
|
|
int httpd_init(void);
|
|
|
|
/** @brief Shutdown the httpd
|
|
*
|
|
* @note This function is the opposite of httpd_init(). It cleans up any
|
|
* resources used by the httpd. If the httpd thread is running (i.e.,
|
|
* httpd_stop has not been called), it will be halted.
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*
|
|
*/
|
|
int httpd_shutdown(void);
|
|
|
|
/** @brief Start the httpd
|
|
*
|
|
* @note Upon WM_SUCCESS, the user can expect that the server is running and
|
|
* ready to receive connections. httpd_stop() should be called to stop the
|
|
* server. A return value of -WM_FAIL generally indicates that the thread
|
|
* has already been started.
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return WM_FAIL :otherwise
|
|
*/
|
|
int httpd_start(void);
|
|
|
|
/** @brief Stop the httpd
|
|
*
|
|
* @note This function is the opposite of httpd_start(). It stops the httpd. If
|
|
* WM_SUCCESS is returned, the server has been stopped and will no longer
|
|
* accept connections. -WM_FAIL is returned if the httpd is uninitialized, or
|
|
* if an internal error occurs (which is not expected). Note that this
|
|
* function forces the httpd thread to stop and closes any open sockets. If
|
|
* a handler is being executed during this time, it will be terminated.
|
|
*
|
|
* @return WM_SUCCESS : if successful
|
|
* @return WM_FAIL : otherwise
|
|
*/
|
|
int httpd_stop(void);
|
|
|
|
/** @brief Check if httpd is running
|
|
*
|
|
* @return 0 : if httpd is not running
|
|
* @return non-zero : if it is running
|
|
*/
|
|
int httpd_is_running(void);
|
|
|
|
/** @brief Helper function to send a buffer over a connection.
|
|
*
|
|
* @note WSGI handlers will often want to send data over a connection. This can be
|
|
* achieved with the regular send() system call, however that call may not send
|
|
* all of the data. This helper function calls send in a loop repeatedly until
|
|
* all data has been sent or until an error occurs. This function internally
|
|
* calls tls_send() if TLS is enabled, else it calls send()
|
|
*
|
|
* @param[in] sock The socket on which the data is to be sent
|
|
* @param[in] buf Pointer to the buffer
|
|
* @param[in] len Length of the buffer
|
|
*
|
|
* @return WM_SUCCESS : if successful
|
|
* @return -WM_FAIL : otherwise
|
|
*
|
|
* \see httpd_send_chunk
|
|
*/
|
|
int httpd_send(int sock, const char *buf, int len);
|
|
|
|
/** @brief Helper function to send an HTTP chunk of data over a connection
|
|
*
|
|
* @note This function sends HTTP chunked data. It includes sending the chunked
|
|
* header (which consists of the chunk size in ascii followed by \\r\\n
|
|
* characters), then the actual http data and at the end chunk end indicator
|
|
* (\\r\\n characters)
|
|
* If the len is passed as 0 to this function, it sends the last chunk i.e.
|
|
* 0\\r\\n
|
|
*
|
|
* Note that while using chunked data, HTTP Header "Transfer Encoding: Chunked"
|
|
* should be sent in the response
|
|
*
|
|
* Send either an HTTP chunk of data or the terminating HTTP chunk.
|
|
*
|
|
* @param[in] sock The socket on which the data is to be sent
|
|
* @param[in] buf Pointer to the buffer or NULL for last chunk
|
|
* @param[in] len Length of the buffer or 0 for last chunk
|
|
*
|
|
* @return WM_SUCCESS : if successful
|
|
* @return -WM_FAIL : otherwise
|
|
*
|
|
*/
|
|
int httpd_send_chunk(int sock, const char *buf, int len);
|
|
|
|
/** @brief Helper function to send a HTTP chunk header
|
|
*
|
|
* @note This function is not required when \ref httpd_send_chunk is used.
|
|
* \ref httpd_send_chunk internally calls this function
|
|
*
|
|
* This function can be followed by a call to \ref httpd_send to send the
|
|
* actual content followed by sending the chunk end indicator (\\r\\n)
|
|
*
|
|
* @param[in] sock The socket over which chunk header is to be sent
|
|
* @param[in] size Length of the chunk to be sent
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return - WM_FAIL :otherwise
|
|
*
|
|
*/
|
|
int httpd_send_chunk_begin(int sock, int size);
|
|
|
|
/** Structure representing a WSGI handler
|
|
*
|
|
*/
|
|
struct httpd_wsgi_call {
|
|
/** URI of the WSGI */
|
|
const char *uri;
|
|
/** Indicator for HTTP headers to be sent in the response*/
|
|
int hdr_fields;
|
|
/** Flag indicating if exact match of the URI is required or not */
|
|
int http_flags;
|
|
/** HTTP GET or HEAD Handler */
|
|
int (*get_handler) (httpd_request_t *req);
|
|
/** HTTP POST Handler */
|
|
int (*set_handler) (httpd_request_t *req);
|
|
/** HTTP PUT Handler */
|
|
int (*put_handler) (httpd_request_t *req);
|
|
/** HTTP DELETE Handler */
|
|
int (*delete_handler) (httpd_request_t *req);
|
|
};
|
|
|
|
|
|
/** @brief Register a WSGI handler
|
|
*
|
|
* @note WSGI handlers declared must be registered with the
|
|
* httpd by calling this function.
|
|
*
|
|
* @param[in] wsgi_call pointer to a struct httpd_wsgi_call. The memory
|
|
* location pointed to by this pointer should be available until
|
|
* the httpd handler is unregistered.
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_register_wsgi_handler(struct httpd_wsgi_call *wsgi_call);
|
|
|
|
/** @brief Register a list of WSGI handlers
|
|
*
|
|
* @note WSGI handler list declared must be registered with the
|
|
* httpd by calling this function.
|
|
*
|
|
* @param[in] wsgi_call_list pointer to a list of struct httpd_wsgi_call. The
|
|
* memory location pointed to by this pointer should be available until
|
|
* the httpd handler list is unregistered.
|
|
* @param[in] handler_cnt number of WSGI handlers in wsgi_call_list
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_register_wsgi_handlers(struct httpd_wsgi_call *wsgi_call_list,
|
|
int handler_cnt);
|
|
/** @brief Unregister a WSGI handler
|
|
*
|
|
* @note This call unregisters a WSGI handler.
|
|
*
|
|
* @param[in] wsgi_call pointer to a struct httpd_wsgi_call
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_unregister_wsgi_handler(struct httpd_wsgi_call *wsgi_call);
|
|
|
|
/** @brief Unregister a list of WSGI handlers
|
|
*
|
|
* @note WSGI handler list declared can be unregistered with the
|
|
* httpd by calling this function.
|
|
*
|
|
* @param[in] wsgi_call_list list of struct httpd_wsgi_call
|
|
* @param[in] handler_cnt number of WSGI handlers in wsgi_call_list
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_unregister_wsgi_handlers(struct httpd_wsgi_call *wsgi_call_list,
|
|
int handler_cnt);
|
|
|
|
/** @brief Maximum length of virtual SSI arguments
|
|
*
|
|
* @note The supported format for virtual SSI directives is:
|
|
*
|
|
* @code
|
|
* <!--#include virtual="foo arg1 arg2 arg3"-->
|
|
* @endcode
|
|
*
|
|
* or
|
|
*
|
|
* @code
|
|
* <!--#include virtual=foo arg1 arg2 arg3-->
|
|
* @endcode
|
|
*
|
|
* HTTPD_MAX_SSI_ARGS is the maximum length for "arg1 arg2 arg3" (not
|
|
* including the quotes). If this length is exceeded, the arguments will be
|
|
* truncated.
|
|
*
|
|
* @note This does not include any null-termination required internally by the
|
|
* httpd or the virtual SSI handlers.
|
|
*
|
|
* @note whitespace between the function name (e.g., foo) and the first
|
|
* argument (e.g. arg1) is ignored and not passed to handlers.
|
|
*
|
|
* @note Double quotes are reserved and should only be used as described in
|
|
* the above examples.
|
|
*/
|
|
#define HTTPD_MAX_SSI_ARGS 32
|
|
|
|
/** @brief SSI virtual include handler function prototype
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t. Minimally,
|
|
* the type and filename members will be initialized. Handlers are not
|
|
* expected to write to this struct.
|
|
*
|
|
* @param[in] args Null-terminated string that is the arguments passed to the
|
|
* handler in the include directive.
|
|
*
|
|
* @param[in] sock Socket to which the handler output should be sent.
|
|
*
|
|
* @param[in] scratch A scratch buffer that can be used by the handler. It is
|
|
* @ref HTTPD_MAX_MESSAGE bytes long.
|
|
*
|
|
* @note SSI virtual include handlers should only send complete chunks i.e.
|
|
* they should send any data using \ref httpd_send_chunk, not \ref httpd_send
|
|
* or any lower-level system calls. These handlers should also not send the
|
|
* final chunk i.e. they should not invoke httpd_send_chunk with a length of 0.
|
|
*
|
|
*/
|
|
typedef int (*httpd_ssifunction) (const httpd_request_t *req, const char *args,
|
|
int sock, char *scratch);
|
|
|
|
|
|
/** @brief Opaque structure representing a virtual SSI handler
|
|
*
|
|
* @note Users should use the macro \ref HTTPD_SSI_CALL to initialize this struct
|
|
* statically.
|
|
*/
|
|
struct httpd_ssi_call {
|
|
/** The name of the function, used in the script file */
|
|
const char *name;
|
|
/** The pointer to the function that implements the handler */
|
|
const httpd_ssifunction function;
|
|
};
|
|
|
|
/** @brief httpd virtual SSI handler declaration
|
|
*
|
|
* @note This macro is used for declaring a virtual SSI handler struct \ref
|
|
* httpd_ssi_call. The function is then added to the list of handlers with \ref
|
|
* httpd_register_ssi, and removed with \ref httpd_unregister_ssi function.
|
|
*
|
|
* @param name Name of the \ref httpd_ssi_call structure object
|
|
*
|
|
* @param str The string name of the function, used in the script file
|
|
*
|
|
* @param function A pointer to the function that implements the handler
|
|
*
|
|
* @hideinitializer
|
|
*/
|
|
#define HTTPD_SSI_CALL(name, str, function) \
|
|
struct httpd_ssi_call name = {str, function}
|
|
|
|
/** Maximum number of virtual SSI handlers that are supported.
|
|
*/
|
|
#define MAX_REGISTERED_SSIS 32
|
|
|
|
/** @brief Register a virtual SSI handler
|
|
*
|
|
* @note virtual SSI handlers declared with \ref HTTPD_SSI_CALL must be
|
|
* registered with the httpd by calling this function.
|
|
*
|
|
* @param[in] ssi_call pointer to the httpd_ssi_call to register
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_E_HTTPD_SSI_MAX :if the maximum number of supported handlers has
|
|
* been reache
|
|
* @return -WM_FAIL :if the handler is already registered
|
|
*
|
|
* @note All SSI handlers are cleared when httpd_init is called.
|
|
*/
|
|
int httpd_register_ssi(struct httpd_ssi_call *ssi_call);
|
|
|
|
/** @brief Unregister a virtual SSI handler
|
|
*
|
|
* @param[in] ssi_call pointer to the httpd_ssi_call to unregister
|
|
*
|
|
* @note All SSI handlers are cleared when httpd_init is called.
|
|
*/
|
|
void httpd_unregister_ssi(struct httpd_ssi_call *ssi_call);
|
|
|
|
/** @brief Register and Enable httpd cli-commands
|
|
*
|
|
* @return WM_SUCCESS if successful
|
|
* @return -WM_FAIL otherwise
|
|
*
|
|
* @note This function can be called by the application
|
|
* after the httpd is initialized.
|
|
*/
|
|
|
|
/* no usage */
|
|
int httpd_cli_init(void);
|
|
|
|
/** HTTP Content types
|
|
*/
|
|
enum http_content_type {
|
|
/** Content-Type: text/plain */
|
|
HTTP_CONTENT_PLAIN_TEXT,
|
|
/** Content-Type: application/json */
|
|
HTTP_CONTENT_JSON,
|
|
/** Content-Type: text/xml */
|
|
HTTP_CONTENT_XML,
|
|
/** Content-Type: text/html */
|
|
HTTP_CONTENT_HTML,
|
|
/** Content-Type: image/jpeg */
|
|
HTTP_CONTENT_JPEG,
|
|
};
|
|
|
|
/** HTTP Headers to be sent in the HTTP response
|
|
*/
|
|
typedef enum {
|
|
/** "Server: Marvell-WM\r\n" */
|
|
HTTPD_HDR_ADD_SERVER = 0x0001,
|
|
/** "Connection: keep-alive\r\n" */
|
|
HTTPD_HDR_ADD_CONN_KEEP_ALIVE = 0x0002,
|
|
/** "Connection: close\r\n" */
|
|
HTTPD_HDR_ADD_CONN_CLOSE = 0x0004,
|
|
/** "Transfer-Encoding: chunked\r\n" */
|
|
HTTPD_HDR_ADD_TYPE_CHUNKED = 0x0008,
|
|
/** "Cache-Control: no-store, no-cache, must-revalidate\r\n" */
|
|
HTTPD_HDR_ADD_CACHE_CTRL = 0x0010,
|
|
/** "Cache-Control: post-check=0, pre-check=0\r\n" */
|
|
HTTPD_HDR_ADD_CACHE_CTRL_NO_CHK = 0x0020,
|
|
/** "Pragma: no-cache\r\n" */
|
|
HTTPD_HDR_ADD_PRAGMA_NO_CACHE = 0x0040,
|
|
} httpd_hdr_field_sel_t;
|
|
|
|
/** Default HTTP headers from \ref httpd_hdr_field_sel_t */
|
|
#define HTTPD_DEFAULT_HDR_FLAGS (HTTPD_HDR_ADD_SERVER | \
|
|
HTTPD_HDR_ADD_CONN_CLOSE | HTTPD_HDR_ADD_TYPE_CHUNKED)
|
|
|
|
/** @brief Send HTTP Status Headers
|
|
*
|
|
* @note This function sends the corresponding HTTP headers on the socket.
|
|
*
|
|
* @param[in] sock the socket to send headers on
|
|
* @param[in] stat_code the status code WM_SUCCESS, -WM_E_HTTPD_HANDLER_404 etc.
|
|
* @param[in] content_type the content type \ref http_content_type
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_hdr_from_code(int sock, int stat_code,
|
|
enum http_content_type content_type);
|
|
|
|
|
|
/** @brief Validate an incoming request with a registered handler
|
|
*
|
|
* @note This function is used to match the incoming request URI against the one that
|
|
* is registered with HTTPD
|
|
*
|
|
* @param[in] req_uri URI of the incoming HTTP request
|
|
* @param[in] uri URI of an handler registered with HTTPD
|
|
* @param[in] flags Flag indicating if exact match is required or not \ref
|
|
* APP_HTTP_FLAGS_NO_EXACT_MATCH
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_validate_uri(char *req_uri, const char *uri, int flags);
|
|
|
|
/** @brief Helper function to receive data over a socket
|
|
*
|
|
* @note This function abstracts the TCP/IP recv call. We need the abstraction
|
|
* because recv could be through TLS connection in which case we do not
|
|
* call the TCP/IP stack 'recv' function directly.
|
|
*
|
|
* This API is only for the httpd handlers who have been passed the socket
|
|
* descriptors by httpd.
|
|
*
|
|
* @param[in] sock The socket on which the data is to be received
|
|
* @param[out] buf The buffer in which data will be received
|
|
* @param[in] n Number of bytes to be received
|
|
* @param[in] flags Same values as that of flag parameter in man page of recv
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_recv(int sock, void *buf, size_t n, int flags);
|
|
|
|
/** @brief Send the entire HTTP response
|
|
*
|
|
* @note This is a helper function which can be used by the WSGI handlers
|
|
* to send the entire HTTP response.
|
|
* This function first purges the incoming headers (this step is valid only for
|
|
* HTTP GET or HEAD request.) Then it sends the first line of the response i.e.
|
|
* 200 OK, 404 Not Found etc. as specified by the user. Further, it sends the
|
|
* default HTTP headers as per the value of hdr_fields parameter of that WSGI.
|
|
* After that, it sends the Content-Type HTTP header using the content_type
|
|
* sent by the user. If the request type is HTTP HEAD, only the headers are
|
|
* sent out and this function terminates, else data provided by the user
|
|
* (chunked/non chunked data) follows.
|
|
*
|
|
* Note that this API is optional and WSGI handlers may prefer to
|
|
* send the response as per their wish using other HTTPD APIs.
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t
|
|
* @param[in] first_line First line of the response. for e.g.: To send 200 OK
|
|
* it will be: "HTTP/1.1 200 OK\r\n"
|
|
* @param[in] content The data to be sent
|
|
* @param[in] length The length of data to be sent
|
|
* @param[in] content_type The content type of the response. for e.g.:
|
|
* To send JSON response it will be: "application/json"
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_response(httpd_request_t *req, const char *first_line,
|
|
char *content, int length, const char *content_type);
|
|
|
|
/** @brief Send HTTP response 301: Moved Permanently
|
|
*
|
|
* @note This is a helper function which can be used by the WSGI handlers to send
|
|
* HTTP response HTTP 301 Moved Permanently. This function first purges the
|
|
* incoming headers (this step is valid only for HTTP GET or HEAD request.)
|
|
* Then it sends the first line of the response i.e. 301 Moved Permanently.
|
|
* Further, it sends the default HTTP headers as per the value of hdr_fields
|
|
* parameter of that WSGI. After that, it sends the HTTP header Location which
|
|
* is the new link for redirection. Then, it sends the Content-Type HTTP header
|
|
* using the content_type sent by the user. If the request type is HTTP HEAD,
|
|
* only the headers are sent out and this function terminates, else data
|
|
* provided by the user (chunked/non chunked data) follows.
|
|
*
|
|
* Note that this API is optional and WSGI handlers may prefer to
|
|
* send the response as per their wish using other HTTPD APIs.
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t
|
|
* @param[in] location The new link for redirection
|
|
* @param[in] content_type The content type of the response. for e.g.:
|
|
* To send JSON response it will be: "application/json"
|
|
* @param[in] content The data to be sent (optional)
|
|
* @param[in] content_len The length of data to be sent
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_response_301(httpd_request_t *req, char *location, const char
|
|
*content_type, char *content, int content_len);
|
|
|
|
/** @brief Send an HTTP header
|
|
*
|
|
* @note This function can be to send out an HTTP header.
|
|
*
|
|
* It accepts a name value pair as input and sends it out as: "name: value\r\n"
|
|
* for e.g.:
|
|
* To send header "Content-Type: application/json\r\n" call
|
|
* httpd_send_header(sock, "Content-Type", "application/json");
|
|
*
|
|
* @param[in] sock the socket to send header on
|
|
* @param[in] name name of the HTTP header
|
|
* @param[in] value value of the HTTP header 'name'
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_header(int sock, const char *name, const char *value);
|
|
|
|
/** @brief Send all http header
|
|
*
|
|
* @note This function can be to send out all http header.
|
|
* Only for array types
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_all_header(httpd_request_t *req, const char *first_line, int body_lenth, const char *content_type);
|
|
|
|
#define HTTPD_SEND_BODY_DATA_MAX_LEN 1024
|
|
/** Send an HTTP body
|
|
*
|
|
* This function can be to send out an HTTP body.
|
|
* Only for array types
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_body(int sock, const unsigned char *body_image, uint32_t body_size);
|
|
|
|
/** @brief Send the default HTTP Headers
|
|
*
|
|
* @note This function can be used by the WSGI handlers to send out some or all
|
|
* headers present in \ref httpd_hdr_field_sel_t. The WSGI handlers when
|
|
* declared can decide which headers they want to send out in the response and
|
|
* accordingly populate hdr_fields parameter in the httpd_wsgi_call structure
|
|
*
|
|
* @param[in] sock The socket to send headers on
|
|
* @param[in] hdr_fields The hdr_fields parameter of the matching WSGI for the
|
|
* HTTP request, selected from \ref httpd_hdr_field_sel_t
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_send_default_headers(int sock, int hdr_fields);
|
|
|
|
/** @brief Purge the headers of the incoming HTTP request
|
|
*
|
|
* @note This function is used to purge the headers of the incoming HTTPD request
|
|
*
|
|
* Note that it is mandatory to consume all the HTTP headers for the proper
|
|
* functioning of web server
|
|
*
|
|
* @param[in] sock the socket of the incoming HTTP request
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_purge_headers(int sock);
|
|
|
|
/** @brief Parse the http headers into the req httpd_request_t structure.
|
|
*
|
|
* @note This function will one by one read lines terminated by CR-LF (\\r\\n) from
|
|
* the socket and parse the headers contained in them. Some of the headers (at
|
|
* this time only the Content-Length) will be then copied to the req
|
|
* httpd_request_t structure.
|
|
*
|
|
* Note that it is mandatory to consume all the HTTP headers
|
|
*
|
|
* After executing this function, the socket will point to the request entity
|
|
* body, if any.
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t
|
|
* @param[in] sock The socket of the incoming HTTP request
|
|
* @param[in] scratch Buffer used to read the HTTP headers
|
|
* @param[in] len Length of the scratch buffer
|
|
*
|
|
* @return WM_SUCCESS :if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_parse_hdr_tags(httpd_request_t *req, int sock,
|
|
char *scratch, int len);
|
|
|
|
/** @brief Get the incoming data in case of HTTP POST request
|
|
*
|
|
* @note This function first parses the HTTP header tags and then receives the data
|
|
* in the buffer provided by the user.
|
|
*
|
|
* It can be called multiple times if the size of user buffer is less than the
|
|
* actual data that is received. Care has been taken that, in such situations,
|
|
* the HTTP headers are parsed only once. When it returns zero it indicates
|
|
* that all the data has been received.
|
|
*
|
|
* Note that this API is optional and WSGI handlers may prefer to parse the
|
|
* headers and get the data as per their wish using other HTTPD APIs.
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t
|
|
* @param[out] content The buffer in which the data is to be received
|
|
* @param[in] length The length of the content buffer
|
|
* @return The number of bytes still remaining to be read if successful
|
|
* @return -WM_FAIL :otherwise
|
|
*/
|
|
int httpd_get_data(httpd_request_t *req, char *content, int length);
|
|
|
|
/** @brief Get the incoming JSON data in case of HTTP POST request
|
|
*
|
|
* @note This function is an extension to \ref httpd_get_data. Additionally this
|
|
* function takes in a pointer to the JSON object and initializes the same. In
|
|
* this case, content is actually used as a scratch buffer. JSON object is what
|
|
* you actually need to use after it returns.
|
|
*
|
|
* Note that this function can be called only once i.e. the size of content
|
|
* buffer passed to this function should be large enough to store all the
|
|
* incoming data.
|
|
*
|
|
* @param[in] req The incoming HTTP request \ref httpd_request_t
|
|
* @param[out] content The buffer in which the data is to be received
|
|
* @param[in] length The length of the content buffer
|
|
* @param[out] obj A pointer to JSON object structure
|
|
* @return The number of bytes still remaining to be read (should be 0 if used
|
|
* appropriately) if successful
|
|
* @return -WM_FAIL : otherwise
|
|
*/
|
|
|
|
typedef struct {
|
|
/* Mandatory. Will be sent to the client */
|
|
const unsigned char *server_cert;
|
|
/* Size of server_cert */
|
|
int server_cert_size;
|
|
/*
|
|
* Server private key. Mandatory.
|
|
* For the perusal of the server
|
|
*/
|
|
const unsigned char *server_key;
|
|
/* Size of server_key */
|
|
int server_key_size;
|
|
/*
|
|
* Needed if the server wants to verify client
|
|
* certificate. Otherwise set to NULL.
|
|
*/
|
|
const unsigned char *client_cert;
|
|
/* Size of client_cert */
|
|
int client_cert_size;
|
|
} httpd_tls_certs_t;
|
|
|
|
|
|
int httpd_auth_init(char *name, char *passwd);
|
|
|
|
char *get_httpd_auth( void );
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
|
|
/**
|
|
* @}
|
|
*/
|
|
|
|
|
|
/*
|
|
* Call this function to set httpd tls certificates.
|
|
*/
|
|
//int httpd_use_tls_certificates(const httpd_tls_certs_t *httpd_tls_certs);
|
|
#endif
|
|
|
|
|
|
|