/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /*************************************************************************** * server.cc * * Wed Aug 22 12:16:03 CEST 2007 * Copyright 2007 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 "server.h" #include "tcpsocket.h" #include <errno.h> #include <stdlib.h> // For fork #include <sys/types.h> #include <unistd.h> #include "configuration.h" #include "transaction.h" #include "transactionparser.h" #include "templateparser.h" #include "macroparser.h" #include "queryhandler.h" #include "queryparser.h" #include "luaquerymapper.h" #include "database.h" #include "widgetgenerator.h" #include "resumeparser.h" #include "journal_commit.h" #include "xml_encode_decode.h" static std::string error_box(std::string message) { std::string errorbox = " <course name=\"error\">\n" " <macro name=\"error\">\n" " <window caption=\"ERROR!\" height=\"240\" layout=\"vbox\" name=\"error\" width=\"320\">\n" " <textedit name=\"errorlabel\" value=\"" + message + "\"/>\n" " <button action=\"cancel\" caption=\"Luk\" name=\"cancel\"/>\n" " </window>\n" " </macro>\n" " </course>\n"; return errorbox; } static void connection(TCPSocket &socket) { socket.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); socket.write("<pracro version=\"1.0\">\n"); try { Transaction transaction; TransactionParser parser(socket, transaction); parser.parse(); Database db; // // Handle commits // if(transaction.commits.size() > 0) { Commits::iterator i = transaction.commits.begin(); while(i != transaction.commits.end()) { Commit &commit = *i; /* Macro macro; MacroParser parser(commit.macro, macro); parser.parse(); */ Macro macro; macro.attributes["name"] = commit.macro; macro.attributes["version"] = "1.0";//commit.version; db.commit(transaction.user, transaction.cpr, macro, commit.fields); /* std::string resume = resume_parser(macro.format.c_str(), commit); std::string journal_commit_addr = config()->lookup("journal_commit_addr"); int journal_commit_port = config()->lookup("journal_commit_port"); journal_commit(transaction.cpr.c_str(), transaction.user.c_str(), journal_commit_addr.c_str(), journal_commit_port, resume.c_str(), resume.length()); */ i++; } } // // Handle requests // Requests::iterator i = transaction.requests.begin(); while(i != transaction.requests.end()) { Request &request = *i; std::string answer; MacroParser mp(request.macro); mp.parse(); Macro *m = mp.getMacro(); printf("Handling request - macro: %s, course: %s\n", request.macro.c_str(), request.course.c_str()); // Read and parse the template file. TemplateParser tp(request.course); tp.parse(); Template *templ = tp.getTemplate(); // Send the queries to Pentominos (if any) TCPSocket s; s.connect("localhost", 11108); QueryHandler qh(&s, transaction.cpr); std::vector< Macro >::iterator mi = templ->course.macroes.begin(); while(mi != templ->course.macroes.end()) { Macro ¯o = (*mi); if(macro.attributes["name"] == request.macro) { std::vector< Query >::iterator qi = m->queries.begin(); while(qi != m->queries.end()) { qh.addQuery(*qi); qi++; } } mi++; } std::string result = qh.exec(); printf("Got result: [%s]\n", result.c_str()); // Parse the result from the queries to pentominos QueryParser qp(result); qp.parse(); // Map the results LUAQueryMapper lqm(qp.result); answer += " <course name=\""; answer += templ->course.attributes["name"]; answer += "\">\n"; // Generate the macro and return it to the client std::vector< Macro >::iterator mi2 = templ->course.macroes.begin(); while(mi2 != templ->course.macroes.end()) { Macro ¯o = (*mi2); answer += " <macro name=\"" + macro.attributes["name"] + "\" completed="; if(db.checkMacro(transaction.cpr, macro.attributes["name"])) answer += "\"true\""; else answer += "\"false\""; answer += ">\n"; if(macro.attributes["name"] == request.macro) { // Handle lua programs if(m->luaprograms.size()) { answer += " <luaprograms>\n"; std::vector< LUAProgram >::iterator lpi = m->luaprograms.begin(); while(lpi != m->luaprograms.end()) { answer += " <luaprogram name=\"" + lpi->attributes["name"] + "\">\n"; answer += xml_encode(lpi->attributes["lua"]); answer += "\n </luaprogram>\n"; lpi++; } answer += " </luaprograms>\n"; } answer += widgetgenerator(*m, lqm, db); } answer += " </macro>\n"; mi2++; } answer += " </course>\n"; socket.write(answer); i++; } } catch(std::exception &e) { socket.write(error_box(xml_encode(e.what()))); } socket.write("</pracro>\n"); } void server() { int port; try { port = config()->lookup("port"); } catch( ... ) { fprintf(stderr, "Could not read port."); return; } TCPSocket *socket = NULL; try { socket = new TCPSocket(); socket->listen(port); } catch (Exception &e) { fprintf(stderr, "Error during parsing:\n%s\n", e.what()); delete socket; socket = NULL; return; } while(socket->connected()) { { // Reload if new port is assigned. int old_port = port; try { port = config()->lookup("port"); } catch( ... ) { fprintf(stderr, "Could not read port."); return; } if(port != old_port) { // Start listening on the new port delete socket; socket = new TCPSocket(); socket->listen(port); } } TCPSocket child = socket->accept(); if(child.connected()) { //socket->disconnect(); connection(child); //delete socket; /* switch(fork()) { case -1: // error fprintf(stderr, "Could not fork: %s\n", strerror(errno)); break; case 0: // child socket->disconnect(); connection(child); delete socket; return; default: // parent child.disconnect(); break; } */ } } delete socket; fprintf(stderr, "Oups... dropped out of the main loop\n"); } #ifdef TEST_SERVER char request[] = "<?xml version='1.0' encoding='UTF-8'?>\n" "<pracro cpr=\"2003791613\" version=\"1.0\">\n" " <request macro=\"example\" course=\"example\"/>\n" "</pracro>\n"; int main() { Configuration conf("../etc/pracrod.conf"); initConfig(&conf); switch(fork()) { case -1: // error return 1; case 0: // child server(); return 0; default: // parent { TCPSocket socket; int port = config()->lookup("port"); socket.connect("localhost", port); socket.write(request); char buf[32]; memset(buf, 0, sizeof(buf)); while(socket.read(buf, 31)) { printf(buf); fflush(stdout); memset(buf, 0, sizeof(buf)); } } return 0; } return 1; } #endif/*TEST_SERVER*/