diff options
Diffstat (limited to 'server')
-rw-r--r-- | server/src/server.cc | 273 |
1 files changed, 53 insertions, 220 deletions
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 |