Dependencies: FatFileSystem mbed WeatherMeters SDFileSystem
Diff: HTTPServer.h
- Revision:
- 0:1a61c61d0845
diff -r 000000000000 -r 1a61c61d0845 HTTPServer.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/HTTPServer.h Tue Apr 03 18:43:13 2012 +0000 @@ -0,0 +1,363 @@ +/* Copyright 2011 Adam Green (http://mbed.org/users/AdamGreen/) + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* Header file for HTTP Server functionality. */ +#ifndef HTTPSERVER_H_ +#define HTTPSERVER_H_ + +#include <mbed.h> +#include "lwip/tcp.h" + + + +// UNDONE: Make protected member of CHTTPServer object? +/** Structure used to buffer data being read in from content files and then + written out the TCP/IP connections. +*/ +struct SBuffer +{ + char* pWrite; /**< Pointer into Data where the next tcp_write() should begin. There are BytesToWrite valid bytes left in the Data array to be sent. */ + // UNDONE: These can be shorts since mbed only has a total of 64k anyway. + unsigned int BytesToWrite; /**< Number of bytes in buffer left to be written to outbound connection. */ + unsigned int UnacknowledgedBytes; /**< Number of bytes outstanding on network waiting for acknowledgment. */ + char Data[TCP_SND_BUF]; /**< The actual buffer holding data to be sent to remote client. */ +}; + + + + + +// ***************** +// * C++ Interface * +// ***************** +/** Interface to be returned from an application to provide callbacks for a + specific HTTP request. +*/ +class IHTTPRequestHandlerContext +{ +public: + /** Called by the CHTTPServer object before any WriteRequestHeader() calls + to let the application to know to expect subsequent + WriteRequestHeader() calls. + + @returns 0 if the application isn't interested in receiving subsequent + WriteRequestHeader() and EndRequestHeaders() callbacks. + Returns non-zero value to receive headers. + */ + virtual int BeginRequestHeaders() = 0; + + /** Called by CHTTPServer for each HTTP request header sent by the HTTP + client. The server won't issue this callback if 0 was previously + returned by the application from the BeginRequestHeaders() method. + + @param pHeaderName is the name of this header field. If this string + is empty then this header line is a continuation of the previous + header line which did have a field name. The string + pointed to by this parameter has a short lifetime and is only + valid during the duration of this call. + @param pHeaderValue is the string value of this header field. The + string pointed to by this parameter has a short lifetime and is + only valid during the duration of this call. + */ + virtual void WriteRequestHeader(const char* pHeaderName, + const char* pHeaderValue) = 0; + + /** Called by the CHTTPServer object after it has completed all of the + necessary WriteRequestHeader() calls to enumerate the headers of the + HTTP client's request. + */ + virtual void EndRequestHeaders() = 0; + + + /** Called by CHTTPServer to let the application know that it should expect + subsequent WriteRequestContentBlock() calls for processing of the + request content as it arrives on the TCP/IP socket. + + Only POST requests from a client should include such content data. + + @param ContentSize is the size of the request content to be sent from + the HTTP client. This value indicates the total number of bytes + that should result from all of the WriteRequestContentBlock() + calls to follow. + + @returns 0 if the application isn't interested in receiving subsequent + WriteRequestContentBlock() and EndRequestContent() callbacks. + Returns non-zero value to receive request content data. + */ + virtual int BeginRequestContent(size_t ContentSize) = 0; + + /** Called for each block of request data received from the HTTP client. + The server won't issue this callback if the application returned 0 from + the BeginRequestContent() method. + + @param pBlockBuffer is a pointer to the block of request content data + most recently received from the HTTP client. + @param BlockBufferSize is the number of bytes contained in + pBlockBuffer. + */ + virtual void WriteRequestContentBlock(const void* pBlockBuffer, + size_t BlockBufferSize) = 0; + + /** Called by CHTTPServer after it has completed all of the + WriteRequestContentBlock() calls for processing of the request content + data sent from the HTTP client. + */ + virtual void EndRequestContent() = 0; + + + /** Called by CHTTPServer object to get the status line from the + application to be returned to the HTTP client for this request. + Examples: "HTTP/1.0 200 OK\r\n" -or- "HTTP/1.0 404 File no found\r\n" + + @param pStatusLineLength points to the length to be filled in by the + application indicating the length, in character, of the returned + status line. It should not include the NULL terminator. It + must have a non-zero value. + + @returns a pointer to the status line to be returned to the HTTP client + for this request. It should start with the "HTTP/1.0" string + and end with a newline designator of "\r\n". The return value + can't be NULL. + */ + virtual const char* GetStatusLine(size_t* pStatusLineLength) = 0; + + /** Called by the CHTTPServer object to get all of the response headers + that the application would like to be returned to the HTTP client. The + CHTTPServer will append this header string to the + "Server: ServerName\r\n" header that it always sends. + + Example: "Content-Length: 100\r\n" + + @param pResponseHeaderLength points to the length to be filled in by + the application indicating the length, in character, of the + returned header string. It should not include the NULL + terminator and can be 0 if the returned value is NULL. + + @returns a pointer to the extra headers to be returned to the HTTP + client for this request. It can be NULL if the application + has no special headers to be returned. + */ + virtual const char* GetResponseHeaders(size_t* pResponseHeaderLength) = 0; + + /** Called by CHTTPServer to let application know that there will be + subsequent ReadResponseContentBlock() calls to obtain the content data + from the application to be sent back to the HTTP client in the + response. + + @returns 0 if the application has no content to be sent back in the + HTTP response. + */ + virtual int BeginResponseContent() = 0; + + /** Called by CHTTPServer to get the next block of response data to be + sent back to the HTTP client. + + @param pBuffer is a pointer to the buffer to be filled in by the + application with data to be sent back to the HTTP client in the + response. + @param BytesToRead indicates the number of bytes that should be placed + into pBuffer by the application. The application should only + place fewer than this requested amount on the last block of + data to be sent back to the HTTP client. + + @returns The number of bytes that were actually placed in pBuffer for + this call. It can only be smaller than BytesToRead on the + last block to be sent since the server uses such truncated + reads to know when it has sent the last block of response + data. + */ + virtual size_t ReadResponseContentBlock(char* pBuffer, + size_t BytesToRead) = 0; + + + /** Called by CHTTPServer to let the application know that it has finished + sending all of the response data to the HTTP client. The application + can use such a call to close any files that it has open for satsifying + this request. + */ + virtual void EndResponseContent() = 0; + + /** Called by the CHTTPServer object when it is completely done processing + this HTTP response request so that the application can free up any + resources it has associated with this HTTP client request, including the + IHTTPRequestHandlerContext derived object servicing these callbacks. + */ + virtual void Release() = 0; +}; + + +/** The application can provide an IRequestHandler interface implementation to + * the HTTP server object. The methods on such attached interface objects will + * be called by the server before it attempts default handling of HTTP + * requests. This gives the application an opportunity to provide overrides + * for handling POST requests or GET requests in a certain part of the URI + * namespace. + */ +class IHTTPRequestHandler +{ +public: + /** Called by the server for each GET request. If the application would + like to handle the GET request rather than using the default server + code then the application should return a valid + IHTTPRequestHandlerContext object pointer on which the server will call + methods. These method calls will inform the application of which + headers were sent in the request and then obtain the response data to + be sent back to the HTTP client. Returning a NULL pointer indicates + that the server should search in its pRootPathname directory for the + requested file. + + @param pURI is a pointer to the URI being requested by the HTTP + client. This is a short lived object that will only be + valid during this call. + + @returns NULL if the CHTTPServer object should process the GET + request on its own. Otherwise return an + IHTTPRequestHandlerContext object pointer so that the + application can be notified of additional request + information and provide the response data. + */ + virtual IHTTPRequestHandlerContext* HandleGetRequest(const char* pURI) = 0; + + /** Called by the server for each HEAD request. If the application would + like to handle the HEAD request rather than using the default server + code then the application should return a valid + IHTTPRequestHandlerContext object pointer on which the server will call + methods. These method calls will inform the application of which + headers were sent in the request and then obtain the response data to + be sent back to the HTTP client. Returning a NULL pointer indicates + that the server should search in its pRootPathname directory for the + requested file. + + @param pURI is a pointer to the URI being requested by the HTTP + client. This is a short lived object that will only be + valid during this call. + + @returns NULL if the CHTTPServer object should process the HEAD + request on its own. Otherwise return an + IHTTPRequestHandlerContext object pointer so that the + application can be notified of additional request + information. + */ + virtual IHTTPRequestHandlerContext* HandleHeadRequest(const char* pURI) = 0; + + /** Called by the server for each POST request. If the application would + like to handle the POST request then it should return a valid + IHTTPRequestHandlerContext object pointer on which the server will call + methods. These method calls will inform the application of which + headers were sent in the request and then obtain the response data to + be sent back to the HTTP client. Returning a NULL pointer indicates + that the server should fail this POST request with a not implemented + error. + + @param pURI is a pointer to the URI being requested by the HTTP + client. This is a short lived object that will only be + valid during this call. + + @returns NULL if the CHTTPServer object should fail the POST + request. Otherwise return an IHTTPRequestHandlerContext + object pointer so that the application can be notified of + additional request information and provide the response data. + */ + virtual IHTTPRequestHandlerContext* HandlePostRequest(const char* pURI) = 0; + + /** Called by the server for each unrecognized request. If the application + would to handle such request then it should return a valid + IHTTPRequestHandlerContext object pointer on which the server will call + methods. These method calls will inform the application of which + headers were sent in the request and then obtain the response data to + be sent back to the HTTP client. Returning a NULL pointer indicates + that the server should fail this bad request with an appropriate error. + + @param pRequest is a pointer to the request being made by the HTTP + client. This is a short lived object that will only be + valid during this call. + + @returns NULL if the CHTTPServer object should fail this + request. Otherwise return an IHTTPRequestHandlerContext + object pointer so that the application can be notified of + additional request information and provide the response data. + */ + virtual IHTTPRequestHandlerContext* HandleBadRequest(const char* pRequest) = 0; +}; + + +// Forward declaration of class used to hold context for each HTTP client +// connection. +class CHTTPContext; + + +/** HTTP server class. +*/ +class CHTTPServer +{ +public: + /** Constructor */ + CHTTPServer(); + + /** Attach IRequestHandler to the HTTP server to allow application to add + custom GET/HEAD/POST handling. + + @param pHandler is a pointer to the application specific request handler object + to be used by the HTTP server when it receives GET/POST requests. + + @returns 0 on successful attachment and a positive value otherwise. + */ + int AttachRequestHandler(IHTTPRequestHandler* pHandler); + + /** Initializes the HTTP server object by binding it to to the specified + port number. + + @param pRootPathame is the pathname of the default root directory from which the + HTTP GET requests are satisfied. + @param pServerName is the name of the server to be returned to the HTTP client + in the Server header. + @param BindPort is the TCP/IP port to which the HTTP server should listen for + incoming requests. The default port for HTTP would be 80. + + @returns 0 on success and a positive value otherwise. + */ + int Bind(const char* pRootPathname, + const char* pServerName = "lwIP_HTTPServer/1.0", + unsigned short BindPort = 80); + +protected: + // Static Method Prototypes for lwIP Callbacks. + static err_t HTTPAccept(void* pvArg, tcp_pcb* pNewPCB, err_t err); + + // Methods called from CHTTPContext. + friend class CHTTPContext; + void FreeBuffer(SBuffer* pBuffer); + void RemoveWaitingContext(CHTTPContext* pHTTPContext); + SBuffer* AllocateBuffer(CHTTPContext* pHTTPContext); + + // Listening port for HTTP Server. + tcp_pcb* m_pHTTPListenPCB; + // Head and tail pointers for queue of client contexts that are waiting to + // be allocated a SBuffer from the BufferPool. + CHTTPContext* m_pContextWaitingHead; + CHTTPContext* m_pContextWaitingTail; + // The default root directory from which the HTTP GET requests are satisfied. + const char* m_pRootPathname; + // Pointer to interface from application allowing it to handle HTTP requests. + IHTTPRequestHandler* m_pRequestHandler; + // Server header returned to HTTP clients. + size_t m_ServerHeaderLength; + char m_ServerHeader[64]; + // Pool of buffers to use for transitioning data from the filesystem to + // the network. + SBuffer m_BufferPool[HTTP_BUFFER_POOL]; +}; + + +#endif /* HTTPSERVER_H_ */