summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordeva <deva>2011-02-04 07:35:10 +0000
committerdeva <deva>2011-02-04 07:35:10 +0000
commit9ec9a98e83076bb339d1d546fa445b2420e5a4fb (patch)
treed507ac2dff3825719c6557a672ad8eb64c303e18
parente137415d0e0325d143b69a9917d8ebba411b3c12 (diff)
A new connection handling mechanism.
-rw-r--r--server/src/Makefile.am8
-rw-r--r--server/src/admin_connection.cc67
-rw-r--r--server/src/admin_connection.h51
-rw-r--r--server/src/client_connection.cc395
-rw-r--r--server/src/client_connection.h79
-rw-r--r--server/src/connection.cc336
-rw-r--r--server/src/connection.h37
-rw-r--r--server/src/httpd.cc11
-rw-r--r--server/src/httpd.h1
-rw-r--r--server/src/server.cc70
10 files changed, 657 insertions, 398 deletions
diff --git a/server/src/Makefile.am b/server/src/Makefile.am
index 143e61d..5989d39 100644
--- a/server/src/Makefile.am
+++ b/server/src/Makefile.am
@@ -12,13 +12,15 @@ pracrod_CXXFLAGS = $(PQXX_CXXFLAGS) $(CONFIG_CXXFLAGS) \
pracrod_SOURCES = \
pracrod.cc \
+ admin_connection.cc \
artefact.cc \
- daemon.cc \
- database.cc \
+ client_connection.cc \
configuration.cc \
configurationparser.cc \
connection.cc \
connectionpool.cc \
+ daemon.cc \
+ database.cc \
debug.cc \
entitylist.cc \
environment.cc \
@@ -63,6 +65,8 @@ pracrod_SOURCES = \
EXTRA_DIST = \
artefact.h \
+ admin_connection.h \
+ client_connection.h \
configuration.h \
configurationparser.h \
connection.h \
diff --git a/server/src/admin_connection.cc b/server/src/admin_connection.cc
new file mode 100644
index 0000000..517b17a
--- /dev/null
+++ b/server/src/admin_connection.cc
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * admin_connection.cc
+ *
+ * Thu Feb 3 09:33:44 CET 2011
+ * Copyright 2011 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 "admin_connection.h"
+
+AdminConnection::AdminConnection(Environment &e, headers_t a)
+ : env(e), args(a) {}
+
+AdminConnection::~AdminConnection() {}
+
+bool AdminConnection::handle(const char *data, size_t size)
+{
+ return true;
+}
+
+std::string AdminConnection::getResponse()
+{
+ return "Hello Admin World";
+}
+
+headers_t AdminConnection::getHeaders()
+{
+ headers_t hdrs;
+ return hdrs;
+}
+
+
+#ifdef TEST_ADMIN_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_ADMIN_CONNECTION*/
diff --git a/server/src/admin_connection.h b/server/src/admin_connection.h
new file mode 100644
index 0000000..98ddda7
--- /dev/null
+++ b/server/src/admin_connection.h
@@ -0,0 +1,51 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * admin_connection.h
+ *
+ * Thu Feb 3 09:33:44 CET 2011
+ * Copyright 2011 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_ADMIN_CONNECTION_H__
+#define __PRACRO_ADMIN_CONNECTION_H__
+
+#include <string>
+
+#include "connection.h"
+#include "environment.h"
+
+class AdminConnection : public Connection {
+public:
+ AdminConnection(Environment &e, headers_t args);
+ ~AdminConnection();
+
+ bool handle(const char *data, size_t size);
+
+ std::string getResponse();
+ headers_t getHeaders();
+
+private:
+ Environment &env;
+ headers_t args;
+};
+
+#endif/*__PRACRO_ADMIN_CONNECTION_H__*/
diff --git a/server/src/client_connection.cc b/server/src/client_connection.cc
new file mode 100644
index 0000000..af70916
--- /dev/null
+++ b/server/src/client_connection.cc
@@ -0,0 +1,395 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * client_connection.cc
+ *
+ * Thu Feb 3 09:33:48 CET 2011
+ * Copyright 2011 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 "client_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;
+}
+
+#ifdef TEST_CONNECTION
+static bool did_commit = false;
+#endif
+
+ClientConnection::Parameters::Parameters()
+{
+ sessionid = "";
+ patientid = "";
+ templ = "";
+ commit = false;
+ discard = false;
+ nocommit = false;
+}
+
+ClientConnection::ClientConnection(Environment &e, Parameters p)
+ : parms(p), env(e), parser(&transaction)
+{
+ DEBUG(connection, "[%p] CREATE\n", this);
+
+#ifdef TEST_CONNECTION
+ did_commit = false;
+#endif
+
+ parser_complete = false;
+}
+
+ClientConnection::~ClientConnection()
+{
+ DEBUG(connection, "[%p] DESTROY\n", this);
+}
+
+void ClientConnection::nocommit(Session *session)
+{
+ if(parms.nocommit) {
+ if(session->isreadonly) { // NoCommit of an empty session discards it.
+ parms.discard = true;
+ return;
+ }
+
+ DEBUG(connection, "NoCommit (%s)\n", session->id().c_str());
+ parms.nocommit = false;
+ session->nocommit();
+ }
+}
+
+void ClientConnection::commit(Session *session)
+{
+ if(parms.commit) {
+ if(session->isreadonly) { // Commit of an empty session discards it.
+ parms.discard = true;
+ return;
+ }
+
+ DEBUG(connection, "Commit (%s)\n", session->id().c_str());
+ std::string sid = session->id();
+ session->commit();
+ env.sessions.deleteSession(sid);
+ parms.sessionid = "";
+ parms.commit = false;
+#ifdef TEST_CONNECTION
+ did_commit = true;
+#endif
+ }
+}
+
+void ClientConnection::discard(Session *session)
+{
+ if(parms.discard) {
+ DEBUG(connection, "Discard (%s)\n", session->id().c_str());
+ std::string sid = session->id();
+ session->discard();
+ env.sessions.deleteSession(sid);
+ parms.sessionid = "";
+ parms.discard = false;
+ }
+}
+
+bool ClientConnection::handle(const char *data, size_t size)
+{
+ Session *session = NULL;
+ try {
+ if(parms.sessionid == "") {
+ // Create new session
+ session = env.sessions.newSession(parms.patientid,
+ parms.templ);
+ } else {
+ // Attach to old session
+ session = env.sessions.session(parms.sessionid);
+
+ // Session didn't exist - create a new one anyway.
+ if(session == NULL) {
+ session = env.sessions.newSession(parms.patientid,
+ parms.templ);
+ }
+ }
+ } catch(Sessions::SessionAlreadyActive &e) {
+ ERR(connection, "Session already active.\n");
+ parser_complete = true;
+ response = error_box(xml_encode("Session "+e.sessionid+" already active."));
+ return true;
+ }
+
+ if(session == NULL) {
+ ERR(connection, "New session could not be created.\n");
+ response = error_box(xml_encode("New session could not be created."));
+ return true;
+ }
+
+ parms.sessionid = session->id();
+
+ try {
+
+ if(!data || !size) {
+ parser_complete = true;
+ commit(session);
+ nocommit(session);
+ discard(session);
+ return true;
+ }
+
+ if(parser.parse(data, size)) {
+ parser_complete = true;
+
+ {
+ SessionAutolock lock(*session);
+ response = handleTransaction(transaction, env, *session);
+ }
+
+ commit(session);
+ nocommit(session);
+ discard(session);
+
+ return true;
+ }
+ } catch(...) {
+ ERR(server, "Failed to parse data!\n");
+ response = error_box(xml_encode("XML Parse error."));
+ return true;
+ }
+
+ return false;
+}
+
+std::string ClientConnection::getResponse()
+{
+ if(parser_complete == false)
+ return error_box(xml_encode("XML Parser need more data."));
+ return response;
+}
+
+headers_t ClientConnection::getHeaders()
+{
+ headers_t hdrs;
+
+ hdrs["Content-Type"] = "text/plain; charset=UTF-8";
+ hdrs["SessionID"] = parms.sessionid;
+
+ return hdrs;
+}
+
+#ifdef TEST_CLIENT_CONNECTION
+//deps: debug.cc transactionparser.cc session.cc xml_encode_decode.cc saxparser.cc transactionhandler.cc journal.cc mutex.cc templateparser.cc exception.cc configuration.cc macroparser.cc semaphore.cc entitylist.cc luaquerymapper.cc inotify.cc log.cc queryhandlerpentominos.cc widgetgenerator.cc queryhandlerpracro.cc resumeparser.cc journal_commit.cc versionstr.cc luaresume.cc luautil.cc artefact.cc environment.cc database.cc macrolist.cc templatelist.cc pracrodao.cc templateheaderparser.cc macroheaderparser.cc pracrodaotest.cc pracrodaopgsql.cc
+//cflags: -DWITHOUT_DATABASE -DWITHOUT_ARTEFACT -I.. $(LUA_CFLAGS) $(EXPAT_CFLAGS) $(PTHREAD_CFLAGS) $(PQXX_CXXFLAGS)
+//libs: $(LUA_LIBS) $(EXPAT_LIBS) $(PTHREAD_LIBS) $(PQXX_LIBS)
+#include "test.h"
+
+static char xml_request[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <request macro=\"test\" template=\"test\"/>\n"
+"</pracro>\n"
+ ;
+
+static char xml_commit[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
+" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
+" <field value=\"DIMS\" name=\"referral.diagnosecode\"/>\n"
+" <field value=\"Avs\" name=\"referral.diagnose\"/>\n"
+" </commit>\n"
+"</pracro>\n"
+ ;
+
+static char xml_commit_p1[] =
+"<?xml version='1.0' encoding='UTF-8'?>\n"
+"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
+" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
+" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
+" <field value=\"DIMS\" name=\"referral.diagn"
+ ;
+
+static char xml_commit_p2[] =
+"ose\"/>\n"
+" </commit>\n"
+"</pracro>\n"
+ ;
+
+TEST_BEGIN;
+
+Environment env;
+std::string sid;
+
+// Without data
+{
+ ClientConnection con(env, "", false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, true);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle("", 0), "Test handler return value.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With commit partial data
+{
+ ClientConnection con(env, "", false);
+ TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
+ "Test handler return value.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test session id.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With commit partial data and journal commit
+{
+ ClientConnection con(env, "", true);
+ TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+ TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
+ "Test handler return value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test session id.");
+ TEST_TRUE(did_commit, "No commit.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+}
+
+// With commit data
+{
+ ClientConnection con(env, "", false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, true);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+// With request data
+{
+ ClientConnection con(env, "", false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ sid = con.getSessionID();
+ TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+{
+ ClientConnection con(env, sid, true);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
+ TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_TRUE(did_commit, "Commit.");
+}
+
+{
+ ClientConnection con(env, sid, false);
+ TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
+ "Test handler return value.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
+ TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
+ TEST_FALSE(did_commit, "No commit.");
+}
+
+TEST_END;
+
+#endif/*TEST_CLIENT_CONNECTION*/
diff --git a/server/src/client_connection.h b/server/src/client_connection.h
new file mode 100644
index 0000000..69e6fe7
--- /dev/null
+++ b/server/src/client_connection.h
@@ -0,0 +1,79 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set et sw=2 ts=2: */
+/***************************************************************************
+ * client_connection.h
+ *
+ * Thu Feb 3 09:33:48 CET 2011
+ * Copyright 2011 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_CLIENT_CONNECTION_H__
+#define __PRACRO_CLIENT_CONNECTION_H__
+
+#include <string>
+
+#include "connection.h"
+
+#include "environment.h"
+#include "transaction.h"
+#include "transactionparser.h"
+
+class Session;
+
+class ClientConnection : public Connection {
+public:
+ class Parameters {
+ public:
+ Parameters();
+ std::string sessionid;
+ std::string patientid;
+ std::string templ;
+ bool commit;
+ bool discard;
+ bool nocommit;
+ };
+
+ ClientConnection(Environment &e, Parameters cp);
+ ~ClientConnection();
+
+ bool handle(const char *data, size_t size);
+
+ std::string getResponse();
+ headers_t getHeaders();
+
+private:
+ void commit(Session *session);
+ void nocommit(Session *session);
+ void discard(Session *session);
+
+ Parameters parms;
+
+ Environment &env;
+
+ Transaction transaction;
+ TransactionParser parser;
+
+ std::string response;
+
+ bool parser_complete;
+};
+
+#endif/*__PRACRO_CLIENT_CONNECTION_H__*/
diff --git a/server/src/connection.cc b/server/src/connection.cc
index e4ec7f4..4f0907d 100644
--- a/server/src/connection.cc
+++ b/server/src/connection.cc
@@ -27,339 +27,3 @@
*/
#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;
-}
-
-#ifdef TEST_CONNECTION
-static bool did_commit = false;
-#endif
-
-Connection::Connection(Environment &e, std::string sid,
- std::string pid, std::string t,
- bool c, bool d, bool nc)
- : env(e), parser(&transaction)
-{
- DEBUG(connection, "[%p] CREATE\n", this);
-
- patientid = pid;
- templ = t;
- sessionid = sid;
- docommit = c;
- dodiscard = d;
- donocommit = nc;
-
-#ifdef TEST_CONNECTION
- did_commit = false;
-#endif
-
- parser_complete = false;
-}
-
-Connection::~Connection()
-{
- DEBUG(connection, "[%p] DESTROY\n", this);
-}
-
-void Connection::nocommit(Session *session)
-{
- if(donocommit) {
- donocommit = false;
- session->nocommit();
- }
-}
-
-void Connection::commit(Session *session)
-{
- if(docommit) {
- std::string sid = session->id();
- session->commit();
- env.sessions.deleteSession(sid);
- sessionid = "";
- docommit = false;
-#ifdef TEST_CONNECTION
- did_commit = true;
-#endif
- }
-}
-
-void Connection::discard(Session *session)
-{
- if(dodiscard) {
- std::string sid = session->id();
- session->discard();
- env.sessions.deleteSession(sid);
- sessionid = "";
- dodiscard = false;
- }
-}
-
-bool Connection::handle(const char *data, size_t size)
-{
- Session *session = NULL;
- if(sessionid == "") {
- // Create new session
- session = env.sessions.newSession(patientid, templ);
- } 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(patientid, templ);
- }
-
- if(session == NULL) {
- ERR(connection, "New session could not be created.");
- response = error_box(xml_encode("New session could not be created."));
- return true;
- }
-
- sessionid = session->id();
-
- try {
-
- if(!data || !size) {
- parser_complete = true;
- commit(session);
- discard(session);
- nocommit(session);
- return true;
- }
-
- if(parser.parse(data, size)) {
- parser_complete = true;
-
- {
- SessionAutolock lock(*session);
- response = handleTransaction(transaction, env, *session);
- }
-
- commit(session);
- discard(session);
- nocommit(session);
-
- return true;
- }
- } catch(...) {
- ERR(server, "Failed to parse data!\n");
- response = error_box(xml_encode("XML Parse error."));
- return true;
- }
-
- return false;
-}
-
-std::string Connection::getResponse()
-{
- if(parser_complete == false)
- return error_box(xml_encode("XML Parser need more data."));
- return response;
-}
-
-std::string Connection::getSessionID()
-{
- return sessionid;
-}
-
-#ifdef TEST_CONNECTION
-//deps: debug.cc transactionparser.cc session.cc xml_encode_decode.cc saxparser.cc transactionhandler.cc journal.cc mutex.cc templateparser.cc exception.cc configuration.cc macroparser.cc semaphore.cc entitylist.cc luaquerymapper.cc inotify.cc log.cc queryhandlerpentominos.cc widgetgenerator.cc queryhandlerpracro.cc resumeparser.cc journal_commit.cc versionstr.cc luaresume.cc luautil.cc artefact.cc environment.cc database.cc macrolist.cc templatelist.cc pracrodao.cc templateheaderparser.cc macroheaderparser.cc pracrodaotest.cc pracrodaopgsql.cc
-//cflags: -DWITHOUT_DATABASE -DWITHOUT_ARTEFACT -I.. $(LUA_CFLAGS) $(EXPAT_CFLAGS) $(PTHREAD_CFLAGS) $(PQXX_CXXFLAGS)
-//libs: $(LUA_LIBS) $(EXPAT_LIBS) $(PTHREAD_LIBS) $(PQXX_LIBS)
-#include "test.h"
-
-static char xml_request[] =
-"<?xml version='1.0' encoding='UTF-8'?>\n"
-"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
-" <request macro=\"test\" template=\"test\"/>\n"
-"</pracro>\n"
- ;
-
-static char xml_commit[] =
-"<?xml version='1.0' encoding='UTF-8'?>\n"
-"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
-" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
-" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
-" <field value=\"DIMS\" name=\"referral.diagnosecode\"/>\n"
-" <field value=\"Avs\" name=\"referral.diagnose\"/>\n"
-" </commit>\n"
-"</pracro>\n"
- ;
-
-static char xml_commit_p1[] =
-"<?xml version='1.0' encoding='UTF-8'?>\n"
-"<pracro version=\"1.0\" user=\"testuser\" cpr=\"1505050505\">\n"
-" <commit version=\"\" macro=\"referral\" template=\"amd_forunders\" >\n"
-" <field value=\"Some docs\" name=\"referral.doctor\"/>\n"
-" <field value=\"DIMS\" name=\"referral.diagn"
- ;
-
-static char xml_commit_p2[] =
-"ose\"/>\n"
-" </commit>\n"
-"</pracro>\n"
- ;
-
-TEST_BEGIN;
-
-Environment env;
-std::string sid;
-
-// Without data
-{
- Connection con(env, "", false);
- TEST_TRUE(con.handle("", 0), "Test handler return value.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- sid = con.getSessionID();
- TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle("", 0), "Test handler return value.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, true);
- TEST_TRUE(con.handle("", 0), "Test handler return value.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_TRUE(did_commit, "Commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle("", 0), "Test handler return value.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-// With commit partial data
-{
- Connection con(env, "", false);
- TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
- "Test handler return value.");
- sid = con.getSessionID();
- TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
- "Test handler return value.");
- TEST_EQUAL_STR(con.getSessionID(), sid, "Test session id.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-// With commit partial data and journal commit
-{
- Connection con(env, "", true);
- TEST_FALSE(con.handle(xml_commit_p1, sizeof(xml_commit_p1) - 1),
- "Test handler return value.");
- sid = con.getSessionID();
- TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
- TEST_EQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_FALSE(did_commit, "No commit.");
- TEST_TRUE(con.handle(xml_commit_p2, sizeof(xml_commit_p2) - 1),
- "Test handler return value.");
- TEST_EQUAL_STR(con.getSessionID(), "", "Test session id.");
- TEST_TRUE(did_commit, "No commit.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
-}
-
-// With commit data
-{
- Connection con(env, "", false);
- TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
- "Test handler return value.");
- sid = con.getSessionID();
- TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, true);
- TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_TRUE(did_commit, "Commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle(xml_commit, sizeof(xml_commit) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-// With request data
-{
- Connection con(env, "", false);
- TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- sid = con.getSessionID();
- TEST_NOTEQUAL_STR(sid, "", "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_EQUAL_STR(con.getSessionID(), sid, "Test existing session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-{
- Connection con(env, sid, true);
- TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getResponse(), "", "Test response value.");
- TEST_EQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_TRUE(did_commit, "Commit.");
-}
-
-{
- Connection con(env, sid, false);
- TEST_TRUE(con.handle(xml_request, sizeof(xml_request) - 1),
- "Test handler return value.");
- TEST_NOTEQUAL_STR(con.getSessionID(), "", "Test existing session id.");
- TEST_NOTEQUAL_STR(con.getSessionID(), sid, "Test new session id.");
- TEST_FALSE(did_commit, "No commit.");
-}
-
-TEST_END;
-
-#endif/*TEST_CONNECTION*/
diff --git a/server/src/connection.h b/server/src/connection.h
index e9a4e50..153e865 100644
--- a/server/src/connection.h
+++ b/server/src/connection.h
@@ -29,43 +29,14 @@
#define __PRACRO_CONNECTION_H__
#include <string>
-#include "environment.h"
-#include "transaction.h"
-#include "transactionparser.h"
-class Session;
+#include "httpd.h"
class Connection {
public:
- Connection(Environment &e, std::string sessionid,
- std::string patientid, std::string templ,
- bool commit, bool discard, bool nocommit);
- ~Connection();
-
- bool handle(const char *data, size_t size);
-
- std::string getResponse();
- std::string getSessionID();
-
-private:
- void commit(Session *session);
- void nocommit(Session *session);
- void discard(Session *session);
-
- std::string patientid;
- std::string templ;
- std::string sessionid;
- bool docommit;
- bool donocommit;
- bool dodiscard;
- Environment &env;
-
- Transaction transaction;
- TransactionParser parser;
-
- std::string response;
-
- bool parser_complete;
+ virtual bool handle(const char *data, size_t size) = 0;
+ virtual std::string getResponse() = 0;
+ virtual headers_t getHeaders() = 0;
};
#endif/*__PRACRO_CONNECTION_H__*/
diff --git a/server/src/httpd.cc b/server/src/httpd.cc
index e47cefc..ce1a1ce 100644
--- a/server/src/httpd.cc
+++ b/server/src/httpd.cc
@@ -39,6 +39,8 @@
#include <microhttpd.h>
+#include "debug.h"
+
typedef struct {
void *ptr;
bool firstrun;
@@ -48,6 +50,8 @@ typedef struct {
int hdit(void *cls, enum MHD_ValueKind kind, const char *key, const char *value)
{
+ DEBUG(httpd, "%s: %s\n", key, value);
+
headers_t *headers = (headers_t*)cls;
(*headers)[key] = value;
@@ -70,8 +74,11 @@ static int request_handler(void *cls,
if(*con_cls == NULL) {
headers_t headers;
+ headers_t getargs;
- MHD_get_connection_values(con, MHD_HEADER_KIND, hdit, &headers);
+ MHD_get_connection_values(con, MHD_HEADER_KIND, &hdit, &headers);
+ int n = MHD_get_connection_values(con, MHD_GET_ARGUMENT_KIND, &hdit, &getargs);
+ DEBUG(httpd, "Num args: %d\n", n);
connection_t* c = new connection_t;
@@ -81,7 +88,7 @@ static int request_handler(void *cls,
c->total = atoi(headers["Content-Length"].c_str());
}
c->acc = 0;
- c->ptr = httpd->begin(url, method, version, headers);
+ c->ptr = httpd->begin(url, method, version, getargs, headers);
*con_cls = c;
}
diff --git a/server/src/httpd.h b/server/src/httpd.h
index 72b23a4..455fa35 100644
--- a/server/src/httpd.h
+++ b/server/src/httpd.h
@@ -70,6 +70,7 @@ public:
virtual void *begin(const std::string &url,
const std::string &method,
const std::string &version,
+ headers_t &getargs,
headers_t &headers) { return NULL; }
// Return false indicates error, and terminates connetion (no reply)
diff --git a/server/src/server.cc b/server/src/server.cc
index 6474fb5..1665bbf 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -32,7 +32,10 @@
#include "httpd.h"
#include "configuration.h"
#include "environment.h"
+
#include "connection.h"
+#include "client_connection.h"
+#include "admin_connection.h"
class PracroHttpd : public Httpd {
public:
@@ -51,52 +54,69 @@ public:
void *begin(const std::string &url,
const std::string &method,
const std::string &version,
+ headers_t &getargs,
headers_t &headers)
{
- std::string sessionid;
- std::string patientid;
- std::string templ;
- if(headers.contains("SessionID")) sessionid = headers["SessionID"];
- if(headers.contains("SessionPatientID"))
- patientid = headers["SessionPatientID"];
- if(headers.contains("SessionTemplate")) templ = headers["SessionTemplate"];
-
- bool commit = headers.contains("SessionCommit");
- bool nocommit = headers.contains("SessionNoCommit");
- bool discard = headers.contains("SessionDiscard");
+ Connection *connection = NULL;
+
+ if(headers.find("User-Agent") != headers.end() &&
+ headers["User-Agent"].find("Pracro") == std::string::npos) { // Admin
+ connection = new AdminConnection(env, getargs);
+ } else { // Pracro client
+ ClientConnection::Parameters parms;
+ if(headers.contains("SessionID"))
+ parms.sessionid = headers["SessionID"];
+ if(headers.contains("SessionPatientID"))
+ parms.patientid = headers["SessionPatientID"];
+ if(headers.contains("SessionTemplate"))
+ parms.templ = headers["SessionTemplate"];
+
+ parms.commit = headers.contains("SessionCommit");
+ parms.nocommit = headers.contains("SessionNoCommit");
+ parms.discard = headers.contains("SessionDiscard");
- Connection *connection = new Connection(env, sessionid, patientid, templ,
- commit, discard, nocommit);
+ connection = new ClientConnection(env, parms);
+ }
return connection;
}
bool data(void *ptr, const char *data, unsigned int data_size)
{
- Connection *connection = (Connection *)ptr;
- connection->handle(data, data_size);
+ if(ptr) {
+ Connection *connection = (Connection *)ptr;
+ connection->handle(data, data_size);
+ }
return true;
}
bool complete(void *ptr, Httpd::Reply &reply)
{
- Connection *connection = (Connection *)ptr;
+ if(ptr) {
+ Connection *connection = (Connection *)ptr;
- // Flush and do commit/discard
- connection->handle(NULL, 0);
+ // Flush and do commit/discard
+ connection->handle(NULL, 0);
+
+ reply.data = connection->getResponse();
+ reply.headers = connection->getHeaders();
+ reply.status = 200; // http 'OK'
+ } else {
+
+ reply.data = "Admin";
+ reply.status = 200; // http 'OK'
+
+ }
- reply.data = connection->getResponse();
- reply.headers["Content-Type"] = "text/plain; charset=UTF-8";
- reply.headers["SessionID"] = connection->getSessionID();
- reply.status = 200; // http 'OK'
-
return true;
}
void cleanup(void *ptr)
{
- Connection *connection = (Connection *)ptr;
- delete connection;
+ if(ptr) {
+ Connection *connection = (Connection *)ptr;
+ delete connection;
+ }
}
private: