Exemple #1
0
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.] */
    }
}
HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
{
    HTTP_HANDLE_DATA* result = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
    if (result == NULL)
    {
        /* error */
    }
    else
    {
        wchar_t hostNameTemp[1024];

        if (MultiByteToWideChar(CP_ACP, 0, hostName, -1, hostNameTemp, sizeof(hostNameTemp) / sizeof(hostNameTemp[0])) == 0)
        {
            /* error */
        }
        else
        {
            result->SessionHandle = InternetOpen(
                NULL,
                INTERNET_OPEN_TYPE_DIRECT,
                NULL,
                NULL,
                0);
            if (result->SessionHandle != NULL)
            {
                result->ConnectionHandle = InternetConnectW(
                    result->SessionHandle,
                    hostNameTemp,
                    INTERNET_DEFAULT_HTTPS_PORT,
                    NULL,
                    NULL,
                    INTERNET_SERVICE_HTTP,
                    0,
                    0);
            }

            if ((result->SessionHandle == NULL) ||
                (result->ConnectionHandle == NULL))
            {
                HTTPAPI_CloseConnection(result);
                result = NULL;
            }
        }
    }

    return (HTTP_HANDLE)result;
}
Exemple #3
0
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)
                            {
                                goOn = false;
                            }
                            else
                            {
                                goOn = true;
                            }
                            break;
                        }
                        case 1:
                        {
                            if ((handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL)
                            {
                                goOn = false;
                            }
                            else
                            {
                                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)
                            {
                                goOn = false;
                            }
                            else
                            {
                                goOn = true;
                            }
                            break;
                        }
                        default:
                        {
                            /*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
                        {
                            st[handleData->k] = true;
                            handleData->k++;
                            st[handleData->k] = false;
                        }
                    }
                    else
                    {
                        st[handleData->k] = false;
                        handleData->k--;
                        switch (handleData->k)
                        {
                        case 0:
                        {
                            HTTPAPI_Deinit();
                            break;
                        }
                        case 1:
                        {
                            HTTPAPI_CloseConnection(handleData->httpHandle);
                            handleData->httpHandle = NULL;
                            break;
                        }
                        case 2:
                        {
                            break;
                        }
                        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;
}