VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/rest/rest-binary.cpp@ 78272

Last change on this file since 78272 was 78272, checked in by vboxsync, 6 years ago

IPRT/rest: RTCRestBinaryResponse::receiveHttpCallback if we are
collecting data in m_pbData we also need to update m_cbData. I'm not
sure if we want to maintain m_cbDownloaded here at all as it is not
even accessible anyway (except to subclasses), but for now just do a
minimal fix to make the result usable.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 20.4 KB
Line 
1/* $Id: rest-binary.cpp 78272 2019-04-24 14:10:29Z vboxsync $ */
2/** @file
3 * IPRT - C++ REST, RTCRestBinary and Descendants.
4 */
5
6/*
7 * Copyright (C) 2018-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#define LOG_GROUP RTLOGGROUP_REST
32#include <iprt/cpp/restbase.h>
33#include <iprt/cpp/restclient.h>
34
35#include <iprt/assert.h>
36#include <iprt/errcore.h>
37#include <iprt/cpp/restoutput.h>
38
39
40/*********************************************************************************************************************************
41* Defined Constants And Macros *
42*********************************************************************************************************************************/
43/** The default maximum download size. */
44#if ARCH_BITS == 32
45# define RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT _32M
46#else
47# define RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT _128M
48#endif
49
50
51
52/*********************************************************************************************************************************
53* RTCRestBinary Implementation. *
54*********************************************************************************************************************************/
55/**
56 * Default constructor.
57 */
58RTCRestBinary::RTCRestBinary() RT_NOEXCEPT
59 : m_pbData(NULL)
60 , m_cbData(0)
61 , m_cbAllocated(0)
62 , m_fFreeable(true)
63 , m_fReadOnly(false)
64{
65}
66
67
68/**
69 * Destructor.
70 */
71RTCRestBinary::~RTCRestBinary()
72{
73 freeData();
74}
75
76/**
77 * Safe copy assignment method.
78 */
79int RTCRestBinary::assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT
80{
81 freeData();
82 if (a_rThat.m_pbData)
83 {
84 m_pbData = (uint8_t *)RTMemDup(a_rThat.m_pbData, a_rThat.m_cbAllocated);
85 AssertReturn(m_pbData, VERR_NO_MEMORY);
86 m_cbData = a_rThat.m_cbData;
87 m_cbAllocated = a_rThat.m_cbAllocated;
88 m_fFreeable = true;
89 m_fReadOnly = false;
90 m_fNullIndicator = false;
91 }
92 else
93 m_fNullIndicator = a_rThat.m_fNullIndicator;
94 return VINF_SUCCESS;
95}
96
97
98/**
99 * Safe buffer copy method.
100 */
101int RTCRestBinary::assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
102{
103 if ( m_pbData == NULL
104 || m_fReadOnly
105 || a_cbData > m_cbAllocated)
106 {
107 freeData();
108 m_pbData = (uint8_t *)RTMemDup(a_pvData, a_cbData);
109 AssertReturn(m_pbData, VERR_NO_MEMORY);
110 m_cbData = a_cbData;
111 m_cbAllocated = a_cbData;
112 m_fFreeable = true;
113 m_fReadOnly = false;
114 }
115 else
116 {
117 m_cbData = a_cbData;
118 memcpy(m_pbData, a_pvData, a_cbData);
119 }
120 m_fNullIndicator = false;
121 return VINF_SUCCESS;
122}
123
124
125/**
126 * Use the specified data buffer directly.
127 */
128int RTCRestBinary::assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
129{
130 freeData();
131 if (a_pvData)
132 {
133 m_pbData = (uint8_t *)a_pvData;
134 m_cbData = a_cbData;
135 m_cbAllocated = 0;
136 m_fFreeable = false;
137 m_fReadOnly = true;
138 m_fNullIndicator = false;
139 }
140 return VINF_SUCCESS;
141}
142
143
144/**
145 * Use the specified data buffer directly.
146 */
147int RTCRestBinary::assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT
148{
149 freeData();
150 if (a_pvBuf)
151 {
152 m_pbData = (uint8_t *)a_pvBuf;
153 m_cbData = a_cbBuf;
154 m_cbAllocated = a_cbBuf;
155 m_fFreeable = false;
156 m_fReadOnly = false;
157 m_fNullIndicator = false;
158 }
159 return VINF_SUCCESS;
160}
161
162
163/**
164 * Frees the data held by the object and resets it default state.
165 */
166void RTCRestBinary::freeData() RT_NOEXCEPT
167{
168 if (m_fFreeable)
169 RTMemFree(m_pbData);
170 m_pbData = NULL;
171 m_cbData = 0;
172 m_cbAllocated = 0;
173 m_fFreeable = true;
174 m_fReadOnly = false;
175}
176
177
178/* Overridden methods: */
179
180RTCRestObjectBase *RTCRestBinary::baseClone() const RT_NOEXCEPT
181{
182 RTCRestBinary *pClone = new (std::nothrow) RTCRestBinary();
183 if (pClone)
184 {
185 int rc = pClone->assignCopy(*this);
186 if (RT_SUCCESS(rc))
187 return pClone;
188 delete pClone;
189 }
190 return NULL;
191}
192
193
194int RTCRestBinary::setNull(void) RT_NOEXCEPT
195{
196 freeData();
197 m_fNullIndicator = true;
198 return VINF_SUCCESS;
199}
200
201
202int RTCRestBinary::resetToDefault(void) RT_NOEXCEPT
203{
204 freeData();
205 return VINF_SUCCESS;
206}
207
208
209RTCRestOutputBase &RTCRestBinary::serializeAsJson(RTCRestOutputBase &a_rDst) const RT_NOEXCEPT
210{
211 AssertMsgFailed(("We should never get here!\n"));
212 a_rDst.nullValue();
213 return a_rDst;
214}
215
216
217int RTCRestBinary::deserializeFromJson(RTCRestJsonCursor const &a_rCursor) RT_NOEXCEPT
218{
219 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NOT_SUPPORTED, "RTCRestBinary does not support deserialization!");
220}
221
222
223int RTCRestBinary::toString(RTCString *a_pDst, uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) const RT_NOEXCEPT
224{
225 RT_NOREF(a_pDst, a_fFlags);
226 AssertFailedReturn(VERR_NOT_SUPPORTED);
227}
228
229
230int RTCRestBinary::fromString(RTCString const &a_rValue, const char *a_pszName, PRTERRINFO a_pErrInfo/*= NULL*/,
231 uint32_t a_fFlags /*= kCollectionFormat_Unspecified*/) RT_NOEXCEPT
232{
233 RT_NOREF(a_rValue, a_pszName, a_fFlags);
234 AssertFailedReturn(RTErrInfoSet(a_pErrInfo, VERR_NOT_SUPPORTED, "RTCRestBinary does not support fromString()!"));
235}
236
237
238RTCRestObjectBase::kTypeClass RTCRestBinary::typeClass(void) const RT_NOEXCEPT
239{
240 return kTypeClass_Binary;
241}
242
243
244const char *RTCRestBinary::typeName(void) const RT_NOEXCEPT
245{
246 return "RTCRestBinary";
247}
248
249
250/** Factory method. */
251/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBinary::createInstance(void) RT_NOEXCEPT
252{
253 return new (std::nothrow) RTCRestBinary();
254}
255
256
257/**
258 * @copydoc RTCRestObjectBase::FNDESERIALIZEINSTANCEFROMJSON
259 */
260/*static*/ DECLCALLBACK(int)
261RTCRestBinary::deserializeInstanceFromJson(RTCRestJsonCursor const &a_rCursor, RTCRestObjectBase **a_ppInstance) RT_NOEXCEPT
262{
263 RTCRestObjectBase *pObj;
264 *a_ppInstance = pObj = createInstance();
265 if (pObj)
266 return pObj->deserializeFromJson(a_rCursor);
267 return a_rCursor.m_pPrimary->addError(a_rCursor, VERR_NO_MEMORY, "Out of memory");
268}
269
270
271
272/*********************************************************************************************************************************
273* RTCRestBinaryParameter Implementation. *
274*********************************************************************************************************************************/
275
276/**
277 * Default constructor.
278 */
279RTCRestBinaryParameter::RTCRestBinaryParameter() RT_NOEXCEPT
280 : RTCRestBinary()
281 , m_cbContentLength(UINT64_MAX)
282 , m_strContentType()
283 , m_pfnProducer(NULL)
284 , m_pvCallbackData(NULL)
285{
286}
287
288
289int RTCRestBinaryParameter::assignCopy(RTCRestBinaryParameter const &a_rThat) RT_NOEXCEPT
290{
291 AssertReturn(a_rThat.m_pfnProducer, VERR_INVALID_STATE);
292 int rc = assignCopy(*(RTCRestBinary const *)&a_rThat);
293 if (RT_SUCCESS(rc))
294 rc = m_strContentType.assignNoThrow(a_rThat.m_strContentType);
295 m_cbContentLength = a_rThat.m_cbContentLength;
296 m_pfnProducer = a_rThat.m_pfnProducer;
297 m_pvCallbackData = a_rThat.m_pvCallbackData;
298 return VINF_SUCCESS;
299}
300
301
302int RTCRestBinaryParameter::assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT
303{
304 m_cbContentLength = a_rThat.getSize();
305 m_strContentType.setNull();
306 m_pfnProducer = NULL;
307 m_pvCallbackData = NULL;
308 return RTCRestBinary::assignCopy(a_rThat);
309}
310
311
312int RTCRestBinaryParameter::assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
313{
314 m_cbContentLength = a_cbData;
315 m_pfnProducer = NULL;
316 m_pvCallbackData = NULL;
317 return RTCRestBinary::assignCopy(a_pvData, a_cbData);
318}
319
320
321int RTCRestBinaryParameter::assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
322{
323 m_cbContentLength = a_cbData;
324 m_pfnProducer = NULL;
325 m_pvCallbackData = NULL;
326 return RTCRestBinary::assignReadOnly(a_pvData, a_cbData);
327}
328
329
330int RTCRestBinaryParameter::assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT
331{
332 AssertMsgFailed(("Please use assignReadOnly!\n"));
333 return assignReadOnly(a_pvBuf, a_cbBuf);
334}
335
336
337RTCRestObjectBase *RTCRestBinaryParameter::baseClone() const RT_NOEXCEPT
338{
339 RTCRestBinaryParameter *pClone = new (std::nothrow) RTCRestBinaryParameter();
340 if (pClone)
341 {
342 int rc = pClone->assignCopy(*this);
343 if (RT_SUCCESS(rc))
344 return pClone;
345 delete pClone;
346 }
347 return NULL;
348}
349
350
351int RTCRestBinaryParameter::resetToDefault() RT_NOEXCEPT
352{
353 m_cbContentLength = UINT64_MAX;
354 m_pfnProducer = NULL;
355 m_pvCallbackData = NULL;
356 return RTCRestBinary::resetToDefault();
357}
358
359
360const char *RTCRestBinaryParameter::typeName(void) const RT_NOEXCEPT
361{
362 return "RTCRestBinaryParameter";
363}
364
365
366/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBinaryParameter::createInstance(void) RT_NOEXCEPT
367{
368 return new (std::nothrow) RTCRestBinaryParameter();
369}
370
371
372int RTCRestBinaryParameter::setContentType(const char *a_pszContentType) RT_NOEXCEPT
373{
374 return m_strContentType.assignNoThrow(a_pszContentType);
375}
376
377
378void RTCRestBinaryParameter::setProducerCallback(PFNPRODUCER a_pfnProducer, void *a_pvCallbackData /*= NULL*/,
379 uint64_t a_cbContentLength /*= UINT64_MAX*/) RT_NOEXCEPT
380{
381 freeData();
382
383 m_pfnProducer = a_pfnProducer;
384 m_pvCallbackData = a_pvCallbackData;
385 m_cbContentLength = a_cbContentLength;
386}
387
388
389int RTCRestBinaryParameter::xmitPrepare(RTHTTP a_hHttp) const RT_NOEXCEPT
390{
391 AssertReturn(m_pbData != NULL || m_pfnProducer != NULL || m_cbContentLength == 0, VERR_INVALID_STATE);
392
393
394 /*
395 * Set the content type if given.
396 */
397 if (m_strContentType.isNotEmpty())
398 {
399 Assert(!RTHttpGetHeader(a_hHttp, RT_STR_TUPLE("Content-Type")));
400 int rc = RTHttpAddHeader(a_hHttp, "Content-Type", m_strContentType.c_str(), m_strContentType.length(),
401 RTHTTPADDHDR_F_BACK);
402 AssertRCReturn(rc, rc);
403 }
404
405 /*
406 * Set the content length if given.
407 */
408 if (m_cbContentLength != UINT64_MAX)
409 {
410 const char *pszContentLength = RTHttpGetHeader(a_hHttp, RT_STR_TUPLE("Content-Length"));
411 AssertMsgReturn(!pszContentLength || RTStrToUInt64(pszContentLength) == m_cbContentLength,
412 ("pszContentLength=%s does not match m_cbContentLength=%RU64\n", pszContentLength, m_cbContentLength),
413 VERR_MISMATCH);
414 if (!pszContentLength)
415 {
416 char szValue[64];
417 ssize_t cchValue = RTStrFormatU64(szValue, sizeof(szValue), m_cbContentLength, 10, 0, 0, 0);
418 int rc = RTHttpAddHeader(a_hHttp, "Content-Length", szValue, cchValue, RTHTTPADDHDR_F_BACK);
419 AssertRCReturn(rc, rc);
420 }
421 }
422
423 /*
424 * Register an upload callback.
425 */
426 int rc = RTHttpSetUploadCallback(a_hHttp, m_cbContentLength, xmitHttpCallback, (RTCRestBinaryParameter *)this);
427 AssertRCReturn(rc, rc);
428
429 return VINF_SUCCESS;
430
431}
432
433
434/*static*/ DECLCALLBACK(int)
435RTCRestBinaryParameter::xmitHttpCallback(RTHTTP hHttp, void *pvBuf, size_t cbBuf,
436 uint64_t offContent, size_t *pcbActual, void *pvUser) RT_NOEXCEPT
437{
438 RTCRestBinaryParameter *pThis = (RTCRestBinaryParameter *)pvUser;
439
440 /*
441 * Call the user upload callback if we've got one.
442 */
443 if (pThis->m_pfnProducer)
444 return pThis->m_pfnProducer(pThis, pvBuf, cbBuf, offContent, pcbActual);
445
446 /*
447 * Feed from the memory buffer.
448 */
449 if (offContent < pThis->m_cbContentLength)
450 {
451 uint64_t const cbLeft = pThis->m_cbContentLength - offContent;
452 size_t const cbToCopy = cbLeft >= cbBuf ? cbBuf : (size_t)cbLeft;
453 memcpy(pvBuf, &pThis->m_pbData[(size_t)offContent], cbToCopy);
454 *pcbActual = cbToCopy;
455 }
456 else
457 *pcbActual = 0;
458
459 RT_NOREF(hHttp);
460 return VINF_SUCCESS;
461}
462
463
464void RTCRestBinaryParameter::xmitComplete(RTHTTP a_hHttp) const RT_NOEXCEPT
465{
466 /* Unset the callback. */
467 int rc = RTHttpSetUploadCallback(a_hHttp, UINT64_MAX, NULL, NULL);
468 AssertRC(rc);
469}
470
471
472/*********************************************************************************************************************************
473* RTCRestBinaryResponse Implementation. *
474*********************************************************************************************************************************/
475
476/**
477 * Default constructor.
478 */
479RTCRestBinaryResponse::RTCRestBinaryResponse() RT_NOEXCEPT
480 : RTCRestBinary()
481 , m_cbContentLength(UINT64_MAX)
482 , m_cbDownloaded(0)
483 , m_pfnConsumer(NULL)
484 , m_pvCallbackData(NULL)
485 , m_cbMaxDownload(RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT)
486{
487}
488
489
490int RTCRestBinaryResponse::assignCopy(RTCRestBinaryResponse const &a_rThat) RT_NOEXCEPT
491{
492 AssertReturn(a_rThat.m_pfnConsumer, VERR_INVALID_STATE);
493 int rc = assignCopy(*(RTCRestBinary const *)&a_rThat);
494 m_cbContentLength = a_rThat.m_cbContentLength;
495 m_cbDownloaded = a_rThat.m_cbDownloaded;
496 m_cbMaxDownload = a_rThat.m_cbMaxDownload;
497 return rc;
498}
499
500
501int RTCRestBinaryResponse::assignCopy(RTCRestBinary const &a_rThat) RT_NOEXCEPT
502{
503 m_cbContentLength = UINT64_MAX;
504 m_cbDownloaded = 0;
505 m_pfnConsumer = NULL;
506 m_pvCallbackData = NULL;
507 return RTCRestBinary::assignCopy(a_rThat);
508}
509
510
511int RTCRestBinaryResponse::assignCopy(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
512{
513 RT_NOREF(a_pvData, a_cbData);
514 AssertMsgFailedReturn(("Makes no sense for downloads.\n"), VERR_INVALID_STATE);
515}
516
517
518int RTCRestBinaryResponse::assignReadOnly(void const *a_pvData, size_t a_cbData) RT_NOEXCEPT
519{
520 RT_NOREF(a_pvData, a_cbData);
521 AssertMsgFailedReturn(("Makes no sense for downloads.\n"), VERR_INVALID_STATE);
522}
523
524
525int RTCRestBinaryResponse::assignWriteable(void *a_pvBuf, size_t a_cbBuf) RT_NOEXCEPT
526{
527 m_cbContentLength = UINT64_MAX;
528 m_cbDownloaded = 0;
529 m_pfnConsumer = NULL;
530 m_pvCallbackData = NULL;
531 AssertStmt(a_cbBuf <= m_cbMaxDownload, m_cbMaxDownload = a_cbBuf);
532 return RTCRestBinary::assignWriteable(a_pvBuf, a_cbBuf);
533}
534
535
536RTCRestObjectBase *RTCRestBinaryResponse::baseClone() const RT_NOEXCEPT
537{
538 RTCRestBinaryResponse *pClone = new (std::nothrow) RTCRestBinaryResponse();
539 if (pClone)
540 {
541 int rc = pClone->assignCopy(*this);
542 if (RT_SUCCESS(rc))
543 return pClone;
544 delete pClone;
545 }
546 return NULL;
547}
548
549
550int RTCRestBinaryResponse::resetToDefault() RT_NOEXCEPT
551{
552 m_cbContentLength = UINT64_MAX;
553 m_cbDownloaded = 0;
554 m_pfnConsumer = NULL;
555 m_pvCallbackData = NULL;
556 m_cbMaxDownload = RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT;
557 return RTCRestBinary::resetToDefault();
558}
559
560
561const char *RTCRestBinaryResponse::typeName(void) const RT_NOEXCEPT
562{
563 return "RTCRestBinaryResponse";
564}
565
566
567/*static*/ DECLCALLBACK(RTCRestObjectBase *) RTCRestBinaryResponse::createInstance(void) RT_NOEXCEPT
568{
569 return new (std::nothrow) RTCRestBinaryResponse();
570}
571
572
573void RTCRestBinaryResponse::setMaxDownloadSize(size_t a_cbMaxDownload) RT_NOEXCEPT
574{
575 if (a_cbMaxDownload == 0)
576 m_cbMaxDownload = RTCREST_MAX_DOWNLOAD_SIZE_DEFAULT;
577 else
578 m_cbMaxDownload = a_cbMaxDownload;
579}
580
581
582void RTCRestBinaryResponse::setConsumerCallback(PFNCONSUMER a_pfnConsumer, void *a_pvCallbackData /*= NULL*/) RT_NOEXCEPT
583{
584 freeData();
585
586 m_pfnConsumer = a_pfnConsumer;
587 m_pvCallbackData = a_pvCallbackData;
588 m_cbDownloaded = 0;
589 m_cbContentLength = UINT64_MAX;
590}
591
592
593int RTCRestBinaryResponse::receivePrepare(RTHTTP a_hHttp, uint32_t a_fCallbackFlags) RT_NOEXCEPT
594{
595 AssertReturn(!m_fReadOnly, VERR_INVALID_STATE);
596
597 /*
598 * Register the download callback.
599 */
600 int rc = RTHttpSetDownloadCallback(a_hHttp, a_fCallbackFlags, receiveHttpCallback, this);
601 AssertRC(rc);
602 return rc;
603}
604
605
606/*static*/ DECLCALLBACK(int)
607RTCRestBinaryResponse::receiveHttpCallback(RTHTTP hHttp, void const *pvBuf, size_t cbBuf, uint32_t uHttpStatus,
608 uint64_t offContent, uint64_t cbContent, void *pvUser) RT_NOEXCEPT
609{
610 RTCRestBinaryResponse *pThis = (RTCRestBinaryResponse *)pvUser;
611 Assert(offContent == pThis->m_cbDownloaded);
612 pThis->m_cbContentLength = cbContent;
613
614 /*
615 * Call the user download callback if we've got one.
616 */
617 if (pThis->m_pfnConsumer)
618 {
619 int rc = pThis->m_pfnConsumer(pThis, pvBuf, cbBuf, uHttpStatus, offContent, cbContent);
620 if (RT_SUCCESS(rc))
621 pThis->m_cbDownloaded = offContent + cbBuf;
622 return rc;
623 }
624
625 /*
626 * Check download limit before adding more data.
627 */
628 AssertMsgReturn(offContent + cbBuf <= pThis->m_cbMaxDownload,
629 ("%RU64 + %zu = %RU64; max=%RU64", offContent, cbBuf, offContent + cbBuf, pThis->m_cbMaxDownload),
630 VERR_TOO_MUCH_DATA);
631
632 /*
633 * Make sure we've got sufficient writable buffer space before we copy in the data.
634 */
635 AssertReturn(!pThis->m_fReadOnly, VERR_INVALID_STATE);
636 if (offContent + cbBuf <= pThis->m_cbAllocated)
637 { /* likely, except for the first time. */ }
638 else
639 {
640 AssertMsgReturn(pThis->m_fFreeable,
641 ("offContent=%RU64 cbBuf=%zu m_cbAllocated=%zu", offContent, cbBuf, pThis->m_cbAllocated),
642 VERR_TOO_MUCH_DATA);
643 AssertMsgReturn(cbContent <= pThis->m_cbMaxDownload || cbContent == UINT64_MAX,
644 ("cbContent: %RU64; max=%RU64", cbContent, pThis->m_cbMaxDownload),
645 VERR_TOO_MUCH_DATA);
646
647 if (offContent == 0 && cbContent != UINT64_MAX)
648 {
649 void *pvNew = RTMemRealloc(pThis->m_pbData, (size_t)cbContent);
650 if (!pvNew)
651 return VERR_NO_MEMORY;
652 pThis->m_pbData = (uint8_t *)pvNew;
653 pThis->m_cbAllocated = (size_t)cbContent;
654 }
655 else
656 {
657 size_t cbNeeded = offContent + cbBuf;
658 size_t cbNew;
659 if (pThis->m_cbAllocated == 0)
660 cbNew = RT_MAX(_64K, RT_ALIGN_Z(cbNeeded, _64K));
661 else if (pThis->m_cbAllocated < _64M && cbNeeded <= _64M)
662 {
663 cbNew = pThis->m_cbAllocated * 2;
664 while (cbNew < cbNeeded)
665 cbNew *= 2;
666 }
667 else
668 cbNew = RT_ALIGN_Z(cbNeeded, _32M);
669
670 void *pvNew = RTMemRealloc(pThis->m_pbData, cbNew);
671 if (!pvNew)
672 return VERR_NO_MEMORY;
673 pThis->m_pbData = (uint8_t *)pvNew;
674 pThis->m_cbAllocated = cbNew;
675 }
676 }
677
678 /*
679 * Do the copying.
680 */
681 memcpy(&pThis->m_pbData[(size_t)offContent], pvBuf, cbBuf);
682 pThis->m_cbDownloaded = offContent + cbBuf;
683
684 /* we cap it at m_cbMaxDownload which is size_t so this cast is safe */
685 pThis->m_cbData = (size_t)pThis->m_cbDownloaded;
686
687 RT_NOREF(hHttp);
688 return VINF_SUCCESS;
689}
690
691
692void RTCRestBinaryResponse::receiveComplete(RTHTTP a_hHttp) RT_NOEXCEPT
693{
694 /* Unset the callback. */
695 int rc = RTHttpSetDownloadCallback(a_hHttp, RTHTTPDOWNLOAD_F_ANY_STATUS, NULL, NULL);
696 AssertRC(rc);
697}
698
Note: See TracBrowser for help on using the repository browser.

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