29#ifndef CPL_VSIL_CURL_CLASS_H_INCLUDED
30#define CPL_VSIL_CURL_CLASS_H_INCLUDED
39#include "cpl_vsil_curl_priv.h"
40#include "cpl_mem_cache.h"
42#include "cpl_curl_priv.h"
53#define HAVE_CURLINFO_REDIRECT_URL
55void VSICurlStreamingClearCache(
void);
57struct curl_slist *VSICurlSetOptions(CURL *hCurlHandle,
const char *pszURL,
58 const char *
const *papszOptions);
59struct curl_slist *VSICurlMergeHeaders(
struct curl_slist *poDest,
60 struct curl_slist *poSrcToDestroy);
62struct curl_slist *VSICurlSetContentTypeFromExt(
struct curl_slist *polist,
65struct curl_slist *VSICurlSetCreationHeadersFromOptions(
66 struct curl_slist *headers,
CSLConstList papszOptions,
const char *pszPath);
81 unsigned int nGenerationAuthParameters = 0;
82 ExistStatus eExists = EXIST_UNKNOWN;
85 time_t nExpireTimestampLocal = 0;
87 bool bHasComputedFileSize =
false;
88 bool bIsDirectory =
false;
90 bool bS3LikeRedirect =
false;
96 bool bGotFileList =
false;
97 unsigned int nGenerationAuthParameters = 0;
101struct WriteFuncStruct
103 char *pBuffer =
nullptr;
105 bool bIsHTTP =
false;
106 bool bMultiRange =
false;
111 bool bFoundContentRange =
false;
113 bool bInterruptDownload =
false;
114 bool bDetectRangeDownloadingError =
false;
118 VSICurlReadCbkFunc pfnReadCbk =
nullptr;
119 void *pReadCbkUserData =
nullptr;
120 bool bInterrupted =
false;
121 bool bInterruptIfNonErrorPayload =
false;
123#if !CURL_AT_LEAST_VERSION(7, 54, 0)
127 bool bIsProxyConnectHeader =
false;
133 const GByte *pabyData =
nullptr;
135 size_t nTotalSize = 0;
137 static size_t ReadCallBackBuffer(
char *buffer,
size_t size,
size_t nitems,
140 PutData *poThis =
static_cast<PutData *
>(instream);
141 const size_t nSizeMax = size * nitems;
142 const size_t nSizeToWrite =
143 std::min(nSizeMax, poThis->nTotalSize - poThis->nOff);
144 memcpy(buffer, poThis->pabyData + poThis->nOff, nSizeToWrite);
145 poThis->nOff += nSizeToWrite;
156class VSICurlFilesystemHandlerBase :
public VSIFilesystemHandler
160 struct FilenameOffsetPair
162 std::string filename_;
165 FilenameOffsetPair(
const std::string &filename,
vsi_l_offset offset)
166 : filename_(filename), offset_(offset)
170 bool operator==(
const FilenameOffsetPair &other)
const
172 return filename_ == other.filename_ && offset_ == other.offset_;
175 struct FilenameOffsetPairHasher
177 std::size_t operator()(
const FilenameOffsetPair &k)
const
179 return std::hash<std::string>()(k.filename_) ^
180 std::hash<vsi_l_offset>()(k.offset_);
184 using RegionCacheType = lru11::Cache<
185 FilenameOffsetPair, std::shared_ptr<std::string>, lru11::NullLock,
188 typename std::list<lru11::KeyValuePair<
189 FilenameOffsetPair, std::shared_ptr<std::string>>>::iterator,
190 FilenameOffsetPairHasher>>;
192 std::unique_ptr<RegionCacheType>
193 m_poRegionCacheDoNotUseDirectly{};
195 RegionCacheType *GetRegionCache();
202 lru11::Cache<std::string, bool> oCacheFileProp;
204 int nCachedFilesInDirList = 0;
205 lru11::Cache<std::string, CachedDirList> oCacheDirList;
207 char **ParseHTMLFileList(
const char *pszFilename,
int nMaxFiles,
208 char *pszData,
bool *pbGotFileList);
211 CPLMutex *hMutex =
nullptr;
213 virtual VSICurlHandle *CreateFileHandle(
const char *pszFilename);
214 virtual char **GetFileList(
const char *pszFilename,
int nMaxFiles,
215 bool *pbGotFileList);
217 void RegisterEmptyDir(
const CPLString &osDirname);
220 AnalyseS3FileList(
const CPLString &osBaseURL,
const char *pszXML,
222 const std::set<std::string> &oSetIgnoredStorageClasses,
225 void AnalyseSwiftFileList(
const CPLString &osBaseURL,
226 const CPLString &osPrefix,
const char *pszJson,
228 int nMaxFiles,
bool &bIsTruncated,
231 static const char *GetOptionsStatic();
233 static bool IsAllowedFilename(
const char *pszFilename);
235 VSICurlFilesystemHandlerBase();
238 ~VSICurlFilesystemHandlerBase()
override;
244 int Stat(
const char *pszFilename,
VSIStatBufL *pStatBuf,
245 int nFlags)
override;
246 int Unlink(
const char *pszFilename)
override;
247 int Rename(
const char *oldpath,
const char *newpath)
override;
248 int Mkdir(
const char *pszDirname,
long nMode)
override;
249 int Rmdir(
const char *pszDirname)
override;
250 char **ReadDir(
const char *pszDirname)
override
252 return ReadDirEx(pszDirname, 0);
254 char **ReadDirEx(
const char *pszDirname,
int nMaxFiles)
override;
255 char **SiblingFiles(
const char *pszFilename)
override;
257 int HasOptimizedReadMultiRange(
const char * )
override
262 const char *GetActualURL(
const char *pszFilename)
override;
264 const char *GetOptions()
override;
266 char **GetFileMetadata(
const char *pszFilename,
const char *pszDomain,
269 char **ReadDirInternal(
const char *pszDirname,
int nMaxFiles,
270 bool *pbGotFileList);
271 void InvalidateDirContent(
const char *pszDirname);
273 virtual const char *GetDebugKey()
const = 0;
275 virtual CPLString GetFSPrefix()
const = 0;
276 virtual bool AllowCachedDataFor(
const char *pszFilename);
278 virtual bool IsLocal(
const char * )
override
283 SupportsSequentialWrite(
const char * ,
288 virtual bool SupportsRandomWrite(
const char * ,
294 std::shared_ptr<std::string> GetRegion(
const char *pszURL,
297 void AddRegion(
const char *pszURL,
vsi_l_offset nFileOffsetStart,
298 size_t nSize,
const char *pData);
300 bool GetCachedFileProp(
const char *pszURL, FileProp &oFileProp);
301 void SetCachedFileProp(
const char *pszURL, FileProp &oFileProp);
302 void InvalidateCachedData(
const char *pszURL);
304 CURLM *GetCurlMultiHandleFor(
const CPLString &osURL);
306 virtual void ClearCache();
307 virtual void PartialClearCache(
const char *pszFilename);
309 bool GetCachedDirList(
const char *pszURL, CachedDirList &oCachedDirList);
310 void SetCachedDirList(
const char *pszURL, CachedDirList &oCachedDirList);
311 bool ExistsInCacheDirList(
const CPLString &osDirname,
bool *pbIsDir);
316 GetStreamingFilename(
const std::string &osFilename)
const override = 0;
318 static std::set<std::string> GetS3IgnoredStorageClasses();
321class VSICurlFilesystemHandler :
public VSICurlFilesystemHandlerBase
326 VSICurlFilesystemHandler() =
default;
328 const char *GetDebugKey()
const override
339 GetStreamingFilename(
const std::string &osFilename)
const override;
351 VSICurlFilesystemHandlerBase *poFS =
nullptr;
353 bool m_bCached =
true;
355 mutable FileProp oFileProp{};
357 mutable std::mutex m_oMutex{};
359 char *m_pszURL =
nullptr;
360 mutable std::string m_osQueryString{};
362 char **m_papszHTTPOptions =
nullptr;
365 int nBlocksToDownload = 1;
367 bool bStopOnInterruptUntilUninstall =
false;
368 bool bInterrupted =
false;
369 VSICurlReadCbkFunc pfnReadCbk =
nullptr;
370 void *pReadCbkUserData =
nullptr;
373 double m_dfRetryDelay = 0.0;
377 void DownloadRegionPostProcess(
const vsi_l_offset startOffset,
378 const int nBlocks,
const char *pBuffer,
386 virtual std::string DownloadRegion(
vsi_l_offset startOffset,
int nBlocks);
388 bool m_bUseHead =
false;
389 bool m_bUseRedirectURLIfNoQueryStringParams =
false;
393 mutable bool m_bPlanetaryComputerURLSigning =
false;
394 mutable std::string m_osPlanetaryComputerCollection{};
395 void ManagePlanetaryComputerSigning()
const;
397 int ReadMultiRangeSingleGet(
int nRanges,
void **ppData,
399 const size_t *panSizes);
400 CPLString GetRedirectURLIfValid(
bool &bHasExpired)
const;
402 void UpdateRedirectInfo(CURL *hCurlHandle,
403 const WriteFuncStruct &sWriteFuncHeaderData);
406 virtual struct curl_slist *
408 const struct curl_slist * )
412 virtual bool AllowAutomaticRedirection()
416 virtual bool CanRestartOnError(
const char *,
const char *,
bool)
420 virtual bool UseLimitRangeGetInsteadOfHead()
424 virtual bool IsDirectoryFromExists(
const char * ,
429 virtual void ProcessGetFileSizeResult(
const char * )
432 void SetURL(
const char *pszURL);
433 virtual bool Authenticate(
const char * )
439 VSICurlHandle(VSICurlFilesystemHandlerBase *poFS,
const char *pszFilename,
440 const char *pszURLIn =
nullptr);
441 ~VSICurlHandle()
override;
445 size_t Read(
void *pBuffer,
size_t nSize,
size_t nMemb)
override;
446 int ReadMultiRange(
int nRanges,
void **ppData,
448 const size_t *panSizes)
override;
449 size_t Write(
const void *pBuffer,
size_t nSize,
size_t nMemb)
override;
451 int Flush()
override;
452 int Close()
override;
454 bool HasPRead()
const override
458 size_t PRead(
void *pBuffer,
size_t nSize,
461 bool IsKnownFileSize()
const
463 return oFileProp.bHasComputedFileSize;
465 vsi_l_offset GetFileSizeOrHeaders(
bool bSetError,
bool bGetHeaders);
468 return GetFileSizeOrHeaders(bSetError,
false);
470 bool Exists(
bool bSetError);
471 bool IsDirectory()
const
473 return oFileProp.bIsDirectory;
477 return oFileProp.nMode;
479 time_t GetMTime()
const
481 return oFileProp.mTime;
488 int InstallReadCbk(VSICurlReadCbkFunc pfnReadCbk,
void *pfnUserData,
489 int bStopOnInterruptUntilUninstall);
490 int UninstallReadCbk();
492 const char *GetURL()
const
502class IVSIS3LikeFSHandler :
public VSICurlFilesystemHandlerBase
507 const char *pszSource,
const char *pszTarget,
508 CSLConstList papszOptions, GDALProgressFunc pProgressFunc,
509 void *pProgressData);
510 virtual int MkdirInternal(
const char *pszDirname,
long nMode,
514 char **GetFileList(
const char *pszFilename,
int nMaxFiles,
515 bool *pbGotFileList)
override;
517 virtual IVSIS3LikeHandleHelper *CreateHandleHelper(
const char *pszURI,
518 bool bAllowNoObject) = 0;
520 virtual int CopyObject(
const char *oldpath,
const char *newpath,
523 int RmdirRecursiveInternal(
const char *pszDirname,
int nBatchSize);
526 IsAllowedHeaderForObjectCreation(
const char * )
531 IVSIS3LikeFSHandler() =
default;
534 int Unlink(
const char *pszFilename)
override;
535 int Mkdir(
const char *pszDirname,
long nMode)
override;
536 int Rmdir(
const char *pszDirname)
override;
537 int Stat(
const char *pszFilename,
VSIStatBufL *pStatBuf,
538 int nFlags)
override;
539 int Rename(
const char *oldpath,
const char *newpath)
override;
541 virtual int DeleteObject(
const char *pszFilename);
543 virtual void UpdateMapFromHandle(IVSIS3LikeHandleHelper *)
546 virtual void UpdateHandleFromMap(IVSIS3LikeHandleHelper *)
550 bool Sync(
const char *pszSource,
const char *pszTarget,
551 const char *
const *papszOptions, GDALProgressFunc pProgressFunc,
552 void *pProgressData,
char ***ppapszOutputs)
override;
554 VSIDIR *OpenDir(
const char *pszPath,
int nRecurseDepth,
555 const char *
const *papszOptions)
override;
558 virtual bool SupportsParallelMultipartUpload()
const
563 virtual CPLString InitiateMultipartUpload(
564 const std::string &osFilename, IVSIS3LikeHandleHelper *poS3HandleHelper,
565 int nMaxRetry,
double dfRetryDelay,
CSLConstList papszOptions);
567 const std::string &osUploadID,
570 IVSIS3LikeHandleHelper *poS3HandleHelper,
571 int nMaxRetry,
double dfRetryDelay,
573 virtual bool CompleteMultipart(
const CPLString &osFilename,
575 const std::vector<CPLString> &aosEtags,
577 IVSIS3LikeHandleHelper *poS3HandleHelper,
578 int nMaxRetry,
double dfRetryDelay);
579 virtual bool AbortMultipart(
const CPLString &osFilename,
581 IVSIS3LikeHandleHelper *poS3HandleHelper,
582 int nMaxRetry,
double dfRetryDelay);
584 bool AbortPendingUploads(
const char *pszFilename)
override;
591class IVSIS3LikeHandle :
public VSICurlHandle
596 bool UseLimitRangeGetInsteadOfHead()
override
600 bool IsDirectoryFromExists(
const char *pszVerb,
int response_code)
override
603 return response_code == 416 &&
EQUAL(pszVerb,
"GET") &&
606 void ProcessGetFileSizeResult(
const char *pszContent)
override
608 oFileProp.bIsDirectory =
609 strstr(pszContent,
"ListBucketResult") !=
nullptr;
613 IVSIS3LikeHandle(VSICurlFilesystemHandlerBase *poFSIn,
614 const char *pszFilename,
const char *pszURLIn)
615 : VSICurlHandle(poFSIn, pszFilename, pszURLIn)
618 ~IVSIS3LikeHandle()
override
631 IVSIS3LikeFSHandler *m_poFS =
nullptr;
633 IVSIS3LikeHandleHelper *m_poS3HandleHelper =
nullptr;
634 bool m_bUseChunked =
false;
638 int m_nBufferOff = 0;
639 int m_nBufferSize = 0;
640 bool m_bClosed =
false;
641 GByte *m_pabyBuffer =
nullptr;
643 int m_nPartNumber = 0;
644 std::vector<CPLString> m_aosEtags{};
645 bool m_bError =
false;
647 CURLM *m_hCurlMulti =
nullptr;
648 CURL *m_hCurl =
nullptr;
649 const void *m_pBuffer =
nullptr;
651 size_t m_nChunkedBufferOff = 0;
652 size_t m_nChunkedBufferSize = 0;
653 size_t m_nWrittenInPUT = 0;
656 double m_dfRetryDelay = 0.0;
657 WriteFuncStruct m_sWriteFuncHeaderData{};
660 bool DoSinglePartPUT();
662 static size_t ReadCallBackBufferChunked(
char *buffer,
size_t size,
663 size_t nitems,
void *instream);
664 size_t WriteChunked(
const void *pBuffer,
size_t nSize,
size_t nMemb);
665 int FinishChunkedTransfer();
667 void InvalidateParentDirectory();
670 VSIS3WriteHandle(IVSIS3LikeFSHandler *poFS,
const char *pszFilename,
671 IVSIS3LikeHandleHelper *poS3HandleHelper,
bool bUseChunked,
673 ~VSIS3WriteHandle()
override;
677 size_t Read(
void *pBuffer,
size_t nSize,
size_t nMemb)
override;
678 size_t Write(
const void *pBuffer,
size_t nSize,
size_t nMemb)
override;
680 int Close()
override;
684 return m_bUseChunked || m_pabyBuffer !=
nullptr;
697 VSICurlFilesystemHandlerBase *m_poFS =
nullptr;
702 int m_nBufferOff = 0;
703 int m_nBufferSize = 0;
704 int m_nBufferOffReadCallback = 0;
705 bool m_bClosed =
false;
706 GByte *m_pabyBuffer =
nullptr;
707 bool m_bError =
false;
709 static size_t ReadCallBackBuffer(
char *buffer,
size_t size,
size_t nitems,
711 virtual bool Send(
bool bIsLastBlock) = 0;
714 VSIAppendWriteHandle(VSICurlFilesystemHandlerBase *poFS,
715 const char *pszFSPrefix,
const char *pszFilename,
717 virtual ~VSIAppendWriteHandle();
721 size_t Read(
void *pBuffer,
size_t nSize,
size_t nMemb)
override;
722 size_t Write(
const void *pBuffer,
size_t nSize,
size_t nMemb)
override;
724 int Close()
override;
728 return m_pabyBuffer !=
nullptr;
736struct VSIDIRWithMissingDirSynthesis :
public VSIDIR
738 std::vector<std::unique_ptr<VSIDIREntry>> aoEntries{};
741 std::vector<std::string> m_aosSubpathsStack{};
743 void SynthetizeMissingDirectories(
const std::string &osCurSubdir,
744 bool bAddEntryForThisSubdir);
751struct CurlRequestHelper
753 WriteFuncStruct sWriteFuncData{};
754 WriteFuncStruct sWriteFuncHeaderData{};
755 char szCurlErrBuf[CURL_ERROR_SIZE + 1] = {};
758 ~CurlRequestHelper();
759 long perform(CURL *hCurlHandle,
760 struct curl_slist *headers,
761 VSICurlFilesystemHandlerBase *poFS,
762 IVSIS3LikeHandleHelper *poS3HandleHelper);
769class NetworkStatisticsLogger
771 static int gnEnabled;
772 static NetworkStatisticsLogger gInstance;
774 NetworkStatisticsLogger() =
default;
776 std::mutex m_mutex{};
785 GIntBig nGETDownloadedBytes = 0;
787 GIntBig nPOSTDownloadedBytes = 0;
788 GIntBig nPOSTUploadedBytes = 0;
791 enum class ContextPathType
798 struct ContextPathItem
800 ContextPathType eType;
803 ContextPathItem(ContextPathType eTypeIn,
const CPLString &osNameIn)
804 : eType(eTypeIn), osName(osNameIn)
808 bool operator<(
const ContextPathItem &other)
const
810 if (
static_cast<int>(eType) <
static_cast<int>(other.eType))
812 if (
static_cast<int>(eType) >
static_cast<int>(other.eType))
814 return osName < other.osName;
821 std::map<ContextPathItem, Stats> children{};
829 std::map<GIntBig, std::vector<ContextPathItem>>
830 m_mapThreadIdToContextPath{};
832 static void ReadEnabled();
834 std::vector<Counters *> GetCountersForContext();
837 static inline bool IsEnabled()
843 return gnEnabled == TRUE;
846 static void EnterFileSystem(
const char *pszName);
848 static void LeaveFileSystem();
850 static void EnterFile(
const char *pszName);
852 static void LeaveFile();
854 static void EnterAction(
const char *pszName);
856 static void LeaveAction();
858 static void LogHEAD();
860 static void LogGET(
size_t nDownloadedBytes);
862 static void LogPUT(
size_t nUploadedBytes);
864 static void LogPOST(
size_t nUploadedBytes,
size_t nDownloadedBytes);
866 static void LogDELETE();
870 static CPLString GetReportAsSerializedJSON();
873struct NetworkStatisticsFileSystem
875 inline explicit NetworkStatisticsFileSystem(
const char *pszName)
877 NetworkStatisticsLogger::EnterFileSystem(pszName);
880 inline ~NetworkStatisticsFileSystem()
882 NetworkStatisticsLogger::LeaveFileSystem();
886struct NetworkStatisticsFile
888 inline explicit NetworkStatisticsFile(
const char *pszName)
890 NetworkStatisticsLogger::EnterFile(pszName);
893 inline ~NetworkStatisticsFile()
895 NetworkStatisticsLogger::LeaveFile();
899struct NetworkStatisticsAction
901 inline explicit NetworkStatisticsAction(
const char *pszName)
903 NetworkStatisticsLogger::EnterAction(pszName);
906 inline ~NetworkStatisticsAction()
908 NetworkStatisticsLogger::LeaveAction();
912int VSICURLGetDownloadChunkSize();
914void VSICURLInitWriteFuncStruct(WriteFuncStruct *psStruct,
VSILFILE *fp,
915 VSICurlReadCbkFunc pfnReadCbk,
916 void *pReadCbkUserData);
917size_t VSICurlHandleWriteFunc(
void *buffer,
size_t count,
size_t nmemb,
919void MultiPerform(CURLM *hCurlMultiHandle, CURL *hEasyHandle =
nullptr);
920void VSICURLResetHeaderAndWriterFunctions(CURL *hCurlHandle);
922int VSICurlParseUnixPermissions(
const char *pszPermissions);
925bool VSICURLGetCachedFileProp(
const char *pszURL, FileProp &oFileProp);
926void VSICURLSetCachedFileProp(
const char *pszURL, FileProp &oFileProp);
927void VSICURLInvalidateCachedFileProp(
const char *pszURL);
928void VSICURLInvalidateCachedFilePropPrefix(
const char *pszURL);
929void VSICURLDestroyCacheFileProp();
The CPLJSONArray class holds JSON object from CPLJSONDocument.
Definition cpl_json.h:54
String list class designed around our use of C "char**" string lists.
Definition cpl_string.h:438
Convenient string class based on std::string.
Definition cpl_string.h:312
Virtual file handle.
Definition cpl_vsi_virtual.h:57
Interface for read and write JSON documents.
Core portability definitions for CPL.
#define EQUAL(a, b)
Alias for strcasecmp() == 0.
Definition cpl_port.h:569
#define CPL_DISALLOW_COPY_ASSIGN(ClassName)
Helper to remove the copy and assignment constructors so that the compiler will not generate the defa...
Definition cpl_port.h:1049
char ** CSLConstList
Type of a constant null-terminated list of nul terminated strings.
Definition cpl_port.h:1190
unsigned char GByte
Unsigned byte type.
Definition cpl_port.h:205
long long GIntBig
Large signed integer type (generally 64-bit integer type).
Definition cpl_port.h:233
Various convenience functions for working with strings and string lists.
#define VSIStatBufL
Type for VSIStatL()
Definition cpl_vsi.h:215
#define VSI_L_OFFSET_MAX
Maximum value for a file offset.
Definition cpl_vsi.h:148
struct VSIDIR VSIDIR
Opaque type for a directory iterator.
Definition cpl_vsi.h:394
FILE VSILFILE
Opaque type for a FILE that implements the VSIVirtualHandle API.
Definition cpl_vsi.h:162
GUIntBig vsi_l_offset
Type for a file offset.
Definition cpl_vsi.h:146