VirtualBox

Changeset 73967 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 29, 2018 7:12:41 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/http: Implemented RTHttpPerform function. bugref:9167

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/rest/RTCRestClientApiBase.cpp

    r73918 r73967  
    125125                     */
    126126                    uint32_t uHttpStatus = 0;
    127                     rc = RTHttpPerform(hHttp, strFullUrl.c_str(), a_enmHttpMethod,
     127                    rc = RTHttpPerform(hHttp, strFullUrl.c_str(), a_enmHttpMethod, strXmitBody.c_str(), strXmitBody.length(),
    128128                                       &uHttpStatus, ppvHdrs, &cbHdrs, ppvBody, &cbBody);
    129129                    if (RT_SUCCESS(rc))
  • trunk/src/VBox/Runtime/generic/http-curl.cpp

    r73918 r73967  
    8181*   Structures and Typedefs                                                                                                      *
    8282*********************************************************************************************************************************/
     83/** Output collection data. */
     84typedef struct RTHTTPOUTPUTDATA
     85{
     86    /** Pointer to the HTTP client instance structure. */
     87    struct RTHTTPINTERNAL  *pHttp;
     88    /** Callback specific data. */
     89    union
     90    {
     91        /** For file destination.  */
     92        RTFILE          hFile;
     93        /** For memory destination. */
     94        struct
     95        {
     96            /** The current size (sans terminator char). */
     97            size_t      cb;
     98            /** The currently allocated size. */
     99            size_t      cbAllocated;
     100            /** Pointer to the buffer. */
     101            uint8_t    *pb;
     102        } Mem;
     103    } uData;
     104} RTHTTPOUTPUTDATA;
     105
    83106/**
    84107 * Internal HTTP client instance.
     
    141164    char               *pszRedirLocation;
    142165
    143     /** Output callback data. */
    144166    union
    145167    {
    146         /** For file destination.  */
    147         RTFILE          hFile;
    148         /** For memory destination. */
    149168        struct
    150169        {
    151             /** The current size (sans terminator char). */
    152             size_t      cb;
    153             /** The currently allocated size. */
    154             size_t      cbAllocated;
    155             /** Pointer to the buffer. */
    156             uint8_t    *pb;
     170            /** Pointer to the memory block we're feeding the cURL/server. */
     171            void const *pvMem;
     172            /** Size of the memory block. */
     173            size_t      cbMem;
     174            /** Current memory block offset. */
     175            size_t      offMem;
    157176        } Mem;
    158     } Output;
    159     /** Output callback status. */
     177    }                   ReadData;
     178
     179    /** Body output callback data. */
     180    RTHTTPOUTPUTDATA    BodyOutput;
     181    /** Headers output callback data. */
     182    RTHTTPOUTPUTDATA    HeadersOutput;
     183    /** The output status.*/
    160184    int                 rcOutput;
     185
    161186    /** Download size hint set by the progress callback. */
    162187    uint64_t            cbDownloadHint;
     
    260285static int rtHttpDarwinTryConfigProxies(PRTHTTPINTERNAL pThis, CFArrayRef hArrayProxies, CFURLRef hUrlTarget, bool fIgnorePacType);
    261286#endif
    262 static CURLcode rtHttpSetWriteCallback(PRTHTTPINTERNAL pThis, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser);
    263287
    264288
     
    271295    int rc = VERR_HTTP_INIT_FAILED;
    272296    CURLcode rcCurl = curl_global_init(CURL_GLOBAL_ALL);
    273     if (!CURL_FAILURE(rcCurl))
     297    if (CURL_SUCCESS(rcCurl))
    274298    {
    275299        CURL *pCurl = curl_easy_init();
     
    283307                pThis->fUseSystemProxySettings  = true;
    284308                pThis->cMaxRedirects            = 0; /* no automatic redir following */
     309                pThis->BodyOutput.pHttp         = pThis;
     310                pThis->HeadersOutput.pHttp      = pThis;
    285311
    286312                *phHttp = (RTHTTP)pThis;
     
    386412}
    387413
     414
     415RTR3DECL(int) RTHttpSetFollowRedirects(RTHTTP hHttp, uint32_t cMaxRedirects)
     416{
     417    PRTHTTPINTERNAL pThis = hHttp;
     418    RTHTTP_VALID_RETURN(pThis);
     419    AssertReturn(!pThis->fBusy, VERR_WRONG_ORDER);
     420
     421    /*
     422     * Update the redirection settings.
     423     */
     424    if (pThis->cMaxRedirects != cMaxRedirects)
     425    {
     426        int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_MAXREDIRS, (long)cMaxRedirects);
     427        AssertMsgReturn(rcCurl == CURLE_OK, ("CURLOPT_MAXREDIRS=%u: %d (%#x)\n", cMaxRedirects, rcCurl, rcCurl),
     428                        VERR_HTTP_CURL_ERROR);
     429
     430        rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_FOLLOWLOCATION, (long)(cMaxRedirects > 0));
     431        AssertMsgReturn(rcCurl == CURLE_OK, ("CURLOPT_FOLLOWLOCATION=%d: %d (%#x)\n", cMaxRedirects > 0, rcCurl, rcCurl),
     432                        VERR_HTTP_CURL_ERROR);
     433
     434        pThis->cMaxRedirects = cMaxRedirects;
     435    }
     436    return VINF_SUCCESS;
     437}
     438
     439
     440/*********************************************************************************************************************************
     441*   Proxy handling.                                                                                                              *
     442*********************************************************************************************************************************/
    388443
    389444RTR3DECL(int) RTHttpUseSystemProxySettings(RTHTTP hHttp)
     
    18621917
    18631918
    1864 RTR3DECL(int) RTHttpSetFollowRedirects(RTHTTP hHttp, uint32_t cMaxRedirects)
    1865 {
    1866     PRTHTTPINTERNAL pThis = hHttp;
    1867     RTHTTP_VALID_RETURN(pThis);
    1868     AssertReturn(!pThis->fBusy, VERR_WRONG_ORDER);
    1869 
    1870     /*
    1871      * Update the redirection settings.
    1872      */
    1873     if (pThis->cMaxRedirects != cMaxRedirects)
    1874     {
    1875         int rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_MAXREDIRS, (long)cMaxRedirects);
    1876         AssertMsgReturn(rcCurl == CURLE_OK, ("CURLOPT_MAXREDIRS=%u: %d (%#x)\n", cMaxRedirects, rcCurl, rcCurl),
    1877                         VERR_HTTP_CURL_ERROR);
    1878 
    1879         rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_FOLLOWLOCATION, (long)(cMaxRedirects > 0));
    1880         AssertMsgReturn(rcCurl == CURLE_OK, ("CURLOPT_FOLLOWLOCATION=%d: %d (%#x)\n", cMaxRedirects > 0, rcCurl, rcCurl),
    1881                         VERR_HTTP_CURL_ERROR);
    1882 
    1883         pThis->cMaxRedirects = cMaxRedirects;
    1884     }
    1885     return VINF_SUCCESS;
    1886 }
    1887 
     1919
     1920/*********************************************************************************************************************************
     1921*   HTTP Headers                                                                                                                 *
     1922*********************************************************************************************************************************/
    18881923
    18891924/**
     
    20502085}
    20512086
     2087
     2088
     2089/*********************************************************************************************************************************
     2090*   HTTPS and root certficates                                                                                                   *
     2091*********************************************************************************************************************************/
    20522092
    20532093/**
     
    22062246
    22072247
     2248/*********************************************************************************************************************************
     2249*   .......
     2250*********************************************************************************************************************************/
     2251
     2252
    22082253/**
    22092254 * Figures out the IPRT status code for a GET.
     
    22122257 * @param   pThis           The HTTP/HTTPS client instance.
    22132258 * @param   rcCurl          What curl returned.
    2214  */
    2215 static int rtHttpGetCalcStatus(PRTHTTPINTERNAL pThis, int rcCurl)
     2259 * @param   puHttpStatus    Where to optionally return the HTTP status.  If specified,
     2260 *                          the HTTP statuses are not translated to IPRT status codes.
     2261 */
     2262static int rtHttpGetCalcStatus(PRTHTTPINTERNAL pThis, int rcCurl, uint32_t *puHttpStatus)
    22162263{
    22172264    int rc = VERR_HTTP_CURL_ERROR;
     
    22252272    {
    22262273        curl_easy_getinfo(pThis->pCurl, CURLINFO_RESPONSE_CODE, &pThis->lLastResp);
     2274        if (puHttpStatus)
     2275        {
     2276            *puHttpStatus = pThis->lLastResp;
     2277            rc = VINF_SUCCESS;
     2278        }
     2279
    22272280        switch (pThis->lLastResp)
    22282281        {
     
    22442297                if (cb > 0 && cb < 2048)
    22452298                    pThis->pszRedirLocation = RTStrDup(pszRedirect);
    2246                 rc = VERR_HTTP_REDIRECTED;
     2299                if (!puHttpStatus)
     2300                    rc = VERR_HTTP_REDIRECTED;
    22472301                break;
    22482302            }
    22492303            case 400:
    22502304                /* bad request */
    2251                 rc = VERR_HTTP_BAD_REQUEST;
     2305                if (!puHttpStatus)
     2306                    rc = VERR_HTTP_BAD_REQUEST;
    22522307                break;
    22532308            case 403:
    22542309                /* forbidden, authorization will not help */
    2255                 rc = VERR_HTTP_ACCESS_DENIED;
     2310                if (!puHttpStatus)
     2311                    rc = VERR_HTTP_ACCESS_DENIED;
    22562312                break;
    22572313            case 404:
    22582314                /* URL not found */
    2259                 rc = VERR_HTTP_NOT_FOUND;
     2315                if (!puHttpStatus)
     2316                    rc = VERR_HTTP_NOT_FOUND;
    22602317                break;
    22612318        }
     
    24302487
    24312488/**
     2489 * Resets state.
     2490 *
     2491 * @param   pThis        HTTP client instance.
     2492 */
     2493static void rtHttpResetState(PRTHTTPINTERNAL pThis)
     2494{
     2495    pThis->fAbort                 = false;
     2496    pThis->rcOutput               = VINF_SUCCESS;
     2497    pThis->cbDownloadHint         = 0;
     2498    Assert(pThis->BodyOutput.pHttp == pThis);
     2499    Assert(pThis->HeadersOutput.pHttp == pThis);
     2500}
     2501
     2502
     2503
     2504/**
    24322505 * cURL callback for writing data.
    24332506 */
    24342507static size_t rtHttpWriteData(char *pcBuf, size_t cbUnit, size_t cUnits, void *pvUser)
    24352508{
    2436     PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pvUser;
     2509    RTHTTPOUTPUTDATA *pOutput = (RTHTTPOUTPUTDATA *)pvUser;
     2510    PRTHTTPINTERNAL   pThis = pOutput->pHttp;
    24372511
    24382512    /*
     
    24402514     */
    24412515    size_t const cbToAppend = cbUnit * cUnits;
    2442     size_t const cbCurSize  = pThis->Output.Mem.cb;
     2516    size_t const cbCurSize  = pOutput->uData.Mem.cb;
    24432517    size_t const cbNewSize  = cbCurSize + cbToAppend;
    24442518    if (   cbToAppend < RTHTTP_MAX_MEM_DOWNLOAD_SIZE
    24452519        && cbNewSize  < RTHTTP_MAX_MEM_DOWNLOAD_SIZE)
    24462520    {
    2447         if (cbNewSize + 1 <= pThis->Output.Mem.cbAllocated)
    2448         {
    2449             memcpy(&pThis->Output.Mem.pb[cbCurSize], pcBuf, cbToAppend);
    2450             pThis->Output.Mem.cb = cbNewSize;
    2451             pThis->Output.Mem.pb[cbNewSize] = '\0';
     2521        if (cbNewSize + 1 <= pOutput->uData.Mem.cbAllocated)
     2522        {
     2523            memcpy(&pOutput->uData.Mem.pb[cbCurSize], pcBuf, cbToAppend);
     2524            pOutput->uData.Mem.cb = cbNewSize;
     2525            pOutput->uData.Mem.pb[cbNewSize] = '\0';
    24522526            return cbToAppend;
    24532527        }
     
    24592533        size_t cbAlloc = RT_ALIGN_Z(cbNewSize + 1, 64);
    24602534        if (   cbAlloc <= pThis->cbDownloadHint
    2461             && pThis->cbDownloadHint < RTHTTP_MAX_MEM_DOWNLOAD_SIZE)
     2535            && pThis->cbDownloadHint < RTHTTP_MAX_MEM_DOWNLOAD_SIZE
     2536            && pOutput == &pThis->BodyOutput)
    24622537            cbAlloc = RT_ALIGN_Z(pThis->cbDownloadHint + 1, 64);
    24632538
    2464         uint8_t *pbNew = (uint8_t *)RTMemRealloc(pThis->Output.Mem.pb, cbAlloc);
     2539        uint8_t *pbNew = (uint8_t *)RTMemRealloc(pOutput->uData.Mem.pb, cbAlloc);
    24652540        if (pbNew)
    24662541        {
     
    24682543            pbNew[cbNewSize] = '\0';
    24692544
    2470             pThis->Output.Mem.cbAllocated = cbAlloc;
    2471             pThis->Output.Mem.pb = pbNew;
    2472             pThis->Output.Mem.cb = cbNewSize;
     2545            pOutput->uData.Mem.cbAllocated = cbAlloc;
     2546            pOutput->uData.Mem.pb = pbNew;
     2547            pOutput->uData.Mem.cb = cbNewSize;
    24732548            return cbToAppend;
    24742549        }
     
    24822557     * Failure - abort.
    24832558     */
    2484     RTMemFree(pThis->Output.Mem.pb);
    2485     pThis->Output.Mem.pb = NULL;
    2486     pThis->Output.Mem.cb = RTHTTP_MAX_MEM_DOWNLOAD_SIZE;
    2487     pThis->fAbort        = true;
     2559    RTMemFree(pOutput->uData.Mem.pb);
     2560    pOutput->uData.Mem.pb = NULL;
     2561    pOutput->uData.Mem.cb = RTHTTP_MAX_MEM_DOWNLOAD_SIZE;
     2562    pThis->fAbort   = true;
    24882563    return 0;
     2564}
     2565
     2566
     2567/**
     2568 * Callback feeding cURL data from RTHTTPINTERNAL::ReadData::Mem.
     2569 */
     2570static size_t rtHttpReadData(void *pvDst, size_t cbUnit, size_t cUnits, void *pvUser)
     2571{
     2572    PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pvUser;
     2573    size_t const cbReq    = cbUnit * cUnits;
     2574    size_t const offMem   = pThis->ReadData.Mem.offMem;
     2575    size_t cbToCopy = pThis->ReadData.Mem.cbMem - offMem;
     2576    if (cbToCopy > cbReq)
     2577        cbToCopy = cbReq;
     2578    memcpy(pvDst, (uint8_t const *)pThis->ReadData.Mem.pvMem + offMem, cbToCopy);
     2579    pThis->ReadData.Mem.offMem = offMem + cbToCopy;
     2580    return cbToCopy;
     2581}
     2582
     2583
     2584/**
     2585 * Helper for installing a (body) write callback function.
     2586 *
     2587 * @returns cURL status code.
     2588 * @param   pThis               The HTTP client instance.
     2589 * @param   pfnWrite            The callback.
     2590 * @param   pvUser              The callback user argument.
     2591 */
     2592static CURLcode rtHttpSetWriteCallback(PRTHTTPINTERNAL pThis, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser)
     2593{
     2594    CURLcode rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEFUNCTION, pfnWrite);
     2595    if (CURL_SUCCESS(rcCurl))
     2596        rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEDATA, pvUser);
     2597    return rcCurl;
     2598}
     2599
     2600
     2601/**
     2602 * Helper for installing a header write callback function.
     2603 *
     2604 * @returns cURL status code.
     2605 * @param   pThis               The HTTP client instance.
     2606 * @param   pfnWrite            The callback.
     2607 * @param   pvUser              The callback user argument.
     2608 */
     2609static CURLcode rtHttpSetHeaderCallback(PRTHTTPINTERNAL pThis, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser)
     2610{
     2611    CURLcode rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HEADERFUNCTION, pfnWrite);
     2612    if (CURL_SUCCESS(rcCurl))
     2613        rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HEADERDATA, pvUser);
     2614    return rcCurl;
     2615}
     2616
     2617
     2618/**
     2619 * Helper for installing a (body) read callback function.
     2620 *
     2621 * @returns cURL status code.
     2622 * @param   pThis               The HTTP client instance.
     2623 * @param   pfnRead             The callback.
     2624 * @param   pvUser              The callback user argument.
     2625 */
     2626static CURLcode rtHttpSetReadCallback(PRTHTTPINTERNAL pThis, PFNRTHTTPREADCALLBACK pfnRead, void *pvUser)
     2627{
     2628    CURLcode rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_READFUNCTION, pfnRead);
     2629    if (CURL_SUCCESS(rcCurl))
     2630        rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_READDATA, pvUser);
     2631    return rcCurl;
    24892632}
    24902633
     
    25272670     * Reset the state and apply settings.
    25282671     */
    2529     pThis->fAbort = false;
    2530     pThis->rcOutput = VINF_SUCCESS;
    2531     pThis->cbDownloadHint = 0;
    2532 
     2672    rtHttpResetState(pThis);
    25332673    int rc = rtHttpApplySettings(hHttp, pszUrl);
    25342674    if (RT_SUCCESS(rc))
    25352675    {
    2536         RT_ZERO(pThis->Output.Mem);
    2537         int rcCurl = rtHttpSetWriteCallback(pThis, &rtHttpWriteData, (void *)pThis);
     2676        RT_ZERO(pThis->BodyOutput.uData.Mem);
     2677        int rcCurl = rtHttpSetWriteCallback(pThis, &rtHttpWriteData, (void *)&pThis->BodyOutput);
    25382678        if (fNoBody)
    25392679        {
    2540             if (!CURL_FAILURE(rcCurl))
     2680            if (CURL_SUCCESS(rcCurl))
    25412681                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_NOBODY, 1L);
    2542             if (!CURL_FAILURE(rcCurl))
     2682            if (CURL_SUCCESS(rcCurl))
    25432683                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HEADER, 1L);
    25442684        }
    2545         if (!CURL_FAILURE(rcCurl))
     2685        if (CURL_SUCCESS(rcCurl))
    25462686        {
    25472687            /*
     
    25492689             */
    25502690            rcCurl = curl_easy_perform(pThis->pCurl);
    2551             rc = rtHttpGetCalcStatus(pThis, rcCurl);
     2691            rc = rtHttpGetCalcStatus(pThis, rcCurl, NULL);
    25522692            if (RT_SUCCESS(rc))
    25532693                rc = pThis->rcOutput;
    25542694            if (RT_SUCCESS(rc))
    25552695            {
    2556                 *ppvResponse = pThis->Output.Mem.pb;
    2557                 *pcb         = pThis->Output.Mem.cb;
    2558                 Log(("rtHttpGetToMem: %zx bytes (allocated %zx)\n", pThis->Output.Mem.cb, pThis->Output.Mem.cbAllocated));
     2696                *ppvResponse = pThis->BodyOutput.uData.Mem.pb;
     2697                *pcb         = pThis->BodyOutput.uData.Mem.cb;
     2698                Log(("rtHttpGetToMem: %zx bytes (allocated %zx)\n",
     2699                     pThis->BodyOutput.uData.Mem.cb, pThis->BodyOutput.uData.Mem.cbAllocated));
    25592700            }
    2560             else if (pThis->Output.Mem.pb)
    2561                 RTMemFree(pThis->Output.Mem.pb);
    2562             RT_ZERO(pThis->Output.Mem);
     2701            else if (pThis->BodyOutput.uData.Mem.pb)
     2702                RTMemFree(pThis->BodyOutput.uData.Mem.pb);
     2703            RT_ZERO(pThis->BodyOutput.uData.Mem);
    25632704        }
    25642705        else
     
    26412782static size_t rtHttpWriteDataToFile(char *pcBuf, size_t cbUnit, size_t cUnits, void *pvUser)
    26422783{
    2643     PRTHTTPINTERNAL pThis = (PRTHTTPINTERNAL)pvUser;
    2644     size_t cbWritten = 0;
    2645     int rc = RTFileWrite(pThis->Output.hFile, pcBuf, cbUnit * cUnits, &cbWritten);
     2784    RTHTTPOUTPUTDATA *pOutput   = (RTHTTPOUTPUTDATA *)pvUser;
     2785    PRTHTTPINTERNAL   pThis     = pOutput->pHttp;
     2786
     2787    size_t            cbWritten = 0;
     2788    int rc = RTFileWrite(pOutput->uData.hFile, pcBuf, cbUnit * cUnits, &cbWritten);
    26462789    if (RT_SUCCESS(rc))
    26472790        return cbWritten;
     2791
    26482792    Log(("rtHttpWriteDataToFile: rc=%Rrc cbUnit=%zd cUnits=%zu\n", rc, cbUnit, cUnits));
    26492793    pThis->rcOutput = rc;
     
    26672811     * Reset the state and apply settings.
    26682812     */
    2669     pThis->fAbort = false;
    2670     pThis->rcOutput = VINF_SUCCESS;
    2671     pThis->cbDownloadHint = 0;
    2672 
     2813    rtHttpResetState(pThis);
    26732814    int rc = rtHttpApplySettings(hHttp, pszUrl);
    26742815    if (RT_SUCCESS(rc))
    26752816    {
    2676         pThis->Output.hFile = NIL_RTFILE;
    2677         int rcCurl = rtHttpSetWriteCallback(pThis, &rtHttpWriteDataToFile, (void *)pThis);
    2678         if (!CURL_FAILURE(rcCurl))
     2817        pThis->BodyOutput.uData.hFile = NIL_RTFILE;
     2818        int rcCurl = rtHttpSetWriteCallback(pThis, &rtHttpWriteDataToFile, (void *)&pThis->BodyOutput);
     2819        if (CURL_SUCCESS(rcCurl))
    26792820        {
    26802821            /*
    26812822             * Open the output file.
    26822823             */
    2683             rc = RTFileOpen(&pThis->Output.hFile, pszDstFile, RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_READWRITE);
     2824            rc = RTFileOpen(&pThis->BodyOutput.uData.hFile, pszDstFile,
     2825                            RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_READWRITE);
    26842826            if (RT_SUCCESS(rc))
    26852827            {
     
    26882830                 */
    26892831                rcCurl = curl_easy_perform(pThis->pCurl);
    2690                 rc = rtHttpGetCalcStatus(pThis, rcCurl);
     2832                rc = rtHttpGetCalcStatus(pThis, rcCurl, NULL);
    26912833                if (RT_SUCCESS(rc))
    26922834                     rc = pThis->rcOutput;
    26932835
    2694                 int rc2 = RTFileClose(pThis->Output.hFile);
     2836                int rc2 = RTFileClose(pThis->BodyOutput.uData.hFile);
    26952837                if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
    26962838                    rc = rc2;
    26972839            }
    2698             pThis->Output.hFile = NIL_RTFILE;
     2840            pThis->BodyOutput.uData.hFile = NIL_RTFILE;
    26992841        }
    27002842        else
     
    27072849
    27082850
    2709 RTR3DECL(int) RTHttpPerform(RTHTTP hHttp, const char *pszUrl, RTHTTPMETHOD enmMethod,
     2851RTR3DECL(int) RTHttpPerform(RTHTTP hHttp, const char *pszUrl, RTHTTPMETHOD enmMethod, void const *pvReqBody, size_t cbReqBody,
    27102852                            uint32_t *puHttpStatus, void **ppvHeaders, size_t *pcbHeaders, void **ppvBody, size_t *pcbBody)
    27112853{
    2712     RT_NOREF(hHttp, pszUrl, enmMethod, puHttpStatus, ppvHeaders, pcbHeaders, ppvBody, pcbBody);
    2713     return VERR_NOT_IMPLEMENTED;
    2714 }
    2715 
     2854    /*
     2855     * Set safe return values and validate input.
     2856     */
     2857    Log(("RTHttpPerform: hHttp=%p pszUrl=%s enmMethod=%d pvReqBody=%p cbReqBody=%zu puHttpStatus=%p ppvHeaders=%p ppvBody=%p\n",
     2858         hHttp, pszUrl, enmMethod, pvReqBody, cbReqBody, puHttpStatus, ppvHeaders, ppvBody));
     2859
     2860    if (ppvHeaders)
     2861        *ppvHeaders = NULL;
     2862    if (pcbHeaders)
     2863        *pcbHeaders = 0;
     2864    if (ppvBody)
     2865        *ppvBody = NULL;
     2866    if (pcbBody)
     2867        *pcbBody = 0;
     2868    if (puHttpStatus)
     2869        *puHttpStatus = UINT32_MAX;
     2870
     2871    PRTHTTPINTERNAL pThis = hHttp;
     2872    RTHTTP_VALID_RETURN(pThis);
     2873    AssertReturn(enmMethod > RTHTTPMETHOD_INVALID && enmMethod < RTHTTPMETHOD_END, VERR_INVALID_PARAMETER);
     2874    AssertPtrReturn(pszUrl, VERR_INVALID_POINTER);
     2875
     2876    /*
     2877     * Set the busy flag (paranoia).
     2878     */
     2879    bool fBusy = ASMAtomicXchgBool(&pThis->fBusy, true);
     2880    AssertReturn(!fBusy, VERR_WRONG_ORDER);
     2881
     2882    /*
     2883     * Reset the state and apply settings.
     2884     */
     2885    rtHttpResetState(pThis);
     2886    int rc = rtHttpApplySettings(hHttp, pszUrl);
     2887    if (RT_SUCCESS(rc))
     2888    {
     2889
     2890        /* HTTP method. */
     2891        int rcCurl = 1;
     2892        switch (enmMethod)
     2893        {
     2894            case RTHTTPMETHOD_GET:
     2895                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPGET, 1L);
     2896                break;
     2897            case RTHTTPMETHOD_PUT:
     2898                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PUT, 1L);
     2899                break;
     2900            case RTHTTPMETHOD_POST:
     2901                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_POST, 1L);
     2902                break;
     2903            case RTHTTPMETHOD_PATCH:
     2904                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CUSTOMREQUEST, "PATCH");
     2905                break;
     2906            case RTHTTPMETHOD_DELETE:
     2907                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CUSTOMREQUEST, "DELETE");
     2908                break;
     2909            case RTHTTPMETHOD_HEAD:
     2910                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_HTTPGET, 1L);
     2911                if (CURL_SUCCESS(rcCurl))
     2912                    rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_NOBODY, 1L);
     2913                break;
     2914            case RTHTTPMETHOD_OPTIONS:
     2915                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CUSTOMREQUEST, "OPTIONS");
     2916                break;
     2917            case RTHTTPMETHOD_TRACE:
     2918                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CUSTOMREQUEST, "TRACE");
     2919                break;
     2920            case RTHTTPMETHOD_END:
     2921            case RTHTTPMETHOD_INVALID:
     2922            case RTHTTPMETHOD_32BIT_HACK:
     2923                AssertFailed();
     2924        }
     2925
     2926        /* Request body. */
     2927        if (pvReqBody && cbReqBody > 0 && CURL_SUCCESS(rcCurl))
     2928        {
     2929            if (enmMethod == RTHTTPMETHOD_POST)
     2930            {
     2931                /** @todo ??? */
     2932                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_POSTFIELDSIZE, cbReqBody);
     2933                if (CURL_SUCCESS(rcCurl))
     2934                    rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_POSTFIELDS, pvReqBody);
     2935            }
     2936            else
     2937            {
     2938                pThis->ReadData.Mem.pvMem  = pvReqBody;
     2939                pThis->ReadData.Mem.cbMem  = cbReqBody;
     2940                pThis->ReadData.Mem.offMem = 0;
     2941                rcCurl = rtHttpSetReadCallback(pThis, &rtHttpReadData, pThis);
     2942            }
     2943        }
     2944
     2945        /* Headers. */
     2946        if (ppvHeaders && CURL_SUCCESS(rcCurl))
     2947        {
     2948            RT_ZERO(pThis->HeadersOutput.uData.Mem);
     2949            rcCurl = rtHttpSetHeaderCallback(pThis, &rtHttpWriteData, &pThis->HeadersOutput);
     2950        }
     2951
     2952        /* Body */
     2953        if (ppvBody && CURL_SUCCESS(rcCurl))
     2954        {
     2955            RT_ZERO(pThis->BodyOutput.uData.Mem);
     2956            rcCurl = rtHttpSetWriteCallback(pThis, &rtHttpWriteData, &pThis->BodyOutput);
     2957        }
     2958
     2959        if (CURL_SUCCESS(rcCurl))
     2960        {
     2961            /*
     2962             * Perform the HTTP operation.
     2963             */
     2964            rcCurl = curl_easy_perform(pThis->pCurl);
     2965            rc = rtHttpGetCalcStatus(pThis, rcCurl, puHttpStatus);
     2966            if (RT_SUCCESS(rc))
     2967                rc = pThis->rcOutput;
     2968            if (RT_SUCCESS(rc))
     2969            {
     2970                if (ppvHeaders)
     2971                {
     2972                    *ppvHeaders = pThis->HeadersOutput.uData.Mem.pb;
     2973                    *pcbHeaders = pThis->HeadersOutput.uData.Mem.cb;
     2974                    pThis->HeadersOutput.uData.Mem.pb = NULL;
     2975                    Log(("RTHttpPerform: headers: %zx bytes (allocated %zx)\n",
     2976                         pThis->HeadersOutput.uData.Mem.cb, pThis->HeadersOutput.uData.Mem.cbAllocated));
     2977                }
     2978                if (ppvBody)
     2979                {
     2980                    *ppvBody = pThis->BodyOutput.uData.Mem.pb;
     2981                    *pcbBody = pThis->BodyOutput.uData.Mem.cb;
     2982                    pThis->BodyOutput.uData.Mem.pb = NULL;
     2983                    Log(("RTHttpPerform: body: %zx bytes (allocated %zx)\n",
     2984                         pThis->HeadersOutput.uData.Mem.cb, pThis->HeadersOutput.uData.Mem.cbAllocated));
     2985                }
     2986            }
     2987        }
     2988        else
     2989            rc = VERR_HTTP_CURL_ERROR;
     2990
     2991        /* Ensure we've freed all unused output and dropped references to input memory.*/
     2992        if (pThis->HeadersOutput.uData.Mem.pb)
     2993            RTMemFree(pThis->HeadersOutput.uData.Mem.pb);
     2994        if (pThis->BodyOutput.uData.Mem.pb)
     2995            RTMemFree(pThis->BodyOutput.uData.Mem.pb);
     2996        RT_ZERO(pThis->HeadersOutput.uData.Mem);
     2997        RT_ZERO(pThis->BodyOutput.uData.Mem);
     2998        RT_ZERO(pThis->ReadData);
     2999    }
     3000
     3001    ASMAtomicWriteBool(&pThis->fBusy, false);
     3002    return rc;
     3003}
     3004
     3005
     3006/*********************************************************************************************************************************
     3007*   Callback APIs.                                                                                                               *
     3008*********************************************************************************************************************************/
    27163009
    27173010RTR3DECL(int) RTHttpSetDownloadProgressCallback(RTHTTP hHttp, PFNRTHTTPDOWNLDPROGRCALLBACK pfnDownloadProgress, void *pvUser)
     
    27273020
    27283021
     3022/** @todo questionable wrt calling convension */
    27293023RTR3DECL(int) RTHttpSetReadCallback(RTHTTP hHttp, PFNRTHTTPREADCALLBACK pfnRead, void *pvUser)
    27303024{
     
    27463040
    27473041
    2748 static CURLcode rtHttpSetWriteCallback(PRTHTTPINTERNAL pThis, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser)
    2749 {
    2750     CURLcode rcCurl;
    2751 
    2752     rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEFUNCTION, pfnWrite);
    2753     if (CURL_FAILURE(rcCurl))
    2754         return rcCurl;
    2755 
    2756     rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_WRITEDATA, pvUser);
    2757     if (CURL_FAILURE(rcCurl))
    2758         return rcCurl;
    2759 
    2760     return rcCurl;
    2761 }
    2762 
    2763 
     3042/** @todo questionable wrt calling convension */
    27643043RTR3DECL(int) RTHttpSetWriteCallback(RTHTTP hHttp, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser)
    27653044{
     
    27753054
    27763055
     3056/** @todo questionable wrt calling convension */
    27773057RTR3DECL(int) RTHttpSetWriteHeaderCallback(RTHTTP hHttp, PFNRTHTTPWRITECALLBACK pfnWrite, void *pvUser)
    27783058{
     
    27943074
    27953075
     3076
     3077
     3078/*********************************************************************************************************************************
     3079*   Temporary raw cURL stuff.                                                                                                    *
     3080*********************************************************************************************************************************/
     3081
    27963082RTR3DECL(int) RTHttpRawSetUrl(RTHTTP hHttp, const char *pszUrl)
    27973083{
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette