A Port of TI's Webserver for the CC3000

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers HttpDynamic.cpp Source File

HttpDynamic.cpp

00001 /*****************************************************************************
00002 *
00003 *  HttpDynamic.c
00004 *  Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
00005 *
00006 *  Redistribution and use in source and binary forms, with or without
00007 *  modification, are permitted provided that the following conditions
00008 *  are met:
00009 *
00010 *    Redistributions of source code must retain the above copyright
00011 *    notice, this list of conditions and the following disclaimer.
00012 *
00013 *    Redistributions in binary form must reproduce the above copyright
00014 *    notice, this list of conditions and the following disclaimer in the
00015 *    documentation and/or other materials provided with the   
00016 *    distribution.
00017 *
00018 *    Neither the name of Texas Instruments Incorporated nor the names of
00019 *    its contributors may be used to endorse or promote products derived
00020 *    from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00025 *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
00026 *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
00027 *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00028 *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
00029 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00030 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00031 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00032 *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033 *
00034 *****************************************************************************/
00035 #include "HttpDynamic.h"
00036 #include "HttpDynamicHandler.h"
00037 #include "HttpRequest.h"
00038 #include "HttpResponse.h"
00039 #include "HttpCore.h"
00040 #include "string.h"
00041 
00042 #ifdef HTTP_CORE_ENABLE_DYNAMIC
00043 
00044 /** 
00045  * @defgroup HttpDynamic Dynamic request handler module
00046  * This module implements dynamic content processing for HTTP requests.
00047  * All requests are handled by C code functions, and the response contents is returned via HttpResopnse routines
00048  * Note this module is only compiled if HTTP_CORE_ENABLE_DYNAMIC is defined in HttpConfig.h
00049  *
00050  * @{
00051  */
00052 
00053 char dynamicResourceName[HTTP_DYNAMIC_NUM_OF_RESOURCES][HTTP_DYNAMIC_MAX_RESOURCE_LEN] = {{"led"},
00054                                              {"wheel"},
00055                                              };
00056                                             
00057 
00058 char dynamicLedParam1[5] = {"num="};
00059 char dynamicLedParam2[8] = {"action="};
00060 
00061 /* text/html is currently the blob for content type */
00062 uint8 uDynamicContentType[10] =  "text/html";
00063 
00064 uint8 uDynamicContentBody[HTTP_DYNAMIC_NUM_OF_RESOURCES][HTTP_DYNAMIC_CONTENT_BODY_LEN];
00065 
00066 PerConnDynamicContent dynamicContent[HTTP_CORE_MAX_CONNECTIONS];
00067 
00068 
00069 /**
00070  * Initialize HttpDynamic module state for a new request, and identify the request
00071  * This function must examine the specified resource string and determine whether it can commit to process this request
00072  * 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)
00073  * then it is the responsibility of this function to parse this information and store it in a connection-specific struct.
00074  * If this function returns nonzero, then the core will call HttpDynamic_ProcessRequest() with the rest of the request details.
00075  * @param uConnection The number of the connection. This value is guaranteed to satisfy: 0 <= uConnection < HTTP_CORE_MAX_CONNECTIONS
00076  * @param resource The resource part of the URL, as specified by the browser in the request, including any query string (and hash)
00077  *                 Note: The resource string exists ONLY during the call to this function. The string pointer should not be copied by this function.
00078  * @return nonzero if request is to be handled by this module. zero if not.
00079  */
00080 int HttpDynamic_InitRequest(uint16 uConnection, struct HttpBlob resource)
00081 {
00082 /*  Resource parsing follows the below assumptions:
00083     1. resource name is expected prior to query sign (just like a static page)
00084     2. query sign is expected. If not present, 0 is returned
00085     3. parameter name followed by a '=' sign is searched for. If not fully present, 0 is returned.
00086     4. parameters may arrive unordered  */
00087     
00088     uint16  uLoopCounter;
00089     uint8   *cStr;
00090     struct HttpBlob subBlob;
00091 
00092     /* look for known resource names according to dynamicResourceName[][]*/
00093     for (uLoopCounter = 0; uLoopCounter < HTTP_DYNAMIC_NUM_OF_RESOURCES; uLoopCounter++)
00094     {
00095         if (HttpString_nextToken(dynamicResourceName[uLoopCounter],  strlen(dynamicResourceName[uLoopCounter]), resource) != NULL)
00096             break;
00097     }
00098 
00099     /* dynamic resource not found */
00100     if (uLoopCounter == HTTP_DYNAMIC_NUM_OF_RESOURCES)
00101         return 0;
00102 
00103     /* if got here, resource name is found on uLoopCounter index */
00104     /* find "query" sign */
00105     if (NULL == HttpString_nextToken("?", 1, resource))
00106         return 0;
00107 
00108     /* find "=" signs preceded by the parameter name */
00109     switch ((enum HttpDynamicNumOfResources)uLoopCounter)
00110     {
00111         case LED:
00112         {
00113             /* search the LED number */
00114             if ((cStr = HttpString_nextToken(dynamicLedParam1, HTTP_DYNAMIC_LED_NUM_LEN, resource)) != NULL)
00115             {
00116                 dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedNumber = (enum HttpDynamicLedNumber)(*(cStr + HTTP_DYNAMIC_LED_NUM_LEN) - '0');
00117             }
00118             else
00119             {
00120                 return 0;
00121             }
00122 
00123             /* search the LED action */
00124             if ((cStr   = HttpString_nextToken(dynamicLedParam2, HTTP_DYNAMIC_LED_ACTION_LEN, resource)) != NULL)
00125             {
00126                 /* try to match LED action to the expected value exactly! */
00127                 subBlob.pData = cStr + HTTP_DYNAMIC_LED_ACTION_LEN;
00128                 subBlob.uLength = 6;
00129                 if (HttpString_nextToken("toggle", 6, subBlob) != NULL)
00130                     dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = toggle;
00131                 else
00132                 {
00133                                     subBlob.uLength = 2;
00134                                     if (HttpString_nextToken("on", 2, subBlob) != NULL)
00135                         dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = ON;
00136                                     else
00137                                     {
00138                         subBlob.uLength = 3;
00139                         if (HttpString_nextToken("off", 3, subBlob) != NULL)
00140                             dynamicContent[uConnection].dynamicHandlerInParam.uLedParam.uLedAction = OFF;
00141                         else
00142                             return 0;
00143                                     }
00144                                 }
00145             }
00146             else
00147             {
00148                 return 0;
00149             }
00150                 
00151             dynamicContent[uConnection].pDynamicHandler = HttpDynamicHandler_ActOnLED;
00152             dynamicContent[uConnection].resourceType = LED;
00153             break;
00154         }
00155                 
00156         case WHEEL:
00157         {
00158                   if ((cStr = HttpString_nextToken(dynamicLedParam2, HTTP_DYNAMIC_LED_ACTION_LEN, resource)) != NULL)
00159                   {
00160                     subBlob.pData = cStr + HTTP_DYNAMIC_LED_ACTION_LEN;
00161                     subBlob.uLength = 9;
00162                     if (HttpString_nextToken("getstatus", 9 , subBlob) == NULL)
00163                     {
00164                       return 0;
00165                     }
00166                   }
00167                   else
00168                       return 0;
00169                   
00170                   dynamicContent[uConnection].pDynamicHandler = HttpDynamicHandler_GetWheelValue;
00171                   dynamicContent[uConnection].resourceType = WHEEL;
00172                   break;
00173             }
00174         }
00175 
00176     return 1;
00177 }
00178 
00179 /**
00180  * Process a dynamic-content HTTP request
00181  * This function is only be called by the core, if HttpDynamic_InitRequest() returns nonzero.
00182  * This function processes the specified HTTP request, and send the response on the connection specified by request->uConnection.
00183  * This function must call the HttpResponse_*() functions in order to send data back to the browser.
00184  * Please refer to HttpResponse.h for more information.
00185  * @param request Pointer to all data available about the request
00186  */
00187 void HttpDynamic_ProcessRequest(struct HttpRequest* request)
00188 {
00189     struct HttpBlob contentType, nullBlob = {0, NULL};
00190     struct HttpBlob contentBody;
00191     int count;
00192 
00193     
00194     /* if HTTP_REQUEST_FLAG_AUTHENTICATED is not set and FLASHDB_FLAG_REQUIRE_AUTH is set then 
00195                 call HttpResponse_CannedError() with status HTTP_STATUS_ERROR_UNAUTHORIZED  */
00196     if (((request->uFlags & HTTP_REQUEST_FLAG_AUTHENTICATED) == 0))
00197     {
00198         /* call HttpResponse_CannedError with 500 ERROR_INTERNAL  */
00199         HttpResponse_CannedError(request->uConnection, HTTP_STATUS_ERROR_UNAUTHORIZED);
00200         return;
00201     }
00202 
00203     /* intialize the content body */
00204     contentBody.pData =uDynamicContentBody[request->uConnection];
00205         contentBody.uLength = 0;
00206 
00207     contentType.pData = uDynamicContentType;
00208     contentType.uLength = 9;
00209 
00210     /* 1. call the dynamic handler as parsed in the init phase */
00211     dynamicContent[request->uConnection].pDynamicHandler(dynamicContent[request->uConnection].dynamicHandlerInParam, &dynamicContent[request->uConnection].dynamicHandlerOutParam);
00212     /* config the ContentLength according to the resource type */
00213     switch (dynamicContent[request->uConnection].resourceType)
00214     {
00215         case LED:
00216         {
00217                           contentBody.pData = (uint8*)"Done";
00218                           contentBody.uLength = 4;
00219                      
00220                           
00221             break;
00222         }
00223         case WHEEL:
00224         {
00225                         char tempdata[6];
00226                         struct HttpBlob tempContent;
00227                         tempContent.pData = (uint8 *)tempdata;
00228                         HttpString_utoa((uint32)dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uWheelPosition, &contentBody);
00229                         *(contentBody.pData + contentBody.uLength) = ':';
00230                         contentBody.uLength +=1;
00231                         HttpString_utoa((uint32)dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uWheelValue, &tempContent);
00232                         for(count=0; count<tempContent.uLength; count++)
00233                         {
00234                           *(contentBody.pData + (count+contentBody.uLength)) = *tempContent.pData;
00235                           tempContent.pData++;
00236                         }
00237                         contentBody.uLength += tempContent.uLength;
00238                         *(contentBody.pData + contentBody.uLength) = ':';
00239                         *(contentBody.pData + contentBody.uLength + 1) = dynamicContent[request->uConnection].dynamicHandlerOutParam.sWheelParam.uLedDummyOut;
00240                         contentBody.uLength += 2;
00241             break;
00242         }
00243     }
00244                 
00245     /* 2. fill the header response (HTTP_RESPONSE_FLAG_COMPRESSED is not set for dynamic) */
00246     HttpResponse_Headers(request->uConnection, HTTP_STATUS_OK, 0, contentBody.uLength, contentType, nullBlob);
00247 
00248     /* 3. fill the content response (if exists) */
00249     if (contentBody.uLength != 0)
00250     {
00251         HttpResponse_Content(request->uConnection, contentBody);
00252     }
00253 
00254 }
00255 
00256 
00257 /// @}
00258 
00259 #endif // HTTP_CORE_ENABLE_DYNAMIC
00260