libbnetapi: BUrlRequest now outputs to BDataIO

Previously, BUrlRequest returns data received via a callback that can't
return any value. This approach have several issues:

- It's not possible to signify failures to the request.
- Users have to implement custom listeners just to handle the common
  case of outputting to a buffer/file/etc.
- The received data has to be serialized into BMessage when
  BUrlProtocolDispatchingListener is employed. This can cause a
  noticible slowdown in real-world scenarios as evident by #10748.

With this change, BUrlRequest will output directly into a BDataIO, which
exposes a richer API for request handlers to work with (for example a
BitTorrent client can request a BPositionIO for non-linear data
delivery), as well as simplifying common cases for users.

The adaptation only requires one additional API:
BHttpRequest::SetStopOnError(). This API simply instructs the HTTP
request handler to cancel the request if an HTTP error is occurred.

Change-Id: I4160884d77bff0e7678e0a623e2587987704443a
Reviewed-on: https://review.haiku-os.org/c/haiku/+/3084
Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
Leorize
2021-02-28 20:39:31 +00:00
committed by Niels Sascha Reedijk
parent 3e27f8d5a7
commit 78b1442051
39 changed files with 1562 additions and 452 deletions
+7 -1
View File
@@ -27,10 +27,16 @@ public:
private:
friend class BUrlProtocolRoster;
#ifdef LIBNETAPI_DEPRECATED
BDataRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#else
BDataRequest(const BUrl& url,
BDataIO* output,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#endif
status_t _ProtocolLoop();
private:
BUrlResult fResult;
@@ -29,9 +29,16 @@ public:
private:
friend class BUrlProtocolRoster;
#ifdef LIBNETAPI_DEPRECATED
BFileRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#else
BFileRequest(const BUrl& url,
BDataIO* output,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#endif
status_t _ProtocolLoop();
private:
@@ -29,16 +29,27 @@ public:
private:
friend class BUrlProtocolRoster;
#ifdef LIBNETAPI_DEPRECATED
BGopherRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#else
BGopherRequest(const BUrl& url,
BDataIO* output,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#endif
status_t _ProtocolLoop();
void _SendRequest();
bool _NeedsParsing();
bool _NeedsLastDotStrip();
#ifdef LIBNETAPI_DEPRECATED
void _ParseInput(bool last);
#else
status_t _ParseInput(bool last);
#endif
BString& _HTMLEscapeString(BString &str);
+17
View File
@@ -41,6 +41,9 @@ public:
void SetDiscardData(bool discard);
void SetDisableListener(bool disable);
void SetAutoReferrer(bool enable);
#ifndef LIBNETAPI_DEPRECATED
void SetStopOnError(bool stop);
#endif
void SetUserName(const BString& name);
void SetPassword(const BString& password);
void SetRangeStart(off_t position);
@@ -67,11 +70,20 @@ public:
private:
friend class BUrlProtocolRoster;
#ifdef LIBNETAPI_DEPRECATED
BHttpRequest(const BUrl& url,
bool ssl = false,
const char* protocolName = "HTTP",
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#else
BHttpRequest(const BUrl& url,
BDataIO* output,
bool ssl = false,
const char* protocolName = "HTTP",
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#endif
BHttpRequest(const BHttpRequest& other);
void _ResetOptions();
@@ -101,10 +113,12 @@ private:
// Utility methods
bool _IsDefaultPort();
#ifdef LIBNETAPI_DEPRECATED
// Listener notification
void _NotifyDataReceived(const char* data,
off_t pos, ssize_t length,
off_t bytesReceived, ssize_t bytesTotal);
#endif
private:
bool fSSL;
@@ -146,6 +160,9 @@ private:
bool fOptDiscardData : 1;
bool fOptDisableListener : 1;
bool fOptAutoReferer : 1;
#ifndef LIBNETAPI_DEPRECATED
bool fOptStopOnError : 1;
#endif
};
// Request method
@@ -23,11 +23,20 @@ namespace Network {
class BNetworkRequest: public BUrlRequest
{
public:
#ifdef LIBNETAPI_DEPRECATED
BNetworkRequest(const BUrl& url,
BUrlProtocolListener* listener,
BUrlContext* context,
const char* threadName,
const char* protocolName);
#else
BNetworkRequest(const BUrl& url,
BDataIO* output,
BUrlProtocolListener* listener,
BUrlContext* context,
const char* threadName,
const char* protocolName);
#endif
virtual status_t Stop();
virtual void SetTimeout(bigtime_t timeout);
@@ -25,9 +25,9 @@ public:
// Synchronous listener access
BUrlProtocolListener* SynchronousListener();
// BHandler interface
virtual void MessageReceived(BMessage* message);
virtual void MessageReceived(BMessage* message);
private:
BUrlProtocolDispatchingListener*
@@ -28,7 +28,11 @@ enum {
B_URL_PROTOCOL_HOSTNAME_RESOLVED,
B_URL_PROTOCOL_RESPONSE_STARTED,
B_URL_PROTOCOL_HEADERS_RECEIVED,
#ifdef LIBNETAPI_DEPRECATED
B_URL_PROTOCOL_DATA_RECEIVED,
#else
B_URL_PROTOCOL_BYTES_WRITTEN,
#endif
B_URL_PROTOCOL_DOWNLOAD_PROGRESS,
B_URL_PROTOCOL_UPLOAD_PROGRESS,
B_URL_PROTOCOL_REQUEST_COMPLETED,
@@ -46,44 +50,44 @@ public:
virtual ~BUrlProtocolDispatchingListener();
virtual void ConnectionOpened(BUrlRequest* caller);
virtual void HostnameResolved(BUrlRequest* caller,
virtual void HostnameResolved(BUrlRequest* caller,
const char* ip);
virtual void ResponseStarted(BUrlRequest* caller);
#ifdef LIBNETAPI_DEPRECATED
virtual void HeadersReceived(BUrlRequest* caller,
const BUrlResult& result);
#else
virtual void HeadersReceived(BUrlRequest* caller);
#endif
virtual void DataReceived(BUrlRequest* caller,
const char* data, off_t position,
ssize_t size);
virtual void ResponseStarted(BUrlRequest* caller);
#ifdef LIBNETAPI_DEPRECATED
virtual void HeadersReceived(BUrlRequest* caller,
const BUrlResult& result);
virtual void DataReceived(BUrlRequest* caller,
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,
virtual void UploadProgress(BUrlRequest* caller,
ssize_t bytesSent, ssize_t bytesTotal);
#else
virtual void HeadersReceived(BUrlRequest* caller);
virtual void BytesWritten(BUrlRequest* caller,
size_t bytesWritten);
virtual void DownloadProgress(BUrlRequest* caller,
off_t bytesReceived, off_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller,
virtual void UploadProgress(BUrlRequest* caller,
off_t bytesSent, off_t bytesTotal);
#endif
virtual void RequestCompleted(BUrlRequest* caller,
virtual void RequestCompleted(BUrlRequest* caller,
bool success);
virtual void DebugMessage(BUrlRequest* caller,
virtual void DebugMessage(BUrlRequest* caller,
BUrlProtocolDebugMessage type,
const char* text);
virtual bool CertificateVerificationFailed(
virtual bool CertificateVerificationFailed(
BUrlRequest* caller,
BCertificate& certificate,
const char* message);
private:
void _SendMessage(BMessage* message,
int8 notification, BUrlRequest* caller);
int8 notification,
BUrlRequest* caller);
private:
BMessenger fMessenger;
@@ -36,37 +36,35 @@ enum BUrlProtocolDebugMessage {
class BUrlProtocolListener {
public:
virtual void ConnectionOpened(BUrlRequest* caller);
virtual void HostnameResolved(BUrlRequest* caller,
virtual void HostnameResolved(BUrlRequest* caller,
const char* ip);
virtual void ResponseStarted(BUrlRequest* caller);
virtual void ResponseStarted(BUrlRequest* caller);
#ifdef LIBNETAPI_DEPRECATED
virtual void HeadersReceived(BUrlRequest* caller,
virtual void HeadersReceived(BUrlRequest* caller,
const BUrlResult& result);
#else
virtual void HeadersReceived(BUrlRequest* caller);
#endif
virtual void DataReceived(BUrlRequest* caller,
virtual void DataReceived(BUrlRequest* caller,
const char* data, off_t position,
ssize_t size);
#ifdef LIBNETAPI_DEPRECATED
virtual void DownloadProgress(BUrlRequest* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller,
virtual void UploadProgress(BUrlRequest* caller,
ssize_t bytesSent, ssize_t bytesTotal);
#else
virtual void HeadersReceived(BUrlRequest* caller);
virtual void BytesWritten(BUrlRequest* caller,
size_t bytesWritten);
virtual void DownloadProgress(BUrlRequest* caller,
off_t bytesReceived, off_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller,
off_t bytesSent, off_t bytesTotal);
#endif
virtual void RequestCompleted(BUrlRequest* caller,
virtual void RequestCompleted(BUrlRequest* caller,
bool success);
virtual void DebugMessage(BUrlRequest* caller,
virtual void DebugMessage(BUrlRequest* caller,
BUrlProtocolDebugMessage type,
const char* text);
virtual bool CertificateVerificationFailed(
virtual bool CertificateVerificationFailed(
BUrlRequest* caller,
BCertificate& certificate,
const char* message);
@@ -10,6 +10,7 @@
#include <stdlib.h>
class BDataIO;
class BUrl;
#ifndef LIBNETAPI_DEPRECATED
@@ -24,9 +25,15 @@ class BUrlRequest;
class BUrlProtocolRoster {
public:
static BUrlRequest* MakeRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#ifdef LIBNETAPI_DEPRECATED
static BUrlRequest* MakeRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#else
static BUrlRequest* MakeRequest(const BUrl& url, BDataIO* output,
BUrlProtocolListener* listener = NULL,
BUrlContext* context = NULL);
#endif
};
#ifndef LIBNETAPI_DEPRECATED
+18
View File
@@ -22,11 +22,20 @@ namespace Network {
class BUrlRequest {
public:
#ifdef LIBNETAPI_DEPRECATED
BUrlRequest(const BUrl& url,
BUrlProtocolListener* listener,
BUrlContext* context,
const char* threadName,
const char* protocolName);
#else
BUrlRequest(const BUrl& url,
BDataIO* output,
BUrlProtocolListener* listener,
BUrlContext* context,
const char* threadName,
const char* protocolName);
#endif
virtual ~BUrlRequest();
// URL protocol thread management
@@ -40,12 +49,18 @@ public:
status_t SetUrl(const BUrl& url);
status_t SetContext(BUrlContext* context);
status_t SetListener(BUrlProtocolListener* listener);
#ifndef LIBNETAPI_DEPRECATED
status_t SetOutput(BDataIO* output);
#endif
// URL protocol parameters access
const BUrl& Url() const;
BUrlContext* Context() const;
BUrlProtocolListener* Listener() const;
const BString& Protocol() const;
#ifndef LIBNETAPI_DEPRECATED
BDataIO* Output() const;
#endif
// URL protocol informations
bool IsRunning() const;
@@ -63,6 +78,9 @@ protected:
BUrl fUrl;
BReference<BUrlContext> fContext;
BUrlProtocolListener* fListener;
#ifndef LIBNETAPI_DEPRECATED
BDataIO* fOutput;
#endif
bool fQuit;
bool fRunning;
@@ -20,42 +20,40 @@ class BUrlSynchronousRequest : public BUrlRequest, public BUrlProtocolListener {
public:
BUrlSynchronousRequest(BUrlRequest& asynchronousRequest);
virtual ~BUrlSynchronousRequest() { };
// Synchronous wait
virtual status_t Perform();
virtual status_t WaitUntilCompletion();
// Protocol hooks
virtual void ConnectionOpened(BUrlRequest* caller);
virtual void HostnameResolved(BUrlRequest* caller,
virtual void HostnameResolved(BUrlRequest* caller,
const char* ip);
virtual void ResponseStarted(BUrlRequest* caller);
virtual void ResponseStarted(BUrlRequest* caller);
#ifdef LIBNETAPI_DEPRECATED
virtual void HeadersReceived(BUrlRequest* caller,
virtual void HeadersReceived(BUrlRequest* caller,
const BUrlResult& result);
#else
virtual void HeadersReceived(BUrlRequest* caller);
#endif
virtual void DataReceived(BUrlRequest* caller,
virtual void DataReceived(BUrlRequest* caller,
const char* data, off_t position,
ssize_t size);
#ifdef LIBNETAPI_DEPRECATED
virtual void DownloadProgress(BUrlRequest* caller,
ssize_t bytesReceived, ssize_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller,
virtual void UploadProgress(BUrlRequest* caller,
ssize_t bytesSent, ssize_t bytesTotal);
#else
virtual void HeadersReceived(BUrlRequest* caller);
virtual void BytesWritten(BUrlRequest* caller,
size_t bytesWritten);
virtual void DownloadProgress(BUrlRequest* caller,
off_t bytesReceived, off_t bytesTotal);
virtual void UploadProgress(BUrlRequest* caller,
off_t bytesSent, off_t bytesTotal);
#endif //LIBNETAPI_DEPRECATED
#endif
virtual void RequestCompleted(BUrlRequest* caller,
virtual void RequestCompleted(BUrlRequest* caller,
bool success);
protected:
bool fRequestComplete;
BUrlRequest& fWrappedRequest;