David Fletcher
/
CC3000WebServer
A Port of TI's Webserver for the CC3000
WebServer/HttpDynamic.cpp
- Committer:
- dflet
- Date:
- 2013-09-14
- Revision:
- 0:6ad60d78b315
File content as of revision 0:6ad60d78b315:
/***************************************************************************** * * 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