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:
@@ -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,
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user