diff options
-rw-r--r-- | client/netcom.cc | 122 | ||||
-rw-r--r-- | client/netcom.h | 21 | ||||
-rw-r--r-- | server/src/server.cc | 273 |
3 files changed, 93 insertions, 323 deletions
diff --git a/client/netcom.cc b/client/netcom.cc index 4126b02..3b3abb7 100644 --- a/client/netcom.cc +++ b/client/netcom.cc @@ -26,74 +26,31 @@ */ #include "netcom.h" -#include <QtNetwork> - #include <QApplication> #include <QByteArray> -#include <QHttp> - #include "widgets/widget.h" -#ifdef USE_SSL -#include <QMessageBox> -#include <QList> -#include <QSslError> -#include <QSslSocket> - -#ifdef QT_NO_OPENSSL -#error "QT not compiled with SSL support." -#endif -#endif - NetCom::NetCom(QString host, quint16 port, QString user, QString cpr) { this->user = user; this->cpr = cpr; - - connect(&http, SIGNAL(readyRead(const QHttpResponseHeader &)), - this, SLOT(readyRead(const QHttpResponseHeader &))); - connect(&http, SIGNAL(stateChanged(int)), this, SLOT(stateChanged(int))); - -#ifdef USE_SSL - connect(&http, SIGNAL(sslErrors(const QList<QSslError> &)), - this, SLOT(sslError(const QList<QSslError> &))); - http.setHost(host, QHttp::ConnectionModeHttps, port); -#else - http.setHost(host, QHttp::ConnectionModeHttp, port); -#endif - - transfering = false; - - QHttpRequestHeader h("HTTP 1.1", "/"); - http.request(h, ""); - - transfering = true; - buffer = ""; - do { - qApp->processEvents(QEventLoop::WaitForMoreEvents); - } while(transfering); - - sessionid = http.lastResponse().value("SessionID"); - printf("SESSION ID: %s\n", sessionid.toStdString().c_str()); + socket.connectToHost(host, port); + connect(&socket, SIGNAL(readyRead()), this, SLOT(readyRead())); + socket.waitForConnected(); + transmitting = false; } NetCom::~NetCom() { - QHttpRequestHeader h("HTTP 1.1", "/"); - h.setValue("SessionCommit", ""); - h.setValue("SessionID", sessionid); - http.request(h, ""); - - transfering = true; - buffer = ""; - do { - qApp->processEvents(QEventLoop::WaitForMoreEvents); - } while(transfering); + socket.disconnectFromHost(); } QDomDocument NetCom::send(QString templ, QString macro, bool lockgui) { + printf("Socket state: %d\n", socket.state()); + if(socket.state() != 3) printf("Socket state not connected: %s\n", socket.errorString().toStdString().c_str()); + if(lockgui && qApp->activeWindow()) qApp->activeWindow()->setEnabled(false); if(lockgui) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); @@ -115,17 +72,14 @@ QDomDocument NetCom::send(QString templ, QString macro, bool lockgui) printf("\nSending request:\n%s", doc.toString().toStdString().c_str()); - QHttpRequestHeader h("HTTP 1.1", "/"); - h.setValue("SessionID", sessionid); - http.request(h, doc.toByteArray()); + socket.write(doc.toByteArray()); + // socket.waitForReadyRead(); - QDomDocument res_doc; - transfering = true; - buffer = ""; do { qApp->processEvents(QEventLoop::WaitForMoreEvents); - } while(transfering); - res_doc.setContent(buffer); + } while(!res_doc.setContent(buffer)); + + buffer = ""; QDomElement elem = res_doc.documentElement(); @@ -137,8 +91,18 @@ QDomDocument NetCom::send(QString templ, QString macro, bool lockgui) return res_doc; } +void NetCom::readyRead() +{ + buffer.append(socket.readAll()); +} + void NetCom::send(QVector< Widget* > widgets, QString templ, QString macro, QString version) { + printf("Socket state: %d\n", socket.state()); + if(socket.state() != 3) printf("Socket state not connected: %s\n", socket.errorString().toStdString().c_str()); + + // if(qApp->activeWindow()) qApp->activeWindow()->setEnabled(false); // Moved down! + QDomDocument doc; QDomProcessingInstruction header = doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'"); @@ -175,40 +139,22 @@ void NetCom::send(QVector< Widget* > widgets, QString templ, QString macro, QStr printf("\nSending commit:\n%s", doc.toString().toStdString().c_str()); - QHttpRequestHeader h("HTTP 1.1", "/"); - h.setValue("SessionID", sessionid); - http.request(h, doc.toByteArray()); + socket.write(doc.toByteArray()); + // socket.waitForReadyRead(); - transfering = true; - buffer = ""; + // + // Wait for the (hopefully) empty answer. + // do { qApp->processEvents(QEventLoop::WaitForMoreEvents); - } while(transfering); + } while(!res_doc.setContent(buffer)); - QApplication::restoreOverrideCursor(); - if(qApp->activeWindow()) qApp->activeWindow()->setEnabled(true); -} + buffer = ""; -void NetCom::readyRead(const QHttpResponseHeader &) -{ - // printf("STATE: readyRead\n"); - buffer += http.readAll(); -} + //QDomElement elem = res_doc.documentElement(); -void NetCom::stateChanged(int state) -{ - // printf("STATE: %d\n", state); - if(transfering && state == QHttp::Connected) transfering = false; -} + printf("\nRecieved commit:\n%s", res_doc.toString().toStdString().c_str()); -#ifdef USE_SSL -void NetCom::sslError(const QList<QSslError> &errlst) -{ - QList<QSslError>::const_iterator i = errlst.begin(); - while(i != errlst.end()) { - QMessageBox::warning(qApp->activeWindow(), "SSL Error", i->errorString()); - i++; - } - http.ignoreSslErrors(); + QApplication::restoreOverrideCursor(); + if(qApp->activeWindow()) qApp->activeWindow()->setEnabled(true); } -#endif diff --git a/client/netcom.h b/client/netcom.h index 718d5a6..35db221 100644 --- a/client/netcom.h +++ b/client/netcom.h @@ -31,9 +31,6 @@ #include <QString> #include <QTcpSocket> #include <QDomDocument> -#include <QHttp> - -//#define USE_SSL //#include "widgets/widget.h" class Widget; @@ -48,23 +45,17 @@ public: void send(QVector< Widget* > widgets, QString templ, QString macro, QString version); public slots: - void stateChanged(int state); - void readyRead(const QHttpResponseHeader &resp); - -#ifdef USE_SSL - void sslError(const QList<QSslError> &errlst); -#endif + void readyRead(); private: - volatile bool transfering; + volatile bool transmitting; + QTcpSocket socket; + + QByteArray buffer; + QDomDocument res_doc; QString user; QString cpr; - - QHttp http; - - QByteArray buffer; - QString sessionid; }; #endif/*__PRACRO_NETCOM_H__*/ diff --git a/server/src/server.cc b/server/src/server.cc index 0b2f6d6..f2be8a4 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -36,8 +36,6 @@ #include <unistd.h> #include <string.h> -#include <microhttpd.h> - #include "configuration.h" #include "transaction.h" #include "transactionparser.h" @@ -59,29 +57,12 @@ #include "macrolist.h" #include "templatelist.h" #include "versionstr.h" -#include "mutex.h" -#include "log.h" - -typedef long long unsigned int sessionid_t; - -typedef struct { - JournalWriter *journalwriter; -} session_t; - -struct conn_t { - Database *db; - Mutex mutex; - std::map<sessionid_t, session_t> sessions; -}; static std::string error_box(std::string message) { std::string errorbox = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" "<pracro version=\"1.0\">\n" -#if 0 - " <error>" + message + "</error>\n" -#else " <template name=\"error\">\n" " <macro name=\"error\" static=\"true\">\n" " <widgets caption=\"ERROR!\" layout=\"vbox\" name=\"error\">\n" @@ -89,7 +70,6 @@ static std::string error_box(std::string message) " </widgets>\n" " </macro>\n" " </template>\n" -#endif "</pracro>\n"; return errorbox; } @@ -138,6 +118,7 @@ static std::string handleCommits(Transaction *transaction, Database &db, static std::string handleRequest(Transaction *transaction, TCPSocket &pentominos_socket, Database &db, + JournalWriter &journalwriter, MacroList ¯olist, TemplateList &templatelist) { @@ -179,7 +160,7 @@ static std::string handleRequest(Transaction *transaction, macro.attributes["name"], time(NULL)-Conf::db_max_ttl); - answer += " <macro uid=\"42\" completed="; + answer += " <macro completed="; if(completed) answer += "\"true\""; else answer += "\"false\""; @@ -291,15 +272,15 @@ static std::string handleTransaction(Transaction *transaction, answer += "<pracro version=\"1.0\">\n"; try { - answer += handleCommits(transaction, db, - journalwriter, macrolist, templatelist); + answer += handleCommits(transaction, db, journalwriter, macrolist, templatelist); } catch( std::exception &e ) { PRACRO_ERR(server, "Commit error: %s\n", e.what()); return error_box(xml_encode(e.what())); } try { - answer += handleRequest(transaction, pentominos_socket, db, macrolist, templatelist); + answer += handleRequest(transaction, pentominos_socket, db, journalwriter, + macrolist, templatelist); } catch( std::exception &e ) { PRACRO_ERR(server, "Request error: %s\n", e.what()); return error_box(xml_encode(e.what())); @@ -312,226 +293,78 @@ static std::string handleTransaction(Transaction *transaction, return answer; } -static std::string handleConnection(const char *buf, size_t size, struct conn_t *conn, - sessionid_t sid, bool commitsession) + +static void handleConnection(TCPSocket *socket) { - /* - if(size == 0) - return error_box(xml_encode("Empty document received.")); - */ TCPSocket pentominos_socket; #ifndef WITHOUT_PENTOMINOS pentominos_socket.connect(Conf::pentominos_addr, Conf::pentominos_port); #endif/*WITHOUT_PENTOMINOS*/ - JournalWriter *journalwriter = NULL; - conn->mutex.lock(); - if(conn->sessions.find(sid) == conn->sessions.end()) { - conn->sessions[sid].journalwriter = - new JournalWriter(Conf::journal_commit_addr.c_str(), Conf::journal_commit_port); - } - journalwriter = conn->sessions[sid].journalwriter; - conn->mutex.unlock(); + Database db(Conf::database_backend, Conf::database_addr, "", Conf::database_user, Conf::database_passwd, ""); + + JournalWriter journalwriter(Conf::journal_commit_addr.c_str(), Conf::journal_commit_port); MacroList macrolist(Conf::xml_basedir + "/macros"); TemplateList templatelist(Conf::xml_basedir + "/templates"); - Transaction transaction; - TransactionParser parser(&transaction); + ssize_t size; + char buf[4096]; - PRACRO_DEBUG(server, "Read %d bytes from network\n", size); - - std::string res; - if(size) { - if(parser.parse(buf, size)) { - PRACRO_DEBUG(server, "Got complete XML document, %d bytes in current buffer.\n", size); - - res = handleTransaction(&transaction, pentominos_socket, - *conn->db, *journalwriter, macrolist, templatelist); - } else { - PRACRO_ERR(server, "Failed to parse data!\n"); - res = error_box(xml_encode("XML Parse error.")); - } - } + Transaction *transaction = NULL; + TransactionParser *parser = NULL; + + // while( (size = socket->read(buf, sizeof(buf))) != -1) { + while( (size = socket->read(buf, sizeof(buf))) > 0) { - if(commitsession) { - journalwriter->commit(); - delete journalwriter; - conn->mutex.lock(); - conn->sessions.erase(sid); - conn->mutex.unlock(); - } + PRACRO_DEBUG(server, "Read %d bytes from network\n", size); + + while(size) { - return res; -} + if(transaction == NULL) { + transaction = new Transaction(); + } -static sessionid_t newSessionID(struct conn_t *conn) -{ - sessionid_t sid; - conn->mutex.lock(); - // Find a random session id that is not in use. - do { - sid = rand(); - } while(conn->sessions.find(sid) != conn->sessions.end()); - conn->mutex.unlock(); - return sid; -} + if(parser == NULL) { + parser = new TransactionParser(transaction); + } -static int handle_request(void *cls, - struct MHD_Connection *con, - const char *url, - const char *method, - const char *version, - const char *data, - unsigned int *data_size, - void **ptr) -{ - struct conn_t *conn = (struct conn_t*)cls; - - PRACRO_DEBUG(httpd, - "handle_request(url=\"%s\", method=\"%s\"," - " version=\"%s\", data_size=\"%d\")\n", - url, method, version, *data_size); - sessionid_t sessionid; - bool commitsession = false; - bool sid_ok = true; - - const char *sessionids = MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionID"); - if(sessionids == NULL) { - sessionid = newSessionID(conn); - } else { - sessionid = atoll(sessionids); - conn->mutex.lock(); - sid_ok = conn->sessions.find(sessionid) != conn->sessions.end(); - conn->mutex.unlock(); - } - PRACRO_DEBUG(httpd, "SessionID: %llu\n", sessionid); + PRACRO_DEBUG(server, "Got %d bytes in read loop\n", size); + if(parser->parse(buf, size)) { + PRACRO_DEBUG(server, "Got complete XML document %d bytes used, %d bytes in current buffer.\n", parser->usedBytes(), size); - const char *session_commit = MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionCommit"); - if(session_commit) { - PRACRO_DEBUG(httpd, "COMMIT: sessionid %llu\n", sessionid); - commitsession = true; + socket->write(handleTransaction(transaction, pentominos_socket, + db, journalwriter, macrolist, templatelist)); + size = size - parser->usedBytes(); + if(size) { + strcpy(buf, buf + parser->usedBytes()); + PRACRO_DEBUG(server, "Replaying %d bytes.\n", size); + } + + delete transaction; transaction = NULL; + delete parser; parser = NULL; + } else { + size = 0; + memset(buf, 0, sizeof(buf)); + } + } } - std::string reply; - if(sid_ok) { - reply = handleConnection(data, *data_size, conn, sessionid, commitsession); - } else { - PRACRO_ERR(httpd, "No such sessionid %llu\n", sessionid); - reply = error_box("No such session ID!"); + if(transaction) { + delete transaction; + transaction = NULL; } - - struct MHD_Response *rsp; - rsp = MHD_create_response_from_data(reply.length(), (char*)reply.c_str(), MHD_NO, MHD_YES); - MHD_add_response_header(rsp, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=UTF-8"); - - char idbuf[32]; - snprintf(idbuf, sizeof(idbuf), "%llu", sessionid); - MHD_add_response_header(rsp, "SessionID", idbuf); - - int ret = MHD_queue_response(con, MHD_HTTP_OK, rsp); - MHD_destroy_response(rsp); - - *data_size = 0; - - return ret; -} - -static void httpderr(void *arg, const char *fmt, va_list ap) -{ - PRACRO_ERR_VA(server, fmt, ap); -} -#define CERT "\ ------BEGIN CERTIFICATE-----\n\ -MIICFTCCAX6gAwIBAgIBAjANBgkqhkiG9w0BAQUFADBVMRswGQYDVQQKExJBcGFj\n\ -aGUgSFRUUCBTZXJ2ZXIxIjAgBgNVBAsTGUZvciB0ZXN0aW5nIHB1cnBvc2VzIG9u\n\ -bHkxEjAQBgNVBAMTCWxvY2FsaG9zdDAeFw0wNzA2MjEwODE4MzZaFw0wODA2MjAw\n\ -ODE4MzZaMEwxGzAZBgNVBAoTEkFwYWNoZSBIVFRQIFNlcnZlcjEZMBcGA1UECxMQ\n\ -VGVzdCBDZXJ0aWZpY2F0ZTESMBAGA1UEAxMJbG9jYWxob3N0MIGfMA0GCSqGSIb3\n\ -DQEBAQUAA4GNADCBiQKBgQDWTACKSoxd5cL06w7RtPIhFqY1l3UE/aRGmPmh8gEo\n\ -w3zNf+gWxco2yjQgBTQhGww1ybOsAUtXPIsUOSFAGvPUKJZf8ibZMiJEzl2919uz\n\ -IcV9+cUm7k3jFPQx4ALQEalbV++o/lfT5lhgsSiH1t1eln2omVrGCjI/1HeYrw7X\n\ -owIDAQABMA0GCSqGSIb3DQEBBQUAA4GBALVFzprK6rYkWVZZZwq85w2lCYJpEl9a\n\ -66IMzIwNNRfyZMoc9D9PSwsXKYfYOg1RpMt7RhWT/bpggGlsFqctsAgJSv8Ol5Cz\n\ -DqTXhpV+8WOG6l4xDYZz3U3ajiu2jth2+aaMuWKy9Wkr8bzHGDufltToLalucne2\n\ -npM7yCJ83Ana\n\ ------END CERTIFICATE-----" - -#define KEY "\ ------BEGIN RSA PRIVATE KEY-----\n\ -MIICXAIBAAKBgQDWTACKSoxd5cL06w7RtPIhFqY1l3UE/aRGmPmh8gEow3zNf+gW\n\ -xco2yjQgBTQhGww1ybOsAUtXPIsUOSFAGvPUKJZf8ibZMiJEzl2919uzIcV9+cUm\n\ -7k3jFPQx4ALQEalbV++o/lfT5lhgsSiH1t1eln2omVrGCjI/1HeYrw7XowIDAQAB\n\ -AoGANUXHjJljs6P+hyw4DuHQn3El+ISiTo9PW02EIUIsD5opWFzHsYGR93Tk6GDi\n\ -yKgUrPprdAMOW61tVaWuImWQ32R2xyrJogjGYo9XE2xAej9N37jM0AGBtn/vd4Dr\n\ -LsYfpjNaM3gqIChD73iYfO+CrNbdLqTxIdG53g/u05GJ4cECQQD0vMm5+a8N82Jb\n\ -oHJgE2jb83WqaYBHe0O03ujtiq3+hPZHoVV3iJWmA/aMlgdtunkJT3PdEsVfQNkH\n\ -fvzR9JhbAkEA4CiZRk5Gcz7cEqyogDTMQYtmrE8hbgofISLuz1rpTEzd8hFAcerU\n\ -nuwFIT3go3hO7oIHMlKU1H5iT1BsFvegWQJBAOSa6A+5A+STIKAX+l52Iu+5tYKN\n\ -885RfMgZpBgm/yoMxwPX1r7GLYsajpV5mszLbz3cIo0xeH3mVBOlccEoqZsCQECP\n\ -8PWq/eebp09Jo46pplsKh5wBfqNvDuBAa4AVszRiv1pFVcZ52JudZyzX4aezsyhH\n\ -E0OPPYamkDI/+6Hx2KECQHF9xV1XatyXuFmfRAInK2BtfGY5UIvJaLxVD3Z1+i6q\n\ -/enz7/wUwvC6G4FSWNMYgAYJOfwZ3BerdkqcRNxyR/Q=\n\ ------END RSA PRIVATE KEY-----" - -extern bool pracro_is_running; -void server() -{ - srand(time(NULL)); - - bool forceshutdown = false; - port_t port = Conf::server_port; - - PRACRO_DEBUG(server, "Server running on port %d.\n", port); - - struct conn_t conn; - conn.db = new Database(Conf::database_backend, Conf::database_addr, - "", Conf::database_user, Conf::database_passwd, ""); - - struct MHD_Daemon *d; - d = MHD_start_daemon(MHD_USE_DEBUG - | MHD_USE_SELECT_INTERNALLY - // | MHD_USE_PEDANTIC_CHECKS - // | MHD_USE_SSL - , - port, - NULL, NULL, - handle_request, &conn, - MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL, - // MHD_OPTION_CONNECTION_LIMIT, 42, - MHD_OPTION_HTTPS_MEM_KEY, KEY, - MHD_OPTION_HTTPS_MEM_CERT, CERT, - //MHD_OPTION_CONNECTION_TIMEOUT, 0, - MHD_OPTION_EXTERNAL_LOGGER, httpderr, NULL, - MHD_OPTION_END); - - if(!d) { - PRACRO_ERR(server, "Failed to initialise MHD_start_daemon!\n"); - return; - } - again: - while(pracro_is_running) sleep(1); - - if(!forceshutdown && conn.sessions.size() != 0) { - char errbuf[128]; - snprintf(errbuf, sizeof(errbuf), "There are %d live sessions." - " Kill again to force shutdown.\n", conn.sessions.size()); - PRACRO_ERR_LOG(server, errbuf); - log(errbuf); - pracro_is_running = true; - forceshutdown = true; - goto again; + if(parser) { + delete parser; + parser = NULL; } - delete conn.db; - MHD_stop_daemon(d); + journalwriter.commit(); - PRACRO_DEBUG(server, "Server gracefully shut down.\n"); + PRACRO_DEBUG(server, "Out of read loop!\n"); } - -#if 0 //#define NON_FORKING #include <sys/socket.h> extern bool pracro_is_running; @@ -595,7 +428,7 @@ void server() PRACRO_DEBUG(server, "Server gracefully shut down.\n"); } -#endif//0 + #ifdef TEST_SERVER |