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.
This commit is contained in:
Adrien Destugues
2014-04-12 08:57:26 +02:00
parent ba65f39ac3
commit cfc4b62367
12 changed files with 72 additions and 22 deletions
+5
View File
@@ -26,6 +26,7 @@ public:
const char *protocolName = "HTTP", const char *protocolName = "HTTP",
BUrlProtocolListener* listener = NULL, BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL); BUrlContext* context = NULL);
BHttpRequest(const BHttpRequest& other);
virtual ~BHttpRequest(); virtual ~BHttpRequest();
void SetMethod(const char* const method); void SetMethod(const char* const method);
@@ -38,6 +39,8 @@ public:
void SetAutoReferrer(bool enable); void SetAutoReferrer(bool enable);
void SetUserName(const BString& name); void SetUserName(const BString& name);
void SetPassword(const BString& password); void SetPassword(const BString& password);
void SetRangeStart(off_t position);
void SetRangeEnd(off_t position);
void SetPostFields(const BHttpForm& fields); void SetPostFields(const BHttpForm& fields);
void SetHeaders(const BHttpHeaders& headers); void SetHeaders(const BHttpHeaders& headers);
@@ -115,6 +118,8 @@ private:
BHttpForm* fOptPostFields; BHttpForm* fOptPostFields;
BDataIO* fOptInputData; BDataIO* fOptInputData;
ssize_t fOptInputDataSize; ssize_t fOptInputDataSize;
off_t fOptRangeStart;
off_t fOptRangeEnd;
bool fOptSetCookies : 1; bool fOptSetCookies : 1;
bool fOptFollowLocation : 1; bool fOptFollowLocation : 1;
bool fOptDiscardData : 1; bool fOptDiscardData : 1;
@@ -44,7 +44,8 @@ public:
virtual void ResponseStarted(BUrlRequest* caller); virtual void ResponseStarted(BUrlRequest* caller);
virtual void HeadersReceived(BUrlRequest* caller); virtual void HeadersReceived(BUrlRequest* caller);
virtual void DataReceived(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, virtual void DownloadProgress(BUrlRequest* caller,
ssize_t bytesReceived, ssize_t bytesTotal); ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller, virtual void UploadProgress(BUrlRequest* caller,
+4 -2
View File
@@ -62,15 +62,17 @@ public:
virtual void HeadersReceived(BUrlRequest* caller); virtual void HeadersReceived(BUrlRequest* caller);
/** /**
DataReceived(data, size) DataReceived(data, position, size)
Frequency: Zero or more Frequency: Zero or more
Parameters: data Pointer to the data block in memory Parameters: data Pointer to the data block in memory
position Offset of the data in the stream
size Size of the data block size Size of the data block
Called each time a full block of data is received. Called each time a full block of data is received.
*/ */
virtual void DataReceived(BUrlRequest* caller, virtual void DataReceived(BUrlRequest* caller,
const char* data, ssize_t size); const char* data, off_t position,
ssize_t size);
/** /**
DownloadProgress(bytesReceived, bytesTotal) DownloadProgress(bytesReceived, bytesTotal)
+2 -1
View File
@@ -26,7 +26,8 @@ public:
virtual void ResponseStarted(BUrlRequest* caller); virtual void ResponseStarted(BUrlRequest* caller);
virtual void HeadersReceived(BUrlRequest* caller); virtual void HeadersReceived(BUrlRequest* caller);
virtual void DataReceived(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, virtual void DownloadProgress(BUrlRequest* caller,
ssize_t bytesReceived, ssize_t bytesTotal); ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller, virtual void UploadProgress(BUrlRequest* caller,
+1 -1
View File
@@ -47,7 +47,7 @@ public:
} }
virtual void DataReceived(BUrlRequest* caller, const char* data, 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); // printf("DataReceived(%p): %ld bytes\n", caller, size);
+1 -1
View File
@@ -105,7 +105,7 @@ BDataRequest::_ProtocolLoop()
if (fListener != NULL) { if (fListener != NULL) {
fListener->DownloadProgress(this, length, length); fListener->DownloadProgress(this, length, length);
if (length > 0) if (length > 0)
fListener->DataReceived(this, payload, length); fListener->DataReceived(this, payload, 0, length);
} }
if (isBase64) if (isBase64)
+10 -8
View File
@@ -77,7 +77,7 @@ BFileRequest::_ProtocolLoop()
ssize_t chunkSize; ssize_t chunkSize;
char chunk[4096]; char chunk[4096];
while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0) { while ((chunkSize = file.Read(chunk, sizeof(chunk))) > 0) {
fListener->DataReceived(this, chunk, chunkSize); fListener->DataReceived(this, chunk, transferredSize, chunkSize);
transferredSize += chunkSize; transferredSize += chunkSize;
} }
// Return error if we didn't transfer everything // Return error if we didn't transfer everything
@@ -110,10 +110,10 @@ BFileRequest::_ProtocolLoop()
fListener->ConnectionOpened(this); fListener->ConnectionOpened(this);
// Add a parent directory entry. // 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]; char name[B_FILE_NAME_LENGTH];
BEntry entry; BEntry entry;
while (directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) { while (directory.GetNextEntry(&entry) != B_ENTRY_NOT_FOUND) {
@@ -137,14 +137,16 @@ BFileRequest::_ProtocolLoop()
entry.GetName(name); entry.GetName(name);
epfl << "\t" << name << "\r\n"; epfl << "\t" << name << "\r\n";
if (fListener != NULL) if (fListener != NULL) {
fListener->DataReceived(this, epfl.String(), epfl.Length()); fListener->DataReceived(this, epfl.String(), transferredSize,
size += epfl.Length(); epfl.Length());
}
transferredSize += epfl.Length();
} }
if (fListener != NULL) if (fListener != NULL)
fListener->DownloadProgress(this, size, size); fListener->DownloadProgress(this, transferredSize, transferredSize);
fResult.SetLength(size); fResult.SetLength(transferredSize);
return B_OK; return B_OK;
} }
+38 -4
View File
@@ -43,10 +43,39 @@ BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
fOptPostFields(NULL), fOptPostFields(NULL),
fOptInputData(NULL), fOptInputData(NULL),
fOptInputDataSize(-1), fOptInputDataSize(-1),
fOptRangeStart(-1),
fOptRangeEnd(-1),
fOptFollowLocation(true) fOptFollowLocation(true)
{ {
_ResetOptions(); _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(); fSocket = new(std::nothrow) BSecureSocket();
else else
fSocket = new(std::nothrow) BSocket(); fSocket = new(std::nothrow) BSocket();
@@ -552,6 +581,7 @@ BHttpRequest::_MakeRequest()
ssize_t bytesRead = 0; ssize_t bytesRead = 0;
ssize_t bytesReceived = 0; ssize_t bytesReceived = 0;
ssize_t bytesTotal = 0; ssize_t bytesTotal = 0;
off_t bytesUnpacked = 0;
char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize]; char* inputTempBuffer = new(std::nothrow) char[kHttpBufferSize];
ssize_t inputTempSize = kHttpBufferSize; ssize_t inputTempSize = kHttpBufferSize;
ssize_t chunkSize = -1; ssize_t chunkSize = -1;
@@ -705,11 +735,13 @@ BHttpRequest::_MakeRequest()
BStackOrHeapArray<char, 4096> buffer(size); BStackOrHeapArray<char, 4096> buffer(size);
size = decompressorStorage.Read(buffer, size); size = decompressorStorage.Read(buffer, size);
if (size > 0) { if (size > 0) {
fListener->DataReceived(this, buffer, size); fListener->DataReceived(this, buffer, bytesUnpacked,
size);
bytesUnpacked += size;
} }
} else { } else {
fListener->DataReceived(this, inputTempBuffer, fListener->DataReceived(this, inputTempBuffer,
bytesRead); bytesReceived - bytesRead, bytesRead);
} }
fListener->DownloadProgress(this, bytesReceived, fListener->DownloadProgress(this, bytesReceived,
bytesTotal); bytesTotal);
@@ -724,7 +756,9 @@ BHttpRequest::_MakeRequest()
BStackOrHeapArray<char, 4096> buffer(size); BStackOrHeapArray<char, 4096> buffer(size);
size = decompressorStorage.Read(buffer, size); size = decompressorStorage.Read(buffer, size);
if (fListener != NULL && size > 0) { if (fListener != NULL && size > 0) {
fListener->DataReceived(this, buffer, size); fListener->DataReceived(this, buffer,
bytesUnpacked, size);
bytesUnpacked += size;
} }
} }
} }
@@ -106,7 +106,9 @@ BUrlProtocolAsynchronousListener::MessageReceived(BMessage* message)
return; return;
} }
DataReceived(caller, data, size); off_t position = message->FindInt32("url:position");
DataReceived(caller, data, position, size);
} }
break; break;
@@ -75,12 +75,15 @@ BUrlProtocolDispatchingListener::HeadersReceived(BUrlRequest* caller)
void void
BUrlProtocolDispatchingListener::DataReceived(BUrlRequest* caller, 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); BMessage message(B_URL_PROTOCOL_NOTIFICATION);
status_t result = message.AddData("url:data", B_STRING_TYPE, data, size, status_t result = message.AddData("url:data", B_STRING_TYPE, data, size,
true, 1); true, 1);
assert(result == B_OK); assert(result == B_OK);
result = message.AddInt32("url:position", position);
assert(result == B_OK);
_SendMessage(&message, B_URL_PROTOCOL_DATA_RECEIVED, caller); _SendMessage(&message, B_URL_PROTOCOL_DATA_RECEIVED, caller);
} }
@@ -40,7 +40,7 @@ BUrlProtocolListener::HeadersReceived(BUrlRequest*)
void void
BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, ssize_t) BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, off_t, ssize_t)
{ {
} }
@@ -79,7 +79,7 @@ BUrlSynchronousRequest::HeadersReceived(BUrlRequest*)
void void
BUrlSynchronousRequest::DataReceived(BUrlRequest*, const char*, BUrlSynchronousRequest::DataReceived(BUrlRequest*, const char*,
ssize_t size) off_t, ssize_t size)
{ {
PRINT(("SynchronousRequest::DataReceived(%zd)\n", size)); PRINT(("SynchronousRequest::DataReceived(%zd)\n", size));
} }