From 9ec9a98e83076bb339d1d546fa445b2420e5a4fb Mon Sep 17 00:00:00 2001 From: deva Date: Fri, 4 Feb 2011 07:35:10 +0000 Subject: A new connection handling mechanism. --- server/src/Makefile.am | 8 +- server/src/admin_connection.cc | 67 +++++++ server/src/admin_connection.h | 51 ++++++ server/src/client_connection.cc | 395 ++++++++++++++++++++++++++++++++++++++++ server/src/client_connection.h | 79 ++++++++ server/src/connection.cc | 336 ---------------------------------- server/src/connection.h | 37 +--- server/src/httpd.cc | 11 +- server/src/httpd.h | 1 + server/src/server.cc | 70 ++++--- 10 files changed, 657 insertions(+), 398 deletions(-) create mode 100644 server/src/admin_connection.cc create mode 100644 server/src/admin_connection.h create mode 100644 server/src/client_connection.cc create mode 100644 server/src/client_connection.h (limited to 'server') 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 + +#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 = + "\n" + "\n" + " " + message + "\n" + "\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[] = +"\n" +"\n" +" \n" +"\n" + ; + +static char xml_commit[] = +"\n" +"\n" +" \n" +" \n" +" \n" +" \n" +" \n" +"\n" + ; + +static char xml_commit_p1[] = +"\n" +"\n" +" \n" +" \n" +" \n" +" \n" +"\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 + +#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 = - "\n" - "\n" - " " + message + "\n" - "\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[] = -"\n" -"\n" -" \n" -"\n" - ; - -static char xml_commit[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -"\n" - ; - -static char xml_commit_p1[] = -"\n" -"\n" -" \n" -" \n" -" \n" -" \n" -"\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 -#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 +#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: -- cgit v1.2.3