void PrintHTTPHeader( HTTPHeader_t *inHeader ) { char temp[20]; //(void)inHeader; // Fix warning when debug=0 //http_utils_log("Header:\n %s", inHeader->buf); //http_utils_log("Length: %d", (int)inHeader->len); strncpy(temp, inHeader->methodPtr, 8); http_utils_log("Method: %s", temp); strncpy(temp, inHeader->urlPtr, 20); http_utils_log("URL: %s", temp); strncpy(temp, inHeader->protocolPtr, 8); http_utils_log("Protocol: %s", temp); http_utils_log("Status Code: %d", inHeader->statusCode); http_utils_log("ChannelID: %d", inHeader->channelID); http_utils_log("Content length: %lld", inHeader->contentLength); http_utils_log("Persistent: %s", YesOrNo( inHeader->persistent )); }
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; }
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; }
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; }