From 1782d12938ba89b67a52677d162d4c865f00cbe0 Mon Sep 17 00:00:00 2001
From: deva <deva>
Date: Tue, 3 Nov 2009 13:49:15 +0000
Subject: First working, but not in any way optimal implementation of a http
 transport layer.

---
 client/netcom.cc     |  58 +++++++++++----------------
 client/netcom.h      |  13 +++---
 server/src/server.cc | 109 +++++++++++++++++++++++++++++----------------------
 3 files changed, 93 insertions(+), 87 deletions(-)

diff --git a/client/netcom.cc b/client/netcom.cc
index 3b3abb7..6150227 100644
--- a/client/netcom.cc
+++ b/client/netcom.cc
@@ -29,28 +29,27 @@
 #include <QApplication>
 #include <QByteArray>
 
+#include <QHttp>
+
 #include "widgets/widget.h"
 
 NetCom::NetCom(QString host, quint16 port, QString user, QString cpr)
 {
   this->user = user;
   this->cpr = cpr;
-  socket.connectToHost(host, port);
-  connect(&socket, SIGNAL(readyRead()), this, SLOT(readyRead()));
-  socket.waitForConnected();
-  transmitting = false;
+
+  connect(&http, SIGNAL(done(bool)), this, SLOT(done(bool)));
+  http.setHost(host, port);
+  
+  transfering = false;
 }
 
 NetCom::~NetCom()
 {
-  socket.disconnectFromHost();
 }
 
 QDomDocument NetCom::send(QString templ, QString macro, bool lockgui)
 {
-  printf("Socket state: %d\n", socket.state());
-  if(socket.state() != 3) printf("Socket state not connected: %s\n", socket.errorString().toStdString().c_str());
-
   if(lockgui && qApp->activeWindow()) qApp->activeWindow()->setEnabled(false);
   if(lockgui) QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
 
@@ -72,14 +71,15 @@ QDomDocument NetCom::send(QString templ, QString macro, bool lockgui)
  
   printf("\nSending request:\n%s", doc.toString().toStdString().c_str());
 
-  socket.write(doc.toByteArray());
-  //  socket.waitForReadyRead();
+  http.post("/", doc.toByteArray());
 
+  QDomDocument res_doc;
+  transfering = true;
+  buffer = "";
   do {
     qApp->processEvents(QEventLoop::WaitForMoreEvents);
-  } while(!res_doc.setContent(buffer));
-
-  buffer = "";
+  } while(transfering);
+  res_doc.setContent(buffer);
 
   QDomElement elem = res_doc.documentElement();
 
@@ -91,18 +91,8 @@ QDomDocument NetCom::send(QString templ, QString macro, bool lockgui)
   return res_doc;
 }
 
-void NetCom::readyRead()
-{
-  buffer.append(socket.readAll());
-}
-
 void NetCom::send(QVector< Widget* > widgets, QString templ, QString macro, QString version)
 {
-  printf("Socket state: %d\n", socket.state());
-  if(socket.state() != 3) printf("Socket state not connected: %s\n", socket.errorString().toStdString().c_str());
-
-  //  if(qApp->activeWindow()) qApp->activeWindow()->setEnabled(false); // Moved down!
-
   QDomDocument doc;
 
   QDomProcessingInstruction header = doc.createProcessingInstruction("xml", "version='1.0' encoding='UTF-8'");
@@ -139,22 +129,20 @@ void NetCom::send(QVector< Widget* > widgets, QString templ, QString macro, QStr
 
   printf("\nSending commit:\n%s", doc.toString().toStdString().c_str());
 
-  socket.write(doc.toByteArray());
-  //  socket.waitForReadyRead();
+  http.post("/", doc.toByteArray());
 
-  //
-  // Wait for the (hopefully) empty answer.
-  //
+  transfering = true;
+  buffer = "";
   do {
     qApp->processEvents(QEventLoop::WaitForMoreEvents);
-  } while(!res_doc.setContent(buffer));
-
-  buffer = "";
-
-  //QDomElement elem = res_doc.documentElement();
-
-  printf("\nRecieved commit:\n%s", res_doc.toString().toStdString().c_str());
+  } while(transfering);
 
   QApplication::restoreOverrideCursor();
   if(qApp->activeWindow()) qApp->activeWindow()->setEnabled(true);
 }
+
+void NetCom::done(bool)
+{
+  buffer = http.readAll();
+  transfering = false;
+}
diff --git a/client/netcom.h b/client/netcom.h
index 35db221..e11509b 100644
--- a/client/netcom.h
+++ b/client/netcom.h
@@ -31,6 +31,7 @@
 #include <QString>
 #include <QTcpSocket>
 #include <QDomDocument>
+#include <QHttp>
 
 //#include "widgets/widget.h"
 class Widget;
@@ -45,17 +46,17 @@ public:
   void send(QVector< Widget* > widgets, QString templ, QString macro, QString version);
 
 public slots:
-  void readyRead();
+  void done(bool);
 
 private:
-  volatile bool transmitting;
-  QTcpSocket socket;
-
-  QByteArray buffer;
-  QDomDocument res_doc;
+  volatile bool transfering;
 
   QString user;
   QString cpr;
+
+  QHttp http;
+
+  QByteArray buffer;
 };
 
 #endif/*__PRACRO_NETCOM_H__*/
diff --git a/server/src/server.cc b/server/src/server.cc
index f2be8a4..9d3caba 100644
--- a/server/src/server.cc
+++ b/server/src/server.cc
@@ -36,6 +36,8 @@
 #include <unistd.h>
 #include <string.h>
 
+#include <microhttpd.h>
+
 #include "configuration.h"
 #include "transaction.h"
 #include "transactionparser.h"
@@ -294,8 +296,11 @@ static std::string handleTransaction(Transaction *transaction,
 }
 
 
-static void handleConnection(TCPSocket *socket)
+static std::string handleConnection(char *buf, size_t size)
 {
+  if(size == 0) 
+    return error_box(xml_encode("Empty document received."));
+
   TCPSocket pentominos_socket;
 #ifndef WITHOUT_PENTOMINOS
   pentominos_socket.connect(Conf::pentominos_addr, Conf::pentominos_port);
@@ -308,63 +313,75 @@ static void handleConnection(TCPSocket *socket)
   MacroList macrolist(Conf::xml_basedir + "/macros");
   TemplateList templatelist(Conf::xml_basedir + "/templates");
 
-  ssize_t size;
-  char buf[4096];
+  Transaction transaction;
+  TransactionParser parser(&transaction);
   
-  Transaction *transaction = NULL;
-  TransactionParser *parser = NULL;
-  
-  //  while( (size = socket->read(buf, sizeof(buf))) != -1) {
-  while( (size = socket->read(buf, sizeof(buf))) > 0) {
+  PRACRO_DEBUG(server, "Read %d bytes from network\n", size);
 
-    PRACRO_DEBUG(server, "Read %d bytes from network\n", size);
-   
-    while(size) {
+  if(parser.parse(buf, size)) {
+    PRACRO_DEBUG(server, "Got complete XML document, %d bytes in current buffer.\n", size);
 
-      if(transaction == NULL) {
-        transaction = new Transaction();
-      }
+    std::string res = handleTransaction(&transaction, pentominos_socket,
+                                        db, journalwriter, macrolist, templatelist);
+    journalwriter.commit();
 
-      if(parser == NULL) {
-        parser = new TransactionParser(transaction);
-      }
+    return res;
+  }
+
+  PRACRO_ERR(server, "Failed to parse data!\n");
+  return error_box(xml_encode("XML Parse error."));
+}
 
-      PRACRO_DEBUG(server, "Got %d bytes in read loop\n", size);
-      if(parser->parse(buf, size)) {
-        PRACRO_DEBUG(server, "Got complete XML document %d bytes used, %d bytes in current buffer.\n", parser->usedBytes(), size);
+static int handle_request(void *cls,
+                          struct MHD_Connection *con,
+                          const char *url,
+                          const char *method,
+                          const char *version,
+                          const char *data,
+                          unsigned int *data_size,
+                          void **ptr)
+{
+  PRACRO_DEBUG(httpd, "handle_request(url=\"%s\", method=\"%s\", version=\"%s\", data_size=\"%d\")\n",
+              url, method, version, *data_size);
 
-        socket->write(handleTransaction(transaction, pentominos_socket,
-                                        db, journalwriter, macrolist, templatelist));
-        size = size - parser->usedBytes();
-        if(size) {
-          strcpy(buf, buf + parser->usedBytes());
-          PRACRO_DEBUG(server, "Replaying %d bytes.\n", size);
-        }
+  std::string reply = handleConnection((char*)data, *data_size);
+  
+  struct MHD_Response *rsp;
+  rsp = MHD_create_response_from_data(reply.length(), (char*)reply.c_str(), MHD_NO, MHD_YES);
+  MHD_add_response_header(rsp, MHD_HTTP_HEADER_CONTENT_TYPE, "text/plain; charset=UTF-8");
+  int ret = MHD_queue_response(con, MHD_HTTP_OK, rsp);
+  MHD_destroy_response(rsp);
         
-        delete transaction; transaction = NULL;
-        delete parser; parser = NULL;
-      } else {
-        size = 0;
-        memset(buf, 0, sizeof(buf));
-      }
-    }
-  }
+  return ret;
+}
 
-  if(transaction) {
-    delete transaction;
-    transaction = NULL;
-  }
+extern bool pracro_is_running;
+void server()
+{
+  port_t port = Conf::server_port;
 
-  if(parser) {
-    delete parser;
-    parser = NULL;
-  }
+  PRACRO_DEBUG(server, "Server running on port %d.\n", port);
+
+  struct MHD_Daemon *d;
+  d = MHD_start_daemon(MHD_USE_DEBUG |  MHD_USE_SELECT_INTERNALLY,
+                       port,
+                       NULL, NULL,
+                       handle_request, NULL,
+                       MHD_OPTION_NOTIFY_COMPLETED, NULL, NULL,
+                       // MHD_OPTION_CONNECTION_LIMIT, 42,
+                       MHD_OPTION_CONNECTION_TIMEOUT, 0,
+                       MHD_OPTION_EXTERNAL_LOGGER, NULL, NULL,
+                       MHD_OPTION_END);
+
+  while(pracro_is_running) sleep(1);
 
-  journalwriter.commit();
+  MHD_stop_daemon(d);
 
-  PRACRO_DEBUG(server, "Out of read loop!\n");
+  PRACRO_DEBUG(server, "Server gracefully shut down.\n");
 }
 
+
+#if 0
 //#define NON_FORKING
 #include <sys/socket.h>
 extern bool pracro_is_running;
@@ -428,7 +445,7 @@ void server()
 
   PRACRO_DEBUG(server, "Server gracefully shut down.\n");
 }
-
+#endif//0
 
 #ifdef TEST_SERVER
 
-- 
cgit v1.2.3