hrev46189 adds 1 changeset to branch 'master' old head: 65e2db9f844ad5b902410fab86806e43c540a504 new head: afd547b368a43aa45c2be5dde6052242ea1eefce overview: http://cgit.haiku-os.org/haiku/log/?qt=range&q=afd547b+%5E65e2db9 ---------------------------------------------------------------------------- afd547b: Refactor UrlRequest/UrlProtocol in the Service Kit * Remove the BUrlRequest class, which was only delegating work to BUrlProtocol and subclasses * Rename BUrlProtocol to BUrlRequest, and BUrlRequestHttp to BHttpRequest * Creating a request is now done through the BUrlProtocolRoster. For now there is just a static MakeRequest method, this will be completed when we get to actually allowing add-ons to provide different request handlers. This allows cleanup of the API for requests: * Remove the universal SetOption method with constants, and have dedicated setters for each protocol option. * Setters can now have multiple parameters, for example you can give BHTTPRequest a BDataIO and a known size * In this case, the BHttpRequest will not use HTTP chunked transfers, which were always used before and made most servers unhappy (tested and failed with lighttpd, google accounts and github). [ Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> ] ---------------------------------------------------------------------------- Revision: hrev46189 Commit: afd547b368a43aa45c2be5dde6052242ea1eefce URL: http://cgit.haiku-os.org/haiku/commit/?id=afd547b Author: Adrien Destugues <pulkomandy@xxxxxxxxxxxxx> Date: Tue Oct 8 09:30:56 2013 UTC ---------------------------------------------------------------------------- 21 files changed, 566 insertions(+), 813 deletions(-) headers/os/net/HttpForm.h | 3 +- .../os/net/{UrlProtocolHttp.h => HttpRequest.h} | 29 +- headers/os/net/UrlProtocol.h | 136 -------- headers/os/net/UrlProtocolAsynchronousListener.h | 16 +- headers/os/net/UrlProtocolDispatchingListener.h | 21 +- headers/os/net/UrlProtocolListener.h | 38 +-- headers/os/net/UrlProtocolRoster.h | 25 ++ headers/os/net/UrlRequest.h | 101 +++--- headers/os/net/UrlResult.h | 4 +- headers/os/net/UrlSynchronousRequest.h | 19 +- src/kits/network/libnetapi/HttpForm.cpp | 7 - src/kits/network/libnetapi/HttpHeaders.cpp | 2 + .../{UrlProtocolHttp.cpp => HttpRequest.cpp} | 223 +++++++------ src/kits/network/libnetapi/Jamfile | 7 +- src/kits/network/libnetapi/UrlProtocol.cpp | 303 ------------------ .../UrlProtocolAsynchronousListener.cpp | 18 +- .../libnetapi/UrlProtocolDispatchingListener.cpp | 18 +- .../network/libnetapi/UrlProtocolListener.cpp | 20 +- src/kits/network/libnetapi/UrlProtocolRoster.cpp | 35 ++ src/kits/network/libnetapi/UrlRequest.cpp | 320 +++++++++++-------- .../network/libnetapi/UrlSynchronousRequest.cpp | 34 +- ---------------------------------------------------------------------------- diff --git a/headers/os/net/HttpForm.h b/headers/os/net/HttpForm.h index a1a766d..ec27253 100644 --- a/headers/os/net/HttpForm.h +++ b/headers/os/net/HttpForm.h @@ -60,8 +60,7 @@ public: // Change behavior status_t MarkAsFile(const BString& filename, - const BString& mimeType); - status_t MarkAsFile(const BString& filename); + const BString& mimeType = ""); void UnmarkAsFile(); status_t CopyBuffer(); diff --git a/headers/os/net/UrlProtocolHttp.h b/headers/os/net/HttpRequest.h similarity index 83% rename from headers/os/net/UrlProtocolHttp.h rename to headers/os/net/HttpRequest.h index b89a7a3..9121f67 100644 --- a/headers/os/net/UrlProtocolHttp.h +++ b/headers/os/net/HttpRequest.h @@ -14,22 +14,34 @@ #include <HttpHeaders.h> #include <NetBuffer.h> #include <NetworkAddress.h> -#include <UrlProtocol.h> +#include <UrlRequest.h> class BAbstractSocket; -class BUrlProtocolHttp : public BUrlProtocol { +class BHttpRequest : public BUrlRequest { public: - BUrlProtocolHttp(BUrl& url, bool ssl = false, + BHttpRequest(const BUrl& url, + BUrlResult& result, bool ssl = false, const char *protocolName = "HTTP", BUrlProtocolListener* listener = NULL, - BUrlContext* context = NULL, - BUrlResult* result = NULL); - virtual ~BUrlProtocolHttp(); - - virtual status_t SetOption(uint32 option, void* value); + BUrlContext* context = NULL); + virtual ~BHttpRequest(); + + void SetMethod(int8 method); + void SetFollowLocation(bool follow); + void SetMaxRedirections(int8 maxRedirections); + void SetReferrer(const BString& referrer); + void SetUserAgent(const BString& agent); + void SetHeaders(BHttpHeaders* headers); + void SetDiscardData(bool discard); + void SetDisableListener(bool disable); + void SetAutoReferrer(bool enable); + void SetPostFields(BHttpForm* fields); + void SetInputData(BDataIO* data, ssize_t size = -1); + void SetUserName(const BString& name); + void SetPassword(const BString& password); static bool IsInformationalStatusCode(int16 code); static bool IsSuccessStatusCode(int16 code); @@ -89,6 +101,7 @@ private: BHttpHeaders* fOptHeaders; BHttpForm* fOptPostFields; BDataIO* fOptInputData; + ssize_t fOptInputDataSize; bool fOptSetCookies : 1; bool fOptFollowLocation : 1; bool fOptDiscardData : 1; diff --git a/headers/os/net/UrlProtocol.h b/headers/os/net/UrlProtocol.h deleted file mode 100644 index f177dbb..0000000 --- a/headers/os/net/UrlProtocol.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2010 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - */ -#ifndef _B_URL_PROTOCOL_H_ -#define _B_URL_PROTOCOL_H_ - - -#include <Url.h> -#include <UrlResult.h> -#include <UrlContext.h> -#include <UrlProtocolListener.h> -#include <OS.h> - - -class BUrlProtocol { -public: - BUrlProtocol(const BUrl& url, - BUrlProtocolListener* listener, - BUrlContext* context, - BUrlResult* result, - const char* threadName, - const char* protocolName); - virtual ~BUrlProtocol(); - - // URL protocol required members - // TODO: (stippi) I know it's sometimes appealing to have these - // "simplistic" methods that can do anything, but they remove - // type-safety. Why not overload SetOption with all possible types? - // Like: - // SetOption(uint32 option, bool value); - // SetOption(uint32 option, int8 value); - // SetOption(uint32 option, int16 value); - // SetOption(uint32 option, int32 value); - // ... - // This keeps the calling side even more simple, since it - // don't need to do pointer stuff with the parameters. Also, since - // this method is forced to be implemented in derived classes, why - // is it here at all? Why not have non-virtual setters for specific - // things, where the setter is properly named? - virtual status_t SetOption(uint32 name, void* value) = 0; - - // URL protocol thread management - virtual thread_id Run(); - virtual status_t Pause(); - virtual status_t Resume(); - virtual status_t Stop(); - - // URL protocol parameters modification - status_t SetUrl(const BUrl& url); - status_t SetResult(BUrlResult* result); - status_t SetContext(BUrlContext* context); - status_t SetListener(BUrlProtocolListener* listener); - - // URL protocol parameters access - const BUrl& Url() const; - BUrlResult* Result() const; - BUrlContext* Context() const; - BUrlProtocolListener* Listener() const; - const BString& Protocol() const; - - // URL protocol informations - bool IsRunning() const; - status_t Status() const; - virtual const char* StatusString(status_t threadStatus) - const; - - -protected: - static int32 _ThreadEntry(void* arg); - virtual status_t _ProtocolLoop(); - virtual void _EmitDebug(BUrlProtocolDebugMessage type, - const char* format, ...); - - // URL result parameters access - BMallocIO& _ResultRawData(); - BHttpHeaders& _ResultHeaders(); - void _SetResultStatusCode(int32 statusCode); - BString& _ResultStatusText(); - -protected: - BUrl fUrl; - BUrlResult* fResult; - BUrlContext* fContext; - BUrlProtocolListener* fListener; - - bool fQuit; - bool fRunning; - status_t fThreadStatus; - thread_id fThreadId; - BString fThreadName; - BString fProtocol; -}; - - -// TODO: Rename, this is in the global namespace. -enum { - B_PROT_THREAD_STATUS__BASE = 0, - B_PROT_SUCCESS = B_PROT_THREAD_STATUS__BASE, - B_PROT_RUNNING, - B_PROT_PAUSED, - B_PROT_ABORTED, - B_PROT_SOCKET_ERROR, - B_PROT_CONNECTION_FAILED, - B_PROT_CANT_RESOLVE_HOSTNAME, - B_PROT_WRITE_FAILED, - B_PROT_READ_FAILED, - B_PROT_NO_MEMORY, - B_PROT_PROTOCOL_ERROR, - // Thread status over this one are guaranteed to be - // errors - B_PROT_THREAD_STATUS__END -}; - - -namespace BPrivate { - -class BUrlProtocolOption { -public: - BUrlProtocolOption(void* value) : fValuePtr(value) { } - - bool Bool() const { return *reinterpret_cast<bool*>(fValuePtr); } - int8 Int8() const { return *reinterpret_cast<int8*>(fValuePtr); } - int16 Int16() const { return *reinterpret_cast<int16*>(fValuePtr); } - int32 Int32() const { return *reinterpret_cast<int32*>(fValuePtr); } - char* String() const { return reinterpret_cast<char*>(fValuePtr); } - void* Pointer() const { return fValuePtr; } - -private: - void* fValuePtr; -}; - -} // namespace BPrivate - - -#endif // _B_URL_PROTOCOL_H_ diff --git a/headers/os/net/UrlProtocolAsynchronousListener.h b/headers/os/net/UrlProtocolAsynchronousListener.h index 52d708e..37b616f 100644 --- a/headers/os/net/UrlProtocolAsynchronousListener.h +++ b/headers/os/net/UrlProtocolAsynchronousListener.h @@ -17,18 +17,18 @@ public: bool transparent = false); virtual ~BUrlProtocolAsynchronousListener(); - virtual void ConnectionOpened(BUrlProtocol* caller); - virtual void HostnameResolved(BUrlProtocol* caller, + virtual void ConnectionOpened(BUrlRequest* caller); + virtual void HostnameResolved(BUrlRequest* caller, const char* ip); - virtual void ResponseStarted(BUrlProtocol* caller); - virtual void HeadersReceived(BUrlProtocol* caller); - virtual void DataReceived(BUrlProtocol* caller, + virtual void ResponseStarted(BUrlRequest* caller); + virtual void HeadersReceived(BUrlRequest* caller); + virtual void DataReceived(BUrlRequest* caller, const char* data, ssize_t size); - virtual void DownloadProgress(BUrlProtocol* caller, + virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); - virtual void UploadProgress(BUrlProtocol* caller, + virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal); - virtual void RequestCompleted(BUrlProtocol* caller, + virtual void RequestCompleted(BUrlRequest* caller, bool success); // Synchronous listener access diff --git a/headers/os/net/UrlProtocolDispatchingListener.h b/headers/os/net/UrlProtocolDispatchingListener.h index a89c3b9..03f5e39 100644 --- a/headers/os/net/UrlProtocolDispatchingListener.h +++ b/headers/os/net/UrlProtocolDispatchingListener.h @@ -38,26 +38,23 @@ public: const BMessenger& messenger); virtual ~BUrlProtocolDispatchingListener(); - virtual void ConnectionOpened(BUrlProtocol* caller); - virtual void HostnameResolved(BUrlProtocol* caller, + virtual void ConnectionOpened(BUrlRequest* caller); + virtual void HostnameResolved(BUrlRequest* caller, const char* ip); - virtual void ResponseStarted(BUrlProtocol* caller); - virtual void HeadersReceived(BUrlProtocol* caller); - virtual void DataReceived(BUrlProtocol* caller, + virtual void ResponseStarted(BUrlRequest* caller); + virtual void HeadersReceived(BUrlRequest* caller); + virtual void DataReceived(BUrlRequest* caller, const char* data, ssize_t size); - virtual void DownloadProgress(BUrlProtocol* caller, + virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); - virtual void UploadProgress(BUrlProtocol* caller, + virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal); - virtual void RequestCompleted(BUrlProtocol* caller, + virtual void RequestCompleted(BUrlRequest* caller, bool success); - virtual void DebugMessage(BUrlProtocol*, - BUrlProtocolDebugMessage, - const char*) { } private: void _SendMessage(BMessage* message, - int8 notification, BUrlProtocol* caller); + int8 notification, BUrlRequest* caller); private: BMessenger fMessenger; diff --git a/headers/os/net/UrlProtocolListener.h b/headers/os/net/UrlProtocolListener.h index e046e4b..ff1764f 100644 --- a/headers/os/net/UrlProtocolListener.h +++ b/headers/os/net/UrlProtocolListener.h @@ -9,7 +9,7 @@ #include <stddef.h> #include <cstdlib> -class BUrlProtocol; +class BUrlRequest; enum BUrlProtocolDebugMessage { @@ -24,15 +24,15 @@ enum BUrlProtocolDebugMessage { class BUrlProtocolListener { public: - /* + /** ConnectionOpened() Frequency: Once Called when the socket is opened. */ - virtual void ConnectionOpened(BUrlProtocol* caller); + virtual void ConnectionOpened(BUrlRequest* caller); - /* + /** HostnameResolved(ip) Frequency: Once Parameters: ip String representing the IP address of the resource @@ -40,28 +40,28 @@ public: Called when the final IP is discovered */ - virtual void HostnameResolved(BUrlProtocol* caller, + virtual void HostnameResolved(BUrlRequest* caller, const char* ip); - /* + /** ReponseStarted() Frequency: Once Called when the request has been emitted and the server begins to reply. Typically when the HTTP status code is received. */ - virtual void ResponseStarted(BUrlProtocol* caller); + virtual void ResponseStarted(BUrlRequest* caller); - /* + /** HeadersReceived() Frequency: Once Called when all the server response metadata (such as headers) have been read and parsed. */ - virtual void HeadersReceived(BUrlProtocol* caller); + virtual void HeadersReceived(BUrlRequest* caller); - /* + /** DataReceived(data, size) Frequency: Zero or more Parameters: data Pointer to the data block in memory @@ -69,10 +69,10 @@ public: Called each time a full block of data is received. */ - virtual void DataReceived(BUrlProtocol* caller, + virtual void DataReceived(BUrlRequest* caller, const char* data, ssize_t size); - /* + /** DownloadProgress(bytesReceived, bytesTotal) Frequency: Once or more Parameters: bytesReceived Number of data bytes received @@ -80,10 +80,10 @@ public: Called each time a data block is received. */ - virtual void DownloadProgress(BUrlProtocol* caller, + virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); - /* + /** UploadProgress(bytesSent, bytesTotal) Frequency: Once or more Parameters: bytesSent Number of data bytes sent @@ -91,10 +91,10 @@ public: Called each time a data block is emitted. */ - virtual void UploadProgress(BUrlProtocol* caller, + virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal); - /* + /** RequestCompleted(success) Frequency: Once Parameters: success true if the resource have been successfully @@ -102,17 +102,17 @@ public: Called once the request is complete. */ - virtual void RequestCompleted(BUrlProtocol* caller, + virtual void RequestCompleted(BUrlRequest* caller, bool success); - /* + /** DebugMessage(type, text) Frequency: zero or more Parameters: type Type of the verbose message (see BUrlProtocolDebug) Called each time a debug message is emitted */ - virtual void DebugMessage(BUrlProtocol* caller, + virtual void DebugMessage(BUrlRequest* caller, BUrlProtocolDebugMessage type, const char* text); }; diff --git a/headers/os/net/UrlProtocolRoster.h b/headers/os/net/UrlProtocolRoster.h new file mode 100644 index 0000000..3e54149 --- /dev/null +++ b/headers/os/net/UrlProtocolRoster.h @@ -0,0 +1,25 @@ +/* + * Copyright 2013 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#ifndef _B_URL_ROSTER_H_ +#define _B_URL_ROSTER_H_ + + +#include <stdlib.h> + + +class BUrl; +class BUrlContext; +class BUrlProtocolListener; +class BUrlRequest; + +class BUrlProtocolRoster { +public: + static BUrlRequest* MakeRequest(const BUrl& url, + BUrlProtocolListener* listener = NULL, + BUrlContext* context = NULL); +}; + +#endif diff --git a/headers/os/net/UrlRequest.h b/headers/os/net/UrlRequest.h index d036783..82b2dbc 100644 --- a/headers/os/net/UrlRequest.h +++ b/headers/os/net/UrlRequest.h @@ -6,64 +6,93 @@ #define _B_URL_REQUEST_H_ -#include <HttpHeaders.h> #include <Url.h> #include <UrlResult.h> #include <UrlContext.h> -#include <UrlProtocol.h> #include <UrlProtocolListener.h> - - -enum { - B_NO_HANDLER_FOR_PROTOCOL = B_ERROR -}; +#include <OS.h> class BUrlRequest { public: BUrlRequest(const BUrl& url, - BUrlProtocolListener* listener = NULL, - BUrlContext* context = NULL); - BUrlRequest(const BUrlRequest& other); + BUrlProtocolListener* listener, + BUrlContext* context, + BUrlResult& result, + const char* threadName, + const char* protocolName); virtual ~BUrlRequest(); - // Request parameters modification - status_t SetUrl(const BUrl& url); - void SetContext(BUrlContext* context); - void SetProtocolListener( - BUrlProtocolListener* listener); - bool SetProtocolOption(int32 option, - void* value); - // Request parameters access - const BUrlProtocol* Protocol(); - const BUrlResult& Result(); - const BUrl& Url(); - - // Request control - virtual status_t Start(); + // URL protocol thread management + virtual thread_id Run(); virtual status_t Pause(); virtual status_t Resume(); - virtual status_t Abort(); + virtual status_t Stop(); - // Request informations - virtual status_t InitCheck() const; + // URL protocol parameters modification + status_t SetUrl(const BUrl& url); + status_t SetResult(BUrlResult& result); + status_t SetContext(BUrlContext* context); + status_t SetListener(BUrlProtocolListener* listener); + + // URL protocol parameters access + const BUrl& Url() const; + BUrlResult& Result() const; + BUrlContext* Context() const; + BUrlProtocolListener* Listener() const; + const BString& Protocol() const; + + // URL protocol informations bool IsRunning() const; status_t Status() const; + virtual const char* StatusString(status_t threadStatus) + const; + - // Overloaded members - BUrlRequest& operator=(const BUrlRequest& other); +protected: + static int32 _ThreadEntry(void* arg); + virtual status_t _ProtocolLoop(); + virtual void _EmitDebug(BUrlProtocolDebugMessage type, + const char* format, ...); + // URL result parameters access + BMallocIO& _ResultRawData(); + BHttpHeaders& _ResultHeaders(); + void _SetResultStatusCode(int32 statusCode); + BString& _ResultStatusText(); protected: - BUrlProtocolListener* fListener; - BUrlProtocol* fUrlProtocol; - BUrlResult fResult; - BUrlContext* fContext; BUrl fUrl; - status_t fInitStatus; + BUrlResult& fResult; + BUrlContext* fContext; + BUrlProtocolListener* fListener; -private: - status_t _SetupProtocol(); + bool fQuit; + bool fRunning; + status_t fThreadStatus; + thread_id fThreadId; + BString fThreadName; + BString fProtocol; +}; + + +// TODO: Rename, this is in the global namespace. +enum { + B_PROT_THREAD_STATUS__BASE = 0, + B_PROT_SUCCESS = B_PROT_THREAD_STATUS__BASE, + B_PROT_RUNNING, + B_PROT_PAUSED, + B_PROT_ABORTED, + B_PROT_SOCKET_ERROR, + B_PROT_CONNECTION_FAILED, + B_PROT_CANT_RESOLVE_HOSTNAME, + B_PROT_WRITE_FAILED, + B_PROT_READ_FAILED, + B_PROT_NO_MEMORY, + B_PROT_PROTOCOL_ERROR, + // Thread status over this one are guaranteed to be + // errors + B_PROT_THREAD_STATUS__END }; #endif // _B_URL_REQUEST_H_ diff --git a/headers/os/net/UrlResult.h b/headers/os/net/UrlResult.h index 6230035..773e88b 100644 --- a/headers/os/net/UrlResult.h +++ b/headers/os/net/UrlResult.h @@ -14,11 +14,11 @@ #include <Url.h> -class BUrlProtocol; +class BUrlRequest; class BUrlResult { - friend class BUrlProtocol; + friend class BUrlRequest; public: BUrlResult(const BUrl& url); diff --git a/headers/os/net/UrlSynchronousRequest.h b/headers/os/net/UrlSynchronousRequest.h index 13f927c..6602608 100644 --- a/headers/os/net/UrlSynchronousRequest.h +++ b/headers/os/net/UrlSynchronousRequest.h @@ -12,7 +12,7 @@ class BUrlSynchronousRequest : public BUrlRequest, public BUrlProtocolListener { public: - BUrlSynchronousRequest(BUrl& url); + BUrlSynchronousRequest(BUrlRequest& asynchronousRequest); virtual ~BUrlSynchronousRequest() { }; // Synchronous wait @@ -20,23 +20,24 @@ public: virtual status_t WaitUntilCompletion(); // Protocol hooks - virtual void ConnectionOpened(BUrlProtocol* caller); - virtual void HostnameResolved(BUrlProtocol* caller, + virtual void ConnectionOpened(BUrlRequest* caller); + virtual void HostnameResolved(BUrlRequest* caller, const char* ip); - virtual void ResponseStarted(BUrlProtocol* caller); - virtual void HeadersReceived(BUrlProtocol* caller); - virtual void DataReceived(BUrlProtocol* caller, + virtual void ResponseStarted(BUrlRequest* caller); + virtual void HeadersReceived(BUrlRequest* caller); + virtual void DataReceived(BUrlRequest* caller, const char* data, ssize_t size); - virtual void DownloadProgress(BUrlProtocol* caller, + virtual void DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal); - virtual void UploadProgress(BUrlProtocol* caller, + virtual void UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal); - virtual void RequestCompleted(BUrlProtocol* caller, + virtual void RequestCompleted(BUrlRequest* caller, bool success); protected: bool fRequestComplete; + BUrlRequest& fWrappedRequest; }; diff --git a/src/kits/network/libnetapi/HttpForm.cpp b/src/kits/network/libnetapi/HttpForm.cpp index 030abe5..19722eb 100644 --- a/src/kits/network/libnetapi/HttpForm.cpp +++ b/src/kits/network/libnetapi/HttpForm.cpp @@ -184,13 +184,6 @@ BHttpFormData::MarkAsFile(const BString& filename, const BString& mimeType) } -status_t -BHttpFormData::MarkAsFile(const BString& filename) -{ - return MarkAsFile(filename, ""); -} - - void BHttpFormData::UnmarkAsFile() { diff --git a/src/kits/network/libnetapi/HttpHeaders.cpp b/src/kits/network/libnetapi/HttpHeaders.cpp index 4f67985..60d8356 100644 --- a/src/kits/network/libnetapi/HttpHeaders.cpp +++ b/src/kits/network/libnetapi/HttpHeaders.cpp @@ -277,6 +277,8 @@ BHttpHeaders::Clear() BHttpHeaders& BHttpHeaders::operator=(const BHttpHeaders& other) { + Clear(); + for (int32 i = 0; i < other.CountHeaders(); i++) AddHeader(other.HeaderAt(i).Name(), other.HeaderAt(i).Value()); diff --git a/src/kits/network/libnetapi/UrlProtocolHttp.cpp b/src/kits/network/libnetapi/HttpRequest.cpp similarity index 84% rename from src/kits/network/libnetapi/UrlProtocolHttp.cpp rename to src/kits/network/libnetapi/HttpRequest.cpp index 4c0ad15..39dbfb2 100644 --- a/src/kits/network/libnetapi/UrlProtocolHttp.cpp +++ b/src/kits/network/libnetapi/HttpRequest.cpp @@ -17,10 +17,7 @@ #include <File.h> #include <Socket.h> #include <SecureSocket.h> -#include <UrlProtocolHttp.h> - - -using BPrivate::BUrlProtocolOption; +#include <HttpRequest.h> static const int32 kHttpProtocolReceiveBufferSize = 1024; @@ -31,11 +28,11 @@ static const char* kHttpProtocolThreadStrStatus[ }; -BUrlProtocolHttp::BUrlProtocolHttp(BUrl& url, bool ssl, +BHttpRequest::BHttpRequest(const BUrl& url, BUrlResult& result, bool ssl, const char* protocolName, BUrlProtocolListener* listener, - BUrlContext* context, BUrlResult* result) + BUrlContext* context) : - BUrlProtocol(url, listener, context, result, "BUrlProtocol.HTTP", protocolName), + BUrlRequest(url, listener, context, result, "BUrlProtocol.HTTP", protocolName), fSSL(ssl), fRequestMethod(B_HTTP_GET), fHttpVersion(B_HTTP_11) @@ -48,83 +45,109 @@ BUrlProtocolHttp::BUrlProtocolHttp(BUrl& url, bool ssl, } -BUrlProtocolHttp::~BUrlProtocolHttp() +BHttpRequest::~BHttpRequest() { delete fSocket; } -status_t -BUrlProtocolHttp::SetOption(uint32 name, void* value) +void +BHttpRequest::SetMethod(int8 method) { - BUrlProtocolOption option(value); + fRequestMethod = method; +} - switch (name) { - case B_HTTPOPT_METHOD: - fRequestMethod = option.Int8(); - break; - case B_HTTPOPT_FOLLOWLOCATION: - fOptFollowLocation = option.Bool(); - break; +void +BHttpRequest::SetFollowLocation(bool follow) +{ + fOptFollowLocation = follow; +} - case B_HTTPOPT_MAXREDIRS: - fOptMaxRedirs = option.Int8(); - break; - case B_HTTPOPT_REFERER: - fOptReferer = option.String(); - break; +void +BHttpRequest::SetMaxRedirections(int8 redirections) +{ + fOptMaxRedirs = redirections; +} - case B_HTTPOPT_USERAGENT: - fOptUserAgent = option.String(); - break; - case B_HTTPOPT_HEADERS: - fOptHeaders = reinterpret_cast<BHttpHeaders*>(option.Pointer()); - break; +void +BHttpRequest::SetReferrer(const BString& referrer) +{ + fOptReferer = referrer; +} - case B_HTTPOPT_DISCARD_DATA: - fOptDiscardData = option.Bool(); - break; - case B_HTTPOPT_DISABLE_LISTENER: - fOptDisableListener = option.Bool(); - break; +void +BHttpRequest::SetUserAgent(const BString& agent) +{ + fOptUserAgent = agent; +} - case B_HTTPOPT_AUTOREFERER: - fOptAutoReferer = option.Bool(); - break; - case B_HTTPOPT_POSTFIELDS: - fOptPostFields = reinterpret_cast<BHttpForm*>(option.Pointer()); +void +BHttpRequest::SetHeaders(BHttpHeaders* headers) +{ + fOptHeaders = headers; +} - if (fOptPostFields != NULL) - fRequestMethod = B_HTTP_POST; - break; - case B_HTTPOPT_INPUTDATA: - fOptInputData = reinterpret_cast<BDataIO*>(option.Pointer()); - break; +void +BHttpRequest::SetDiscardData(bool discard) +{ + fOptDiscardData = discard; +} - case B_HTTPOPT_AUTHUSERNAME: - fOptUsername = option.String(); - break; - case B_HTTPOPT_AUTHPASSWORD: - fOptPassword = option.String(); - break; +void +BHttpRequest::SetDisableListener(bool disable) +{ + fOptDisableListener = disable; +} - default: - return B_ERROR; - } - return B_OK; +void +BHttpRequest::SetAutoReferrer(bool enable) +{ + fOptAutoReferer = enable; +} + + +void +BHttpRequest::SetPostFields(BHttpForm* fields) +{ + fOptPostFields = fields; + + if (fOptPostFields != NULL) + fRequestMethod = B_HTTP_POST; +} + + +void +BHttpRequest::SetInputData(BDataIO* data, ssize_t size) +{ + fOptInputData = data; + fOptInputDataSize = size; +} + + +void +BHttpRequest::SetUserName(const BString& name) +{ + fOptUsername = name; +} + + +void +BHttpRequest::SetPassword(const BString& password) +{ + fOptPassword = password; } /*static*/ bool -BUrlProtocolHttp::IsInformationalStatusCode(int16 code) +BHttpRequest::IsInformationalStatusCode(int16 code) { return (code >= B_HTTP_STATUS__INFORMATIONAL_BASE) && (code < B_HTTP_STATUS__INFORMATIONAL_END); @@ -132,7 +155,7 @@ BUrlProtocolHttp::IsInformationalStatusCode(int16 code) /*static*/ bool -BUrlProtocolHttp::IsSuccessStatusCode(int16 code) +BHttpRequest::IsSuccessStatusCode(int16 code) { return (code >= B_HTTP_STATUS__SUCCESS_BASE) && (code < B_HTTP_STATUS__SUCCESS_END); @@ -140,7 +163,7 @@ BUrlProtocolHttp::IsSuccessStatusCode(int16 code) /*static*/ bool -BUrlProtocolHttp::IsRedirectionStatusCode(int16 code) +BHttpRequest::IsRedirectionStatusCode(int16 code) { return (code >= B_HTTP_STATUS__REDIRECTION_BASE) && (code < B_HTTP_STATUS__REDIRECTION_END); @@ -148,7 +171,7 @@ BUrlProtocolHttp::IsRedirectionStatusCode(int16 code) /*static*/ bool -BUrlProtocolHttp::IsClientErrorStatusCode(int16 code) +BHttpRequest::IsClientErrorStatusCode(int16 code) { return (code >= B_HTTP_STATUS__CLIENT_ERROR_BASE) && (code < B_HTTP_STATUS__CLIENT_ERROR_END); @@ -156,7 +179,7 @@ BUrlProtocolHttp::IsClientErrorStatusCode(int16 code) /*static*/ bool -BUrlProtocolHttp::IsServerErrorStatusCode(int16 code) +BHttpRequest::IsServerErrorStatusCode(int16 code) { return (code >= B_HTTP_STATUS__SERVER_ERROR_BASE) && (code < B_HTTP_STATUS__SERVER_ERROR_END); @@ -164,17 +187,17 @@ BUrlProtocolHttp::IsServerErrorStatusCode(int16 code) /*static*/ int16 -BUrlProtocolHttp::StatusCodeClass(int16 code) +BHttpRequest::StatusCodeClass(int16 code) { - if (BUrlProtocolHttp::IsInformationalStatusCode(code)) + if (BHttpRequest::IsInformationalStatusCode(code)) return B_HTTP_STATUS_CLASS_INFORMATIONAL; - else if (BUrlProtocolHttp::IsSuccessStatusCode(code)) + else if (BHttpRequest::IsSuccessStatusCode(code)) return B_HTTP_STATUS_CLASS_SUCCESS; - else if (BUrlProtocolHttp::IsRedirectionStatusCode(code)) + else if (BHttpRequest::IsRedirectionStatusCode(code)) return B_HTTP_STATUS_CLASS_REDIRECTION; - else if (BUrlProtocolHttp::IsClientErrorStatusCode(code)) + else if (BHttpRequest::IsClientErrorStatusCode(code)) return B_HTTP_STATUS_CLASS_CLIENT_ERROR; - else if (BUrlProtocolHttp::IsServerErrorStatusCode(code)) + else if (BHttpRequest::IsServerErrorStatusCode(code)) return B_HTTP_STATUS_CLASS_SERVER_ERROR; return B_HTTP_STATUS_CLASS_INVALID; @@ -182,12 +205,12 @@ BUrlProtocolHttp::StatusCodeClass(int16 code) const char* -BUrlProtocolHttp::StatusString(status_t threadStatus) const +BHttpRequest::StatusString(status_t threadStatus) const { if (threadStatus < B_PROT_THREAD_STATUS__END) - return BUrlProtocol::StatusString(threadStatus); + return BUrlRequest::StatusString(threadStatus); else if (threadStatus >= B_PROT_HTTP_THREAD_STATUS__END) - return BUrlProtocol::StatusString(-1); + return BUrlRequest::StatusString(-1); else return kHttpProtocolThreadStrStatus[threadStatus - B_PROT_THREAD_STATUS__END]; @@ -195,7 +218,7 @@ BUrlProtocolHttp::StatusString(status_t threadStatus) const void -BUrlProtocolHttp::_ResetOptions() +BHttpRequest::_ResetOptions() { fOptFollowLocation = true; fOptMaxRedirs = 8; @@ -215,7 +238,7 @@ BUrlProtocolHttp::_ResetOptions() #include <stdio.h> status_t -BUrlProtocolHttp::_ProtocolLoop() +BHttpRequest::_ProtocolLoop() { printf("UHP[%p]::{Loop} %s\n", this, fUrl.UrlString().String()); @@ -252,7 +275,7 @@ BUrlProtocolHttp::_ProtocolLoop() if (fOptAutoReferer) fOptReferer = fUrl.UrlString(); - switch (StatusCodeClass(fResult->StatusCode())) { + switch (StatusCodeClass(fResult.StatusCode())) { case B_HTTP_STATUS_CLASS_INFORMATIONAL: // Header 100:continue should have been // handled in the _MakeRequest read loop @@ -268,7 +291,7 @@ BUrlProtocolHttp::_ProtocolLoop() // TODO: Some browsers seems to translate POST requests to // GET when following a 302 redirection - if (fResult->StatusCode() == B_HTTP_STATUS_MOVED_PERMANENTLY) { + if (fResult.StatusCode() == B_HTTP_STATUS_MOVED_PERMANENTLY) { BString locationUrl = fHeaders["Location"]; // Absolute path @@ -289,7 +312,7 @@ BUrlProtocolHttp::_ProtocolLoop() break; case B_HTTP_STATUS_CLASS_CLIENT_ERROR: - switch (fResult->StatusCode()) { + switch (fResult.StatusCode()) { case B_HTTP_STATUS_UNAUTHORIZED: if (fAuthentication.Method() != B_HTTP_AUTHENTICATION_NONE) { newRequest = false; @@ -321,7 +344,7 @@ BUrlProtocolHttp::_ProtocolLoop() "%ld headers and %ld bytes of data remaining", fHeaders.CountHeaders(), fInputBuffer.Size()); - if (fResult->StatusCode() == 404) + if (fResult.StatusCode() == 404) return B_PROT_HTTP_NOT_FOUND; return B_PROT_SUCCESS; @@ -329,7 +352,7 @@ BUrlProtocolHttp::_ProtocolLoop() bool -BUrlProtocolHttp::_ResolveHostName() +BHttpRequest::_ResolveHostName() { _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Resolving %s", fUrl.UrlString().String()); @@ -357,7 +380,7 @@ BUrlProtocolHttp::_ResolveHostName() status_t -BUrlProtocolHttp::_MakeRequest() +BHttpRequest::_MakeRequest() { _EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Connection to %s on port %d.", fUrl.Authority().String(), fRemoteAddr.Port()); @@ -442,13 +465,19 @@ BUrlProtocolHttp::_MakeRequest() read = fOptInputData->Read(outputTempBuffer, 1024); if (read > 0) { - char hexSize[16]; - size_t hexLength = sprintf(hexSize, "%ld", read); - - fSocket->Write(hexSize, hexLength); - fSocket->Write("\r\n", 2); - fSocket->Write(outputTempBuffer, read); - fSocket->Write("\r\n", 2); + if (fOptInputDataSize < 0) + { + // Chunked transfer + char hexSize[16]; + size_t hexLength = sprintf(hexSize, "%ld", read); + + fSocket->Write(hexSize, hexLength); + fSocket->Write("\r\n", 2); + fSocket->Write(outputTempBuffer, read); + fSocket->Write("\r\n", 2); + } else { + fSocket->Write(outputTempBuffer, read); + } } } @@ -626,7 +655,7 @@ BUrlProtocolHttp::_MakeRequest() status_t -BUrlProtocolHttp::_GetLine(BString& destString) +BHttpRequest::_GetLine(BString& destString) { // Find a complete line in inputBuffer uint32 characterIndex = 0; @@ -653,7 +682,7 @@ BUrlProtocolHttp::_GetLine(BString& destString) void -BUrlProtocolHttp::_ParseStatus() +BHttpRequest::_ParseStatus() { // Status line should be formatted like: HTTP/M.m SSS ... // With: M = Major version of the protocol @@ -682,7 +711,7 @@ BUrlProtocolHttp::_ParseStatus() void -BUrlProtocolHttp::_ParseHeaders() +BHttpRequest::_ParseHeaders() { BString currentHeader; if (_GetLine(currentHeader) == B_ERROR) @@ -700,7 +729,7 @@ BUrlProtocolHttp::_ParseHeaders() void -BUrlProtocolHttp::_CreateRequest() +BHttpRequest::_CreateRequest() { BString request; @@ -748,7 +777,7 @@ BUrlProtocolHttp::_CreateRequest() void -BUrlProtocolHttp::_AddHeaders() +BHttpRequest::_AddHeaders() { // HTTP 1.1 additional headers if (fHttpVersion == B_HTTP_11) { @@ -813,8 +842,14 @@ BUrlProtocolHttp::_AddHeaders() fOutputHeaders.AddHeader("Content-Length", fOptPostFields->ContentLength()); } else if (fOptInputData != NULL - && (fRequestMethod == B_HTTP_POST || fRequestMethod == B_HTTP_PUT)) - fOutputHeaders.AddHeader("Transfer-Encoding", "chunked"); + && (fRequestMethod == B_HTTP_POST || fRequestMethod == B_HTTP_PUT)) + { + if(fOptInputDataSize >= 0) { + fOutputHeaders.AddHeader("Content-Length", fOptInputDataSize); + } else { + fOutputHeaders.AddHeader("Transfer-Encoding", "chunked"); + } + } // Optional headers specified by the user if (fOptHeaders != NULL) { @@ -850,7 +885,7 @@ BUrlProtocolHttp::_AddHeaders() void -BUrlProtocolHttp::_AddOutputBufferLine(const char* line) +BHttpRequest::_AddOutputBufferLine(const char* line) { _EmitDebug(B_URL_PROTOCOL_DEBUG_HEADER_OUT, "%s", line); fOutputBuffer << line << "\r\n"; diff --git a/src/kits/network/libnetapi/Jamfile b/src/kits/network/libnetapi/Jamfile index bcc0a79..ec079c2 100644 --- a/src/kits/network/libnetapi/Jamfile +++ b/src/kits/network/libnetapi/Jamfile @@ -54,23 +54,20 @@ for architectureObject in [ MultiArchSubDirSetup ] { # TODO: The HTTP stuff should all go into an add-on. It needs # linking against libcrypto.so and only the add-on should link # against it. - # Building of the commented out files has not been completely tested - # after integrating the code from the GSoC 2010 "Services Kit" - # project and doing some renaming of types, constants and methods. HttpAuthentication.cpp HttpHeaders.cpp HttpForm.cpp + HttpRequest.cpp HttpTime.cpp $(md5Sources) Url.cpp UrlContext.cpp - UrlProtocol.cpp UrlProtocolAsynchronousListener.cpp UrlProtocolDispatchingListener.cpp - UrlProtocolHttp.cpp # TODO: -> add-on, See above. UrlProtocolListener.cpp + UrlProtocolRoster.cpp UrlRequest.cpp UrlResult.cpp UrlSynchronousRequest.cpp diff --git a/src/kits/network/libnetapi/UrlProtocol.cpp b/src/kits/network/libnetapi/UrlProtocol.cpp deleted file mode 100644 index d25c19a..0000000 --- a/src/kits/network/libnetapi/UrlProtocol.cpp +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2010 Haiku Inc. All rights reserved. - * Distributed under the terms of the MIT License. - * - * Authors: - * Christophe Huriaux, c.huriaux@xxxxxxxxx - */ - - -#include <UrlProtocol.h> -#include <Debug.h> -#include <stdio.h> - - -static const char* kProtocolThreadStrStatus[B_PROT_THREAD_STATUS__END+1] - = { - "Request successfully completed", - "Request running", - "Socket error", - "Connection failed", - "Hostname resolution failed", - "Network write failed", - "Network read failed", - "Out of memory", - "Protocol-specific error", - "Unknown error" - }; - - -BUrlProtocol::BUrlProtocol(const BUrl& url, BUrlProtocolListener* listener, - BUrlContext* context, BUrlResult* result, const char* threadName, - const char* protocolName) - : - fUrl(url), - fResult(result), - fContext(context), - fListener(listener), - fQuit(false), - fRunning(false), - fThreadId(0), - fThreadName(threadName), - fProtocol(protocolName) -{ -} - - -BUrlProtocol::~BUrlProtocol() -{ -} - - -// #pragma mark URL protocol thread management - - -thread_id -BUrlProtocol::Run() -{ - // Thread already running - if (fRunning) { - PRINT(("BUrlProtocol::Run() : Oops, already running ! " - "[urlProtocol=%p]!\n", this)); - return fThreadId; - } - - fThreadId = spawn_thread(BUrlProtocol::_ThreadEntry, fThreadName, - B_NORMAL_PRIORITY, this); - - if (fThreadId < B_OK) - return fThreadId; - - status_t launchErr = resume_thread(fThreadId); - if (launchErr < B_OK) { - PRINT(("BUrlProtocol::Run() : Failed to resume thread %ld\n", - fThreadId)); - return launchErr; - } - - fRunning = true; - return fThreadId; -} - - -status_t -BUrlProtocol::Pause() -{ - // TODO - return B_ERROR; -} - - -status_t -BUrlProtocol::Resume() -{ - // TODO - return B_ERROR; -} - - -status_t -BUrlProtocol::Stop() -{ - if (!fRunning) - return B_ERROR; - - status_t threadStatus = B_OK; - fQuit = true; - - wait_for_thread(fThreadId, &threadStatus); - return threadStatus; -} - - -// #pragma mark URL protocol parameters modification - - -status_t -BUrlProtocol::SetUrl(const BUrl& url) -{ - // We should avoid to change URL while the thread is running ... - if (IsRunning()) - return B_ERROR; - - fUrl = url; - return B_OK; -} - - -status_t -BUrlProtocol::SetResult(BUrlResult* result) -{ - if (IsRunning()) - return B_ERROR; - - fResult = result; - return B_OK; -} - - -status_t -BUrlProtocol::SetContext(BUrlContext* context) -{ - if (IsRunning()) - return B_ERROR; - - fContext = context; - return B_OK; -} - - -status_t -BUrlProtocol::SetListener(BUrlProtocolListener* listener) -{ - if (IsRunning()) - return B_ERROR; - - fListener = listener; - return B_OK; -} - - -// #pragma mark URL protocol parameters access - - -const BUrl& -BUrlProtocol::Url() const -{ - return fUrl; -} - - -BUrlResult* -BUrlProtocol::Result() const -{ - return fResult; -} - - -BUrlContext* -BUrlProtocol::Context() const -{ - return fContext; -} - - -BUrlProtocolListener* -BUrlProtocol::Listener() const -{ - return fListener; -} - - -const BString& -BUrlProtocol::Protocol() const -{ - return fProtocol; -} - - -// #pragma mark URL protocol informations - - -bool -BUrlProtocol::IsRunning() const -{ - return fRunning; -} - - -status_t -BUrlProtocol::Status() const -{ - return fThreadStatus; -} - - -const char* -BUrlProtocol::StatusString(status_t threadStatus) const -{ - if (threadStatus < B_PROT_THREAD_STATUS__BASE) - threadStatus = B_PROT_THREAD_STATUS__END; - else if (threadStatus >= B_PROT_PROTOCOL_ERROR) - threadStatus = B_PROT_PROTOCOL_ERROR; - - return kProtocolThreadStrStatus[threadStatus]; -} - - -// #pragma mark Thread management - - -/*static*/ int32 -BUrlProtocol::_ThreadEntry(void* arg) -{ - BUrlProtocol* urlProtocol = reinterpret_cast<BUrlProtocol*>(arg); - urlProtocol->fThreadStatus = B_PROT_RUNNING; - - status_t protocolLoopExitStatus = urlProtocol->_ProtocolLoop(); - - urlProtocol->fRunning = false; - urlProtocol->fThreadStatus = protocolLoopExitStatus; - - if (urlProtocol->fListener != NULL) - urlProtocol->fListener->RequestCompleted(urlProtocol, - protocolLoopExitStatus == B_PROT_SUCCESS); - - return B_OK; -} - - -status_t -BUrlProtocol::_ProtocolLoop() -{ - // Dummy _ProtocolLoop - while (!fQuit) - snooze(1000); - - return B_PROT_SUCCESS; -} - - -void -BUrlProtocol::_EmitDebug(BUrlProtocolDebugMessage type, - const char* format, ...) -{ - if (fListener == NULL) - return; - - va_list arguments; - va_start(arguments, format); - - char debugMsg[256]; - vsnprintf(debugMsg, 256, format, arguments); - fListener->DebugMessage(this, type, debugMsg); - va_end(arguments); -} - - -BMallocIO& -BUrlProtocol::_ResultRawData() -{ - return fResult->fRawData; -} - - -BHttpHeaders& -BUrlProtocol::_ResultHeaders() -{ - return fResult->fHeaders; -} - - -void -BUrlProtocol::_SetResultStatusCode(int32 statusCode) -{ - fResult->fStatusCode = statusCode; -} - - -BString& -BUrlProtocol::_ResultStatusText() -{ - return fResult->fStatusString; -} diff --git a/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp b/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp index 5d61442..b577d56 100644 --- a/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolAsynchronousListener.cpp @@ -46,52 +46,52 @@ BUrlProtocolAsynchronousListener::~BUrlProtocolAsynchronousListener() void -BUrlProtocolAsynchronousListener::ConnectionOpened(BUrlProtocol*) +BUrlProtocolAsynchronousListener::ConnectionOpened(BUrlRequest*) { } void -BUrlProtocolAsynchronousListener::HostnameResolved(BUrlProtocol*, const char*) +BUrlProtocolAsynchronousListener::HostnameResolved(BUrlRequest*, const char*) { } void -BUrlProtocolAsynchronousListener::ResponseStarted(BUrlProtocol*) +BUrlProtocolAsynchronousListener::ResponseStarted(BUrlRequest*) { } void -BUrlProtocolAsynchronousListener::HeadersReceived(BUrlProtocol*) +BUrlProtocolAsynchronousListener::HeadersReceived(BUrlRequest*) { } void -BUrlProtocolAsynchronousListener::DataReceived(BUrlProtocol*, const char*, +BUrlProtocolAsynchronousListener::DataReceived(BUrlRequest*, const char*, ssize_t) { } void -BUrlProtocolAsynchronousListener::DownloadProgress(BUrlProtocol*, ssize_t, +BUrlProtocolAsynchronousListener::DownloadProgress(BUrlRequest*, ssize_t, ssize_t) { } void -BUrlProtocolAsynchronousListener::UploadProgress(BUrlProtocol*, ssize_t, +BUrlProtocolAsynchronousListener::UploadProgress(BUrlRequest*, ssize_t, ssize_t) { } void -BUrlProtocolAsynchronousListener::RequestCompleted(BUrlProtocol*, bool) +BUrlProtocolAsynchronousListener::RequestCompleted(BUrlRequest*, bool) { } @@ -114,7 +114,7 @@ BUrlProtocolAsynchronousListener::MessageReceived(BMessage* message) return; } - BUrlProtocol* caller; + BUrlRequest* caller; if (message->FindPointer(kUrlProtocolCaller, reinterpret_cast<void**>(&caller)) != B_OK) return; diff --git a/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp b/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp index 4601f1b..77d7b5b 100644 --- a/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolDispatchingListener.cpp @@ -37,7 +37,7 @@ BUrlProtocolDispatchingListener::~BUrlProtocolDispatchingListener() void -BUrlProtocolDispatchingListener::ConnectionOpened(BUrlProtocol* caller) +BUrlProtocolDispatchingListener::ConnectionOpened(BUrlRequest* caller) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); _SendMessage(&message, B_URL_PROTOCOL_CONNECTION_OPENED, caller); @@ -45,7 +45,7 @@ BUrlProtocolDispatchingListener::ConnectionOpened(BUrlProtocol* caller) void -BUrlProtocolDispatchingListener::HostnameResolved(BUrlProtocol* caller, +BUrlProtocolDispatchingListener::HostnameResolved(BUrlRequest* caller, const char* ip) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); @@ -56,7 +56,7 @@ BUrlProtocolDispatchingListener::HostnameResolved(BUrlProtocol* caller, void -BUrlProtocolDispatchingListener::ResponseStarted(BUrlProtocol* caller) +BUrlProtocolDispatchingListener::ResponseStarted(BUrlRequest* caller) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); _SendMessage(&message, B_URL_PROTOCOL_RESPONSE_STARTED, caller); @@ -64,7 +64,7 @@ BUrlProtocolDispatchingListener::ResponseStarted(BUrlProtocol* caller) void -BUrlProtocolDispatchingListener::HeadersReceived(BUrlProtocol* caller) +BUrlProtocolDispatchingListener::HeadersReceived(BUrlRequest* caller) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); _SendMessage(&message, B_URL_PROTOCOL_HEADERS_RECEIVED, caller); @@ -72,7 +72,7 @@ BUrlProtocolDispatchingListener::HeadersReceived(BUrlProtocol* caller) void -BUrlProtocolDispatchingListener::DataReceived(BUrlProtocol* caller, +BUrlProtocolDispatchingListener::DataReceived(BUrlRequest* caller, const char* data, ssize_t size) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); @@ -83,7 +83,7 @@ BUrlProtocolDispatchingListener::DataReceived(BUrlProtocol* caller, void -BUrlProtocolDispatchingListener::DownloadProgress(BUrlProtocol* caller, +BUrlProtocolDispatchingListener::DownloadProgress(BUrlRequest* caller, ssize_t bytesReceived, ssize_t bytesTotal) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); @@ -95,7 +95,7 @@ BUrlProtocolDispatchingListener::DownloadProgress(BUrlProtocol* caller, void -BUrlProtocolDispatchingListener::UploadProgress(BUrlProtocol* caller, +BUrlProtocolDispatchingListener::UploadProgress(BUrlRequest* caller, ssize_t bytesSent, ssize_t bytesTotal) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); @@ -108,7 +108,7 @@ BUrlProtocolDispatchingListener::UploadProgress(BUrlProtocol* caller, void -BUrlProtocolDispatchingListener::RequestCompleted(BUrlProtocol* caller, +BUrlProtocolDispatchingListener::RequestCompleted(BUrlRequest* caller, bool success) { BMessage message(B_URL_PROTOCOL_NOTIFICATION); @@ -120,7 +120,7 @@ BUrlProtocolDispatchingListener::RequestCompleted(BUrlProtocol* caller, void BUrlProtocolDispatchingListener::_SendMessage(BMessage* message, - int8 notification, BUrlProtocol* caller) + int8 notification, BUrlRequest* caller) { ASSERT(message != NULL); diff --git a/src/kits/network/libnetapi/UrlProtocolListener.cpp b/src/kits/network/libnetapi/UrlProtocolListener.cpp index b26d088..80ac7fc 100644 --- a/src/kits/network/libnetapi/UrlProtocolListener.cpp +++ b/src/kits/network/libnetapi/UrlProtocolListener.cpp @@ -9,62 +9,62 @@ #include <iostream> #include <cstdio> -#include <UrlProtocol.h> +#include <UrlRequest.h> #include <UrlProtocolListener.h> using namespace std; void -BUrlProtocolListener::ConnectionOpened(BUrlProtocol*) +BUrlProtocolListener::ConnectionOpened(BUrlRequest*) { } void -BUrlProtocolListener::HostnameResolved(BUrlProtocol*, const char*) +BUrlProtocolListener::HostnameResolved(BUrlRequest*, const char*) { } void -BUrlProtocolListener::ResponseStarted(BUrlProtocol*) +BUrlProtocolListener::ResponseStarted(BUrlRequest*) { } void -BUrlProtocolListener::HeadersReceived(BUrlProtocol*) +BUrlProtocolListener::HeadersReceived(BUrlRequest*) { } void -BUrlProtocolListener::DataReceived(BUrlProtocol*, const char*, ssize_t) +BUrlProtocolListener::DataReceived(BUrlRequest*, const char*, ssize_t) { } void -BUrlProtocolListener::DownloadProgress(BUrlProtocol*, ssize_t, ssize_t) +BUrlProtocolListener::DownloadProgress(BUrlRequest*, ssize_t, ssize_t) { } void -BUrlProtocolListener::UploadProgress(BUrlProtocol*, ssize_t, ssize_t) +BUrlProtocolListener::UploadProgress(BUrlRequest*, ssize_t, ssize_t) { } void -BUrlProtocolListener::RequestCompleted(BUrlProtocol*, bool) +BUrlProtocolListener::RequestCompleted(BUrlRequest*, bool) { } void -BUrlProtocolListener::DebugMessage(BUrlProtocol* caller, +BUrlProtocolListener::DebugMessage(BUrlRequest* caller, BUrlProtocolDebugMessage type, const char* text) { switch (type) { diff --git a/src/kits/network/libnetapi/UrlProtocolRoster.cpp b/src/kits/network/libnetapi/UrlProtocolRoster.cpp new file mode 100644 index 0000000..e9bc951 --- /dev/null +++ b/src/kits/network/libnetapi/UrlProtocolRoster.cpp @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2013 Haiku Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Christophe Huriaux, c.huriaux@xxxxxxxxx + * Adrien Destugues, pulkomandy@xxxxxxxxxxxxx + */ + +#include <UrlProtocolRoster.h> + +#include <new> + +#include <UrlRequest.h> +#include <HttpRequest.h> +#include <Debug.h> + + +/* static */ BUrlRequest* +BUrlProtocolRoster::MakeRequest(const BUrl& url, + BUrlProtocolListener* listener, BUrlContext* context) +{ + BUrlResult* result = new BUrlResult(url); + // FIXME this is leaked + // TODO: instanciate the correct BUrlProtocol using add-on interface + if (url.Protocol() == "http") { + return new(std::nothrow) BHttpRequest(url, *result, false, "HTTP", listener, + context); + } else if (url.Protocol() == "https") { + return new(std::nothrow) BHttpRequest(url, *result, true, "HTTPS", listener, + context); + } + + return NULL; +} diff --git a/src/kits/network/libnetapi/UrlRequest.cpp b/src/kits/network/libnetapi/UrlRequest.cpp index bf139ce..95721ad 100644 --- a/src/kits/network/libnetapi/UrlRequest.cpp +++ b/src/kits/network/libnetapi/UrlRequest.cpp @@ -6,240 +6,298 @@ * Christophe Huriaux, c.huriaux@xxxxxxxxx */ -#include <new> #include <UrlRequest.h> -#include <UrlProtocolHttp.h> #include <Debug.h> +#include <stdio.h> -BUrlRequest::BUrlRequest(const BUrl& url, BUrlProtocolListener* listener, - BUrlContext* context) - : - fListener(listener), - fUrlProtocol(NULL), - fResult(url), - fContext(context), - fUrl(), - fInitStatus(B_ERROR) -{ - SetUrl(url); -} +static const char* kProtocolThreadStrStatus[B_PROT_THREAD_STATUS__END+1] + = { + "Request successfully completed", + "Request running", + "Socket error", + "Connection failed", + "Hostname resolution failed", + "Network write failed", + "Network read failed", + "Out of memory", + "Protocol-specific error", + "Unknown error" + }; -BUrlRequest::BUrlRequest(const BUrlRequest& other) +BUrlRequest::BUrlRequest(const BUrl& url, BUrlProtocolListener* listener, + BUrlContext* context, BUrlResult& result, const char* threadName, + const char* protocolName) : - fListener(NULL), - fUrlProtocol(NULL), - fResult(other.fUrl), - fContext(), - fUrl(), - fInitStatus(B_ERROR) + fUrl(url), + fResult(result), + fContext(context), + fListener(listener), + fQuit(false), + fRunning(false), + fThreadId(0), + fThreadName(threadName), + fProtocol(protocolName) { - *this = other; } BUrlRequest::~BUrlRequest() { - if (fUrlProtocol != NULL) - delete fUrlProtocol; } -// #pragma mark Request parameters modification +// #pragma mark URL protocol thread management -status_t -BUrlRequest::SetUrl(const BUrl& url) -{ - fUrl = url; - fResult.SetUrl(url); - if (fUrlProtocol != NULL && url.Protocol() == fUrl.Protocol()) { - fUrlProtocol->SetUrl(url); - return B_OK; +thread_id +BUrlRequest::Run() +{ + // Thread already running + if (fRunning) { + PRINT(("BUrlRequest::Run() : Oops, already running ! " + "[urlProtocol=%p]!\n", this)); + return fThreadId; } - fInitStatus = _SetupProtocol(); - return fInitStatus; -} + fThreadId = spawn_thread(BUrlRequest::_ThreadEntry, fThreadName, + B_NORMAL_PRIORITY, this); + if (fThreadId < B_OK) + return fThreadId; -void -BUrlRequest::SetContext(BUrlContext* context) -{ - fContext = context; + status_t launchErr = resume_thread(fThreadId); + if (launchErr < B_OK) { + PRINT(("BUrlRequest::Run() : Failed to resume thread %ld\n", + fThreadId)); + return launchErr; + } - if (fUrlProtocol != NULL) - fUrlProtocol->SetContext(context); + fRunning = true; + return fThreadId; } -void -BUrlRequest::SetProtocolListener(BUrlProtocolListener* listener) +status_t +BUrlRequest::Pause() { - fListener = listener; - - if (fUrlProtocol != NULL) - fUrlProtocol->SetListener(listener); + // TODO + return B_ERROR; } -bool -BUrlRequest::SetProtocolOption(int32 option, void* value) +status_t +BUrlRequest::Resume() { - if (fUrlProtocol == NULL) - return false; - - fUrlProtocol->SetOption(option, value); - return true; + // TODO + return B_ERROR; } -// #pragma mark Request parameters access +status_t +BUrlRequest::Stop() +{ + if (!fRunning) + return B_ERROR; + status_t threadStatus = B_OK; + fQuit = true; -const BUrlProtocol* -BUrlRequest::Protocol() -{ - return fUrlProtocol; + wait_for_thread(fThreadId, &threadStatus); + return threadStatus; } -const BUrlResult& -BUrlRequest::Result() -{ - return fResult; -} +// #pragma mark URL protocol parameters modification -const BUrl& -BUrlRequest::Url() +status_t +BUrlRequest::SetUrl(const BUrl& url) { - return fUrl; -} - + // We should avoid to change URL while the thread is running ... + if (IsRunning()) + return B_ERROR; -// #pragma mark Request control + fUrl = url; + return B_OK; +} status_t -BUrlRequest::Start() +BUrlRequest::SetResult(BUrlResult& result) { - if (fUrlProtocol == NULL) { - PRINT(("BUrlRequest::Perform() : Oops, no BUrlProtocol defined!\n")); + if (IsRunning()) return B_ERROR; - } - - thread_id protocolThread = fUrlProtocol->Run(); - - if (protocolThread < B_OK) - return protocolThread; + fResult = result; return B_OK; } status_t -BUrlRequest::Pause() +BUrlRequest::SetContext(BUrlContext* context) { - if (fUrlProtocol == NULL) + if (IsRunning()) return B_ERROR; - return fUrlProtocol->Pause(); + fContext = context; + return B_OK; } status_t -BUrlRequest::Resume() +BUrlRequest::SetListener(BUrlProtocolListener* listener) { - if (fUrlProtocol == NULL) + if (IsRunning()) return B_ERROR; - return fUrlProtocol->Resume(); + fListener = listener; + return B_OK; } -status_t -BUrlRequest::Abort() +// #pragma mark URL protocol parameters access + + +const BUrl& +BUrlRequest::Url() const { - if (fUrlProtocol == NULL) - return B_ERROR; + return fUrl; +} - status_t returnCode = fUrlProtocol->Stop(); - delete fUrlProtocol; - fUrlProtocol = NULL; - return returnCode; +BUrlResult& +BUrlRequest::Result() const +{ + return fResult; } -// #pragma mark Request informations +BUrlContext* +BUrlRequest::Context() const +{ + return fContext; +} -status_t -BUrlRequest::InitCheck() const +BUrlProtocolListener* +BUrlRequest::Listener() const { - return fInitStatus; + return fListener; } +const BString& +BUrlRequest::Protocol() const +{ + return fProtocol; +} + + +// #pragma mark URL protocol informations + + bool BUrlRequest::IsRunning() const { - if (fUrlProtocol == NULL) - return false; - - return fUrlProtocol->IsRunning(); + return fRunning; } status_t BUrlRequest::Status() const { - if (fUrlProtocol == NULL) - return B_ERROR; + return fThreadStatus; +} + - return fUrlProtocol->Status(); +const char* +BUrlRequest::StatusString(status_t threadStatus) const +{ + if (threadStatus < B_PROT_THREAD_STATUS__BASE) + threadStatus = B_PROT_THREAD_STATUS__END; + else if (threadStatus >= B_PROT_PROTOCOL_ERROR) + threadStatus = B_PROT_PROTOCOL_ERROR; + + return kProtocolThreadStrStatus[threadStatus]; } -// #pragma mark Overloaded members +// #pragma mark Thread management -BUrlRequest& -BUrlRequest::operator=(const BUrlRequest& other) +/*static*/ int32 +BUrlRequest::_ThreadEntry(void* arg) { - delete fUrlProtocol; - fUrlProtocol = NULL; - fUrl = other.fUrl; - fListener = other.fListener; - fContext = other.fContext; - fResult = BUrlResult(other.fUrl); - SetUrl(other.fUrl); + BUrlRequest* urlProtocol = reinterpret_cast<BUrlRequest*>(arg); + urlProtocol->fThreadStatus = B_PROT_RUNNING; + + status_t protocolLoopExitStatus = urlProtocol->_ProtocolLoop(); - return *this; + urlProtocol->fRunning = false; + urlProtocol->fThreadStatus = protocolLoopExitStatus; + + if (urlProtocol->fListener != NULL) + urlProtocol->fListener->RequestCompleted(urlProtocol, + protocolLoopExitStatus == B_PROT_SUCCESS); + + return B_OK; } status_t -BUrlRequest::_SetupProtocol() +BUrlRequest::_ProtocolLoop() { - // TODO: instanciate the correct BUrlProtocol w/ the services roster - delete fUrlProtocol; - fUrlProtocol = NULL; + // Dummy _ProtocolLoop + while (!fQuit) + snooze(1000); - if (fUrl.Protocol() == "http") - fUrlProtocol = new(std::nothrow) BUrlProtocolHttp(fUrl, false, "HTTP", - fListener, fContext, &fResult); - else if (fUrl.Protocol() == "https") - fUrlProtocol = new(std::nothrow) BUrlProtocolHttp(fUrl, true, "HTTPS", - fListener, fContext, &fResult); - else - return B_NO_HANDLER_FOR_PROTOCOL; + return B_PROT_SUCCESS; +} - if (fUrlProtocol == NULL) - return B_NO_MEMORY; - return B_OK; +void +BUrlRequest::_EmitDebug(BUrlProtocolDebugMessage type, + const char* format, ...) +{ + if (fListener == NULL) + return; + + va_list arguments; + va_start(arguments, format); + + char debugMsg[256]; + vsnprintf(debugMsg, 256, format, arguments); + fListener->DebugMessage(this, type, debugMsg); + va_end(arguments); +} + + +BMallocIO& +BUrlRequest::_ResultRawData() +{ + return fResult.fRawData; +} + + +BHttpHeaders& +BUrlRequest::_ResultHeaders() +{ + return fResult.fHeaders; +} + + +void +BUrlRequest::_SetResultStatusCode(int32 statusCode) +{ + fResult.fStatusCode = statusCode; +} + + +BString& +BUrlRequest::_ResultStatusText() +{ + return fResult.fStatusString; } diff --git a/src/kits/network/libnetapi/UrlSynchronousRequest.cpp b/src/kits/network/libnetapi/UrlSynchronousRequest.cpp index 2e819f4..b23e092 100644 --- a/src/kits/network/libnetapi/UrlSynchronousRequest.cpp +++ b/src/kits/network/libnetapi/UrlSynchronousRequest.cpp @@ -13,10 +13,12 @@ #define PRINT(x) printf x; -BUrlSynchronousRequest::BUrlSynchronousRequest(BUrl& url) +BUrlSynchronousRequest::BUrlSynchronousRequest(BUrlRequest& request) : - BUrlRequest(url, this), - fRequestComplete(false) + BUrlRequest(request.Url(), this, request.Context(), request.Result(), + "BUrlSynchronousRequest", request.Protocol()), + fRequestComplete(false), + fWrappedRequest(request) { } @@ -24,10 +26,16 @@ BUrlSynchronousRequest::BUrlSynchronousRequest(BUrl& url) status_t BUrlSynchronousRequest::Perform() { - SetProtocolListener(this); + fWrappedRequest.SetListener(this); fRequestComplete = false; - return Start(); + thread_id worker = fWrappedRequest.Run(); + // TODO something to do with the thread_id maybe ? + + if (worker < B_OK) + return worker; + else + return B_OK; } @@ -42,35 +50,35 @@ BUrlSynchronousRequest::WaitUntilCompletion() void -BUrlSynchronousRequest::ConnectionOpened(BUrlProtocol*) +BUrlSynchronousRequest::ConnectionOpened(BUrlRequest*) { PRINT(("SynchronousRequest::ConnectionOpened()\n")); } void -BUrlSynchronousRequest::HostnameResolved(BUrlProtocol*, const char* ip) +BUrlSynchronousRequest::HostnameResolved(BUrlRequest*, const char* ip) { PRINT(("SynchronousRequest::HostnameResolved(%s)\n", ip)); } void -BUrlSynchronousRequest::ResponseStarted(BUrlProtocol*) +BUrlSynchronousRequest::ResponseStarted(BUrlRequest*) { PRINT(("SynchronousRequest::ResponseStarted()\n")); } void -BUrlSynchronousRequest::HeadersReceived(BUrlProtocol*) +BUrlSynchronousRequest::HeadersReceived(BUrlRequest*) { PRINT(("SynchronousRequest::HeadersReceived()\n")); } void -BUrlSynchronousRequest::DataReceived(BUrlProtocol*, const char*, +BUrlSynchronousRequest::DataReceived(BUrlRequest*, const char*, ssize_t size) { PRINT(("SynchronousRequest::DataReceived(%zd)\n", size)); @@ -78,7 +86,7 @@ BUrlSynchronousRequest::DataReceived(BUrlProtocol*, const char*, void -BUrlSynchronousRequest::DownloadProgress(BUrlProtocol*, +BUrlSynchronousRequest::DownloadProgress(BUrlRequest*, ssize_t bytesReceived, ssize_t bytesTotal) { PRINT(("SynchronousRequest::DownloadProgress(%zd, %zd)\n", bytesReceived, @@ -87,7 +95,7 @@ BUrlSynchronousRequest::DownloadProgress(BUrlProtocol*, void -BUrlSynchronousRequest::UploadProgress(BUrlProtocol*, ssize_t bytesSent, +BUrlSynchronousRequest::UploadProgress(BUrlRequest*, ssize_t bytesSent, ssize_t bytesTotal) { PRINT(("SynchronousRequest::UploadProgress(%zd, %zd)\n", bytesSent, @@ -96,7 +104,7 @@ BUrlSynchronousRequest::UploadProgress(BUrlProtocol*, ssize_t bytesSent, void -BUrlSynchronousRequest::RequestCompleted(BUrlProtocol* caller, bool success) +BUrlSynchronousRequest::RequestCompleted(BUrlRequest* caller, bool success) { PRINT(("SynchronousRequest::RequestCompleted(%s) : %s\n", (success?"true":"false"), caller->StatusString(caller->Status())));