Skip to content

Commit

Permalink
Try to fix azadkuh#14
Browse files Browse the repository at this point in the history
  • Loading branch information
oliviermaridat committed Aug 5, 2016
1 parent 0d01b0e commit 3bcadbf
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 101 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
build-ant
# 3rdparty, tmp and build direcotry
build.properties
3rdparty
Expand Down
16 changes: 11 additions & 5 deletions src/private/qhttpbase.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,20 +156,24 @@ class HttpReader : public TBase

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

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

bool append(const char* data, size_t length) {
int currentLength = icollectedData.length();

if ( (currentLength + (int)length) >= icollectCapacity )
return false; // capacity if full
if ( !icollectRequired ) // not allowed to collect data
return false;
int newLength = icollectedData.length() + (int) length;

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

icollectedData.append(data, length);
return true;
Expand All @@ -179,6 +183,8 @@ class HttpReader : public TBase
TReadState ireadState = EEmpty;
bool isuccessful = false;

/// shall I collect incoming body data by myself?
bool icollectRequired = false;
int icollectCapacity = 0;
QByteArray icollectedData;
};
Expand Down
7 changes: 3 additions & 4 deletions src/private/qhttpclient_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,9 @@ class QHttpClientPrivate : public HttpParser<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 @@ -138,10 +137,10 @@ class QHttpClientPrivate : public HttpParser<QHttpClientPrivate>
parse(buffer, readLength);
}

onDispatchResponse();
finalizeConnection();
}

void onDispatchResponse() {
void finalizeConnection() {
// if ilastResponse has been sent previously, just return
if ( ilastResponse->d_func()->ireadState == QHttpResponsePrivate::ESent )
return;
Expand Down
97 changes: 55 additions & 42 deletions src/private/qhttpserverconnection_private.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,51 +26,31 @@ namespace server {
///////////////////////////////////////////////////////////////////////////////
class QHttpConnectionPrivate : public HttpParser<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) : HttpParser(HTTP_REQUEST), q_ptr(q) {

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

if ( ilastRequest )
ilastRequest->deleteLater();
if ( ilastResponse )
ilastResponse->deleteLater();

q_func()->deleteLater();
});


QObject::connect(
q_func(), &QHttpConnection::disconnected,
[this](){ release(); }
);

QHTTP_LINE_DEEPLOG
}

virtual ~QHttpConnectionPrivate() {
QHTTP_LINE_DEEPLOG
}

void createSocket(qintptr sokDesc, TBackend bend) {
isocket.ibackendType = bend;

if ( bend == ETcpSocket ) {
QTcpSocket* sok = new QTcpSocket( q_func() );
isocket.itcpSocket = sok;
sok->setSocketDescriptor(sokDesc);

QObject::connect(sok, &QTcpSocket::readyRead, [this](){
onReadyRead();
});
Expand All @@ -81,12 +61,12 @@ class QHttpConnectionPrivate : public HttpParser<QHttpConnectionPrivate>
QObject::connect(sok, &QTcpSocket::disconnected,
q_func(), &QHttpConnection::disconnected,
Qt::QueuedConnection);

} else if ( bend == ELocalSocket ) {
QLocalSocket* sok = new QLocalSocket( q_func() );
isocket.ilocalSocket = sok;
sok->setSocketDescriptor(sokDesc);

QObject::connect(sok, &QLocalSocket::readyRead, [this](){
onReadyRead();
});
Expand All @@ -98,30 +78,63 @@ class QHttpConnectionPrivate : public HttpParser<QHttpConnectionPrivate>
q_func(), &QHttpConnection::disconnected,
Qt::QueuedConnection);
}

}


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

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

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

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

q_func()->deleteLater();
}

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;

public:
void onReadyRead() {
while ( isocket.bytesAvailable() > 0 ) {
char buffer[4097] = {0};
size_t readLength = (size_t) isocket.readRaw(buffer, 4096);

parse(buffer, readLength);
}

onDispatchRequest();
}

void onDispatchRequest() {
// if ilastRequest has been sent previously, just return
if ( ilastRequest->d_func()->ireadState == QHttpRequestPrivate::ESent )
return;

ilastRequest->d_func()->ireadState = QHttpRequestPrivate::ESent;
emit ilastRequest->end();
}

public:
int messageBegin(http_parser* parser);
int url(http_parser* parser, const char* at, size_t length);
Expand All @@ -133,12 +146,12 @@ class QHttpConnectionPrivate : public HttpParser<QHttpConnectionPrivate>
int headersComplete(http_parser* parser);
int body(http_parser* parser, const char* at, size_t length);
int messageComplete(http_parser* parser);

#ifdef USE_CUSTOM_URL_CREATOR
public:
static QUrl createUrl(const char *urlData, const http_parser_url &urlInfo);
#endif // USE_CUSTOM_URL_CREATOR

};

///////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 1 addition & 1 deletion src/qhttpclient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ QHttpClientPrivate::body(http_parser*, const char* at, size_t length) {

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

return 0;
}
Expand Down
Loading

0 comments on commit 3bcadbf

Please sign in to comment.