static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO()

in adapters/httpapi_compact.c [1057:1194]


static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
{
    HTTPAPI_RESULT result;
    char    buf[TEMP_BUFFER_SIZE];
    const unsigned char* receivedContent;

    http_instance->is_io_error = 0;

    //Read HTTP response body
    if (!chunked)
    {
        if (bodyLength)
        {
            if (responseContent != NULL)
            {
                if (BUFFER_pre_build(responseContent, bodyLength) != 0)
                {
                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
                    result = HTTPAPI_ALLOC_FAILED;
                }
                else if (BUFFER_content(responseContent, &receivedContent) != 0)
                {
                    (void)BUFFER_unbuild(responseContent);

                    /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
                    result = HTTPAPI_ALLOC_FAILED;
                }
                else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
                {
                    /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
                    result = HTTPAPI_READ_DATA_FAILED;
                }
                else
                {
                    /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
                    result = HTTPAPI_OK;
                }
            }
            else
            {
                /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
                if (skipN(http_instance, bodyLength) < 0)
                {
                    /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                    result = HTTPAPI_READ_DATA_FAILED;
                }
                else
                {
                    result = HTTPAPI_OK;
                }
            }
        }
        else
        {
            /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
            result = HTTPAPI_OK;
        }
    }
    else
    {
        size_t size = 0;
        /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
        result = HTTPAPI_OK;
        while (result == HTTPAPI_OK)
        {
            size_t chunkSize;
            if (readLine(http_instance, buf, sizeof(buf)) < 0)    // read [length in hex]/r/n
            {
                /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/
                /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                result = HTTPAPI_READ_DATA_FAILED;
            }
            else if (ParseStringToHexadecimal(buf, &chunkSize) != 1)     // chunkSize is length of next line (/r/n is not counted)
            {
                //Cannot match string, error
                /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the received message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/
                result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
            }
            else if (chunkSize == 0)
            {
                // 0 length means next line is just '\r\n' and end of chunks
                if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
                    || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
                {
                    (void)BUFFER_unbuild(responseContent);

                    result = HTTPAPI_READ_DATA_FAILED;
                }
                break;
            }
            else
            {
                if (responseContent != NULL)
                {
                    if (BUFFER_enlarge(responseContent, chunkSize) != 0)
                    {
                        (void)BUFFER_unbuild(responseContent);

                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
                        result = HTTPAPI_ALLOC_FAILED;
                    }
                    else if (BUFFER_content(responseContent, &receivedContent) != 0)
                    {
                        (void)BUFFER_unbuild(responseContent);

                        /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
                        result = HTTPAPI_ALLOC_FAILED;
                    }
                    else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
                    {
                        result = HTTPAPI_READ_DATA_FAILED;
                    }
                }
                else
                {
                    /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
                    if (skipN(http_instance, chunkSize) < 0)
                    {
                        /*Codes_SRS_HTTPAPI_COMPACT_21_082: [ If the HTTPAPI_ExecuteRequest retries 20 seconds to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/
                        result = HTTPAPI_READ_DATA_FAILED;
                    }
                }

                if (result == HTTPAPI_OK)
                {
                    if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
                        || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
                    {
                        result = HTTPAPI_READ_DATA_FAILED;
                    }
                    size += chunkSize;
                }
            }
        }

    }
    return result;
}