Refactor Connection

This commit is contained in:
Joe Ferris 2011-10-14 11:22:24 -04:00
parent 25ff48a08a
commit b4708b2b88
8 changed files with 166 additions and 93 deletions

View File

@ -2,7 +2,7 @@ PATH
remote: . remote: .
specs: specs:
capybara-webkit (0.7.2) capybara-webkit (0.7.2)
capybara (>= 1.0.0, < 1.2) capybara (< 1.2, >= 1.0.0)
GEM GEM
remote: http://rubygems.org/ remote: http://rubygems.org/
@ -39,7 +39,7 @@ GEM
diff-lcs (~> 1.1.2) diff-lcs (~> 1.1.2)
rspec-mocks (2.6.0) rspec-mocks (2.6.0)
rubyzip (0.9.4) rubyzip (0.9.4)
selenium-webdriver (2.8.0) selenium-webdriver (2.7.0)
childprocess (>= 0.2.1) childprocess (>= 0.2.1)
ffi (>= 1.0.7) ffi (>= 1.0.7)
json_pure json_pure

28
src/CommandFactory.cpp Normal file
View File

@ -0,0 +1,28 @@
#include "CommandFactory.h"
#include "Visit.h"
#include "Find.h"
#include "Command.h"
#include "Reset.h"
#include "Node.h"
#include "Url.h"
#include "Source.h"
#include "Evaluate.h"
#include "Execute.h"
#include "FrameFocus.h"
#include "Header.h"
#include "Render.h"
#include "Body.h"
#include "Status.h"
#include "Headers.h"
#include "SetCookie.h"
#include "ClearCookies.h"
#include "GetCookies.h"
CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
m_page = page;
}
Command *CommandFactory::createCommand(const char *name) {
#include "find_command.h"
return NULL;
}

16
src/CommandFactory.h Normal file
View File

@ -0,0 +1,16 @@
#include <QObject>
class Command;
class WebPage;
class CommandFactory : public QObject {
Q_OBJECT
public:
CommandFactory(WebPage *page, QObject *parent = 0);
Command *createCommand(const char *name);
private:
WebPage *m_page;
};

68
src/CommandParser.cpp Normal file
View File

@ -0,0 +1,68 @@
#include "CommandParser.h"
#include <QIODevice>
CommandParser::CommandParser(QIODevice *device, QObject *parent) :
QObject(parent) {
m_device = device;
m_expectingDataSize = -1;
connect(m_device, SIGNAL(readyRead()), this, SLOT(checkNext()));
}
void CommandParser::checkNext() {
if (m_expectingDataSize == -1) {
if (m_device->canReadLine()) {
readLine();
checkNext();
}
} else {
if (m_device->bytesAvailable() >= m_expectingDataSize) {
readDataBlock();
checkNext();
}
}
}
void CommandParser::readLine() {
char buffer[128];
qint64 lineLength = m_device->readLine(buffer, 128);
if (lineLength != -1) {
buffer[lineLength - 1] = 0;
processNext(buffer);
}
}
void CommandParser::readDataBlock() {
char *buffer = new char[m_expectingDataSize + 1];
m_device->read(buffer, m_expectingDataSize);
buffer[m_expectingDataSize] = 0;
processNext(buffer);
m_expectingDataSize = -1;
delete[] buffer;
}
void CommandParser::processNext(const char *data) {
if (m_commandName.isNull()) {
m_commandName = data;
m_argumentsExpected = -1;
} else {
processArgument(data);
}
}
void CommandParser::processArgument(const char *data) {
if (m_argumentsExpected == -1) {
m_argumentsExpected = QString(data).toInt();
} else if (m_expectingDataSize == -1) {
m_expectingDataSize = QString(data).toInt();
} else {
m_arguments.append(QString::fromUtf8(data));
}
if (m_arguments.length() == m_argumentsExpected) {
emit commandReady(m_commandName, m_arguments);
m_commandName = QString();
m_arguments.clear();
m_argumentsExpected = -1;
}
}

29
src/CommandParser.h Normal file
View File

@ -0,0 +1,29 @@
#include <QObject>
#include <QStringList>
class QIODevice;
class CommandParser : public QObject {
Q_OBJECT
public:
CommandParser(QIODevice *device, QObject *parent = 0);
public slots:
void checkNext();
signals:
void commandReady(QString commandName, QStringList arguments);
private:
void readLine();
void readDataBlock();
void processNext(const char *line);
void processArgument(const char *data);
QIODevice *m_device;
QString m_commandName;
QStringList m_arguments;
int m_argumentsExpected;
int m_expectingDataSize;
};

View File

@ -1,24 +1,9 @@
#include "Connection.h" #include "Connection.h"
#include "WebPage.h" #include "WebPage.h"
#include "UnsupportedContentHandler.h" #include "UnsupportedContentHandler.h"
#include "Visit.h" #include "CommandParser.h"
#include "Find.h" #include "CommandFactory.h"
#include "Command.h" #include "Command.h"
#include "Reset.h"
#include "Node.h"
#include "Url.h"
#include "Source.h"
#include "Evaluate.h"
#include "Execute.h"
#include "FrameFocus.h"
#include "Header.h"
#include "Render.h"
#include "Body.h"
#include "Status.h"
#include "Headers.h"
#include "SetCookie.h"
#include "ClearCookies.h"
#include "GetCookies.h"
#include <QTcpSocket> #include <QTcpSocket>
#include <iostream> #include <iostream>
@ -27,76 +12,31 @@ Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
QObject(parent) { QObject(parent) {
m_socket = socket; m_socket = socket;
m_page = page; m_page = page;
m_commandParser = new CommandParser(socket, this);
m_commandFactory = new CommandFactory(page, this);
m_command = NULL; m_command = NULL;
m_expectingDataSize = -1;
m_pageSuccess = true; m_pageSuccess = true;
m_commandWaiting = false; m_commandWaiting = false;
connect(m_socket, SIGNAL(readyRead()), this, SLOT(checkNext())); connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
connect(m_commandParser, SIGNAL(commandReady(QString, QStringList)), this, SLOT(commandReady(QString, QStringList)));
connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool))); connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
} }
void Connection::checkNext() {
if (m_expectingDataSize == -1) {
if (m_socket->canReadLine()) {
readLine();
checkNext();
}
} else {
if (m_socket->bytesAvailable() >= m_expectingDataSize) {
readDataBlock();
checkNext();
}
}
}
void Connection::readLine() { void Connection::commandReady(QString commandName, QStringList arguments) {
char buffer[128]; m_commandName = commandName;
qint64 lineLength = m_socket->readLine(buffer, 128); m_arguments = arguments;
if (lineLength != -1) {
buffer[lineLength - 1] = 0;
processNext(buffer);
}
}
void Connection::readDataBlock() { if (m_page->isLoading())
char *buffer = new char[m_expectingDataSize + 1]; m_commandWaiting = true;
m_socket->read(buffer, m_expectingDataSize); else
buffer[m_expectingDataSize] = 0; startCommand();
processNext(buffer);
m_expectingDataSize = -1;
delete[] buffer;
}
void Connection::processNext(const char *data) {
if (m_commandName.isNull()) {
m_commandName = data;
m_argumentsExpected = -1;
} else {
processArgument(data);
}
}
void Connection::processArgument(const char *data) {
if (m_argumentsExpected == -1) {
m_argumentsExpected = QString(data).toInt();
} else if (m_expectingDataSize == -1) {
m_expectingDataSize = QString(data).toInt();
} else {
m_arguments.append(QString::fromUtf8(data));
}
if (m_arguments.length() == m_argumentsExpected) {
if (m_page->isLoading())
m_commandWaiting = true;
else
startCommand();
}
} }
void Connection::startCommand() { void Connection::startCommand() {
m_commandWaiting = false; m_commandWaiting = false;
if (m_pageSuccess) { if (m_pageSuccess) {
m_command = createCommand(m_commandName.toAscii().constData()); m_command = m_commandFactory->createCommand(m_commandName.toAscii().constData());
if (m_command) { if (m_command) {
connect(m_command, connect(m_command,
SIGNAL(finished(Response *)), SIGNAL(finished(Response *)),
@ -115,11 +55,6 @@ void Connection::startCommand() {
} }
} }
Command *Connection::createCommand(const char *name) {
#include "find_command.h"
return NULL;
}
void Connection::pendingLoadFinished(bool success) { void Connection::pendingLoadFinished(bool success) {
m_pageSuccess = success; m_pageSuccess = success;
if (m_commandWaiting) if (m_commandWaiting)
@ -143,9 +78,5 @@ void Connection::writeResponse(Response *response) {
m_socket->write(messageLength.toAscii()); m_socket->write(messageLength.toAscii());
m_socket->write(messageUtf8); m_socket->write(messageUtf8);
delete response; delete response;
m_arguments.clear();
m_commandName = QString();
m_argumentsExpected = -1;
} }

View File

@ -5,6 +5,8 @@ class QTcpSocket;
class WebPage; class WebPage;
class Command; class Command;
class Response; class Response;
class CommandParser;
class CommandFactory;
class Connection : public QObject { class Connection : public QObject {
Q_OBJECT Q_OBJECT
@ -13,16 +15,11 @@ class Connection : public QObject {
Connection(QTcpSocket *socket, WebPage *page, QObject *parent = 0); Connection(QTcpSocket *socket, WebPage *page, QObject *parent = 0);
public slots: public slots:
void checkNext(); void commandReady(QString commandName, QStringList arguments);
void finishCommand(Response *response); void finishCommand(Response *response);
void pendingLoadFinished(bool success); void pendingLoadFinished(bool success);
private: private:
void readLine();
void readDataBlock();
void processNext(const char *line);
Command *createCommand(const char *name);
void processArgument(const char *line);
void startCommand(); void startCommand();
void writeResponse(Response *response); void writeResponse(Response *response);
@ -30,9 +27,9 @@ class Connection : public QObject {
QString m_commandName; QString m_commandName;
Command *m_command; Command *m_command;
QStringList m_arguments; QStringList m_arguments;
int m_argumentsExpected;
WebPage *m_page; WebPage *m_page;
int m_expectingDataSize; CommandParser *m_commandParser;
CommandFactory *m_commandFactory;
bool m_pageSuccess; bool m_pageSuccess;
bool m_commandWaiting; bool m_commandWaiting;
}; };

View File

@ -28,6 +28,8 @@ HEADERS = \
SetCookie.h \ SetCookie.h \
ClearCookies.h \ ClearCookies.h \
GetCookies.h \ GetCookies.h \
CommandParser.h \
CommandFactory.h \
SOURCES = \ SOURCES = \
main.cpp \ main.cpp \
@ -57,6 +59,8 @@ SOURCES = \
SetCookie.cpp \ SetCookie.cpp \
ClearCookies.cpp \ ClearCookies.cpp \
GetCookies.cpp \ GetCookies.cpp \
CommandParser.cpp \
CommandFactory.cpp \
RESOURCES = webkit_server.qrc RESOURCES = webkit_server.qrc
QT += network webkit QT += network webkit