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:48:57 +02:00
parent ba65f39ac3
commit cfc4b62367
12 changed files with 72 additions and 22 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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)

View File

@ -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;
}

View File

@ -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<char, 4096> 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<char, 4096> 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;
}
}
}

View File

@ -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;

View File

@ -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);
}

View File

@ -40,7 +40,7 @@ BUrlProtocolListener::HeadersReceived(BUrlRequest*)
void
BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, ssize_t)
BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, off_t, ssize_t)
{
}

View File

@ -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));
}