From cfc4b62367c09ad0c26ba233d3804d815948463a Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sat, 12 Apr 2014 08:48:57 +0200 Subject: [PATCH] Network Kit: Prepare for HTTP range requests * The DataReceived hook gets a position argument, making it possible for listeners to handle out-of-order data (from two range requests at different positions, for example) * Adjust HaikuDepot (only user of the API in our sources) * Add a copy constructor to HTTPRequest that copies the relevant parameters from an existing request. Makes it easy to repeat a request with a different range. Could be useful for restarting downloads, or paralellizing them. * Add SetRangeStart, SetRangeEnd calls to HTTPRequest, no implementation yet. I'm putting all the API changes in this commit as it needs to be synced with a matching haikuwebkit release. * All archs must update to HaikuWebkit 1.3.0. Previous versions are broken by this. --- headers/os/net/HttpRequest.h | 5 +++ .../os/net/UrlProtocolDispatchingListener.h | 3 +- headers/os/net/UrlProtocolListener.h | 6 ++- headers/os/net/UrlSynchronousRequest.h | 3 +- src/apps/haikudepot/WebAppInterface.cpp | 2 +- src/kits/network/libnetapi/DataRequest.cpp | 2 +- src/kits/network/libnetapi/FileRequest.cpp | 18 ++++---- src/kits/network/libnetapi/HttpRequest.cpp | 42 +++++++++++++++++-- .../UrlProtocolAsynchronousListener.cpp | 4 +- .../UrlProtocolDispatchingListener.cpp | 5 ++- .../network/libnetapi/UrlProtocolListener.cpp | 2 +- .../libnetapi/UrlSynchronousRequest.cpp | 2 +- 12 files changed, 72 insertions(+), 22 deletions(-) diff --git a/headers/os/net/HttpRequest.h b/headers/os/net/HttpRequest.h index cc35a85f76..b41e98ca4e 100644 --- a/headers/os/net/HttpRequest.h +++ b/headers/os/net/HttpRequest.h @@ -26,6 +26,7 @@ public: const char *protocolName = "HTTP", BUrlProtocolListener* listener = NULL, BUrlContext* context = NULL); + BHttpRequest(const BHttpRequest& other); virtual ~BHttpRequest(); void SetMethod(const char* const method); @@ -38,6 +39,8 @@ public: void SetAutoReferrer(bool enable); void SetUserName(const BString& name); void SetPassword(const BString& password); + void SetRangeStart(off_t position); + void SetRangeEnd(off_t position); void SetPostFields(const BHttpForm& fields); void SetHeaders(const BHttpHeaders& headers); @@ -115,6 +118,8 @@ private: BHttpForm* fOptPostFields; BDataIO* fOptInputData; ssize_t fOptInputDataSize; + off_t fOptRangeStart; + off_t fOptRangeEnd; bool fOptSetCookies : 1; bool fOptFollowLocation : 1; bool fOptDiscardData : 1; diff --git a/headers/os/net/UrlProtocolDispatchingListener.h b/headers/os/net/UrlProtocolDispatchingListener.h index 03f5e395b7..6511ab4892 100644 --- a/headers/os/net/UrlProtocolDispatchingListener.h +++ b/headers/os/net/UrlProtocolDispatchingListener.h @@ -44,7 +44,8 @@ public: virtual void ResponseStarted(BUrlRequest* caller); virtual void HeadersReceived(BUrlRequest* caller); virtual void DataReceived(BUrlRequest* caller, - const char* data, ssize_t size); + const char* data, off_t position, + ssize_t size); virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); virtual void UploadProgress(BUrlRequest* caller, diff --git a/headers/os/net/UrlProtocolListener.h b/headers/os/net/UrlProtocolListener.h index ff1764fd15..a081c40c01 100644 --- a/headers/os/net/UrlProtocolListener.h +++ b/headers/os/net/UrlProtocolListener.h @@ -62,15 +62,17 @@ public: virtual void HeadersReceived(BUrlRequest* caller); /** - DataReceived(data, size) + DataReceived(data, position, size) Frequency: Zero or more Parameters: data Pointer to the data block in memory + position Offset of the data in the stream size Size of the data block Called each time a full block of data is received. */ virtual void DataReceived(BUrlRequest* caller, - const char* data, ssize_t size); + const char* data, off_t position, + ssize_t size); /** DownloadProgress(bytesReceived, bytesTotal) diff --git a/headers/os/net/UrlSynchronousRequest.h b/headers/os/net/UrlSynchronousRequest.h index 6602608807..ae73736135 100644 --- a/headers/os/net/UrlSynchronousRequest.h +++ b/headers/os/net/UrlSynchronousRequest.h @@ -26,7 +26,8 @@ public: virtual void ResponseStarted(BUrlRequest* caller); virtual void HeadersReceived(BUrlRequest* caller); virtual void DataReceived(BUrlRequest* caller, - const char* data, ssize_t size); + const char* data, off_t position, + ssize_t size); virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); virtual void UploadProgress(BUrlRequest* caller, diff --git a/src/apps/haikudepot/WebAppInterface.cpp b/src/apps/haikudepot/WebAppInterface.cpp index 31202ecfa2..4e6306ccaa 100644 --- a/src/apps/haikudepot/WebAppInterface.cpp +++ b/src/apps/haikudepot/WebAppInterface.cpp @@ -47,7 +47,7 @@ public: } virtual void DataReceived(BUrlRequest* caller, const char* data, - ssize_t size) + off_t position, ssize_t size) { // printf("DataReceived(%p): %ld bytes\n", caller, size); diff --git a/src/kits/network/libnetapi/DataRequest.cpp b/src/kits/network/libnetapi/DataRequest.cpp index 4b394d959f..40c8c251ff 100644 --- a/src/kits/network/libnetapi/DataRequest.cpp +++ b/src/kits/network/libnetapi/DataRequest.cpp @@ -105,7 +105,7 @@ BDataRequest::_ProtocolLoop() if (fListener != NULL) { fListener->DownloadProgress(this, length, length); if (length > 0) - fListener->DataReceived(this, payload, length); + fListener->DataReceived(this, payload, 0, length); } if (isBase64) diff --git a/src/kits/network/libnetapi/FileRequest.cpp b/src/kits/network/libnetapi/FileRequest.cpp index cfbd5910b4..e5db0fe70a 100644 --- a/src/kits/network/libnetapi/FileRequest.cpp +++ b/src/kits/network/libnetapi/FileRequest.cpp @@ -77,7 +77,7 @@ BFileRequest::_ProtocolLoop() ssize_t chunkSize; char chunk[4096]; while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0) { - fListener->DataReceived(this, chunk, chunkSize); + fListener->DataReceived(this, chunk, transferredSize, chunkSize); transferredSize += chunkSize; } // Return error if we didn't transfer everything @@ -110,10 +110,10 @@ BFileRequest::_ProtocolLoop() fListener->ConnectionOpened(this); // Add a parent directory entry. - fListener->DataReceived(this, "+/,\t..\r\n",8); + fListener->DataReceived(this, "+/,\t..\r\n", transferredSize, 8); + transferredSize += 8; } - int size = 0; char name[B_FILE_NAME_LENGTH]; BEntry entry; while (directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) { @@ -137,14 +137,16 @@ BFileRequest::_ProtocolLoop() entry.GetName(name); epfl << "\t" << name << "\r\n"; - if (fListener != NULL) - fListener->DataReceived(this, epfl.String(), epfl.Length()); - size += epfl.Length(); + if (fListener != NULL) { + fListener->DataReceived(this, epfl.String(), transferredSize, + epfl.Length()); + } + transferredSize += epfl.Length(); } if (fListener != NULL) - fListener->DownloadProgress(this, size, size); - fResult.SetLength(size); + fListener->DownloadProgress(this, transferredSize, transferredSize); + fResult.SetLength(transferredSize); return B_OK; } diff --git a/src/kits/network/libnetapi/HttpRequest.cpp b/src/kits/network/libnetapi/HttpRequest.cpp index d342b7b777..63e2b2951d 100644 --- a/src/kits/network/libnetapi/HttpRequest.cpp +++ b/src/kits/network/libnetapi/HttpRequest.cpp @@ -43,10 +43,39 @@ BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName, fOptPostFields(NULL), fOptInputData(NULL), fOptInputDataSize(-1), + fOptRangeStart(-1), + fOptRangeEnd(-1), fOptFollowLocation(true) { _ResetOptions(); - if (ssl) + if (fSSL) + fSocket = new(std::nothrow) BSecureSocket(); + else + fSocket = new(std::nothrow) BSocket(); +} + + +BHttpRequest::BHttpRequest(const BHttpRequest& other) + : + BUrlRequest(other.Url(), other.fListener, other.fContext, + "BUrlProtocol.HTTP", other.fSSL ? "HTTPS" : "HTTP"), + fSocket(NULL), + fSSL(other.fSSL), + fRequestMethod(other.fRequestMethod), + fHttpVersion(other.fHttpVersion), + fResult(other.fUrl), + fRequestStatus(kRequestInitialState), + fOptHeaders(NULL), + fOptPostFields(NULL), + fOptInputData(NULL), + fOptInputDataSize(NULL), + fOptRangeStart(other.fOptRangeStart), + fOptRangeEnd(other.fOptRangeEnd), + fOptFollowLocation(other.fOptFollowLocation) +{ + _ResetOptions(); + // FIXME some options may be copied from other instead. + if (fSSL) fSocket = new(std::nothrow) BSecureSocket(); else fSocket = new(std::nothrow) BSocket(); @@ -552,6 +581,7 @@ BHttpRequest::_MakeRequest() ssize_t bytesRead = 0; ssize_t bytesReceived = 0; ssize_t bytesTotal = 0; + off_t bytesUnpacked = 0; char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize]; ssize_t inputTempSize = kHttpBufferSize; ssize_t chunkSize = -1; @@ -705,11 +735,13 @@ BHttpRequest::_MakeRequest() BStackOrHeapArray buffer(size); size = decompressorStorage.Read(buffer, size); if (size > 0) { - fListener->DataReceived(this, buffer, size); + fListener->DataReceived(this, buffer, bytesUnpacked, + size); + bytesUnpacked += size; } } else { fListener->DataReceived(this, inputTempBuffer, - bytesRead); + bytesReceived - bytesRead, bytesRead); } fListener->DownloadProgress(this, bytesReceived, bytesTotal); @@ -724,7 +756,9 @@ BHttpRequest::_MakeRequest() BStackOrHeapArray buffer(size); size = decompressorStorage.Read(buffer, size); if (fListener != NULL && size > 0) { - fListener->DataReceived(this, buffer, size); + fListener->DataReceived(this, buffer, + bytesUnpacked, size); + bytesUnpacked += size; } } } diff --git a/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp b/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp index 9262eb45ba..1de09c2781 100644 --- a/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp @@ -106,7 +106,9 @@ BUrlProtocolAsynchronousListener::MessageReceived(BMessage* message) return; } - DataReceived(caller, data, size); + off_t position = message->FindInt32("url:position"); + + DataReceived(caller, data, position, size); } break; diff --git a/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp b/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp index 088f74e817..ac0de9f69e 100644 --- a/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp @@ -75,12 +75,15 @@ BUrlProtocolDispatchingListener::HeadersReceived(BUrlRequest* caller) void BUrlProtocolDispatchingListener::DataReceived(BUrlRequest* caller, - const char* data, ssize_t size) + const char* data, off_t position, ssize_t size) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); status_t result = message.AddData("url:data", B_STRING_TYPE, data, size, true, 1); assert(result == B_OK); + + result = message.AddInt32("url:position", position); + assert(result == B_OK); _SendMessage(&message, B_URL_PROTOCOL_DATA_RECEIVED, caller); } diff --git a/src/kits/network/libnetapi/UrlProtocolListener.cpp b/src/kits/network/libnetapi/UrlProtocolListener.cpp index b76f6f2417..40d85890d6 100644 --- a/src/kits/network/libnetapi/UrlProtocolListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolListener.cpp @@ -40,7 +40,7 @@ BUrlProtocolListener::HeadersReceived(BUrlRequest*) void -BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, ssize_t) +BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, off_t, ssize_t) { } diff --git a/src/kits/network/libnetapi/UrlSynchronousRequest.cpp b/src/kits/network/libnetapi/UrlSynchronousRequest.cpp index 050d46b339..859484b993 100644 --- a/src/kits/network/libnetapi/UrlSynchronousRequest.cpp +++ b/src/kits/network/libnetapi/UrlSynchronousRequest.cpp @@ -79,7 +79,7 @@ BUrlSynchronousRequest::HeadersReceived(BUrlRequest*) void BUrlSynchronousRequest::DataReceived(BUrlRequest*, const char*, - ssize_t size) + off_t, ssize_t size) { PRINT(("SynchronousRequest::DataReceived(%zd)\n", size)); }