none
Azure IoT SDK simplesample_http for CC3200 - IoT Hubs Connection Error RRS feed

  • Question

  • Hi,

    I'm having trouble getting the simplesample_http example -- provided as part of the Azure IoT SDK for the TI CC3200 -- to connect to my IoT hub.  I followed the instructions found on the GitHub page for the CC3200.  I created a new device and provisioned it using Device Explorer and the instructions found on the corresponding GitHub page.  I've included the proper User Step information for the current date-time macros, WIFI SSID and SECURITY_KEY macros, and the device-specific connection string.  The example compiles and flashes to the device without issue.  I have also flashed the provided certificate to the CC3200 to /cert/ms.der as required. 

    During startup, I observe the following through my terminal emulator.  I added a few more Error print points of my own to track what was being executed. 

    Starting the simplesample_http example
    CC3200 has connected to AP and acquired an IP address.
    IP Address: XXX.XXX.X.XXX
    Info: IoT Hub SDK for C, version 1.0.0-preview.6
    Line 198: IoTHubClient accepted the message for delivery

    Error: Time:Wed Aug 23 09:48:40 2028 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:383 HTTPAPI_Init() == HTTPAPI_OK
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:448 the program has been hereError: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:392 handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:462 handleData->k is 0Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:478 handleData->k is defaultError: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:486 unable to recover sending to a working state
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/iothubtransporthttp.c Func:DoEvent Line:1206 unable to HTTPAPIEX_ExecuteRequest
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:383 HTTPAPI_Init() == HTTPAPI_OK
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:448 the program has been hereError: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:392 handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:462 handleData->k is 0Error: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:478 handleData->k is defaultError: Time:Thu May 13 16:10:32 2032 File:../../src/httpapiex.c Func:HTTPAPIEX_ExecuteRequest Line:486 unable to recover sending to a working state
    Error: Time:Thu May 13 16:10:32 2032 File:../../src/iothubtransporthttp.c Func:DoMessages Line:1428 unable to HTTPAPIEX_ExecuteRequest

    One thing I noticed right away is that the timestamps are years off, so I double-checked the date-time macros in main.c, and they are correct.  I don't see any calls to an SNTP server in the program, and I don't know what is generating these timestamps, but I wonder if they are either part of the cause or symptomatic of the core problem.   Reading through the errors, it looks like HTTPAPI_Init() successfully completes, but HTTPAPI_CreateConnection() does not.  The error on Line 392 of httpapiex.c indicates that the hostname is NULL.  It's my understanding that this should be assigned from the parsed connection string in simplesample_http.c, which must have completed OK since I get no errors from the IoTHubClient_LL_CreateFromConnectionString() parser in iothub_client_ll.c.   Yet something isn't lining up.  Can you please provide some guidance as to where the issue may be occurring? 

    Here is my modified httpapiex.c so that line numbers in my terminal printouts match the code.  (only modifications are added Error prints for debugging)

    Thanks for your time and assistance.

    // Copyright (c) Microsoft. All rights reserved.
    // Licensed under the MIT license. See LICENSE file in the project root for full license information.
    
    #include <stdlib.h>
    #ifdef _CRTDBG_MAP_ALLOC
    #include <crtdbg.h>
    #endif
    #include "gballoc.h"
    
    #include "httpapiex.h"
    #include "iot_logging.h"
    #include "strings.h"
    #include "crt_abstractions.h"
    #include "vector.h"
    
    typedef struct HTTPAPIEX_SAVED_OPTION_TAG
    {
        const char* optionName;
        const void* value;
    }HTTPAPIEX_SAVED_OPTION;
    
    typedef struct HTTPAPIEX_HANDLE_DATA_TAG
    {
        STRING_HANDLE hostName;
        int k;
        HTTP_HANDLE httpHandle;
        VECTOR_HANDLE savedOptions;
    }HTTPAPIEX_HANDLE_DATA;
    
    DEFINE_ENUM_STRINGS(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES);
    
    #define LOG_HTTAPIEX_ERROR() LogError("error code = %s\r\n", ENUM_TO_STRING(HTTPAPIEX_RESULT, result))
    
    HTTPAPIEX_HANDLE HTTPAPIEX_Create(const char* hostName)
    {
        HTTPAPIEX_HANDLE result;
        /*Codes_SRS_HTTPAPIEX_02_001: [If parameter hostName is NULL then HTTPAPIEX_Create shall return NULL.]*/
        if (hostName == NULL)
        {
            LogError("invalid (NULL) parameter\r\n");
            result = NULL;
        }
        else
        {
            /*Codes_SRS_HTTPAPIEX_02_005: [If creating the handle fails for any reason, then HTTAPIEX_Create shall return NULL.] */
            HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)malloc(sizeof(HTTPAPIEX_HANDLE_DATA));
            if (handleData == NULL)
            {
                LogError("malloc failed.\r\n");
                result = NULL;
            }
            else
            {
                /*Codes_SRS_HTTPAPIEX_02_002: [Parameter hostName shall be saved.]*/
                handleData->hostName = STRING_construct(hostName);
                if (handleData->hostName == NULL)
                {
                    free(handleData);
                    LogError("unable to STRING_construct\r\n");
                    result = NULL;
                }
                else
                {
                    /*Codes_SRS_HTTPAPIEX_02_004: [Otherwise, HTTPAPIEX_Create shall return a HTTAPIEX_HANDLE suitable for further calls to the module.] */
                    handleData->savedOptions = VECTOR_create(sizeof(HTTPAPIEX_SAVED_OPTION));
                    if (handleData->savedOptions == NULL)
                    {
                        STRING_delete(handleData->hostName);
                        free(handleData);
                        result = NULL;
                    }
                    else
                    {
                        handleData->k = -1;
                        handleData->httpHandle = NULL;
                        result = handleData;
                    }
                }
            }
        }
        return result;
    }
    
    /*this function builds the default request http headers if none are specified*/
    /*returns 0 if no error*/
    /*any other code is error*/
    static int buildRequestHttpHeadersHandle(HTTPAPIEX_HANDLE_DATA *handleData, BUFFER_HANDLE requestContent, HTTP_HEADERS_HANDLE originalRequestHttpHeadersHandle, bool* isOriginalRequestHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedRequestHttpHeadersHandle)
    {
        int result;
    
    
        if (originalRequestHttpHeadersHandle != NULL)
        {
            *toBeUsedRequestHttpHeadersHandle = originalRequestHttpHeadersHandle;
            *isOriginalRequestHttpHeadersHandle = true;
    
        }
        else
        {
            /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers
            Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call
            Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
            */
            *isOriginalRequestHttpHeadersHandle = false;
            *toBeUsedRequestHttpHeadersHandle = HTTPHeaders_Alloc();
        }
    
        if (*toBeUsedRequestHttpHeadersHandle == NULL)
        {
            result = __LINE__;
            LogError("unable to HTTPHeaders_Alloc\r\n");
        }
        else
        {
            char temp[22];
            (void)size_tToString(temp, 22, BUFFER_length(requestContent)); /*cannot fail, MAX_uint64 has 19 digits*/
            /*Codes_SRS_HTTPAPIEX_02_011: [If parameter requestHttpHeadersHandle is not NULL then HTTPAPIEX_ExecuteRequest shall create or update the following headers of the request:
            Host:{hostname}
            Content-Length:the size of the requestContent parameter, and shall use the so constructed HTTPHEADERS object to all calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
            */
            /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers
            Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call
            Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.]
            */
            if (!(
                (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Host", STRING_c_str(handleData->hostName)) == HTTP_HEADERS_OK) &&
                (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Content-Length", temp) == HTTP_HEADERS_OK)
                ))
            {
                if (! *isOriginalRequestHttpHeadersHandle)
                { 
                    HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
                }
                *toBeUsedRequestHttpHeadersHandle = NULL;
                result = __LINE__;
            }
            else
            {
                result = 0;
            }
        }
        return result;
    }
    
    static int buildResponseHttpHeadersHandle(HTTP_HEADERS_HANDLE originalResponsetHttpHeadersHandle, bool* isOriginalResponseHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedResponsetHttpHeadersHandle)
    {
        int result;
        if (originalResponsetHttpHeadersHandle == NULL)
        {
            if ((*toBeUsedResponsetHttpHeadersHandle = HTTPHeaders_Alloc()) == NULL)
            {
                result = __LINE__;
            }
            else
            {
                *isOriginalResponseHttpHeadersHandle = false;
                result = 0;
            }
        }
        else
        {
            *isOriginalResponseHttpHeadersHandle = true;
            *toBeUsedResponsetHttpHeadersHandle = originalResponsetHttpHeadersHandle;
            result = 0;
        }
        return result;
    }
    
    
    static int buildBufferIfNotExist(BUFFER_HANDLE originalRequestContent, bool* isOriginalRequestContent, BUFFER_HANDLE* toBeUsedRequestContent)
    {
        int result;
        if (originalRequestContent == NULL)
        {
            *toBeUsedRequestContent = BUFFER_new();
            if (*toBeUsedRequestContent == NULL)
            {
                result = __LINE__;
            }
            else
            {
                *isOriginalRequestContent = false;
                result = 0;
            }
        }
        else
        {
            *isOriginalRequestContent = true;
            *toBeUsedRequestContent = originalRequestContent;
            result = 0;
        }
        return result;
    }
    
    static unsigned int dummyStatusCode;
    
    static int buildAllRequests(HTTPAPIEX_HANDLE_DATA* handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
        HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode,
        HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent,
    
        const char** toBeUsedRelativePath, 
        HTTP_HEADERS_HANDLE *toBeUsedRequestHttpHeadersHandle, bool *isOriginalRequestHttpHeadersHandle,
        BUFFER_HANDLE *toBeUsedRequestContent, bool *isOriginalRequestContent,
        unsigned int** toBeUsedStatusCode,
        HTTP_HEADERS_HANDLE *toBeUsedResponseHttpHeadersHandle, bool *isOriginalResponseHttpHeadersHandle,
        BUFFER_HANDLE *toBeUsedResponseContent, bool *isOriginalResponseContent)
    {
        int result;
        (void)requestType;
        /*Codes_SRS_HTTPAPIEX_02_013: [If requestContent is NULL then HTTPAPIEX_ExecuteRequest shall behave as if a buffer of zero size would have been used, that is, it shall call HTTPAPI_ExecuteRequest with parameter content = NULL and contentLength = 0.]*/
        /*Codes_SRS_HTTPAPIEX_02_014: [If requestContent is not NULL then its content and its size shall be used for parameters content and contentLength of HTTPAPI_ExecuteRequest.] */
        if (buildBufferIfNotExist(requestContent, isOriginalRequestContent, toBeUsedRequestContent) != 0)
        {
            result = __LINE__;
            LogError("unable to build the request content\r\n");
        }
        else
        {
            if (buildRequestHttpHeadersHandle(handle, *toBeUsedRequestContent, requestHttpHeadersHandle, isOriginalRequestHttpHeadersHandle, toBeUsedRequestHttpHeadersHandle) != 0)
            {
                /*Codes_SRS_HTTPAPIEX_02_010: [If any of the operations in SRS_HTTAPIEX_02_009 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
                result = __LINE__;
                if (*isOriginalRequestContent == false) 
                {
                    BUFFER_delete(*toBeUsedRequestContent);
                }
                LogError("unable to build the request http headers handle\r\n");
            }
            else
            {
                /*Codes_SRS_HTTPAPIEX_02_008: [If parameter relativePath is NULL then HTTPAPIEX_INVALID_ARG shall not assume a relative path - that is, it will assume an empty path ("").] */
                if (relativePath == NULL)
                {
                    *toBeUsedRelativePath = "";
                }
                else
                {
                    *toBeUsedRelativePath = relativePath;
                }
    
                /*Codes_SRS_HTTPAPIEX_02_015: [If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall not write in statusCode the HTTP status code, and it will use a temporary internal int for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */
                if (statusCode == NULL)
                {
                    /*Codes_SRS_HTTPAPIEX_02_016: [If statusCode is not NULL then If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall use it for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */
                    *toBeUsedStatusCode = &dummyStatusCode;
                }
                else
                {
                    *toBeUsedStatusCode = statusCode;
                }
    
                /*Codes_SRS_HTTPAPIEX_02_017: [If responseHeaders handle is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal instance of HTTPHEADERS object and use that for responseHeaders parameter of HTTPAPI_ExecuteRequest call.] */
                /*Codes_SRS_HTTPAPIEX_02_019: [If responseHeaders is not NULL, then then HTTPAPIEX_ExecuteRequest shall use that object as parameter responseHeaders of HTTPAPI_ExecuteRequest call.] */
                if (buildResponseHttpHeadersHandle(responseHttpHeadersHandle, isOriginalResponseHttpHeadersHandle, toBeUsedResponseHttpHeadersHandle) != 0)
                {
                    /*Codes_SRS_HTTPAPIEX_02_018: [If creating the temporary http headers in SRS_HTTPAPIEX_02_017 fails then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
                    result = __LINE__;
                    if (*isOriginalRequestContent == false)
                    {
                        BUFFER_delete(*toBeUsedRequestContent);
                    }
                    if (*isOriginalRequestHttpHeadersHandle == false)
                    {
                        HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
                    }
                    LogError("unable to build response content\r\n");
                }
                else
                {
                    /*Codes_SRS_HTTPAPIEX_02_020: [If responseContent is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal BUFFER object and use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */
                    /*Codes_SRS_HTTPAPIEX_02_022: [If responseContent is not NULL then HTTPAPIEX_ExecuteRequest use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */
                    if (buildBufferIfNotExist(responseContent, isOriginalResponseContent, toBeUsedResponseContent) != 0)
                    {
                        /*Codes_SRS_HTTPAPIEX_02_021: [If creating the BUFFER_HANDLE in SRS_HTTPAPIEX_02_020 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */
                        result = __LINE__;
                        if (*isOriginalRequestContent == false)
                        {
                            BUFFER_delete(*toBeUsedRequestContent);
                        }
                        if (*isOriginalRequestHttpHeadersHandle == false)
                        {
                            HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle);
                        }
                        if (*isOriginalResponseHttpHeadersHandle == false)
                        {
                            HTTPHeaders_Free(*toBeUsedResponseHttpHeadersHandle);
                        }
                        LogError("unable to build response content\r\n");
                    }
                    else
                    {
                        result = 0;
                    }
                }
            }
        }
        return result;
    }
    
    HTTPAPIEX_RESULT HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
        HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode,
        HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent)
    {
        HTTPAPIEX_RESULT result;
        /*Codes_SRS_HTTPAPIEX_02_006: [If parameter handle is NULL then HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.]*/
        if (handle == NULL)
        {
            result = HTTPAPIEX_INVALID_ARG;
            LOG_HTTAPIEX_ERROR();
        }
        else
        {
            /*Codes_SRS_HTTPAPIEX_02_007: [If parameter requestType does not indicate a valid request, HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.] */
            if (requestType >= COUNT_ARG(HTTPAPI_REQUEST_TYPE_VALUES))
            {
                result = HTTPAPIEX_INVALID_ARG;
                LOG_HTTAPIEX_ERROR();
            }
            else
            {
                HTTPAPIEX_HANDLE_DATA *handleData = (HTTPAPIEX_HANDLE_DATA *)handle;
    
                /*call to buildAll*/
                const char* toBeUsedRelativePath;
                HTTP_HEADERS_HANDLE toBeUsedRequestHttpHeadersHandle; bool isOriginalRequestHttpHeadersHandle;
                BUFFER_HANDLE toBeUsedRequestContent; bool isOriginalRequestContent;
                unsigned int* toBeUsedStatusCode;
                HTTP_HEADERS_HANDLE toBeUsedResponseHttpHeadersHandle; bool isOriginalResponseHttpHeadersHandle;
                BUFFER_HANDLE toBeUsedResponseContent;  bool isOriginalResponseContent;
    
                if (buildAllRequests(handleData, requestType, relativePath, requestHttpHeadersHandle, requestContent, statusCode, responseHttpHeadersHandle, responseContent,
                    &toBeUsedRelativePath,
                    &toBeUsedRequestHttpHeadersHandle, &isOriginalRequestHttpHeadersHandle,
                    &toBeUsedRequestContent, &isOriginalRequestContent,
                    &toBeUsedStatusCode,
                    &toBeUsedResponseHttpHeadersHandle, &isOriginalResponseHttpHeadersHandle,
                    &toBeUsedResponseContent, &isOriginalResponseContent) != 0)
                {
                    result = HTTPAPIEX_ERROR;
                    LOG_HTTAPIEX_ERROR();
                }
                else
                {
    
                    /*Codes_SRS_HTTPAPIEX_02_023: [HTTPAPIEX_ExecuteRequest shall try to execute the HTTP call by ensuring the following API call sequence is respected:]*/
                    /*Codes_SRS_HTTPAPIEX_02_024: [If any point in the sequence fails, HTTPAPIEX_ExecuteRequest shall attempt to recover by going back to the previous step and retrying that step.]*/
                    /*Codes_SRS_HTTPAPIEX_02_025: [If the first step fails, then the sequence fails.]*/
                    /*Codes_SRS_HTTPAPIEX_02_026: [A step shall be retried at most once.]*/
                    /*Codes_SRS_HTTPAPIEX_02_027: [If a step has been retried then all subsequent steps shall be retried too.]*/
                    bool st[3] = { false, false, false }; /*the three levels of possible failure in resilient send: HTTAPI_Init, HTTPAPI_CreateConnection, HTTPAPI_ExecuteRequest*/
                    if (handleData->k == -1)
                    {
                        handleData->k = 0;
                    }
    
                    do
                    {
                        bool goOn;
    
                        if (handleData->k > 2)
                        {
                            /* error */
                            break;
                        }
    
                        if (st[handleData->k] == true) /*already been tried*/
                        {
                            goOn = false;
                        }
                        else
                        {
                            switch (handleData->k)
                            {
                            case 0:
                            {
                                if (HTTPAPI_Init() != HTTPAPI_OK)
                                {
                                    LogError("HTTPAPI_Init() != HTTPAPI_OK\r\n");
    								goOn = false;
                                }
                                else
                                {
                                    LogError("HTTPAPI_Init() == HTTPAPI_OK\r\n");
    								goOn = true;
                                }
                                break;
                            }
                            case 1:
                            {
                                if ((handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL)
                                {
                                    LogError("handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL\r\n");
    								goOn = false;
                                }
                                else
                                {
                                    LogError("handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) != NULL\r\n");
    								size_t i;
                                    size_t vectorSize = VECTOR_size(handleData->savedOptions);
                                    for (i = 0; i < vectorSize; i++)
                                    {
                                        /*Codes_SRS_HTTPAPIEX_02_035: [HTTPAPIEX_ExecuteRequest shall pass all the saved options (see HTTPAPIEX_SetOption) to the newly create HTTPAPI_HANDLE in step 2 by calling HTTPAPI_SetOption.]*/
                                        /*Codes_SRS_HTTPAPIEX_02_036: [If setting the option fails, then the failure shall be ignored.] */
                                        HTTPAPIEX_SAVED_OPTION* option = VECTOR_element(handleData->savedOptions, i);
                                        if (HTTPAPI_SetOption(handleData->httpHandle, option->optionName, option->value) != HTTPAPI_OK)
                                        {
                                            LogError("HTTPAPI_SetOption failed when called for option %s\r\n", option->optionName);
                                        }
                                    }
                                    goOn = true;
                                }
                                break;
                            }
                            case 2:
                            {
                                if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, BUFFER_u_char(toBeUsedRequestContent), BUFFER_length(toBeUsedRequestContent), toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK)
                                {
                                    LogError("HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, BUFFER_u_char(toBeUsedRequestContent), BUFFER_length(toBeUsedRequestContent), toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK");
    								goOn = false;
                                }
                                else
                                {
                                    LogError("HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, BUFFER_u_char(toBeUsedRequestContent), BUFFER_length(toBeUsedRequestContent), toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) == HTTPAPI_OK"); 
    								goOn = true;
                                }
                                break;
                            }
                            default:
                            {
                                /*serious error*/
                                LogError("Serious error"); 
    							goOn = false;
                                break;
                            }
                            }
                        }
    
                        if (goOn)
                        {
                            if (handleData->k == 2)
                            {
                                /*Codes_SRS_HTTPAPIEX_02_028: [HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_OK when a call to HTTPAPI_ExecuteRequest has been completed successfully.]*/
                                result = HTTPAPIEX_OK;
                                goto out;
                            }
                            else
                            {
                                LogError("the program has been here"); 
    							st[handleData->k] = true;
                                handleData->k++;
                                st[handleData->k] = false;
                            }
                        }
                        else
                        {
                            st[handleData->k] = false;
                            handleData->k--;
                            switch (handleData->k)
                            {
                            case 0:
                            {
                                LogError("handleData->k is 0"); 
    							HTTPAPI_Deinit();
                                break;
                            }
                            case 1:
                            {
                                HTTPAPI_CloseConnection(handleData->httpHandle);
                                handleData->httpHandle = NULL;
                                break;
                            }
                            case 2:
                            {
                                break;
                            }
                            default:
                            {
    							LogError("handleData->k is default"); 
                                break;
                            }
                            }
                        }
                    } while (handleData->k >= 0);
                    /*Codes_SRS_HTTPAPIEX_02_029: [Otherwise, HTTAPIEX_ExecuteRequest shall return HTTPAPIEX_RECOVERYFAILED.] */
                    result = HTTPAPIEX_RECOVERYFAILED;
                    LogError("unable to recover sending to a working state\r\n");
                out:;
                    /*in all cases, unbuild the temporaries*/
                    if (isOriginalRequestContent == false)
                    {
                        BUFFER_delete(toBeUsedRequestContent);
                    }
                    if (isOriginalRequestHttpHeadersHandle == false)
                    {
                        HTTPHeaders_Free(toBeUsedRequestHttpHeadersHandle);
                    }
                    if (isOriginalResponseContent == false)
                    {
                        BUFFER_delete(toBeUsedResponseContent);
                    }
                    if (isOriginalResponseHttpHeadersHandle == false)
                    {
                        HTTPHeaders_Free(toBeUsedResponseHttpHeadersHandle);
                    }
                }
            }
        }
        return result;
    }
    
    
    void HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle)
    {
        if (handle != NULL)
        {
            /*Codes_SRS_HTTPAPIEX_02_042: [HTTPAPIEX_Destroy shall free all the resources used by HTTAPIEX_HANDLE.]*/
            size_t i;
            size_t vectorSize;
            HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle;
            
            if (handleData->k == 2)
            {
                HTTPAPI_CloseConnection(handleData->httpHandle);
                HTTPAPI_Deinit();
            }
            STRING_delete(handleData->hostName);
    
            vectorSize = VECTOR_size(handleData->savedOptions);
            for (i = 0; i < vectorSize; i++)
            {
                HTTPAPIEX_SAVED_OPTION*savedOption = VECTOR_element(handleData->savedOptions, i);
                free((void*)savedOption->optionName);
                free((void*)savedOption->value);
            }
            VECTOR_destroy(handleData->savedOptions);
    
            free(handle);
        }
        else
        {
            /*Codes_SRS_HTTPAPIEX_02_043: [If parameter handle is NULL then HTTPAPIEX_Destroy shall take no action.] */
        }
    }
    
    static bool sameName(const void* element, const void* value)
    {
        return (strcmp(((HTTPAPIEX_SAVED_OPTION*)element)->optionName, value) == 0) ? true : false;
    }
    
    /*return 0 on success, any other value is error*/
    /*obs: value is already cloned at the time of calling this function */
    static int createOrUpdateOption(HTTPAPIEX_HANDLE_DATA* handleData, const char* optionName, const void* value)
    {
        /*this function is called after the option value has been saved (cloned)*/
        int result;
        
        /*decide bwtween update or create*/
        HTTPAPIEX_SAVED_OPTION* whereIsIt = VECTOR_find_if(handleData->savedOptions, sameName, optionName);
        if (whereIsIt != NULL)
        {
            free((void*)(whereIsIt->value));
            whereIsIt->value = value;
            result = 0;
        }
        else
        {
            HTTPAPIEX_SAVED_OPTION newOption;
            if (mallocAndStrcpy_s((char**)&(newOption.optionName), optionName) != 0)
            {
                free((void*)value);
                result = __LINE__;
            }
            else
            {
                newOption.value = value;
                if (VECTOR_push_back(handleData->savedOptions, &newOption, 1) != 0)
                {
                    LogError("unable to VECTOR_push_back\r\n");
                    free((void*)newOption.optionName);
                    free((void*)value);
                    result = __LINE__;
                }
                else
                {
                    result = 0;
                }
            }
        }
        
        return result;
    }
    
    HTTPAPIEX_RESULT HTTPAPIEX_SetOption(HTTPAPIEX_HANDLE handle, const char* optionName, const void* value)
    {
        HTTPAPIEX_RESULT result;
        /*Codes_SRS_HTTPAPIEX_02_032: [If parameter handle is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
        /*Codes_SRS_HTTPAPIEX_02_033: [If parameter optionName is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
        /*Codes_SRS_HTTPAPIEX_02_034: [If parameter value is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */
        if (
            (handle == NULL) ||
            (optionName == NULL) ||
            (value == NULL)
            )
        {
            result = HTTPAPIEX_INVALID_ARG;
            LOG_HTTAPIEX_ERROR();
        }
        else
        {
            const void* savedOption;
            HTTPAPI_RESULT saveOptionResult;
    
            /*Codes_SRS_HTTPAPIEX_02_037: [HTTPAPIEX_SetOption shall attempt to save the value of the option by calling HTTPAPI_CloneOption passing optionName and value, irrespective of the existence of a HTTPAPI_HANDLE] */
            saveOptionResult = HTTPAPI_CloneOption(optionName, value, &savedOption);
    
            if(saveOptionResult == HTTPAPI_INVALID_ARG)
            {
                /*Codes_SRS_HTTPAPIEX_02_038: [If HTTPAPI_CloneOption returns HTTPAPI_INVALID_ARG then HTTPAPIEX shall return HTTPAPIEX_INVALID_ARG.] */
                result = HTTPAPIEX_INVALID_ARG;
                LOG_HTTAPIEX_ERROR();
            }
            else if (saveOptionResult != HTTPAPI_OK)
            {
                /*Codes_SRS_HTTPAPIEX_02_040: [For all other return values of HTTPAPI_SetOption, HTTPIAPIEX_SetOption shall return HTTPAPIEX_ERROR.] */
                result = HTTPAPIEX_ERROR;
                LOG_HTTAPIEX_ERROR();
            }
            else
            {
                HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle;
                /*Codes_SRS_HTTPAPIEX_02_039: [If HTTPAPI_CloneOption returns HTTPAPI_OK then HTTPAPIEX_SetOption shall create or update the pair optionName/value.]*/
                if (createOrUpdateOption(handleData, optionName, savedOption) != 0)
                {
                    /*Codes_SRS_HTTPAPIEX_02_041: [If creating or updating the pair optionName/value fails then shall return HTTPAPIEX_ERROR.] */
                    result = HTTPAPIEX_ERROR;
                    LOG_HTTAPIEX_ERROR();
                    
                }
                else
                {
                    /*Codes_SRS_HTTPAPIEX_02_031: [If HTTPAPI_HANDLE exists then HTTPAPIEX_SetOption shall call HTTPAPI_SetOption passing the same optionName and value and shall return a value conforming to the below table:] */
                    if (handleData->httpHandle != NULL)
                    {
                        HTTPAPI_RESULT HTTPAPI_result = HTTPAPI_SetOption(handleData->httpHandle, optionName, value);
                        if (HTTPAPI_result == HTTPAPI_OK)
                        {
                            result = HTTPAPIEX_OK;
                        }
                        else if (HTTPAPI_result == HTTPAPI_INVALID_ARG)
                        {
                            result = HTTPAPIEX_INVALID_ARG;
                            LOG_HTTAPIEX_ERROR();
                        }
                        else
                        {
                            result = HTTPAPIEX_ERROR;
                            LOG_HTTAPIEX_ERROR();
                        }
                    }
                    else
                    {
                        result = HTTPAPIEX_OK;
                    }
                }
            }
        }
        return result;
    }
    

    Monday, November 23, 2015 5:16 AM

All replies