David Fletcher
/
CC3000WebServer
A Port of TI's Webserver for the CC3000
Diff: WebServer/HttpDynamic.cpp
- Revision:
- 0:6ad60d78b315
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebServer/HttpDynamic.cpp Sat Sep 14 17:38:41 2013 +0000 @@ -0,0 +1,260 @@ +/***************************************************************************** +* +* HttpDynamic.c +* Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions +* are met: +* +* Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the +* distribution. +* +* Neither the name of Texas Instruments Incorporated nor the names of +* its contributors may be used to endorse or promote products derived +* from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* +*****************************************************************************/ +#include "HttpDynamic.h" +#include "HttpDynamicHandler.h" +#include "HttpRequest.h" +#include "HttpResponse.h" +#include "HttpCore.h" +#include "string.h" + +#ifdef HTTP_CORE_ENABLE_DYNAMIC + +/** + * @defgroup HttpDynamic Dynamic request handler module + * This module implements dynamic content processing for HTTP requests. + * All requests are handled by C code functions, and the response contents is returned via HttpResopnse routines + * Note this module is only compiled if HTTP_CORE_ENABLE_DYNAMIC is defined in HttpConfig.h + * + * @{ + */ + +char dynamicResourceName[HTTP_DYNAMIC_NUM_OF_RESOURCES][HTTP_DYNAMIC_MAX_RESOURCE_LEN] = {{"led"}, + {"wheel"}, + }; + + +char dynamicLedParam1[5] = {"num="}; +char dynamicLedParam2[8] = {"action="}; + +/* text/html is currently the blob for content type */ +uint8 uDynamicContentType[10] = "text/html"; + +uint8 uDynamicContentBody[HTTP_DYNAMIC_NUM_OF_RESOURCES][HTTP_DYNAMIC_CONTENT_BODY_LEN]; + +PerConnDynamicContent dynamicContent[HTTP_CORE_MAX_CONNECTIONS]; + + +/** + * Initialize HttpDynamic module state for a new request, and identify the request + * This function must examine the specified resource string and determine whether it can commit to process this request + * Also, if the resource string includes any information that this module needs in order to process the request (such as the contents of the query string) + * then it is the responsibility of this function to parse this information and store it in a connection-specific struct. + * If this function returns nonzero, then the core will call HttpDynamic_ProcessRequest() with the rest of the request details. + * @param uConnection The number of the connection. This value is guaranteed to satisfy: 0 <= uConnection < HTTP_CORE_MAX_CONNECTIONS + * @param resource The resource part of the URL, as specified by the browser in the request, including any query string (and hash) + * Note: The resource string exists ONLY during the call to this function. The string pointer should not be copied by this function. + * @return nonzero if request is to be handled by this module. zero if not. + */ +int HttpDynamic_InitRequest(uint16 uConnection, struct HttpBlob resource) +{ +/* Resource parsing follows the below assumptions: + 1. resource name is expected prior to query sign (just like a static page) + 2. query sign is expected. If not present, 0 is returned + 3. parameter name followed by a '=' sign is searched for. If not fully present, 0 is returned. + 4. parameters may arrive unordered */ + + uint16 uLoopCounter; + uint8 *cStr; + struct HttpBlob subBlob; + + /* look for known resource names according to dynamicResourceName[][]*/ + for (uLoopCounter = 0; uLoopCounter < HTTP_DYNAMIC_NUM_OF_RESOURCES; uLoopCounter++) + { + if (HttpString_nextToken(dynamicResourceName[uLoopCounter], strlen(dynamicResourceName[uLoopCounter]), resource) != NULL) + break; + } + + /* dynamic resource not found */ + if (uLoopCounter == HTTP_DYNAMIC_NUM_OF_RESOURCES) + return 0; + + /* if got here, resource name is found on uLoopCounter index */ + /* find "query" sign */ + if (NULL == HttpString_nextToken("?", 1, resource)) + return 0; + + /* find "=" signs preceded by the parameter name */ + switch ((enum HttpDynamicNumOfResources)uLoopCounter) + { + case LED: + { + /* search the LED number */ + if ((cStr = HttpString_nextToken(dynamicLedParam1, HTTP_DYNAMIC_LED_NUM_LEN, resource)) != NULL) + { + dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedNumber = (enum HttpDynamicLedNumber)(*(cStr + HTTP_DYNAMIC_LED_NUM_LEN) - '0'); + } + else + { + return 0; + } + + /* search the LED action */ + if ((cStr = HttpString_nextToken(dynamicLedParam2, HTTP_DYNAMIC_LED_ACTION_LEN, resource)) != NULL) + { + /* try to match LED action to the expected value exactly! */ + subBlob.pData = cStr + HTTP_DYNAMIC_LED_ACTION_LEN; + subBlob.uLength = 6; + if (HttpString_nextToken("toggle", 6, subBlob) != NULL) + dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = toggle; + else + { + subBlob.uLength = 2; + if (HttpString_nextToken("on", 2, subBlob) != NULL) + dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = ON; + else + { + subBlob.uLength = 3; + if (HttpString_nextToken("off", 3, subBlob) != NULL) + dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = OFF; + else + return 0; + } + } + } + else + { + return 0; + } + + dynamicContent[uConnection].pDynamicHandler = HttpDynamicHandler_ActOnLED; + dynamicContent[uConnection].resourceType = LED; + break; + } + + case WHEEL: + { + if ((cStr = HttpString_nextToken(dynamicLedParam2, HTTP_DYNAMIC_LED_ACTION_LEN, resource)) != NULL) + { + subBlob.pData = cStr + HTTP_DYNAMIC_LED_ACTION_LEN; + subBlob.uLength = 9; + if (HttpString_nextToken("getstatus", 9 , subBlob) == NULL) + { + return 0; + } + } + else + return 0; + + dynamicContent[uConnection].pDynamicHandler = HttpDynamicHandler_GetWheelValue; + dynamicContent[uConnection].resourceType = WHEEL; + break; + } + } + + return 1; +} + +/** + * Process a dynamic-content HTTP request + * This function is only be called by the core, if HttpDynamic_InitRequest() returns nonzero. + * This function processes the specified HTTP request, and send the response on the connection specified by request->uConnection. + * This function must call the HttpResponse_*() functions in order to send data back to the browser. + * Please refer to HttpResponse.h for more information. + * @param request Pointer to all data available about the request + */ +void HttpDynamic_ProcessRequest(struct HttpRequest* request) +{ + struct HttpBlob contentType, nullBlob = {0, NULL}; + struct HttpBlob contentBody; + int count; + + + /* if HTTP_REQUEST_FLAG_AUTHENTICATED is not set and FLASHDB_FLAG_REQUIRE_AUTH is set then + call HttpResponse_CannedError() with status HTTP_STATUS_ERROR_UNAUTHORIZED */ + if (((request->uFlags & HTTP_REQUEST_FLAG_AUTHENTICATED) == 0)) + { + /* call HttpResponse_CannedError with 500 ERROR_INTERNAL */ + HttpResponse_CannedError(request->uConnection, HTTP_STATUS_ERROR_UNAUTHORIZED); + return; + } + + /* intialize the content body */ + contentBody.pData =uDynamicContentBody[request->uConnection]; + contentBody.uLength = 0; + + contentType.pData = uDynamicContentType; + contentType.uLength = 9; + + /* 1. call the dynamic handler as parsed in the init phase */ + dynamicContent[request->uConnection].pDynamicHandler(dynamicContent[request->uConnection].dynamicHandlerInParam, &dynamicContent[request->uConnection].dynamicHandlerOutParam); + /* config the ContentLength according to the resource type */ + switch (dynamicContent[request->uConnection].resourceType) + { + case LED: + { + contentBody.pData = (uint8*)"Done"; + contentBody.uLength = 4; + + + break; + } + case WHEEL: + { + char tempdata[6]; + struct HttpBlob tempContent; + tempContent.pData = (uint8 *)tempdata; + HttpString_utoa((uint32)dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uWheelPosition, &contentBody); + *(contentBody.pData + contentBody.uLength) = ':'; + contentBody.uLength +=1; + HttpString_utoa((uint32)dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uWheelValue, &tempContent); + for(count=0; count<tempContent.uLength; count++) + { + *(contentBody.pData + (count+contentBody.uLength)) = *tempContent.pData; + tempContent.pData++; + } + contentBody.uLength += tempContent.uLength; + *(contentBody.pData + contentBody.uLength) = ':'; + *(contentBody.pData + contentBody.uLength + 1) = dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uLedDummyOut; + contentBody.uLength += 2; + break; + } + } + + /* 2. fill the header response (HTTP_RESPONSE_FLAG_COMPRESSED is not set for dynamic) */ + HttpResponse_Headers(request->uConnection, HTTP_STATUS_OK, 0, contentBody.uLength, contentType, nullBlob); + + /* 3. fill the content response (if exists) */ + if (contentBody.uLength != 0) + { + HttpResponse_Content(request->uConnection, contentBody); + } + +} + + +/// @} + +#endif // HTTP_CORE_ENABLE_DYNAMIC +