A Port of TI's Webserver for the CC3000

Dependencies:   mbed

WebServer/FlashDB.cpp

Committer:
dflet
Date:
2013-09-16
Revision:
2:e6a185df9e4c
Parent:
0:6ad60d78b315

File content as of revision 2:e6a185df9e4c:

/*****************************************************************************
*
*  FlashDB.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 "mbed.h"
#include "Common.h"
#include "FlashDB.h"
#include "HttpString.h"
#include "string.h"


/// This database flag indicates that all resource strings are to be matched with a case-sensitive string comparison function
#define FLASH_DB_FLAG_CASE_SENSITIVE (1 << 0)

/**
 * The header structure of the flash database
 */
//#ifdef __CCS__
struct __attribute__ ((__packed__)) FlashDBHeader
//#elif __IAR_SYSTEMS_ICC__
//#pragma pack(1)
//struct FlashDBHeader
//#endif
{
    /// Amount of content type entries
    uint16 uContentTypeAmount;
    /// Offset of content-type entry list
    uint16 uContentTypeOffset;
    /// Amount of content entries
    uint16 uContentAmount;
    /// Offset of content entry list
    uint16 uContentOffset;
    /// Database flags. See FLASH_DB_FLAG_*
    uint16 uFlags;
};

/**
 * The header structure for a content entity in the database
 */
//#ifdef __CCS__
struct __attribute__ ((__packed__)) FlashDBContentTypeEntry
//#elif __IAR_SYSTEMS_ICC__
//#pragma pack(1)
//struct FlashDBContentTypeEntry
//#endif
{
    /// Length of the value string. Should be 255 characters at most.
    uint16 uValueLength;
    /// Offset of the value string
    uint16 uValueOffset;
};

extern const char FlashDBContentData[];

/**
 * The header structure for a content entity in the database
 */
//#ifdef __CCS__
struct __attribute__ ((__packed__)) FlashDBContentEntry
//#elif __IAR_SYSTEMS_ICC__
//#pragma pack(1)
//struct FlashDBContentEntry
//#endif
{
    /// Length of the resource string. Should be 255 characters at most.
    uint16 uResourceLength;
    /// Offset of the resource string
    //uint32 uResourceOffset;
    unsigned long uResourceOffset;
    /// Flags. See FLASHDB_FLAG_*
    uint16 uFlags;
    /// Index of content type entry for this resource, in the content type list
    uint16 uContentType;
    /// Length (in bytes) of the content blob
    uint16 uContentLength;
    /// Offset of the content blob in the database
    //uint32 uContentOffset;
    unsigned long uContentOffset;
};

extern const char FlashDBContentData[];

/**
 * The layout of the database file is as follows:
 *    Database Header
 *    Content type entry 1
 *    Content type entry 2
 *      and so on...
 *    Content entry 1
 *    Content entry 2
 *      and so on...
 *    Content type string 1
 *    Content type string 2
 *      and so on...
 *    Content blob 1
 *    Content blob 2
 *      and so on...
 *
 * Note: All offsets in the structures are absolute offsets, meaning they are relative to the database base pointer, as passed to FlashDB_Init()
 */

/* this global shows a sample how static pages/files are stored in the memory */
   
#if 0
struct StaticExamplePages
{
	struct FlashDBHeader				header;
	struct FlashDBContentTypeEntry		contentTypeList[];
	struct FlashDBContentEntry			ContentList[];
	char						contentType[][];
	char						resource[][];
	char					        content[][];
};
#endif

struct FlashDBHeader	*gFlashDB;

/**
 * Initialize the flash database module
 * @param pDatabase Pointer to the beginning of the database in flash memory
 */
void FlashDB_Init()
{
        gFlashDB = (struct FlashDBHeader *)FlashDBContentData;
}

/**
 * Find a content-type in the database
 * @param index The index of the content type in the database
 * @param[out] pResult Returns the string and its length
 * @return nonzero if successful. zero if index out of range.
 */
int FlashDB_FindContentType(uint16 index, struct HttpBlob* pResult)
{
	struct FlashDBContentTypeEntry	*pContentTypeEntryList;

	if (index > gFlashDB->uContentTypeAmount)
		return 0;
	
	pContentTypeEntryList = (struct FlashDBContentTypeEntry *)((unsigned char*)gFlashDB + gFlashDB->uContentTypeOffset);
	pContentTypeEntryList = (struct FlashDBContentTypeEntry *)(pContentTypeEntryList + index);
	pResult->uLength = pContentTypeEntryList->uValueLength;
	pResult->pData =  (unsigned char*)((unsigned char*)gFlashDB + pContentTypeEntryList->uValueOffset);

	return 1;
}

/**
 * Lookup content in the database, given a resource identifier
 * @param pResource The resource as given in the HTTP request
 * @param[out] pResult Returns the content and its metadata
 * @return nonzero if successful. zero if such a resource was not found.
 */
int FlashDB_FindContent(struct HttpBlob pResource, struct FlashDBContent* pResult)
{
	/* it is assumed that the resource list is sorted */
	struct FlashDBContentEntry *pContentFieldStart;
	struct FlashDBContentEntry *pContentFieldMoving;
    struct HttpBlob MainPage;
	uint16	uLowSearchIndex = 0;
	uint16	uMidSearchIndex;
	uint16	uHighSearchIndex;
	int		uComparison;
	int16	found = -1;	/* not found */
	struct HttpBlob	ResourceBlob;
    
	uHighSearchIndex = gFlashDB->uContentAmount - 1;
	pContentFieldStart = (struct FlashDBContentEntry *)((unsigned char*)gFlashDB + gFlashDB->uContentOffset);

	while (uLowSearchIndex <= uHighSearchIndex)
	{
		uMidSearchIndex = (uLowSearchIndex + uHighSearchIndex)/2;
		pContentFieldMoving = pContentFieldStart + uMidSearchIndex;
		ResourceBlob.pData = (unsigned char*)((unsigned char*)gFlashDB + pContentFieldMoving->uResourceOffset);
		ResourceBlob.uLength = pContentFieldMoving->uResourceLength;
		
                if(pResource.uLength ==1 && *(pResource.pData)=='/')
                {
                  MainPage.uLength = 11;
                  MainPage.pData = (unsigned char*)"/index.html";
                  uComparison = HttpString_strcmp(MainPage, ResourceBlob);
                }
                else
                  uComparison = HttpString_strcmp(pResource, ResourceBlob);
		// found the exact blob 
		if (uComparison == 0)
		{
			found = 1;
			printf("Content found \r\n");
			break;
		}
		
		// the requested blob is "larger" than the current blob 
		else if (uComparison > 0)
		{
			uLowSearchIndex = uMidSearchIndex + 1;
			
		}
		// the requested blob is "smaller" than the current blob 
		else
		{
			uHighSearchIndex = uMidSearchIndex - 1;
			
		}
	}
    
	if (found == -1)
	   {
	    printf("Content not found \r\n");
		return 0;
		}
	else
	{
		pResult->uContentType = pContentFieldMoving->uContentType;
		pResult->uFlags = pContentFieldMoving->uFlags;
		pResult->contentBlob.uLength = pContentFieldMoving->uContentLength;
		pResult->contentBlob.pData = (unsigned char*)((unsigned char*)gFlashDB + pContentFieldMoving->uContentOffset);
		return 1;
	}
}