summaryrefslogtreecommitdiff
path: root/rotord/src/rotord.cpp
diff options
context:
space:
mode:
authorComment <tim@gray.(none)>2013-07-26 22:46:17 +0100
committerComment <tim@gray.(none)>2013-07-26 22:46:17 +0100
commitf4170d6bfb763ad0af4002277a37dcd1692534d5 (patch)
treedb32d9753de780063e3afeb64764e13e5c4f5087 /rotord/src/rotord.cpp
parent3d7eea02aa7a155b84c8c74ecbfd55a1941a9297 (diff)
tidy files
Diffstat (limited to 'rotord/src/rotord.cpp')
-rwxr-xr-xrotord/src/rotord.cpp230
1 files changed, 230 insertions, 0 deletions
diff --git a/rotord/src/rotord.cpp b/rotord/src/rotord.cpp
new file mode 100755
index 0000000..6f2d765
--- /dev/null
+++ b/rotord/src/rotord.cpp
@@ -0,0 +1,230 @@
+#include "rotord.h"
+
+RenderContextHandler::RenderContextHandler(const std::string _content,const HTTPServerResponse::HTTPStatus _status){
+ content=_content;
+ status=_status;
+}
+
+
+void RenderContextHandler::handleRequest(HTTPServerRequest& request,HTTPServerResponse& response) {
+
+ response.setChunkedTransferEncoding(true);
+ response.setContentType("text/html");
+ response.setStatus(status);
+
+ std::ostream& ostr = response.send();
+
+ ostr << "<?xml version='1.0' encoding='ISO-8859-1'?>\n"; //this is the mysterious extra header
+ ostr << content;
+
+}
+
+
+HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request){
+
+
+ Poco::URI theuri=Poco::URI(request.getURI());
+ std::vector <std::string> command;
+ theuri.getPathSegments(command);
+
+ Logger& logger = Logger::get("Rotor");
+ logger.information(request.clientAddress().toString()+" "+request.getMethod());
+
+ HTTPResponse::HTTPStatus status=HTTPResponse::HTTP_BAD_REQUEST; //by default
+
+ std::string body;
+ std::ostringstream os;
+ os<<request.stream().rdbuf();
+ body=os.str();
+
+ xmlIO XML; //xml object handles the servers responses
+ XML.addTag("rotor");
+
+ //can we create a tinyxml object here and pass a pointer to it to the render context?
+ //can tinyxml output to a string? is there any reason to use poco instead?
+
+ if (command.size()) {
+ if (command[0]=="new") {
+ XML.pushTag("rotor");
+ if (request.getMethod()=="GET") {
+ string sID=idGen.createOne().toString(); //create() seems to cause problems
+ //Creates a new time-based UUID, using the MAC address of one of the system's ethernet adapters.
+ //Throws a SystemException if no MAC address can be obtained.
+ //
+ //seems to hang, to me
+ logger.information("starting thread "+sID);
+ manager.start(new Rotor::Render_context(sID));
+ //XML.addTag("sID");
+ XML.addValue("sID",sID);
+ status=HTTPResponse::HTTP_OK;
+ }
+ if (request.getMethod()=="PUT") { //unofficial manual thread name
+ if (body.size()) {
+ string sID=body;
+ bool found=false;
+ for (auto& task: manager.taskList()) {
+ if(task->name()==sID) {
+ logger.error("ERROR: tried to create thread with existing name "+sID);
+ XML.addValue("error","Render context /"+sID+"/ exists already");
+ found=true;
+ }
+ }
+ if (!found){
+ logger.information("starting thread "+sID);
+ manager.start(new Rotor::Render_context(sID));
+ XML.addValue("sID",sID);
+ status=HTTPResponse::HTTP_OK;
+ }
+ }
+ }
+ }
+ else if (command[0]=="list") {
+ XML.pushTag("rotor");
+ if (request.getMethod()=="GET") {
+ logger.information("sending tasklist");
+ //std::list < Poco::AutoPtr < Poco::Task > >::iterator it;
+ //it=manager.taskList().begin();
+ //for (it=manager.taskList().begin();it !=manager.taskList().end();++it) {
+ //content+="<sID>"+(*it)->name()+"</sID>\n";
+ //}
+
+ //massive problems making an iterator for the tasklist, the above crashes
+ //solution: auto type range-based for-loop
+ //this is c++11 specific but works
+
+ for (auto& task: manager.taskList()) { //c++11
+ XML.addValue("sID",task->name());
+ }
+ status=HTTPResponse::HTTP_OK;
+ }
+ }
+ else if (command[0]=="exit") {
+ logger.information("exiting");
+ exit(0);
+ }
+ else {
+ bool found=false;
+ for (auto& task: manager.taskList()) { //c++11
+ if(task->name()==command[0]) {
+ //valid session command
+ found=true;
+ XML.addAttribute("rotor","context",task->name(),0);
+ XML.pushTag("rotor");
+ if (command.size()==1) {
+ //just invoking sID
+ if (request.getMethod()=="DELETE") {
+ task->cancel();
+ status=HTTPResponse::HTTP_OK;
+ logger.information("deleted context "+command[0]);
+ XML.addValue("status","context deleted successfully");
+ }
+ else {
+ logger.error("ERROR: Render context invoked with no command: "+command[0]);
+ XML.addValue("error","Render context invoked with no command");
+ }
+ }
+ else { //session modifier command- to be passed to render context
+ //some commands need to return error codes
+ //ie where the audio file isn't found
+ //on the other hand, some commands need to know state of the renderer?
+
+
+ vector<string> sc; //method,id,command1,{command2,}{body}
+ sc.push_back(request.getMethod());
+ for (auto& i: command){
+ sc.push_back(i);
+ }
+ sc.push_back(body);
+
+ ((Poco::AutoPtr<Rotor::Render_context>)task)->session_command(sc,XML,status);
+
+ }
+ }
+ }
+ if (!found) {
+ status=HTTPResponse::HTTP_NOT_FOUND;
+ logger.error("ERROR: context not found: "+command[0]);
+ XML.pushTag("rotor");
+ XML.addValue("error","Render context not found");
+ }
+ }
+ }
+ else {
+ logger.error("ERROR: Empty request");
+ XML.addValue("error","Empty request");
+ }
+ string content;
+ XML.copyXmlToString(content);
+ return new RenderContextHandler(content, status);
+}
+
+
+RotorServer::RotorServer(): _helpRequested(false)
+{
+}
+
+RotorServer::~RotorServer()
+{
+}
+
+void RotorServer::initialize(Application& self){
+ loadConfiguration();
+ ServerApplication::initialize(self);
+}
+
+void RotorServer::uninitialize(){
+ ServerApplication::uninitialize();
+}
+
+void RotorServer::defineOptions(OptionSet& options) {
+ ServerApplication::defineOptions(options);
+ options.addOption(
+ Option("help", "h", "display argument help information")
+ .required(false)
+ .repeatable(false)
+ .callback(OptionCallback<RotorServer>(this, &RotorServer::handleHelp)
+ )
+ );
+}
+
+void RotorServer::handleHelp(const std::string& name, const std::string& value){
+ HelpFormatter helpFormatter(options());
+ helpFormatter.setCommand(commandName());
+ helpFormatter.setUsage("OPTIONS");
+ helpFormatter.setHeader(
+ "Rotor");
+ helpFormatter.format(std::cout);
+ stopOptionsProcessing();
+ _helpRequested = true;
+}
+
+int RotorServer::main(const std::vector<std::string>& args){
+ if (!_helpRequested) {
+
+ unsigned short port;
+
+ Logger& logger = Logger::get("Rotor");
+
+ xmlIO xml;
+ if(xml.loadFile("settings.xml") ){
+ port=xml.getAttribute("Rotor","port",9000,0);
+ }
+ else logger.information("settings.xml not found, using defaults");
+
+ logger.information("rotord running on port "+ofToString(port));
+
+ port = (unsigned short) config().getInt("port", port); //override from command line
+
+ std::string format(config().getString("format", DateTimeFormat::SORTABLE_FORMAT));
+
+
+
+ ServerSocket svs(port);
+ HTTPServer srv(new RotorRequestHandlerFactory(),svs, new HTTPServerParams);
+ srv.start();
+ waitForTerminationRequest();
+ srv.stop();
+ }
+ return Application::EXIT_OK;
+}
+ \ No newline at end of file