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).
This commit is contained in:
@@ -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();
|
||||
|
||||
|
||||
@@ -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();
|
||||
BUrlContext* context = NULL);
|
||||
virtual ~BHttpRequest();
|
||||
|
||||
virtual status_t SetOption(uint32 option, void* value);
|
||||
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;
|
||||
@@ -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_
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
@@ -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
|
||||
+67
-38
@@ -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;
|
||||
|
||||
// Overloaded members
|
||||
BUrlRequest& operator=(const BUrlRequest& other);
|
||||
virtual const char* StatusString(status_t threadStatus)
|
||||
const;
|
||||
|
||||
|
||||
protected:
|
||||
BUrlProtocolListener* fListener;
|
||||
BUrlProtocol* fUrlProtocol;
|
||||
BUrlResult fResult;
|
||||
BUrlContext* fContext;
|
||||
BUrl fUrl;
|
||||
status_t fInitStatus;
|
||||
static int32 _ThreadEntry(void* arg);
|
||||
virtual status_t _ProtocolLoop();
|
||||
virtual void _EmitDebug(BUrlProtocolDebugMessage type,
|
||||
const char* format, ...);
|
||||
|
||||
private:
|
||||
status_t _SetupProtocol();
|
||||
// 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
|
||||
};
|
||||
|
||||
#endif // _B_URL_REQUEST_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);
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
+128
-93
@@ -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);
|
||||
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);
|
||||
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";
|
||||
@@ -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
|
||||
|
||||
@@ -1,303 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010 Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*
|
||||
* Authors:
|
||||
* Christophe Huriaux, [email protected]
|
||||
*/
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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@gmail.com
|
||||
* Adrien Destugues, pulkomandy@pulkomandy.tk
|
||||
*/
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -6,240 +6,298 @@
|
||||
* Christophe Huriaux, c.huriaux@gmail.com
|
||||
*/
|
||||
|
||||
#include <new>
|
||||
|
||||
#include <UrlRequest.h>
|
||||
#include <UrlProtocolHttp.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"
|
||||
};
|
||||
|
||||
|
||||
BUrlRequest::BUrlRequest(const BUrl& url, BUrlProtocolListener* listener,
|
||||
BUrlContext* context)
|
||||
BUrlContext* context, BUrlResult& result, const char* threadName,
|
||||
const char* protocolName)
|
||||
:
|
||||
fListener(listener),
|
||||
fUrlProtocol(NULL),
|
||||
fResult(url),
|
||||
fUrl(url),
|
||||
fResult(result),
|
||||
fContext(context),
|
||||
fUrl(),
|
||||
fInitStatus(B_ERROR)
|
||||
fListener(listener),
|
||||
fQuit(false),
|
||||
fRunning(false),
|
||||
fThreadId(0),
|
||||
fThreadName(threadName),
|
||||
fProtocol(protocolName)
|
||||
{
|
||||
SetUrl(url);
|
||||
}
|
||||
|
||||
|
||||
BUrlRequest::BUrlRequest(const BUrlRequest& other)
|
||||
:
|
||||
fListener(NULL),
|
||||
fUrlProtocol(NULL),
|
||||
fResult(other.fUrl),
|
||||
fContext(),
|
||||
fUrl(),
|
||||
fInitStatus(B_ERROR)
|
||||
{
|
||||
*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)
|
||||
thread_id
|
||||
BUrlRequest::Run()
|
||||
{
|
||||
fUrl = url;
|
||||
fResult.SetUrl(url);
|
||||
|
||||
if (fUrlProtocol != NULL && url.Protocol() == fUrl.Protocol()) {
|
||||
fUrlProtocol->SetUrl(url);
|
||||
return B_OK;
|
||||
// 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;
|
||||
|
||||
if (fUrlProtocol != NULL)
|
||||
fUrlProtocol->SetContext(context);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BUrlRequest::SetProtocolListener(BUrlProtocolListener* listener)
|
||||
{
|
||||
fListener = listener;
|
||||
|
||||
if (fUrlProtocol != NULL)
|
||||
fUrlProtocol->SetListener(listener);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
BUrlRequest::SetProtocolOption(int32 option, void* value)
|
||||
{
|
||||
if (fUrlProtocol == NULL)
|
||||
return false;
|
||||
|
||||
fUrlProtocol->SetOption(option, value);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Request parameters access
|
||||
|
||||
|
||||
const BUrlProtocol*
|
||||
BUrlRequest::Protocol()
|
||||
{
|
||||
return fUrlProtocol;
|
||||
}
|
||||
|
||||
|
||||
const BUrlResult&
|
||||
BUrlRequest::Result()
|
||||
{
|
||||
return fResult;
|
||||
}
|
||||
|
||||
|
||||
const BUrl&
|
||||
BUrlRequest::Url()
|
||||
{
|
||||
return fUrl;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Request control
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::Start()
|
||||
{
|
||||
if (fUrlProtocol == NULL) {
|
||||
PRINT(("BUrlRequest::Perform() : Oops, no BUrlProtocol defined!\n"));
|
||||
return B_ERROR;
|
||||
status_t launchErr = resume_thread(fThreadId);
|
||||
if (launchErr < B_OK) {
|
||||
PRINT(("BUrlRequest::Run() : Failed to resume thread %ld\n",
|
||||
fThreadId));
|
||||
return launchErr;
|
||||
}
|
||||
|
||||
thread_id protocolThread = fUrlProtocol->Run();
|
||||
|
||||
if (protocolThread < B_OK)
|
||||
return protocolThread;
|
||||
|
||||
return B_OK;
|
||||
fRunning = true;
|
||||
return fThreadId;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::Pause()
|
||||
{
|
||||
if (fUrlProtocol == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return fUrlProtocol->Pause();
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::Resume()
|
||||
{
|
||||
if (fUrlProtocol == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
return fUrlProtocol->Resume();
|
||||
// TODO
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::Abort()
|
||||
BUrlRequest::Stop()
|
||||
{
|
||||
if (fUrlProtocol == NULL)
|
||||
if (!fRunning)
|
||||
return B_ERROR;
|
||||
|
||||
status_t returnCode = fUrlProtocol->Stop();
|
||||
delete fUrlProtocol;
|
||||
fUrlProtocol = NULL;
|
||||
status_t threadStatus = B_OK;
|
||||
fQuit = true;
|
||||
|
||||
return returnCode;
|
||||
wait_for_thread(fThreadId, &threadStatus);
|
||||
return threadStatus;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Request informations
|
||||
// #pragma mark URL protocol parameters modification
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::InitCheck() const
|
||||
BUrlRequest::SetUrl(const BUrl& url)
|
||||
{
|
||||
return fInitStatus;
|
||||
// We should avoid to change URL while the thread is running ...
|
||||
if (IsRunning())
|
||||
return B_ERROR;
|
||||
|
||||
fUrl = url;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::SetResult(BUrlResult& result)
|
||||
{
|
||||
if (IsRunning())
|
||||
return B_ERROR;
|
||||
|
||||
fResult = result;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::SetContext(BUrlContext* context)
|
||||
{
|
||||
if (IsRunning())
|
||||
return B_ERROR;
|
||||
|
||||
fContext = context;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BUrlRequest::SetListener(BUrlProtocolListener* listener)
|
||||
{
|
||||
if (IsRunning())
|
||||
return B_ERROR;
|
||||
|
||||
fListener = listener;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark URL protocol parameters access
|
||||
|
||||
|
||||
const BUrl&
|
||||
BUrlRequest::Url() const
|
||||
{
|
||||
return fUrl;
|
||||
}
|
||||
|
||||
|
||||
BUrlResult&
|
||||
BUrlRequest::Result() const
|
||||
{
|
||||
return fResult;
|
||||
}
|
||||
|
||||
|
||||
BUrlContext*
|
||||
BUrlRequest::Context() const
|
||||
{
|
||||
return fContext;
|
||||
}
|
||||
|
||||
|
||||
BUrlProtocolListener*
|
||||
BUrlRequest::Listener() const
|
||||
{
|
||||
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 fUrlProtocol->Status();
|
||||
return fThreadStatus;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Overloaded members
|
||||
|
||||
|
||||
BUrlRequest&
|
||||
BUrlRequest::operator=(const BUrlRequest& other)
|
||||
const char*
|
||||
BUrlRequest::StatusString(status_t threadStatus) const
|
||||
{
|
||||
delete fUrlProtocol;
|
||||
fUrlProtocol = NULL;
|
||||
fUrl = other.fUrl;
|
||||
fListener = other.fListener;
|
||||
fContext = other.fContext;
|
||||
fResult = BUrlResult(other.fUrl);
|
||||
SetUrl(other.fUrl);
|
||||
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 *this;
|
||||
return kProtocolThreadStrStatus[threadStatus];
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark Thread management
|
||||
|
||||
|
||||
/*static*/ int32
|
||||
BUrlRequest::_ThreadEntry(void* arg)
|
||||
{
|
||||
BUrlRequest* urlProtocol = reinterpret_cast<BUrlRequest*>(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
|
||||
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;
|
||||
|
||||
if (fUrlProtocol == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
return B_OK;
|
||||
return B_PROT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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())));
|
||||
|
||||
Reference in New Issue
Block a user