Example #1
0
OSStatus _FTCRespondInComingMessage(int fd, HTTPHeader_t* inHeader, mico_Context_t * const inContext)
{
    OSStatus err = kUnknownErr;
    const char *        value;
    size_t              valueSize;

    easylink_log_trace();

    switch(inHeader->statusCode){
      case kStatusAccept:
        easylink_log("Easylink server accepted!");
        err = kNoErr;
        goto exit;
      break;
      case kStatusOK:
        easylink_log("Easylink server respond status OK!");
        err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );
        require_noerr(err, exit);
        if( strnicmpx( value, valueSize, kMIMEType_JSON ) == 0 ){
          easylink_log("Receive JSON config data!");
          err = ConfigIncommingJsonMessage( inHeader->extraDataPtr, inContext);
          SocketClose(&fd);
          inContext->micoStatus.sys_state = eState_Software_Reset;
          require(inContext->micoStatus.sys_state_change_sem, exit);
          mico_rtos_set_semaphore(&inContext->micoStatus.sys_state_change_sem);
        }else if(strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0){
          easylink_log("Receive OTA data!");
          mico_rtos_lock_mutex(&inContext->flashContentInRam_mutex);
          memset(&inContext->flashContentInRam.bootTable, 0, sizeof(boot_table_t));
          inContext->flashContentInRam.bootTable.length = inHeader->contentLength;
          inContext->flashContentInRam.bootTable.start_address = UPDATE_START_ADDRESS;
          inContext->flashContentInRam.bootTable.type = 'A';
          inContext->flashContentInRam.bootTable.upgrade_type = 'U';
          inContext->flashContentInRam.micoSystemConfig.easyLinkEnable = false;
          MICOUpdateConfiguration(inContext);
          mico_rtos_unlock_mutex(&inContext->flashContentInRam_mutex);
          SocketClose(&fd);
          inContext->micoStatus.sys_state = eState_Software_Reset;
          require(inContext->micoStatus.sys_state_change_sem, exit);
          mico_rtos_set_semaphore(&inContext->micoStatus.sys_state_change_sem);
        }else{
          return kUnsupportedDataErr;
        }
        err = kNoErr;
        goto exit;
      break;
      default:
        goto exit;
    }

 exit:
    return err;

}
Example #2
0
static OSStatus onReceivedData(struct _HTTPHeader_t * inHeader, uint32_t inPos, uint8_t * inData, size_t inLen, void * inUserContext )
{
  OSStatus err = kUnknownErr;
  const char *    value;
  size_t          valueSize;
  configContext_t *context = (configContext_t *)inUserContext;

  err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );
  if(err == kNoErr && strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0){
    config_log("OTA data %d, %d to: %x", inPos, inLen, context->flashStorageAddress);
#ifdef MICO_FLASH_FOR_UPDATE  
    if(inPos == 0){
      context->flashStorageAddress = UPDATE_START_ADDRESS;
      mico_rtos_lock_mutex(&Context->flashContentInRam_mutex); //We are write the Flash content, no other write is possiable
      context->isFlashLocked = true;
      err = MicoFlashInitialize( MICO_FLASH_FOR_UPDATE );
      require_noerr(err, flashErrExit);
      err = MicoFlashErase(MICO_FLASH_FOR_UPDATE, UPDATE_START_ADDRESS, UPDATE_END_ADDRESS);
      require_noerr(err, flashErrExit);
      err = MicoFlashWrite(MICO_FLASH_FOR_UPDATE, &context->flashStorageAddress, (uint8_t *)inData, inLen);
      require_noerr(err, flashErrExit);
    }else{
      err = MicoFlashWrite(MICO_FLASH_FOR_UPDATE, &context->flashStorageAddress, (uint8_t *)inData, inLen);
      require_noerr(err, flashErrExit);
    }
#else
    config_log("OTA storage is not exist");
    return kUnsupportedErr;
#endif
  }
  else if(inHeader->chunkedData == true){
    config_log("ChunkedData: %d, %d:", inPos, inLen);
    for(uint32_t i = 0; i<inLen; i++)
      printf("%c", inData[i]);
    printf("\r\n");
  }
  else{
    return kUnsupportedErr;
  }

  if(err!=kNoErr)  config_log("onReceivedData");
  return err;

#ifdef MICO_FLASH_FOR_UPDATE  
flashErrExit:
  MicoFlashFinalize(MICO_FLASH_FOR_UPDATE);
  mico_rtos_unlock_mutex(&Context->flashContentInRam_mutex);
  return err;
#endif
}
Example #3
0
int HTTPScanFHeaderValue( const char *inHeaderPtr, size_t inHeaderLen, const char *inName, const char *inFormat, ... )
{
    int                 n;
    const char *        valuePtr;
    size_t              valueLen;
    va_list             args;

    n = (int) HTTPGetHeaderField( inHeaderPtr, inHeaderLen, inName, NULL, NULL, &valuePtr, &valueLen, NULL );
    require_noerr_quiet( n, exit );

    va_start( args, inFormat );
    n = VSNScanF( valuePtr, valueLen, inFormat, args );
    va_end( args );

exit:
    return( n );
}
Example #4
0
int SocketReadHTTPHeader( int inSock, HTTPHeader_t *inHeader )
{
    int        err =0;
    char *          buf;
    char *          dst;
    char *          lim;
    char *          end;
    size_t          len;
    ssize_t         n;
    const char *    value;
    size_t          valueSize;

    buf = inHeader->buf;
    dst = buf + inHeader->len;
    lim = buf + sizeof( inHeader->buf );
    for( ;; )
    {
        // If there's data from a previous read, move it to the front to search it first.
        len = inHeader->extraDataLen;
        if( len > 0 )
        {
            require_action( len <= (size_t)( lim - dst ), exit, err = kParamErr );
            memmove( dst, inHeader->extraDataPtr, len );
            inHeader->extraDataLen = 0;
        }
        else
        {
            //do
            //{
                n = read( inSock, dst, (size_t)( lim - dst ) );
            //    err = map_socket_value_errno( inSock, n >= 0, n );
            //}   while( err == EINTR );
            if(      n  > 0 ) len = (size_t) n;
            else  { err = kConnectionErr; goto exit; }
            //else goto exit;
        }
        dst += len;
        inHeader->len += len;
        
        if(findHeader( inHeader,  &end ))
            break ;
    }

    inHeader->len = (size_t)( end - buf );
    err = HTTPHeaderParse( inHeader );
    require_noerr( err, exit );
    inHeader->extraDataLen = (size_t)( dst - end );
    if(inHeader->extraDataPtr) {
        free((uint8_t *)inHeader->extraDataPtr);
        inHeader->extraDataPtr = 0;
    }

    if(inHeader->otaDataPtr) {
        free((uint8_t *)inHeader->otaDataPtr);
        inHeader->otaDataPtr = 0;
    }

    err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );
    
    if(err == kNoErr && strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0){
        http_utils_log("Receive OTA data!");        
        err = PlatformFlashInitialize();
        require_noerr(err, exit);
        err = PlatformFlashWrite(&flashStorageAddress, (uint32_t *)end, inHeader->extraDataLen);
        require_noerr(err, exit);
    }else{
        inHeader->extraDataPtr = calloc(inHeader->contentLength, sizeof(uint8_t));
        require_action(inHeader->extraDataPtr, exit, err = kNoMemoryErr);
        memcpy((uint8_t *)inHeader->extraDataPtr, end, inHeader->extraDataLen);
        err = kNoErr;
    }

exit:
    return err;
}
Example #5
0
OSStatus HTTPHeaderParse( HTTPHeader_t *ioHeader )
{
    OSStatus            err;
    const char *        src;
    const char *        end;
    const char *        ptr;
    char                c;
    const char *        value;
    size_t              valueSize;
    int                 x;

    require_action( ioHeader->len < sizeof( ioHeader->buf ), exit, err = kParamErr );

    // Reset fields up-front to good defaults to simplify handling of unused fields later.

    ioHeader->methodPtr         = "";
    ioHeader->methodLen         = 0;
    ioHeader->urlPtr            = "";
    ioHeader->urlLen            = 0;
    memset( &ioHeader->url, 0, sizeof( ioHeader->url ) );
    ioHeader->protocolPtr       = "";
    ioHeader->protocolLen       = 0;
    ioHeader->statusCode        = -1;
    ioHeader->reasonPhrasePtr   = "";
    ioHeader->reasonPhraseLen   = 0;
    ioHeader->channelID         = 0;
    ioHeader->contentLength     = 0;
    ioHeader->persistent        = false;

    // Check for a 4-byte interleaved binary data header (see RFC 2326 section 10.12). It has the following format:
    //
    //      '$' <1:channelID> <2:dataSize in network byte order> ... followed by dataSize bytes of binary data.
    src = ioHeader->buf;
    if( ( ioHeader->len == 4 ) && ( src[ 0 ] == '$' ) )
    {
        const uint8_t *     usrc;

        usrc = (const uint8_t *) src;
        ioHeader->channelID     =   usrc[ 1 ];
        ioHeader->contentLength = ( usrc[ 2 ] << 8 ) | usrc[ 3 ];

        ioHeader->methodPtr = src;
        ioHeader->methodLen = 1;

        err = kNoErr;
        goto exit;
    }

    // Parse the start line. This will also determine if it's a request or response.
    // Requests are in the format <method> <url> <protocol>/<majorVersion>.<minorVersion>, for example:
    //
    //      GET /abc/xyz.html HTTP/1.1
    //      GET http://www.host.com/abc/xyz.html HTTP/1.1
    //      GET http://user:[email protected]/abc/xyz.html HTTP/1.1
    //
    // Responses are in the format <protocol>/<majorVersion>.<minorVersion> <statusCode> <reasonPhrase>, for example:
    //
    //      HTTP/1.1 404 Not Found
    ptr = src;
    end = src + ioHeader->len;
    for( c = 0; ( ptr < end ) && ( ( c = *ptr ) != ' ' ) && ( c != '/' ); ++ptr ) {}
    require_action( ptr < end, exit, err = kMalformedErr );

    if( c == ' ' ) // Requests have a space after the method. Responses have '/' after the protocol.
    {
        ioHeader->methodPtr = src;
        ioHeader->methodLen = (size_t)( ptr - src );
        ++ptr;

        // Parse the URL.
        ioHeader->urlPtr = ptr;
        while( ( ptr < end ) && ( *ptr != ' ' ) ) ++ptr;
        ioHeader->urlLen = (size_t)( ptr - ioHeader->urlPtr );
        require_action( ptr < end, exit, err = kMalformedErr );
        ++ptr;

        err = URLParseComponents( ioHeader->urlPtr, ioHeader->urlPtr + ioHeader->urlLen, &ioHeader->url, NULL );
        require_noerr( err, exit );

        // Parse the protocol and version.
        ioHeader->protocolPtr = ptr;
        while( ( ptr < end ) && ( ( c = *ptr ) != '\r' ) && ( c != '\n' ) ) ++ptr;
        ioHeader->protocolLen = (size_t)( ptr - ioHeader->protocolPtr );
        require_action( ptr < end, exit, err = kMalformedErr );
        ++ptr;
    }
    else // Response
    {
        // Parse the protocol version.
        ioHeader->protocolPtr = src;
        for( ++ptr; ( ptr < end ) && ( *ptr != ' ' ); ++ptr ) {}
        ioHeader->protocolLen = (size_t)( ptr - ioHeader->protocolPtr );
        require_action( ptr < end, exit, err = kMalformedErr );
        ++ptr;

        // Parse the status code.
        x = 0;
        for( c = 0; ( ptr < end ) && ( ( c = *ptr ) >= '0' ) && ( c <= '9' ); ++ptr ) x = ( x * 10 ) + ( c - '0' ); 
        ioHeader->statusCode = x;
        if( c == ' ' ) ++ptr;

        // Parse the reason phrase.
        ioHeader->reasonPhrasePtr = ptr;
        while( ( ptr < end ) && ( ( c = *ptr ) != '\r' ) && ( c != '\n' ) ) ++ptr;
        ioHeader->reasonPhraseLen = (size_t)( ptr - ioHeader->reasonPhrasePtr );
        require_action( ptr < end, exit, err = kMalformedErr );
        ++ptr;
    }

    // There should at least be a blank line after the start line so make sure there's more data.
    require_action( ptr < end, exit, err = kMalformedErr );

    // Determine persistence. Note: HTTP 1.0 defaults to non-persistent if a Connection header field is not present.
    err = HTTPGetHeaderField( ioHeader->buf, ioHeader->len, "Connection", NULL, NULL, &value, &valueSize, NULL );
    if( err )   ioHeader->persistent = (Boolean)( strnicmpx( ioHeader->protocolPtr, ioHeader->protocolLen, "HTTP/1.0" ) != 0 );
    else        ioHeader->persistent = (Boolean)( strnicmpx( value, valueSize, "close" ) != 0 );

    // Content-Length is such a common field that we get it here during general parsing.
    HTTPScanFHeaderValue( ioHeader->buf, ioHeader->len, "Content-Length", "%llu", &ioHeader->contentLength );
    err = kNoErr;

exit:
    return err;
}
Example #6
0
OSStatus SocketReadHTTPBody( int inSock, HTTPHeader_t *inHeader )
{
    OSStatus err = kParamErr;
    ssize_t readResult;
    int selectResult;
    fd_set readSet;
    const char *    value;
    size_t          valueSize;

    require( inHeader, exit );

    err = kNotReadableErr;

    FD_ZERO( &readSet );
    FD_SET( inSock, &readSet );
    while ( inHeader->extraDataLen < inHeader->contentLength )
    {
        selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
        require( selectResult >= 1, exit );


        err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );
        require_noerr(err, exit);
        if( strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0 ){
            inHeader->otaDataPtr = calloc(OTA_Data_Length_per_read, sizeof(uint8_t)); 
            require_action(inHeader->otaDataPtr, exit, err = kNoMemoryErr);
            if((inHeader->contentLength - inHeader->extraDataLen)<OTA_Data_Length_per_read){
                readResult = read( inSock,
                           (uint8_t*)( inHeader->otaDataPtr ),
                           ( inHeader->contentLength - inHeader->extraDataLen ) );
            }else{
                readResult = read( inSock,
                           (uint8_t*)( inHeader->otaDataPtr ),
                           OTA_Data_Length_per_read);
            }

            if( readResult  > 0 ) inHeader->extraDataLen += readResult;
            else { err = kConnectionErr; goto exit; }
            //else goto exit;

            err = PlatformFlashWrite(&flashStorageAddress, (uint32_t *)inHeader->otaDataPtr, readResult);
            require_noerr(err, exit);

            free(inHeader->otaDataPtr);
            inHeader->otaDataPtr = 0;
        }else{
            readResult = read( inSock,
                           (uint8_t*)( inHeader->extraDataPtr + inHeader->extraDataLen ),
                           ( inHeader->contentLength - inHeader->extraDataLen ) );

            if( readResult  > 0 ) inHeader->extraDataLen += readResult;
            else if( readResult == 0 ) { err = kConnectionErr; goto exit; }
            else goto exit;
        }
    }

    err = kNoErr;

exit:
    if(inHeader->otaDataPtr) {
        free(inHeader->otaDataPtr);
        inHeader->otaDataPtr = 0;
    }
    return err;
}
Example #7
0
int SocketReadHTTPHeader( int inSock, HTTPHeader_t *inHeader )
{
  int        err =0;
  char *          buf;
  char *          dst;
  char *          lim;
  char *          end;
  size_t          len;
  ssize_t         n;
  const char *    value;
  size_t          valueSize;
  
  buf = inHeader->buf;
  dst = buf + inHeader->len;
  lim = buf + sizeof( inHeader->buf );
  for( ;; )
  {
    if(findHeader( inHeader,  &end ))
      break ;
    n = read( inSock, dst, (size_t)( lim - dst ) );
    if(      n  > 0 ) len = (size_t) n;
    else  { err = kConnectionErr; goto exit; }
    dst += len;
    inHeader->len += len;
  }
  
  inHeader->len = (size_t)( end - buf );
  err = HTTPHeaderParse( inHeader );
  require_noerr( err, exit );
  inHeader->extraDataLen = (size_t)( dst - end );
  if(inHeader->extraDataPtr) {
    free((uint8_t *)inHeader->extraDataPtr);
    inHeader->extraDataPtr = 0;
  }
  
  if(inHeader->otaDataPtr) {
    free((uint8_t *)inHeader->otaDataPtr);
    inHeader->otaDataPtr = 0;
  }
  
  /* For MXCHIP OTA function, store extra data to OTA data temporary */
  err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );

  if(err == kNoErr && strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0){
#ifdef MICO_FLASH_FOR_UPDATE  
    http_utils_log("Receive OTA data!");        
    err = MicoFlashInitialize( MICO_FLASH_FOR_UPDATE );
    require_noerr(err, exit);
    err = MicoFlashWrite(MICO_FLASH_FOR_UPDATE, &flashStorageAddress, (uint8_t *)end, inHeader->extraDataLen);
    require_noerr(err, exit);
#else
    http_utils_log("OTA flash memory is not existed!");
    err = kUnsupportedErr;
#endif
    goto exit;
  }

  /* For chunked extra data without content length */
  if(inHeader->chunkedData == true){
    inHeader->chunkedDataBufferLen = (inHeader->extraDataLen > 256)? inHeader->extraDataLen:256;
    inHeader->chunkedDataBufferPtr = calloc(inHeader->chunkedDataBufferLen, sizeof(uint8_t)); //Make extra data buffer larger than chunk length
    require_action(inHeader->chunkedDataBufferPtr, exit, err = kNoMemoryErr);
    memcpy((uint8_t *)inHeader->chunkedDataBufferPtr, end, inHeader->extraDataLen);
    inHeader->extraDataPtr = inHeader->chunkedDataBufferPtr;
    return kNoErr;
  }

  /* Extra data with content length */
  if (inHeader->contentLength != 0){ //Content length >0, create a memory buffer (Content length) and store extra data
    size_t copyDataLen = (inHeader->contentLength >= inHeader->extraDataLen)? inHeader->contentLength:inHeader->extraDataLen;
    inHeader->extraDataPtr = calloc(copyDataLen , sizeof(uint8_t));
    require_action(inHeader->extraDataPtr, exit, err = kNoMemoryErr);
    memcpy((uint8_t *)inHeader->extraDataPtr, end, copyDataLen);
    err = kNoErr;
  } /* Extra data without content length, data is ended by conntection close */
  else if(inHeader->extraDataLen != 0){ //Content length =0, but extra data length >0, create a memory buffer (1500)and store extra data
    inHeader->dataEndedbyClose = true;
    inHeader->extraDataPtr = calloc(1500, sizeof(uint8_t));
    require_action(inHeader->extraDataPtr, exit, err = kNoMemoryErr);
    memcpy((uint8_t *)inHeader->extraDataPtr, end, inHeader->extraDataLen);
    err = kNoErr;
  }
  else
    return kNoErr;
  
exit:
  return err;
}
Example #8
0
OSStatus SocketReadHTTPBody( int inSock, HTTPHeader_t *inHeader )
{
  OSStatus err = kParamErr;
  ssize_t readResult;
  int selectResult;
  fd_set readSet;
  const char *    value;
  size_t          valueSize;
  size_t    lastChunkLen, chunckheaderLen; 
  char *nextPackagePtr;
#ifdef MICO_FLASH_FOR_UPDATE
  bool writeToFlash = false;
#endif
  
  require( inHeader, exit );
  
  err = kNotReadableErr;
  
  FD_ZERO( &readSet );
  FD_SET( inSock, &readSet );

  /* Chunked data, return after receive one chunk */
  if( inHeader->chunkedData == true ){
    /* Move next chunk to chunked data buffer header point */
    lastChunkLen = inHeader->extraDataPtr - inHeader->chunkedDataBufferPtr + inHeader->contentLength;
    if(inHeader->contentLength) lastChunkLen+=2;  //Last chunck data has a CRLF tail
    memmove( inHeader->chunkedDataBufferPtr, inHeader->chunkedDataBufferPtr + lastChunkLen, inHeader->chunkedDataBufferLen - lastChunkLen  );
    inHeader->extraDataLen -= lastChunkLen;

    while ( findChunkedDataLength( inHeader->chunkedDataBufferPtr, inHeader->extraDataLen, &inHeader->extraDataPtr ,"%llu", &inHeader->contentLength ) == false){
      require_action(inHeader->extraDataLen < inHeader->chunkedDataBufferLen, exit, err=kMalformedErr );

      selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
      require( selectResult >= 1, exit ); 

      readResult = read( inSock, inHeader->extraDataPtr, (size_t)( inHeader->chunkedDataBufferLen - inHeader->extraDataLen ) );

      if( readResult  > 0 ) inHeader->extraDataLen += readResult;
      else { err = kConnectionErr; goto exit; }
    }

    chunckheaderLen = inHeader->extraDataPtr - inHeader->chunkedDataBufferPtr;

    if(inHeader->contentLength == 0){ //This is the last chunk
      while( findCRLF( inHeader->extraDataPtr, inHeader->extraDataLen - chunckheaderLen, &nextPackagePtr ) == false){ //find CRLF
        selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
        require( selectResult >= 1, exit ); 

        readResult = read( inSock,
                          (uint8_t *)( inHeader->extraDataPtr + inHeader->extraDataLen - chunckheaderLen ),
                          256 - inHeader->extraDataLen ); //Assume chunk trailer length is less than 256 (256 is the min chunk buffer, maybe dangerous

        if( readResult  > 0 ) inHeader->extraDataLen += readResult;
        else { err = kConnectionErr; goto exit; }
      }

      err = kNoErr;
      goto exit;
    }
    else{
      /* Extend chunked data buffer */
      if( inHeader->chunkedDataBufferLen < inHeader->contentLength + chunckheaderLen + 2){
        inHeader->chunkedDataBufferLen = inHeader->contentLength + chunckheaderLen + 256;
        inHeader->chunkedDataBufferPtr = realloc(inHeader->chunkedDataBufferPtr, inHeader->chunkedDataBufferLen);
        require_action(inHeader->extraDataPtr, exit, err = kNoMemoryErr);
      }

      /* Read chunked data */
      while ( inHeader->extraDataLen < inHeader->contentLength + chunckheaderLen + 2 ){
        selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
        require( selectResult >= 1, exit ); 

        readResult = read( inSock,
                          (uint8_t *)( inHeader->extraDataPtr + inHeader->extraDataLen - chunckheaderLen),
                          ( inHeader->contentLength - (inHeader->extraDataLen - chunckheaderLen) + 2 ));
        
        if( readResult  > 0 ) inHeader->extraDataLen += readResult;
        else { err = kConnectionErr; goto exit; }
      } 
      
      if( *(inHeader->extraDataPtr + inHeader->contentLength) != '\r' ||
         *(inHeader->extraDataPtr + inHeader->contentLength +1 ) != '\n'){
           err = kMalformedErr; 
           goto exit;
         }
    }
  }

  /* We has extra data but total length is not clear, store them to 1500 bytes buffer 
     return when connection is disconnected by remote server */
  if( inHeader->dataEndedbyClose == true){ 
    if(inHeader->contentLength == 0) { //First read body, return using data received by SocketReadHTTPHeader
      inHeader->contentLength = inHeader->extraDataLen;
    }else{
      selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
      require( selectResult >= 1, exit ); 
      
      readResult = read( inSock,
                        (uint8_t*)( inHeader->extraDataPtr ),
                        1500 );
      if( readResult  > 0 ) inHeader->contentLength = readResult;
      else { err = kConnectionErr; goto exit; }
    }
    err = kNoErr;
    goto exit;
  }
  
  /* We has extra data and we has a predefined buffer to store the total extra data
     return when all data has received*/
  while ( inHeader->extraDataLen < inHeader->contentLength )
  {
    selectResult = select( inSock + 1, &readSet, NULL, NULL, NULL );
    require( selectResult >= 1, exit );
    
    
    err = HTTPGetHeaderField( inHeader->buf, inHeader->len, "Content-Type", NULL, NULL, &value, &valueSize, NULL );
    require_noerr(err, exit);
    if( strnicmpx( value, valueSize, kMIMEType_MXCHIP_OTA ) == 0 ){
#ifdef MICO_FLASH_FOR_UPDATE  
      writeToFlash = true;
      inHeader->otaDataPtr = calloc(OTA_Data_Length_per_read, sizeof(uint8_t)); 
      require_action(inHeader->otaDataPtr, exit, err = kNoMemoryErr);
      if((inHeader->contentLength - inHeader->extraDataLen)<OTA_Data_Length_per_read){
        readResult = read( inSock,
                          (uint8_t*)( inHeader->otaDataPtr ),
                          ( inHeader->contentLength - inHeader->extraDataLen ) );
      }else{
        readResult = read( inSock,
                          (uint8_t*)( inHeader->otaDataPtr ),
                          OTA_Data_Length_per_read);
      }
      
      if( readResult  > 0 ) inHeader->extraDataLen += readResult;
      else { err = kConnectionErr; goto exit; }
      
      err = MicoFlashWrite(MICO_FLASH_FOR_UPDATE, &flashStorageAddress, (uint8_t *)inHeader->otaDataPtr, readResult);
      require_noerr(err, exit);
      
      free(inHeader->otaDataPtr);
      inHeader->otaDataPtr = 0;
#else
      http_utils_log("OTA flash memory is not existed, !");
      err = kUnsupportedErr;
#endif
    }else{
      readResult = read( inSock,
                        (uint8_t*)( inHeader->extraDataPtr + inHeader->extraDataLen ),
                        ( inHeader->contentLength - inHeader->extraDataLen ) );
      
      if( readResult  > 0 ) inHeader->extraDataLen += readResult;
      else { err = kConnectionErr; goto exit; }
    }
  }  
  err = kNoErr;
  
exit:
  if(err != kNoErr) inHeader->len = 0;
  if(inHeader->otaDataPtr) {
    free(inHeader->otaDataPtr);
    inHeader->otaDataPtr = 0;
  }
#ifdef MICO_FLASH_FOR_UPDATE
  if(writeToFlash == true) MicoFlashFinalize(MICO_FLASH_FOR_UPDATE);
#endif
  return err;
}