VirtualBox

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

Last change on this file since 96563 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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