VirtualBox

Changeset 74126 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
Sep 6, 2018 6:29:40 PM (6 years ago)
Author:
vboxsync
Message:

IPRT/rest: More work on binary downloads and uploads. bugref:9167

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

Legend:

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

    r74117 r74126  
    3636
    3737
     38/*********************************************************************************************************************************
     39*   Defined Constants And Macros                                                                                                 *
     40*********************************************************************************************************************************/
     41/** The default maximum download size. */
     42#if ARCH_BITS == 32
     43# define RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT  _32M
     44#else
     45# define RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT  _128M
     46#endif
     47
    3848
    3949/** Default constructor. */
     
    4151    : RTCRestObjectBase()
    4252    , m_pbData(NULL)
    43     , m_cbData(UINT64_MAX)
     53    , m_cbAllocated(0)
     54    , m_fFreeData(false)
     55    , m_cbContentLength(UINT64_MAX)
    4456    , m_pvCallbackData(NULL)
     57    , m_strContentType()
     58    , m_pfnProducer(NULL)
    4559    , m_pfnConsumer(NULL)
    46     , m_pfnProducer(NULL)
    47     , m_fFreeData(false)
    48     , m_strContentType()
     60    , m_cbDownloaded(0)
     61    , m_cbMaxDownload(RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT)
    4962{
    5063}
     
    5669RTCRestBinaryString::~RTCRestBinaryString()
    5770{
    58     if (m_pbData)
    59     {
    60         if (m_fFreeData)
    61             RTMemFree(m_pbData);
    62         m_pbData = NULL;
    63     }
    64     m_fFreeData      = false;
     71    freeData();
    6572    m_pvCallbackData = NULL;
    6673    m_pfnProducer    = NULL;
     
    7986
    8087
     88void RTCRestBinaryString::freeData()
     89{
     90    if (m_pbData)
     91    {
     92        if (m_fFreeData)
     93            RTMemFree(m_pbData);
     94        m_pbData = NULL;
     95    }
     96    m_fFreeData       = false;
     97    m_cbAllocated     = 0;
     98    m_cbDownloaded    = 0;
     99    m_cbContentLength = UINT64_MAX;
     100}
     101
     102
    81103/*********************************************************************************************************************************
    82104*   Overridden methods                                                                                                           *
     
    141163*********************************************************************************************************************************/
    142164
     165int RTCRestBinaryString::setContentType(const char *a_pszContentType)
     166{
     167    return m_strContentType.assignNoThrow(a_pszContentType);
     168}
     169
     170
     171int RTCRestBinaryString::setUploadData(void const *a_pvData, size_t a_cbData, bool a_fCopy /*= true*/)
     172{
     173    freeData();
     174
     175    if (a_cbData != 0)
     176    {
     177        if (a_fCopy)
     178        {
     179            m_pbData = (uint8_t *)RTMemDup(a_pvData, a_cbData);
     180            AssertReturn(m_pbData, VERR_NO_MEMORY);
     181            m_fFreeData   = true;
     182            m_cbAllocated = a_cbData;
     183        }
     184        else
     185        {
     186            AssertPtrReturn(a_pvData, VERR_INVALID_POINTER);
     187            m_pbData = (uint8_t *)a_pvData;
     188        }
     189    }
     190    m_cbContentLength = a_cbData;
     191
     192    return VINF_SUCCESS;
     193}
     194
     195
     196void RTCRestBinaryString::setProducerCallback(PFNPRODUCER a_pfnProducer, void *a_pvCallbackData /*= NULL*/,
     197                                              uint64_t a_cbContentLength /*= UINT64_MAX*/)
     198{
     199    freeData();
     200
     201    m_cbContentLength = a_cbContentLength;
     202    m_pfnProducer     = a_pfnProducer;
     203    m_pvCallbackData  = a_pvCallbackData;
     204}
     205
     206
    143207int RTCRestBinaryString::xmitPrepare(RTHTTP a_hHttp) const
    144208{
     209    AssertReturn(m_pbData != NULL || m_pfnProducer != NULL || m_cbContentLength == 0, VERR_INVALID_STATE);
     210
     211
    145212    /*
    146213     * Set the content type if given.
     
    157224     * Set the content length if given.
    158225     */
    159     if (m_cbData != UINT64_MAX)
     226    if (m_cbContentLength != UINT64_MAX)
    160227    {
    161228        const char *pszContentLength = RTHttpGetHeader(a_hHttp, RT_STR_TUPLE("Content-Length"));
    162         AssertMsgReturn(!pszContentLength || RTStrToUInt64(pszContentLength) == m_cbData,
    163                         ("pszContentLength=%s does not match m_cbData=%RU64\n", pszContentLength, m_cbData),
     229        AssertMsgReturn(!pszContentLength || RTStrToUInt64(pszContentLength) == m_cbContentLength,
     230                        ("pszContentLength=%s does not match m_cbContentLength=%RU64\n", pszContentLength, m_cbContentLength),
    164231                        VERR_MISMATCH);
    165232        if (!pszContentLength)
    166233        {
    167234            char szValue[64];
    168             ssize_t cchValue = RTStrFormatU64(szValue, sizeof(szValue), m_cbData, 10, 0, 0, 0);
     235            ssize_t cchValue = RTStrFormatU64(szValue, sizeof(szValue), m_cbContentLength, 10, 0, 0, 0);
    169236            int rc = RTHttpAddHeader(a_hHttp, "Content-Length", szValue, cchValue, RTHTTPADDHDR_F_BACK);
    170237            AssertRCReturn(rc, rc);
     
    175242     * Register an upload callback.
    176243     */
    177     AssertReturn(m_pbData != NULL || m_pfnProducer != NULL || m_cbData == 0, VERR_INVALID_STATE);
    178 
    179     int rc = RTHttpSetUploadCallback(a_hHttp, m_cbData, xmitHttpCallback, (RTCRestBinaryString *)this);
     244    int rc = RTHttpSetUploadCallback(a_hHttp, m_cbContentLength, xmitHttpCallback, (RTCRestBinaryString *)this);
    180245    AssertRCReturn(rc, rc);
    181246
     
    199264     * Feed from the memory buffer.
    200265     */
    201     if (offContent < pThis->m_cbData)
    202     {
    203         uint64_t const cbLeft = pThis->m_cbData - offContent;
     266    if (offContent < pThis->m_cbContentLength)
     267    {
     268        uint64_t const cbLeft = pThis->m_cbContentLength - offContent;
    204269        size_t const cbToCopy = cbLeft >= cbBuf ? cbBuf : (size_t)cbLeft;
    205270        memcpy(pvBuf, &pThis->m_pbData[(size_t)offContent], cbToCopy);
     
    217282{
    218283    /* Unset the callback. */
    219     int rc = RTHttpSetUploadCallback(a_hHttp, m_cbData, NULL, NULL);
     284    int rc = RTHttpSetUploadCallback(a_hHttp, UINT64_MAX, NULL, NULL);
    220285    AssertRC(rc);
    221286}
    222287
    223288
     289/*********************************************************************************************************************************
     290*   Download related methods                                                                                                     *
     291*********************************************************************************************************************************/
     292
     293void RTCRestBinaryString::setMaxDownloadSize(size_t a_cbMaxDownload)
     294{
     295    if (a_cbMaxDownload == 0)
     296        m_cbMaxDownload = RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT;
     297    else
     298        m_cbMaxDownload = a_cbMaxDownload;
     299}
     300
     301
     302void RTCRestBinaryString::setConsumerCallback(PFNCONSUMER a_pfnConsumer, void *a_pvCallbackData /*= NULL*/)
     303{
     304    freeData();
     305
     306    a_pfnConsumer    = a_pfnConsumer;
     307    m_pvCallbackData = a_pvCallbackData;
     308}
     309
     310
     311int RTCRestBinaryString::receivePrepare(RTHTTP a_hHttp, uint32_t a_fCallbackFlags)
     312{
     313    /*
     314     * Register an download callback.
     315     */
     316    int rc = RTHttpSetDownloadCallback(a_hHttp, a_fCallbackFlags, receiveHttpCallback, this);
     317    AssertRCReturn(rc, rc);
     318
     319    return VINF_SUCCESS;
     320}
     321
     322
     323void RTCRestBinaryString::receiveComplete(RTHTTP a_hHttp)
     324{
     325    /* Unset the callback. */
     326    int rc = RTHttpSetDownloadCallback(a_hHttp, RTHTTPDOWNLOAD_F_ANY_STATUS, NULL, NULL);
     327    AssertRC(rc);
     328}
     329
     330
     331/*static*/ DECLCALLBACK(int)
     332RTCRestBinaryString::receiveHttpCallback(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
     333                                         uint64_t offContent, uint64_t cbContent, void *pvUser)
     334{
     335    RTCRestBinaryString *pThis = (RTCRestBinaryString *)pvUser;
     336    Assert(offContent == pThis->m_cbDownloaded);
     337    pThis->m_cbContentLength = cbContent;
     338
     339    /*
     340     * Call the user download callback if we've got one.
     341     */
     342    if (pThis->m_pfnConsumer)
     343    {
     344        int rc = pThis->m_pfnConsumer(pThis, pvBuf, cbBuf, uHttpStatus, offContent, cbContent);
     345        if (RT_SUCCESS(rc))
     346            pThis->m_cbDownloaded = offContent + cbBuf;
     347        return rc;
     348    }
     349
     350    /*
     351     * Check download limit before adding more data.
     352     */
     353    AssertMsgReturn(offContent + cbBuf <= pThis->m_cbMaxDownload,
     354                    ("%RU64 + %zu = %RU64; max=%RU64", offContent, cbBuf, offContent + cbBuf, pThis->m_cbMaxDownload),
     355                    VERR_TOO_MUCH_DATA);
     356    if (offContent == 0 && cbContent != UINT64_MAX)
     357        AssertMsgReturn(cbContent <= pThis->m_cbMaxDownload, ("cbContent: %RU64; max=%RU64", cbContent,  pThis->m_cbMaxDownload),
     358                        VERR_TOO_MUCH_DATA);
     359
     360    /*
     361     * Make sure we've got buffer space before we copy in the data.
     362     */
     363    if (offContent + cbBuf <= pThis->m_cbAllocated)
     364    { /* likely, except for the first time. */ }
     365    else if (offContent == 0 && cbContent != UINT64_MAX)
     366    {
     367        void *pvNew = RTMemRealloc(pThis->m_pbData, (size_t)cbContent);
     368        if (!pvNew)
     369            return VERR_NO_MEMORY;
     370        pThis->m_pbData = (uint8_t *)pvNew;
     371        pThis->m_cbAllocated = (size_t)cbContent;
     372    }
     373    else
     374    {
     375        size_t cbNeeded = offContent + cbBuf;
     376        size_t cbNew;
     377        if (pThis->m_cbAllocated == 0)
     378            cbNew = RT_MAX(_64K, RT_ALIGN_Z(cbNeeded, _64K));
     379        else if (pThis->m_cbAllocated < _64M && cbNeeded <= _64M)
     380        {
     381            cbNew = pThis->m_cbAllocated * 2;
     382            while (cbNew < cbNeeded)
     383                cbNew *= 2;
     384        }
     385        else
     386            cbNew = RT_ALIGN_Z(cbNeeded, _32M);
     387
     388        void *pvNew = RTMemRealloc(pThis->m_pbData, cbNew);
     389        if (!pvNew)
     390            return VERR_NO_MEMORY;
     391        pThis->m_pbData = (uint8_t *)pvNew;
     392        pThis->m_cbAllocated = cbNew;
     393    }
     394
     395    /*
     396     * Do the copying.
     397     */
     398    memcpy(&pThis->m_pbData[(size_t)offContent], pvBuf, cbBuf);
     399    pThis->m_cbDownloaded = offContent + cbBuf;
     400
     401    RT_NOREF(hHttp);
     402    return VINF_SUCCESS;
     403}
     404
  • trunk/src/VBox/Runtime/generic/http-curl.cpp

    r74120 r74126  
    29062906            rtHttpGetDownloadStatusAndLength(pThis);
    29072907
    2908         if (   (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_F_ONLY_STATUS_MASK) == RTHTTPDOWNLOAD_F_F_ANY_STATUS
    2909             || (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_F_ONLY_STATUS_MASK) == pThis->uDownloadHttpStatus)
     2908        if (   (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK) == RTHTTPDOWNLOAD_F_ANY_STATUS
     2909            || (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK) == pThis->uDownloadHttpStatus)
    29102910        {
    29112911            int rc = pThis->pfnDownloadCallback(pThis, pchBuf, cbToAppend, pThis->uDownloadHttpStatus, pThis->offDownloadContent,
     
    29902990
    29912991    /* Call the callback if the HTTP status code matches, otherwise let it go to /dev/null. */
    2992     if (   (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_F_ONLY_STATUS_MASK) == RTHTTPDOWNLOAD_F_F_ANY_STATUS
    2993         || (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_F_ONLY_STATUS_MASK) == pThis->uDownloadHttpStatus)
     2992    if (   (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK) == RTHTTPDOWNLOAD_F_ANY_STATUS
     2993        || (pThis->fDownloadCallback & RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK) == pThis->uDownloadHttpStatus)
    29942994    {
    29952995        int rc = pThis->pfnDownloadCallback(pThis, pchBuf, cbBuf, pThis->uDownloadHttpStatus, pThis->offDownloadContent,
     
    35413541    PRTHTTPINTERNAL pThis = hHttp;
    35423542    RTHTTP_VALID_RETURN(pThis);
    3543     AssertReturn(!pfnCallback || (fFlags & RTHTTPDOWNLOAD_F_F_ONLY_STATUS_MASK) != 0, VERR_INVALID_FLAGS);
     3543    AssertReturn(!pfnCallback || (fFlags & RTHTTPDOWNLOAD_F_ONLY_STATUS_MASK) != 0, VERR_INVALID_FLAGS);
    35443544
    35453545    pThis->pfnDownloadCallback      = pfnCallback;
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