diff options
| author | deva <deva> | 2011-02-04 07:35:10 +0000 | 
|---|---|---|
| committer | deva <deva> | 2011-02-04 07:35:10 +0000 | 
| commit | 9ec9a98e83076bb339d1d546fa445b2420e5a4fb (patch) | |
| tree | d507ac2dff3825719c6557a672ad8eb64c303e18 | |
| parent | e137415d0e0325d143b69a9917d8ebba411b3c12 (diff) | |
A new connection handling mechanism.
| -rw-r--r-- | server/src/Makefile.am | 8 | ||||
| -rw-r--r-- | server/src/admin_connection.cc | 67 | ||||
| -rw-r--r-- | server/src/admin_connection.h | 51 | ||||
| -rw-r--r-- | server/src/client_connection.cc | 395 | ||||
| -rw-r--r-- | server/src/client_connection.h | 79 | ||||
| -rw-r--r-- | server/src/connection.cc | 336 | ||||
| -rw-r--r-- | server/src/connection.h | 37 | ||||
| -rw-r--r-- | server/src/httpd.cc | 11 | ||||
| -rw-r--r-- | server/src/httpd.h | 1 | ||||
| -rw-r--r-- | server/src/server.cc | 70 | 
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: | 
