Starts the server; make slight changes in server code
so that it understands qt's resource system (qrc)
we can use that to manage the html related files
(would be stored in app bundle for mac osx, and in
perhaps /usr/local/share for Linux by qt)
Change-Id: I8cc9e7bd99000d287bac5e6c8bd86008924351c6
diff --git a/gui/chronosharegui.cpp b/gui/chronosharegui.cpp
index 04bff02..038f05a 100644
--- a/gui/chronosharegui.cpp
+++ b/gui/chronosharegui.cpp
@@ -34,12 +34,18 @@
using namespace boost;
using namespace Ccnx;
+static const string HTTP_SERVER_ADDRESS = "localhost";
+static const string HTTP_SERVER_PORT = "9001";
+static const string DOC_ROOT = ":/html";
+static const QString ICON_PICTURE_QSTRING(":/images/friends-group-icon.png");
+
INIT_LOGGER ("Gui");
ChronoShareGui::ChronoShareGui(QWidget *parent)
: QDialog(parent)
, m_watcher(0)
, m_dispatcher(0)
+ , m_httpServer(0)
#ifdef ADHOC_SUPPORTED
, m_executor (1)
#endif
@@ -132,6 +138,17 @@
m_watcher = new FsWatcher (m_dirPath,
bind (&Dispatcher::Did_LocalFile_AddOrModify, m_dispatcher, _1),
bind (&Dispatcher::Did_LocalFile_Delete, m_dispatcher, _1));
+ QFileInfo indexHtmlInfo(":/html/index.html");
+ if (indexHtmlInfo.exists())
+ {
+ m_httpServer = new http::server::server(HTTP_SERVER_ADDRESS, HTTP_SERVER_PORT, DOC_ROOT);
+ m_httpServerThread = boost::thread(&http::server::server::run, m_httpServer);
+ }
+ else
+ {
+ _LOG_ERROR ("Http server doc root dir does not exist!");
+ // shall we bail here?
+ }
}
ChronoShareGui::~ChronoShareGui()
@@ -142,6 +159,7 @@
delete m_watcher; // stop filewatching ASAP
delete m_dispatcher; // stop dispatcher ASAP, but after watcher (to prevent triggering callbacks on deleted object)
+ delete m_httpServer;
// cleanup
delete m_trayIcon;
@@ -169,7 +187,7 @@
messageBox.setWindowTitle(title);
messageBox.setText(text);
- messageBox.setIconPixmap(QPixmap(":/images/friends-group-icon.png"));
+ messageBox.setIconPixmap(QPixmap(ICON_PICTURE_QSTRING));
messageBox.exec();
}
@@ -181,7 +199,7 @@
messageBox.setText(text);
messageBox.setInformativeText(infotext);
- messageBox.setIconPixmap(QPixmap(":/images/friends-group-icon.png"));
+ messageBox.setIconPixmap(QPixmap(ICON_PICTURE_QSTRING));
messageBox.exec();
}
@@ -284,7 +302,7 @@
void ChronoShareGui::setIcon()
{
// set the icon image
- m_trayIcon->setIcon(QIcon(":/images/friends-group-icon.png"));
+ m_trayIcon->setIcon(QIcon(ICON_PICTURE_QSTRING));
}
void ChronoShareGui::openSharedFolder()
diff --git a/gui/chronosharegui.h b/gui/chronosharegui.h
index eba4c12..3e9e0c3 100644
--- a/gui/chronosharegui.h
+++ b/gui/chronosharegui.h
@@ -40,6 +40,8 @@
#include "fs-watcher.h"
#include "dispatcher.h"
+#include "server.hpp"
+#include <boost/thread/thread.hpp>
class ChronoShareGui : public QDialog
{
@@ -118,6 +120,8 @@
FsWatcher *m_watcher;
Dispatcher *m_dispatcher;
+ http::server::server *m_httpServer;
+ boost::thread m_httpServerThread;
QLabel* labelUsername;
QPushButton* button;
diff --git a/gui/html.qrc b/gui/html.qrc
new file mode 100644
index 0000000..29a8104
--- /dev/null
+++ b/gui/html.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>images/friends-group-icon.png</file>
+ </qresource>
+</RCC>
diff --git a/gui/html/index.html b/gui/html/index.html
new file mode 100644
index 0000000..f372d2e
--- /dev/null
+++ b/gui/html/index.html
@@ -0,0 +1,3 @@
+<html>
+<h1>It works!</h1>
+</html>
diff --git a/gui/images.qrc b/gui/images.qrc
index 15d4acf..630a137 100644
--- a/gui/images.qrc
+++ b/gui/images.qrc
@@ -1,5 +1,5 @@
<RCC>
- <qresource prefix="/images">
- <file>friends-group-icon.png</file>
+ <qresource prefix="/">
+ <file>html/index.html</file>
</qresource>
</RCC>
diff --git a/gui/friends-group-icon.png b/gui/images/friends-group-icon.png
similarity index 100%
rename from gui/friends-group-icon.png
rename to gui/images/friends-group-icon.png
Binary files differ
diff --git a/server/request_handler.cpp b/server/request_handler.cpp
index bd1f5d2..d1d5061 100644
--- a/server/request_handler.cpp
+++ b/server/request_handler.cpp
@@ -16,12 +16,19 @@
#include "mime_types.hpp"
#include "reply.hpp"
#include "request.hpp"
+#include <QIODevice>
+#include <QFile>
+#include <QDataStream>
+#include <QString>
+#include "logging.h"
+
+INIT_LOGGER("HttpServer")
namespace http {
namespace server {
request_handler::request_handler(const std::string& doc_root)
- : doc_root_(doc_root)
+ : doc_root_(doc_root.c_str())
{
}
@@ -59,19 +66,36 @@
}
// Open the file to send back.
- std::string full_path = doc_root_ + request_path;
- std::ifstream is(full_path.c_str(), std::ios::in | std::ios::binary);
- if (!is)
+ // The following is a hack to make the server understands Qt's
+ // resource system, so that the html resources can be managed using Qt's
+ // resource system (e.g. no need to worry about the location of html)
+ // in Mac OS, it will be inside the bundle, in Linux, perhaps somewhere
+ // in /usr/local/share
+ QString full_path = doc_root_.absolutePath() + QString(request_path.c_str());
+ QFile file(full_path);
+ if (!file.exists() || !file.open(QIODevice::ReadOnly))
{
rep = reply::stock_reply(reply::not_found);
return;
}
+ _LOG_DEBUG("Serving file: " << request_path);
// Fill out the reply to be sent to the client.
rep.status = reply::ok;
char buf[512];
- while (is.read(buf, sizeof(buf)).gcount() > 0)
- rep.content.append(buf, is.gcount());
+ QDataStream in(&file);
+ while (true)
+ {
+ int bytes = in.readRawData(buf, sizeof(buf));
+ if (bytes > 0)
+ {
+ rep.content.append(buf, bytes);
+ }
+ else
+ {
+ break;
+ }
+ }
rep.headers.resize(2);
rep.headers[0].name = "Content-Length";
rep.headers[0].value = boost::lexical_cast<std::string>(rep.content.size());
diff --git a/server/request_handler.hpp b/server/request_handler.hpp
index 661bad7..384907c 100644
--- a/server/request_handler.hpp
+++ b/server/request_handler.hpp
@@ -13,6 +13,7 @@
#include <string>
#include <boost/noncopyable.hpp>
+#include <QDir>
namespace http {
namespace server {
@@ -33,7 +34,7 @@
private:
/// The directory containing the files to be served.
- std::string doc_root_;
+ QDir doc_root_;
/// Perform URL-decoding on a string. Returns false if the encoding was
/// invalid.
diff --git a/server/server.cpp b/server/server.cpp
index 5fcc5d9..fa20be7 100644
--- a/server/server.cpp
+++ b/server/server.cpp
@@ -11,7 +11,9 @@
#include "server.hpp"
#include <boost/bind.hpp>
#include <signal.h>
+#include "logging.h"
+INIT_LOGGER ("HttpServer");
namespace http {
namespace server {
@@ -44,6 +46,8 @@
acceptor_.listen();
start_accept();
+
+ _LOG_DEBUG("Listen on [" << address << ": " << port << "] with doc_root = " << doc_root);
}
void server::run()
diff --git a/wscript b/wscript
index 7fb7500..fd62ae7 100644
--- a/wscript
+++ b/wscript
@@ -139,18 +139,21 @@
http_server = bld (
target = "http_server",
- features = "cxx",
+ features = "qt4 cxx",
source = bld.path.ant_glob(['server/*.cpp']),
- includes = "server .",
- use = "BOOST"
+ includes = "server src .",
+ use = "BOOST QTCORE"
)
qt = bld (
target = "ChronoShare",
features = "qt4 cxx cxxprogram",
defines = "WAF",
- source = bld.path.ant_glob(['gui/*.cpp', 'gui/*.cc', 'gui/*.qrc']),
- includes = "ccnx scheduler executor fs-watcher gui src adhoc . ",
+ # do not include html.qrc as we don't want it to be compiled into binary
+ # qt seems to adopt a pattern of compiling every resource file into the
+ # executable; if things don't work, we can use that as last resort
+ source = bld.path.ant_glob(['gui/*.cpp', 'gui/*.cc', 'gui/images.qrc']),
+ includes = "ccnx scheduler executor fs-watcher gui src adhoc server . ",
use = "BOOST BOOST_FILESYSTEM SQLITE3 QTCORE QTGUI LOG4CXX fs_watcher ccnx database chronoshare http_server"
)