Factor out a BNetworkRequest

* Shares common behavior between the Gopher and HTTP request handlers.
* Most of this can be used when implemeting other protocols.
This commit is contained in:
Adrien Destugues 2014-08-04 15:59:53 +02:00
parent fedec7b31f
commit 2f9b187497
7 changed files with 129 additions and 151 deletions

View File

@ -8,15 +8,10 @@
#include <deque>
#include <NetBuffer.h>
#include <NetworkAddress.h>
#include <UrlRequest.h>
#include <NetworkRequest.h>
class BAbstractSocket;
class BGopherRequest : public BUrlRequest {
class BGopherRequest : public BNetworkRequest {
public:
BGopherRequest(const BUrl& url,
BUrlProtocolListener* listener = NULL,
@ -29,21 +24,17 @@ public:
private:
status_t _ProtocolLoop();
bool _ResolveHostName();
void _SendRequest();
bool _NeedsParsing();
bool _NeedsLastDotStrip();
void _ParseInput(bool last);
status_t _GetLine(BString& destString);
BString& _HTMLEscapeString(BString &str);
private:
char fItemType;
BString fPath;
BAbstractSocket* fSocket;
BNetworkAddress fRemoteAddr;
BNetBuffer fInputBuffer;
ssize_t fPosition;

View File

@ -11,15 +11,11 @@
#include <HttpForm.h>
#include <HttpHeaders.h>
#include <HttpResult.h>
#include <NetBuffer.h>
#include <NetworkAddress.h>
#include <UrlRequest.h>
#include <NetworkRequest.h>
class BAbstractSocket;
class BHttpRequest : public BUrlRequest {
class BHttpRequest : public BNetworkRequest {
public:
BHttpRequest(const BUrl& url,
bool ssl = false,
@ -63,15 +59,12 @@ public:
private:
void _ResetOptions();
status_t _ProtocolLoop();
bool _ResolveHostName();
status_t _MakeRequest();
void _SendRequest();
void _SendHeaders();
void _SendPostData();
status_t _GetLine(BString& destString);
void _ParseStatus();
void _ParseHeaders();
@ -85,15 +78,11 @@ private:
bool _IsDefaultPort();
private:
BAbstractSocket* fSocket;
BNetworkAddress fRemoteAddr;
bool fSSL;
BString fRequestMethod;
int8 fHttpVersion;
BNetBuffer fInputBuffer;
BHttpHeaders fHeaders;
// Request status

View File

@ -0,0 +1,38 @@
/*
* Copyright 2014 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _B_NET_REQUEST_H_
#define _B_NET_REQUEST_H_
#include <NetBuffer.h>
#include <NetworkAddress.h>
#include <UrlRequest.h>
class BAbstractSocket;
class BNetworkRequest: public BUrlRequest
{
public:
BNetworkRequest(const BUrl& url,
BUrlProtocolListener* listener,
BUrlContext* context,
const char* threadName,
const char* protocolName);
protected:
bool _ResolveHostName(uint16_t port);
status_t _GetLine(BString& destString);
protected:
BAbstractSocket* fSocket;
BNetworkAddress fRemoteAddr;
BNetBuffer fInputBuffer;
};
#endif

View File

@ -182,7 +182,7 @@ static const bool kInlineImages = true;
BGopherRequest::BGopherRequest(const BUrl& url, BUrlProtocolListener* listener,
BUrlContext* context)
:
BUrlRequest(url, listener, context, "BUrlProtocol.Gopher", "gopher"),
BNetworkRequest(url, listener, context, "BUrlProtocol.Gopher", "gopher"),
fItemType(GOPHER_TYPE_NONE),
fPosition(0),
fResult()
@ -236,7 +236,7 @@ BGopherRequest::_ProtocolLoop()
if (fSocket == NULL)
return B_NO_MEMORY;
if (!_ResolveHostName()) {
if (!_ResolveHostName(70)) {
_EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR,
"Unable to resolve hostname (%s), aborting.",
fUrl.Host().String());
@ -386,36 +386,6 @@ BGopherRequest::_ProtocolLoop()
}
bool
BGopherRequest::_ResolveHostName()
{
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Resolving %s",
fUrl.UrlString().String());
uint16_t port;
if (fUrl.HasPort())
port = fUrl.Port();
else
port = 70;
// FIXME stop forcing AF_INET, when BNetworkAddress stops giving IPv6
// addresses when there isn't an IPv6 link available.
fRemoteAddr = BNetworkAddress(AF_INET, fUrl.Host(), port);
if (fRemoteAddr.InitCheck() != B_OK)
return false;
//! ProtocolHook:HostnameResolved
if (fListener != NULL)
fListener->HostnameResolved(this, fRemoteAddr.ToString().String());
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Hostname resolved to: %s",
fRemoteAddr.ToString().String());
return true;
}
void
BGopherRequest::_SendRequest()
{
@ -726,36 +696,6 @@ BGopherRequest::_ParseInput(bool last)
}
status_t
BGopherRequest::_GetLine(BString& destString)
{
// Find a complete line in inputBuffer
uint32 characterIndex = 0;
while ((characterIndex < fInputBuffer.Size())
&& ((fInputBuffer.Data())[characterIndex] != '\n'))
characterIndex++;
if (characterIndex == fInputBuffer.Size())
return B_ERROR;
char* temporaryBuffer = new(std::nothrow) char[characterIndex + 1];
if (temporaryBuffer == NULL)
return B_NO_MEMORY;
fInputBuffer.RemoveData(temporaryBuffer, characterIndex + 1);
// Strip end-of-line character(s)
if (temporaryBuffer[characterIndex - 1] == '\r')
destString.SetTo(temporaryBuffer, characterIndex - 1);
else
destString.SetTo(temporaryBuffer, characterIndex);
delete[] temporaryBuffer;
return B_OK;
}
BString&
BGopherRequest::_HTMLEscapeString(BString &str)
{

View File

@ -30,11 +30,11 @@
static const int32 kHttpBufferSize = 4096;
BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
BUrlProtocolListener* listener, BUrlContext* context)
:
BUrlRequest(url, listener, context, "BUrlProtocol.HTTP", protocolName),
fSocket(NULL),
BNetworkRequest(url, listener, context, "BUrlProtocol.HTTP", protocolName),
fSSL(ssl),
fRequestMethod(B_HTTP_GET),
fHttpVersion(B_HTTP_11),
@ -58,9 +58,8 @@ BHttpRequest::BHttpRequest(const BUrl& url, bool ssl, const char* protocolName,
BHttpRequest::BHttpRequest(const BHttpRequest& other)
:
BUrlRequest(other.Url(), other.fListener, other.fContext,
BNetworkRequest(other.Url(), other.fListener, other.fContext,
"BUrlProtocol.HTTP", other.fSSL ? "HTTPS" : "HTTP"),
fSocket(NULL),
fSSL(other.fSSL),
fRequestMethod(other.fRequestMethod),
fHttpVersion(other.fHttpVersion),
@ -320,7 +319,7 @@ BHttpRequest::_ProtocolLoop()
fHeaders.Clear();
_ResultHeaders().Clear();
if (!_ResolveHostName()) {
if (!_ResolveHostName(fSSL ? 443 : 80)) {
_EmitDebug(B_URL_PROTOCOL_DEBUG_ERROR,
"Unable to resolve hostname (%s), aborting.",
fUrl.Host().String());
@ -425,36 +424,6 @@ BHttpRequest::_ProtocolLoop()
}
bool
BHttpRequest::_ResolveHostName()
{
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Resolving %s",
fUrl.UrlString().String());
uint16_t port;
if (fUrl.HasPort())
port = fUrl.Port();
else
port = fSSL ? 443 : 80;
// FIXME stop forcing AF_INET, when BNetworkAddress stops giving IPv6
// addresses when there isn't an IPv6 link available.
fRemoteAddr = BNetworkAddress(AF_INET, fUrl.Host(), port);
if (fRemoteAddr.InitCheck() != B_OK)
return false;
//! ProtocolHook:HostnameResolved
if (fListener != NULL)
fListener->HostnameResolved(this, fRemoteAddr.ToString().String());
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Hostname resolved to: %s",
fRemoteAddr.ToString().String());
return true;
}
status_t
BHttpRequest::_MakeRequest()
{
@ -713,36 +682,6 @@ BHttpRequest::_MakeRequest()
}
status_t
BHttpRequest::_GetLine(BString& destString)
{
// Find a complete line in inputBuffer
uint32 characterIndex = 0;
while ((characterIndex < fInputBuffer.Size())
&& ((fInputBuffer.Data())[characterIndex] != '\n'))
characterIndex++;
if (characterIndex == fInputBuffer.Size())
return B_ERROR;
char* temporaryBuffer = new(std::nothrow) char[characterIndex + 1];
if (temporaryBuffer == NULL)
return B_NO_MEMORY;
fInputBuffer.RemoveData(temporaryBuffer, characterIndex + 1);
// Strip end-of-line character(s)
if (temporaryBuffer[characterIndex - 1] == '\r')
destString.SetTo(temporaryBuffer, characterIndex - 1);
else
destString.SetTo(temporaryBuffer, characterIndex);
delete[] temporaryBuffer;
return B_OK;
}
void
BHttpRequest::_ParseStatus()
{

View File

@ -77,6 +77,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
$(md5Sources)
NetworkRequest.cpp
Url.cpp
UrlContext.cpp
UrlProtocolAsynchronousListener.cpp

View File

@ -0,0 +1,80 @@
/*
* Copyright 2010-2014 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Christophe Huriaux, c.huriaux@gmail.com
* Niels Sascha Reedijk, niels.reedijk@gmail.com
* Adrien Destugues, pulkomandy@pulkomandy.tk
*/
#include <NetworkRequest.h>
BNetworkRequest::BNetworkRequest(const BUrl& url, BUrlProtocolListener* listener,
BUrlContext* context, const char* threadName, const char* protocolName)
:
BUrlRequest(url, listener, context, threadName, protocolName),
fSocket(NULL)
{
}
bool
BNetworkRequest::_ResolveHostName(uint16_t port)
{
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Resolving %s",
fUrl.UrlString().String());
if (fUrl.HasPort())
port = fUrl.Port();
// FIXME stop forcing AF_INET, when BNetworkAddress stops giving IPv6
// addresses when there isn't an IPv6 link available.
fRemoteAddr = BNetworkAddress(AF_INET, fUrl.Host(), port);
if (fRemoteAddr.InitCheck() != B_OK)
return false;
//! ProtocolHook:HostnameResolved
if (fListener != NULL)
fListener->HostnameResolved(this, fRemoteAddr.ToString().String());
_EmitDebug(B_URL_PROTOCOL_DEBUG_TEXT, "Hostname resolved to: %s",
fRemoteAddr.ToString().String());
return true;
}
status_t
BNetworkRequest::_GetLine(BString& destString)
{
// Find a complete line in inputBuffer
uint32 characterIndex = 0;
while ((characterIndex < fInputBuffer.Size())
&& ((fInputBuffer.Data())[characterIndex] != '\n'))
characterIndex++;
if (characterIndex == fInputBuffer.Size())
return B_ERROR;
char* temporaryBuffer = new(std::nothrow) char[characterIndex + 1];
if (temporaryBuffer == NULL)
return B_NO_MEMORY;
fInputBuffer.RemoveData(temporaryBuffer, characterIndex + 1);
// Strip end-of-line character(s)
if (temporaryBuffer[characterIndex - 1] == '\r')
destString.SetTo(temporaryBuffer, characterIndex - 1);
else
destString.SetTo(temporaryBuffer, characterIndex);
delete[] temporaryBuffer;
return B_OK;
}