summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2010-05-07 12:36:13 +0000
committerdeva <deva>2010-05-07 12:36:13 +0000
commit016e4ba553044edee32c2a20ee34463ad82106e8 (patch)
tree8fdde7232ee847ba39eb94449b18fd3de7bb4fb8
parent965e43178736e6635cf27410e6d73f4ec0fdced2 (diff)
Use connection object instead of struct and make xml parsing on-the-fly instead of collecting all data first.
-rw-r--r--server/src/Makefile.am2
-rw-r--r--server/src/connection.cc129
-rw-r--r--server/src/connection.h57
-rw-r--r--server/src/resumeparser.cc3
-rw-r--r--server/src/server.cc169
-rw-r--r--server/src/transactionhandler.cc5
-rw-r--r--server/src/transactionparser.cc8
-rw-r--r--server/src/widgetgenerator.cc8
8 files changed, 228 insertions, 153 deletions
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 =
+ "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<pracro version=\"1.0\">\n"
+ " <error>" + message + "</error>\n"
+ "</pracro>\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 <string>
+#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 <string.h>
+#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 <microhttpd.h>
#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 =
- "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
- "<pracro version=\"1.0\">\n"
- " <error>" + message + "</error>\n"
- "</pracro>\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<std::string, std::string> headers;
- std::string data;
- size_t data_size;
- std::string url;
- std::string method;
- std::string version;
-};
-
-//static std::map<struct MHD_Connection *, struct condata> 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 += " <resume>";
- 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 += "</resume>\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 &macro,
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 &macro,
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 &macro,
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++;
}