From 016e4ba553044edee32c2a20ee34463ad82106e8 Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 7 May 2010 12:36:13 +0000 Subject: Use connection object instead of struct and make xml parsing on-the-fly instead of collecting all data first. --- server/src/Makefile.am | 2 + server/src/connection.cc | 129 ++++++++++++++++++++++++++++++ server/src/connection.h | 57 +++++++++++++ server/src/resumeparser.cc | 3 +- server/src/server.cc | 169 ++++++--------------------------------- server/src/transactionhandler.cc | 5 +- server/src/transactionparser.cc | 8 +- server/src/widgetgenerator.cc | 8 +- 8 files changed, 228 insertions(+), 153 deletions(-) create mode 100644 server/src/connection.cc create mode 100644 server/src/connection.h diff --git a/server/src/Makefile.am b/server/src/Makefile.am index afc72f9..0a3569f 100644 --- a/server/src/Makefile.am +++ b/server/src/Makefile.am @@ -16,6 +16,7 @@ pracrod_SOURCES = \ database.cc \ configuration.cc \ configurationparser.cc \ + connection.cc \ connectionpool.cc \ debug.cc \ entitylist.cc \ @@ -89,6 +90,7 @@ EXTRA_DIST = \ artefact.h \ configuration.h \ configurationparser.h \ + connection.h \ connectionpool.h \ daemon.h \ database.h \ diff --git a/server/src/connection.cc b/server/src/connection.cc new file mode 100644 index 0000000..36c030e --- /dev/null +++ b/server/src/connection.cc @@ -0,0 +1,129 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * connection.cc + * + * Fri May 7 11:35:44 CEST 2010 + * Copyright 2010 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "connection.h" + +#include "transactionhandler.h" +#include "xml_encode_decode.h" + +static std::string error_box(std::string message) +{ + std::string errorbox = + "\n" + "\n" + " " + message + "\n" + "\n"; + return errorbox; +} + +Connection::Connection(Environment &e, std::string sid, bool c) + : env(e), parser(&transaction) +{ + PRACRO_DEBUG(connection, "[%p] CREATE\n", this); + + sessionid = sid; + commit = c; +} + +Connection::~Connection() +{ + PRACRO_DEBUG(connection, "[%p] DESTROY\n", this); +} + +bool Connection::handle(const char *data, size_t size) +{ + Session *session = NULL; + if(sessionid == "") { + // Create new session + session = env.sessions.newSession(); + } else { + // Attach to old session + session = env.sessions.session(sessionid); + + // Session didn't exist - create a new one anyway. + if(session == NULL) session = env.sessions.newSession(); + } + + if(session == NULL) { + PRACRO_ERR(connection, "New session could not be created."); + response = error_box(xml_encode("New session could not be created.")); + return true; + } + + sessionid = session->id(); + + if(!data || !size) return true; + + try { + if(parser.parse(data, size)) { + { + SessionAutolock lock(*session); + response = handleTransaction(transaction, env, *session); + } + + if(commit) { + session->commit(); + env.sessions.deleteSession(session->id()); + } + + return true; + } + } catch(...) { + PRACRO_ERR(server, "Failed to parse data!\n"); + response = error_box(xml_encode("XML Parse error.")); + return true; + } + + return false; +} + +std::string Connection::getResponse() +{ + return response; +} + +std::string Connection::getSessionID() +{ + return sessionid; +} + +#ifdef TEST_CONNECTION +//Additional dependency files +//deps: +//Required cflags (autoconf vars may be used) +//cflags: +//Required link options (autoconf vars may be used) +//libs: +#include "test.h" + +TEST_BEGIN; + +// TODO: Put some testcode here (see test.h for usable macros). + +TEST_END; + +#endif/*TEST_CONNECTION*/ diff --git a/server/src/connection.h b/server/src/connection.h new file mode 100644 index 0000000..f91ddc1 --- /dev/null +++ b/server/src/connection.h @@ -0,0 +1,57 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * connection.h + * + * Fri May 7 11:35:43 CEST 2010 + * Copyright 2010 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#ifndef __PRACRO_CONNECTION_H__ +#define __PRACRO_CONNECTION_H__ + +#include +#include "environment.h" +#include "transaction.h" +#include "transactionparser.h" + +class Connection { +public: + Connection(Environment &e, std::string sessionid, bool commit); + ~Connection(); + + bool handle(const char *data, size_t size); + + std::string getResponse(); + std::string getSessionID(); + +private: + std::string sessionid; + bool commit; + Environment &env; + + Transaction transaction; + TransactionParser parser; + + std::string response; +}; + +#endif/*__PRACRO_CONNECTION_H__*/ diff --git a/server/src/resumeparser.cc b/server/src/resumeparser.cc index bf3483e..4d514ac 100644 --- a/server/src/resumeparser.cc +++ b/server/src/resumeparser.cc @@ -26,9 +26,10 @@ */ #include "resumeparser.h" -#include "luaresume.h" #include +#include "luaresume.h" + static std::string resume_parser_format(Resume &r, Commit &commit) { const char* format = r.attributes["format"].c_str(); diff --git a/server/src/server.cc b/server/src/server.cc index 4283a11..118db85 100644 --- a/server/src/server.cc +++ b/server/src/server.cc @@ -41,84 +41,8 @@ #include #include "configuration.h" -#include "transaction.h" -#include "transactionparser.h" -#include "database.h" +#include "connection.h" #include "log.h" -#include "environment.h" -#include "transactionhandler.h" -#include "connectionpool.h" -#include "session.h" -#include "xml_encode_decode.h" - -static std::string error_box(std::string message) -{ - std::string errorbox = - "\n" - "\n" - " " + message + "\n" - "\n"; - return errorbox; -} - -static std::string handleConnection(const std::string &data, - Environment &env, - std::string &sessionid, - bool sessioncommit) -{ - std::string res; - - Session *session = NULL; - if(sessionid == "") { - session = env.sessions.newSession(); - } else { - session = env.sessions.session(sessionid); - if(session == NULL) session = env.sessions.newSession(); - } - - if(session == NULL) { - PRACRO_ERR(server, "New session could not be created."); - return error_box(xml_encode("New session could not be created.")); - } - - sessionid = session->id(); - - { - SessionAutolock lock(*session); - - if(data.length()) { - Transaction transaction; - TransactionParser parser(&transaction); - - if(!parser.parse(data.c_str(), data.length())) { - PRACRO_ERR(server, "Failed to parse data!\n"); - PRACRO_ERR(server, "DATA:[[%s]]\n", data.c_str()); - res = error_box(xml_encode("XML Parse error.")); - } else { - res = handleTransaction(transaction, env, *session); - } - } - - } - - if(sessioncommit) { - session->commit(); - env.sessions.deleteSession(session->id()); - } - - return res; -} - -struct condata { - std::map headers; - std::string data; - size_t data_size; - std::string url; - std::string method; - std::string version; -}; - -//static std::map condata; static int handle_request_callback(void *cls, struct MHD_Connection *con, @@ -129,92 +53,51 @@ static int handle_request_callback(void *cls, unsigned int *data_size, void **con_cls) { + int ret = MHD_YES; + + Connection *connection = (Connection*)*con_cls; + PRACRO_DEBUG(httpd, "handle_request_callback con:%p condata:%p\n", con, *con_cls); // Test for new connection - if(*con_cls == NULL) { - PRACRO_DEBUG(httpd, - "handle_request(url=\"%s\", method=\"%s\"," - " version=\"%s\", data_size=\"%d\")\n", - url, method, version, *data_size); - - struct condata *cd = new struct condata; - cd->url = url; - cd->method = method; - cd->version = version; - cd->data_size = 0; - cd->data = ""; - + if(connection == NULL) { + std::string sessionid; const char *sid = MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionID"); - if(sid) cd->headers["SessionID"] = sid; + if(sid) sessionid = sid; const char *scm = MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionCommit"); - if(scm) cd->headers["SessionCommit"] = scm; - - const char *csz = MHD_lookup_connection_value(con, MHD_HEADER_KIND, - "Content-Length"); - if(csz) { - cd->headers["Content-Length"] = csz; - cd->data_size = atol(csz); - PRACRO_DEBUG(httpd, "Content-Length: %s (%d)\n", csz, cd->data_size); - } - - *con_cls = cd; + Environment *env = (Environment *)cls; + connection = new Connection(*env, sessionid, scm != NULL); + *con_cls = connection; } - struct condata *cd = (struct condata*)*con_cls; - cd->data.append(data, *data_size); - - int ret = MHD_YES; + if(!connection) return MHD_NO; - PRACRO_DEBUG(httpd, "Waiting for %d bytes of data. Got %d (total %d)\n", - cd->data_size, *data_size, cd->data.length()); - - if(cd->data.length() >= cd->data_size) { - - Environment *env = (Environment *)cls; - - const char *sid = MHD_lookup_connection_value(con, MHD_HEADER_KIND, - "SessionID"); - std::string sessionid; - if(sid) sessionid = sid; - - const char *sessioncommit = - MHD_lookup_connection_value(con, MHD_HEADER_KIND, "SessionCommit"); - - PRACRO_DEBUG(httpd, "Starting to handle SessionID: %s%s\n", - sessionid.c_str(), - sessioncommit != NULL?" COMMIT":""); - - PRACRO_DEBUG(httpd, "Data: [%s]\n", cd->data.c_str()); - - std::string reply = - handleConnection(cd->data, *env, sessionid, sessioncommit != NULL); + if(connection->handle(data, *data_size)) { + std::string response = connection->getResponse(); + PRACRO_DEBUG(httpd, "Sending response: [[%s]]\n", response.c_str()); + struct MHD_Response *rsp = - MHD_create_response_from_data(reply.length(), (char*)reply.c_str(), - MHD_NO, MHD_YES); + MHD_create_response_from_data(response.size(), + (void*)response.data(), + MHD_NO, // must free + MHD_YES); // must copy + MHD_add_response_header(rsp, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=UTF-8"); - if(sessionid != "") { - MHD_add_response_header(rsp, "SessionID", sessionid.c_str()); - } + MHD_add_response_header(rsp, "SessionID", + connection->getSessionID().c_str()); ret = MHD_queue_response(con, MHD_HTTP_OK, rsp); MHD_destroy_response(rsp); - PRACRO_DEBUG(httpd, "Finished handling SessionID: %s%s\n", - sessionid.c_str(), - sessioncommit != NULL?" COMMIT":""); - - - delete cd; + delete connection; *con_cls = NULL; - } *data_size = 0; @@ -231,8 +114,8 @@ void requestCompletedCallback(void *cls, // If connection was interrupted prematurely delete the content data here. if(*con_cls) { - struct condata *cd = (struct condata*)*con_cls; - delete cd; + Connection *connection = (Connection*)*con_cls; + delete connection; *con_cls = NULL; } } diff --git a/server/src/transactionhandler.cc b/server/src/transactionhandler.cc index 7a45800..662896b 100644 --- a/server/src/transactionhandler.cc +++ b/server/src/transactionhandler.cc @@ -219,8 +219,9 @@ static std::string handleRequest(Transaction &transaction, Environment &env, if(completed) { answer += " "; - answer += db->getResume(transaction.cpr, macro, time(NULL) - - Conf::db_max_ttl); + answer += xml_encode(db->getResume(transaction.cpr, + macro, + time(NULL) - Conf::db_max_ttl)); answer += "\n"; } diff --git a/server/src/transactionparser.cc b/server/src/transactionparser.cc index 7422a13..7595bb2 100644 --- a/server/src/transactionparser.cc +++ b/server/src/transactionparser.cc @@ -72,17 +72,17 @@ void TransactionParser::startTag(std::string name, if(name == "field") { if(!transaction->commits.size()) { PRACRO_ERR(transactionparser, "Field without a commit tag!"); - return; + throw std::exception(); } if(attributes.find("name") == attributes.end()) { PRACRO_ERR(transactionparser, "Field is missing 'name' attribute"); - return; + throw std::exception(); } if(attributes.find("value") == attributes.end()) { PRACRO_ERR(transactionparser, "Field is missing 'value' attribute"); - return; + throw std::exception(); } transaction->commits.back().fields[attributes["name"]] = @@ -101,6 +101,8 @@ void TransactionParser::parseError(const char *buf, size_t len, PRACRO_ERR(transactionparser, "\tBuffer %u bytes: [%s]\n", len, xml.c_str()); + + throw std::exception(); } #ifdef TEST_TRANSACTIONPARSER diff --git a/server/src/widgetgenerator.cc b/server/src/widgetgenerator.cc index 1e60479..425c71e 100644 --- a/server/src/widgetgenerator.cc +++ b/server/src/widgetgenerator.cc @@ -109,9 +109,9 @@ static std::string send_macro_widget(Macro ¯o, if(luamap != "") { Value value = mapper.map(luamap); if(value.timestamp > now - Conf::pentominos_max_ttl) { - widget.attributes["value"] = xml_encode(value.value); + widget.attributes["value"] = value.value; timestamp = value.timestamp; - prefilled = xml_encode(value.source); + prefilled = value.source; } PRACRO_DEBUG(prefill, "map: (%s, %d)\n", @@ -137,7 +137,7 @@ static std::string send_macro_widget(Macro ¯o, if(values[widget.attributes["name"]].timestamp > timestamp) { if(values[widget.attributes["name"]].timestamp > now - Conf::db_max_ttl) { - widget.attributes["value"] = xml_encode(values[widget.attributes["name"]].value); + widget.attributes["value"] = values[widget.attributes["name"]].value; timestamp = values[widget.attributes["name"]].timestamp; prefilled = "pracro"; } @@ -152,7 +152,7 @@ static std::string send_macro_widget(Macro ¯o, while(p != widget.attributes.end()) { if(p->first != "tagname" && p->first != "map") { if( ! (p->first == "name" && p->second == "") ) - result += " " + p->first + "=\"" + p->second + "\""; + result += " " + p->first + "=\"" + xml_encode(p->second) + "\""; } p++; } -- cgit v1.2.3