Skip to content

Commit

Permalink
try to fix issue#14
Browse files Browse the repository at this point in the history
  • Loading branch information
azadkuh committed May 31, 2016
1 parent 9b18a8c commit c0e1aba
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 68 deletions.
12 changes: 7 additions & 5 deletions src/private/httpreader.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -30,20 +30,20 @@ public:

public:
void collectData(int atMost) {
icollectRequired = true;
icollectCapacity = atMost;
icollectedData.clear();
if ( atMost > 0 )
icollectedData.reserve(atMost);
}

bool shouldCollect() const {
return icollectCapacity > 0;
}

bool append(const char* data, size_t length) {
if ( !icollectRequired ) // not allowed to collect data
return false;

int newLength = icollectedData.length() + (int) length;

if ( shouldCollect() && newLength >= icollectCapacity )
if ( icollectCapacity > 0 && newLength > icollectCapacity )
return false; // the capacity is full

icollectedData.append(data, length);
Expand All @@ -65,6 +65,8 @@ public:
bool isuccessful = false;
TReadState ireadState = EEmpty;

/// shall I collect incoming body data by myself?
bool icollectRequired = false;
int icollectCapacity = 0;
QByteArray icollectedData;
};
Expand Down
14 changes: 6 additions & 8 deletions src/private/qhttpclient_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ class QHttpClientPrivate :

public:
explicit QHttpClientPrivate(QHttpClient* q) : q_ptr(q) {
QObject::connect(q_func(), &QHttpClient::disconnected, [this](){
release();
});
QObject::connect(
q_func(), &QHttpClient::disconnected,
[this](){ release(); }
);

QHTTP_LINE_DEEPLOG
}
Expand All @@ -41,10 +42,9 @@ class QHttpClientPrivate :
void release() {
// if socket drops and http_parser can not call messageComplete,
// dispatch the ilastResponse
onDispatchResponse();
finalizeConnection();

isocket.disconnectAllQtConnections();
isocket.close();
isocket.release();

if ( ilastRequest ) {
Expand Down Expand Up @@ -115,11 +115,9 @@ class QHttpClientPrivate :

parse(buffer, readLength);
}

onDispatchResponse();
}

void onDispatchResponse() {
void finalizeConnection() {
if ( ilastResponse == nullptr )
return;

Expand Down
66 changes: 37 additions & 29 deletions src/private/qhttpserverconnection_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,41 +27,15 @@ namespace server {
class QHttpConnectionPrivate :
public details::HttpRequestParser<QHttpConnectionPrivate>
{
protected:
Q_DECLARE_PUBLIC(QHttpConnection)
QHttpConnection* const q_ptr;

public:
QByteArray itempUrl;

// Since there can only be one request/response pair per connection at any
// time even with pipelining.
QHttpRequest* ilastRequest = nullptr;
QHttpResponse* ilastResponse = nullptr;

TServerHandler ihandler = nullptr;

public:
explicit QHttpConnectionPrivate(QHttpConnection* q) : q_ptr(q) {

QObject::connect(
q_func(), &QHttpConnection::disconnected,
[this](){
// if socket drops and http_parser can not call
// messageComplete, dispatch the ilastRequest
finalizeConnection();
isocket.release();

if ( ilastRequest )
ilastRequest->deleteLater();

if ( ilastResponse )
ilastResponse->deleteLater();

q_func()->deleteLater();
ilastRequest = nullptr;
ilastResponse = nullptr;
});
q_func(), &QHttpConnection::disconnected,
[this](){ release(); }
);

QHTTP_LINE_DEEPLOG
}
Expand All @@ -81,6 +55,27 @@ class QHttpConnectionPrivate :
}
}

void release() {
// if socket drops and http_parser can not call
// messageComplete, dispatch the ilastRequest
finalizeConnection();

isocket.disconnectAllQtConnections();
isocket.release();

if ( ilastRequest ) {
ilastRequest->deleteLater();
ilastRequest = nullptr;
}

if ( ilastResponse ) {
ilastResponse->deleteLater();
ilastResponse = nullptr;
}

q_func()->deleteLater();
}

public:
void onReadyRead() {
while ( isocket.bytesAvailable() > 0 ) {
Expand Down Expand Up @@ -158,6 +153,19 @@ class QHttpConnectionPrivate :
Qt::QueuedConnection
);
}

protected:
QHttpConnection* const q_ptr;

QByteArray itempUrl;

// Since there can only be one request/response pair per connection at any
// time even with pipelining.
QHttpRequest* ilastRequest = nullptr;
QHttpResponse* ilastResponse = nullptr;

TServerHandler ihandler = nullptr;

};

///////////////////////////////////////////////////////////////////////////////
Expand Down
16 changes: 7 additions & 9 deletions src/qhttpabstracts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,8 @@ class QHTTP_API QHttpAbstractInput : public QObject
* @note if you set this handler, the data() signal won't be emitted anymore.
*/
template<class Func>
void onData(Func&& f) {
QObject::connect(this, &QHttpAbstractInput::data,
std::forward<Func&&>(f)
);
void onData(Func f) {
QObject::connect(this, &QHttpAbstractInput::data, f);
}


Expand All @@ -87,10 +85,8 @@ class QHTTP_API QHttpAbstractInput : public QObject
* @note if you set this handler, the end() signal won't be emitted anymore.
*/
template<class Func>
void onEnd(Func&& f) {
QObject::connect(this, &QHttpAbstractInput::end,
std::forward<Func&&>(f)
);
void onEnd(Func f) {
QObject::connect(this, &QHttpAbstractInput::end, f);
}

public:
Expand All @@ -100,7 +96,9 @@ class QHTTP_API QHttpAbstractInput : public QObject
*
* @param atMost maximum acceptable incoming data. if the incoming data
* exceeds this value, the connection won't read any more data and
* end() signal will be emitted. -1 means unlimited.
* end() signal will be emitted.
* default value (-1) means read data as "content-length" or unlimited if
* the body size is unknown.
*/
virtual void collectData(int atMost = -1) =0;

Expand Down
13 changes: 7 additions & 6 deletions src/qhttpclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,9 +255,11 @@ QHttpClientPrivate::body(http_parser*, const char* at, size_t length) {

ilastResponse->d_func()->ireadState = QHttpResponsePrivate::EPartial;

if ( ilastResponse->d_func()->shouldCollect() ) {
if ( !ilastResponse->d_func()->append(at, length) )
onDispatchResponse(); // forcefully dispatch the ilastResponse
if ( ilastResponse->d_func()->icollectRequired ) {
if ( !ilastResponse->d_func()->append(at, length) ) {
// forcefully dispatch the ilastResponse
finalizeConnection();
}

return 0;
}
Expand All @@ -271,9 +273,8 @@ QHttpClientPrivate::messageComplete(http_parser*) {
if ( ilastResponse == nullptr )
return 0;

// response is ready to be dispatched
ilastResponse->d_func()->isuccessful = true;
ilastResponse->d_func()->ireadState = QHttpResponsePrivate::EComplete;
// response is done
finalizeConnection();
return 0;
}

Expand Down
23 changes: 12 additions & 11 deletions src/qhttpserverconnection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ QHttpConnectionPrivate::url(http_parser*, const char* at, size_t length) {

int
QHttpConnectionPrivate::headerField(http_parser*, const char* at, size_t length) {
if ( ilastResponse == nullptr )
if ( ilastRequest == nullptr )
return 0;

// insert the header we parsed previously
Expand All @@ -117,7 +117,7 @@ QHttpConnectionPrivate::headerField(http_parser*, const char* at, size_t length)

int
QHttpConnectionPrivate::headerValue(http_parser*, const char* at, size_t length) {
if ( ilastResponse == nullptr )
if ( ilastRequest == nullptr )
return 0;

itempHeaderValue.append(at, length);
Expand All @@ -126,7 +126,7 @@ QHttpConnectionPrivate::headerValue(http_parser*, const char* at, size_t length)

int
QHttpConnectionPrivate::headersComplete(http_parser* parser) {
if ( ilastResponse == nullptr )
if ( ilastRequest == nullptr )
return 0;

ilastRequest->d_func()->iurl = QUrl(itempUrl);
Expand Down Expand Up @@ -183,14 +183,16 @@ QHttpConnectionPrivate::headersComplete(http_parser* parser) {

int
QHttpConnectionPrivate::body(http_parser*, const char* at, size_t length) {
if ( ilastResponse == nullptr )
if ( ilastRequest == nullptr )
return 0;

ilastRequest->d_func()->ireadState = QHttpRequestPrivate::EPartial;

if ( ilastRequest->d_func()->shouldCollect() ) {
if ( !ilastRequest->d_func()->append(at, length) )
onDispatchRequest(); // forcefully dispatch the ilastRequest
if ( ilastRequest->d_func()->icollectRequired ) {
if ( !ilastRequest->d_func()->append(at, length) ) {
// forcefully dispatch the ilastRequest
finalizeConnection();
}

return 0;
}
Expand All @@ -201,12 +203,11 @@ QHttpConnectionPrivate::body(http_parser*, const char* at, size_t length) {

int
QHttpConnectionPrivate::messageComplete(http_parser*) {
if ( ilastResponse == nullptr )
if ( ilastRequest == nullptr )
return 0;

// request is ready to be dispatched
ilastRequest->d_func()->isuccessful = true;
ilastRequest->d_func()->ireadState = QHttpRequestPrivate::EComplete;
// request is done
finalizeConnection();
return 0;
}

Expand Down

0 comments on commit c0e1aba

Please sign in to comment.