summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/ioprocessor
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml/plugins/ioprocessor')
-rw-r--r--src/uscxml/plugins/ioprocessor/CMakeLists.txt25
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp230
-rw-r--r--src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h23
-rw-r--r--src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.cpp329
-rw-r--r--src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h116
5 files changed, 474 insertions, 249 deletions
diff --git a/src/uscxml/plugins/ioprocessor/CMakeLists.txt b/src/uscxml/plugins/ioprocessor/CMakeLists.txt
index fb4315b..0ba56eb 100644
--- a/src/uscxml/plugins/ioprocessor/CMakeLists.txt
+++ b/src/uscxml/plugins/ioprocessor/CMakeLists.txt
@@ -26,6 +26,7 @@ if (WITH_IOPROC_BASICHTTP)
set(USCXML_IOPROCESSORS "basichttp ${USCXML_IOPROCESSORS}")
file(GLOB_RECURSE BASICHTTP_IOPROCESSOR
basichttp/*.cpp
+ http/*.cpp
basichttp/*.h
)
if (BUILD_AS_PLUGINS)
@@ -42,6 +43,30 @@ if (WITH_IOPROC_BASICHTTP)
endif()
endif()
+
+OPTION(WITH_IOPROC_HTTP "Build the http i/o processor" ON)
+if (WITH_IOPROC_HTTP)
+ SET(WITH_IOPROC_HTTP_TIMEOUT 10)
+ set(USCXML_IOPROCESSORS "http ${USCXML_IOPROCESSORS}")
+ file(GLOB_RECURSE HTTP_IOPROCESSOR
+ http/*.cpp
+ http/*.h
+ )
+ if (BUILD_AS_PLUGINS)
+ source_group("" FILES ${HTTP_IOPROCESSOR})
+ add_library(ioproc_http SHARED ${HTTP_IOPROCESSOR} "../Plugins.cpp")
+ target_link_libraries(ioproc_http
+ uscxml
+ )
+ set_target_properties(ioproc_http PROPERTIES FOLDER "Plugins//IO Processors")
+ set_target_properties(ioproc_http PROPERTIES COMPILE_FLAGS "-DPLUMA_EXPORTS")
+ set_target_properties(ioproc_http PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib/plugins")
+ else()
+ list (APPEND USCXML_FILES ${HTTP_IOPROCESSOR})
+ endif()
+endif()
+
+set(WITH_IOPROC_HTTP_TIMEOUT ${WITH_IOPROC_HTTP_TIMEOUT} PARENT_SCOPE)
set(USCXML_INCLUDE_DIRS ${USCXML_INCLUDE_DIRS} PARENT_SCOPE)
set(USCXML_OPT_LIBS ${USCXML_OPT_LIBS} PARENT_SCOPE)
set(USCXML_FILES ${USCXML_FILES} PARENT_SCOPE)
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
index 2f8f0aa..8f3d03e 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.cpp
@@ -23,10 +23,6 @@
#include "uscxml/messages/Event.h"
#include "uscxml/util/DOM.h"
-#include <event2/dns.h>
-#include <event2/buffer.h>
-#include <event2/keyvalq_struct.h>
-
#include <string.h>
#include "uscxml/interpreter/Logging.h"
@@ -62,12 +58,9 @@ bool pluginConnect(pluma::Host& host) {
// see http://www.w3.org/TR/scxml/#BasicHTTPEventProcessor
BasicHTTPIOProcessor::BasicHTTPIOProcessor() {
- HTTPServer::getInstance();
}
BasicHTTPIOProcessor::~BasicHTTPIOProcessor() {
- HTTPServer* httpServer = HTTPServer::getInstance();
- httpServer->unregisterServlet(this);
}
@@ -87,231 +80,12 @@ std::shared_ptr<IOProcessorImpl> BasicHTTPIOProcessor::create(IOProcessorCallbac
return io;
}
-Data BasicHTTPIOProcessor::getDataModelVariables() {
- Data data;
-
- // we are not connected!
- if(_url.length() == 0)
- return data;
-
- data.compound["location"] = Data(_url, Data::VERBATIM);
-
- URL url(_url);
- data.compound["host"] = Data(url.host(), Data::VERBATIM);
- data.compound["port"] = Data(url.port(), Data::VERBATIM);
- data.compound["path"] = Data(url.path(), Data::VERBATIM);
- data.compound["scheme"] = Data(url.scheme(), Data::VERBATIM);
-
- std::list<std::string> pathComps = url.pathComponents();
- std::list<std::string>::const_iterator pathCompIter = pathComps.begin();
- while(pathCompIter != pathComps.end()) {
- data.compound["pathComponents"].array.push_back(Data(*pathCompIter, Data::VERBATIM));
- pathCompIter++;
- }
-
- return data;
-}
-
bool BasicHTTPIOProcessor::requestFromHTTP(const HTTPServer::Request& req) {
- Event event = req;
- event.eventType = Event::EXTERNAL;
-
-// std::cout << req.raw << std::endl;
-
- /**
- * If a single instance of the parameter '_scxmleventname' is present, the
- * SCXML Processor must use its value as the name of the SCXML event that it
- * raises.
- */
-
- {
- // if we sent ourself an event it will end up here
- // this will call the const subscript operator
- if (req.data.at("content").hasKey("_scxmleventname")) {
- event.name = req.data.at("content").at("_scxmleventname").atom;
- }
- if (req.data.at("content").hasKey("content")) {
- event.data.atom = req.data.at("content").at("content").atom;
- }
- }
-
- // if we used wget, it will end up here - unify?
- if (req.data.hasKey("content")) {
- const Data& data = req.data["content"];
- for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin();
- compIter!= data.compound.end(); compIter++) {
- if (compIter->first == "content") {
- event.data.atom = compIter->second.atom;
- } else {
- event.data[compIter->first] = compIter->second;
- }
- }
- }
-
- if (req.data.hasKey("header")) {
- const Data& data = req.data["header"];
- for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin();
- compIter!= data.compound.end(); compIter++) {
- if (compIter->first == "_scxmleventname") {
- event.name = compIter->second.atom;
- }
- }
- }
-
- // test 532
- if (event.name.length() == 0)
- event.name = "http." + req.data.compound.at("type").atom;
-
- eventToSCXML(event, USCXML_IOPROC_BASICHTTP_TYPE, _url);
+ HTTPIOProcessor::requestFromHTTP(req);
evhttp_send_reply(req.evhttpReq, 200, "OK", NULL);
+ getUnansweredRequests().erase(req.getUUID());
return true;
}
-bool BasicHTTPIOProcessor::isValidTarget(const std::string& target) {
- try {
- URL url(target);
- if (url.scheme().compare("http") != 0)
- return false;
-
- return true;
- } catch (ErrorEvent e) {
- }
- return false;
-}
-
-void BasicHTTPIOProcessor::eventFromSCXML(const std::string& target, const Event& event) {
-
- // TODO: is this still needed with isValidTarget()?
- if (target.length() == 0) {
- _callbacks->enqueueInternal(Event("error.communication", Event::PLATFORM));
- return;
- }
-
- bool isLocal = target == _url;
- URL targetURL(target);
- std::stringstream kvps;
- std::string kvpSeperator;
-
- // event name
- if (event.name.size() > 0) {
- char* eventNameCStr = evhttp_encode_uri("_scxmleventname");
- char* eventValueCStr = evhttp_encode_uri(event.name.c_str());
- kvps << kvpSeperator << eventNameCStr << "=" << eventValueCStr;
- kvpSeperator = "&";
- targetURL.addOutHeader("_scxmleventname", eventValueCStr);
- free(eventNameCStr);
- free(eventValueCStr);
- }
-
- // event namelist
- if (event.namelist.size() > 0) {
- std::map<std::string, Data>::const_iterator namelistIter = event.namelist.begin();
- while (namelistIter != event.namelist.end()) {
- char* keyCStr = evhttp_encode_uri(namelistIter->first.c_str());
- // this is simplified - Data might be more elaborate than a simple string atom
- char* valueCStr = evhttp_encode_uri(namelistIter->second.atom.c_str());
- kvps << kvpSeperator << keyCStr << "=" << valueCStr;
- free(keyCStr);
- free(valueCStr);
- kvpSeperator = "&";
- targetURL.addOutHeader(namelistIter->first, namelistIter->second);
- namelistIter++;
- }
- }
-
- // event params
- if (event.params.size() > 0) {
- std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin();
- while (paramIter != event.params.end()) {
- char* keyCStr = evhttp_encode_uri(paramIter->first.c_str());
- // this is simplified - Data might be more elaborate than a simple string atom
- char* valueCStr = evhttp_encode_uri(paramIter->second.atom.c_str());
- kvps << kvpSeperator << keyCStr << "=" << valueCStr;
- free(keyCStr);
- free(valueCStr);
- kvpSeperator = "&";
- targetURL.addOutHeader(paramIter->first, paramIter->second);
- paramIter++;
- }
- }
-
- // try hard to find actual content
- char* keyCStr = evhttp_encode_uri("content");
- if (!event.data.empty()) {
- char* valueCStr = NULL;
- if (event.data.atom.length() || event.data.array.size() || event.data.compound.size()) {
- valueCStr = evhttp_encode_uri(Data::toJSON(event.data).c_str());
- } else if(event.data.node) {
- std::stringstream xmlStream;
- xmlStream << event.data.node;
- valueCStr = evhttp_encode_uri(xmlStream.str().c_str());
- } else if(event.data.binary) {
- valueCStr = evhttp_encode_uri(event.data.binary.base64().c_str());
- }
- if (valueCStr != NULL) {
- kvps << kvpSeperator << keyCStr << "=" << valueCStr;
- free(valueCStr);
- kvpSeperator = "&";
- }
- }
- free(keyCStr);
-
- targetURL.setOutContent(kvps.str());
- targetURL.addOutHeader("Content-Type", "application/x-www-form-urlencoded");
-
- targetURL.setRequestType(URLRequestType::POST);
- targetURL.addMonitor(this);
-
- _sendRequests[event.sendid] = std::make_pair(targetURL, event);
- if (isLocal) {
- // test201 use a blocking request with local communication
- targetURL.download(true);
- } else {
- URLFetcher::fetchURL(targetURL);
- }
-}
-
-void BasicHTTPIOProcessor::downloadStarted(const URL& url) {}
-
-void BasicHTTPIOProcessor::downloadCompleted(const URL& url) {
- std::map<std::string, std::pair<URL, Event> >::iterator reqIter = _sendRequests.begin();
- while(reqIter != _sendRequests.end()) {
- if (reqIter->second.first == url) {
- // test513
- std::string statusCode = url.getStatusCode();
- if (statusCode.length() > 0) {
- std::string statusPrefix = statusCode.substr(0,1);
- std::string statusRest = statusCode.substr(1);
- Event event;
- event.data = url;
- event.name = "HTTP." + statusPrefix + "." + statusRest;
- eventToSCXML(event, USCXML_IOPROC_BASICHTTP_TYPE, std::string(_url));
- }
- _sendRequests.erase(reqIter);
- return;
- }
- reqIter++;
- }
- assert(false);
-}
-
-void BasicHTTPIOProcessor::downloadFailed(const URL& url, int errorCode) {
-
- std::map<std::string, std::pair<URL, Event> >::iterator reqIter = _sendRequests.begin();
- while(reqIter != _sendRequests.end()) {
- if (reqIter->second.first == url) {
- Event failEvent;
- failEvent.name = "error.communication";
- eventToSCXML(failEvent, USCXML_IOPROC_BASICHTTP_TYPE, std::string(_url));
-
- _sendRequests.erase(reqIter);
- return;
- }
- reqIter++;
- }
- assert(false);
-
-}
-
}
diff --git a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h
index bf64111..fb9ed3e 100644
--- a/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h
+++ b/src/uscxml/plugins/ioprocessor/basichttp/BasicHTTPIOProcessor.h
@@ -42,6 +42,7 @@ extern "C" {
#include "uscxml/server/HTTPServer.h"
#include "uscxml/interpreter/InterpreterImpl.h"
#include "uscxml/plugins/IOProcessorImpl.h"
+#include "uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h"
#ifndef _WIN32
#include <sys/time.h>
@@ -59,7 +60,7 @@ namespace uscxml {
* @ingroup ioproc
* The basichttp I/O processor as per standard.
*/
-class USCXML_PLUGIN_API BasicHTTPIOProcessor : public IOProcessorImpl, public HTTPServlet, public URLMonitor {
+class USCXML_PLUGIN_API BasicHTTPIOProcessor : public HTTPIOProcessor {
public:
BasicHTTPIOProcessor();
virtual ~BasicHTTPIOProcessor();
@@ -72,29 +73,9 @@ public:
return names;
}
- virtual void eventFromSCXML(const std::string& target, const Event& event);
- virtual bool isValidTarget(const std::string& target);
-
- Data getDataModelVariables();
-
/// HTTPServlet
bool requestFromHTTP(const HTTPServer::Request& req);
- void setURL(const std::string& url) {
- _url = url;
- }
-
- bool canAdaptPath() {
- return false;
- }
-
- // URLMonitor
- void downloadStarted(const URL& url);
- void downloadCompleted(const URL& url);
- void downloadFailed(const URL& url, int errorCode);
-protected:
- std::string _url;
- std::map<std::string, std::pair<URL, Event> > _sendRequests;
};
#ifdef BUILD_AS_PLUGINS
diff --git a/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.cpp b/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.cpp
new file mode 100644
index 0000000..276fd4e
--- /dev/null
+++ b/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.cpp
@@ -0,0 +1,329 @@
+/**
+ * @file
+ * @author 2017 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#include "uscxml/Common.h"
+
+#include "uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h"
+#include "uscxml/messages/Event.h"
+#include "uscxml/util/DOM.h"
+
+#include <event2/dns.h>
+#include <event2/buffer.h>
+#include <event2/keyvalq_struct.h>
+
+#include <string.h>
+
+#include "uscxml/interpreter/Logging.h"
+#include <boost/algorithm/string.hpp>
+
+#ifdef _WIN32
+#define NOMINMAX
+#include <winsock2.h>
+#include <windows.h>
+#endif
+
+#ifndef _WIN32
+#include <netdb.h>
+#include <arpa/inet.h>
+#endif
+
+#ifdef BUILD_AS_PLUGINS
+#include <Pluma/Connector.hpp>
+#endif
+
+namespace uscxml {
+
+#ifndef ioprocessor_scxml_EXPORTS
+# ifdef BUILD_AS_PLUGINS
+PLUMA_CONNECTOR
+bool pluginConnect(pluma::Host& host) {
+ host.add( new HTTPIOProcessorProvider() );
+ return true;
+}
+# endif
+#endif
+
+HTTPIOProcessor::HTTPIOProcessor() {
+ HTTPServer::getInstance();
+}
+
+HTTPIOProcessor::~HTTPIOProcessor() {
+ HTTPServer* httpServer = HTTPServer::getInstance();
+ httpServer->unregisterServlet(this);
+}
+
+
+std::shared_ptr<IOProcessorImpl> HTTPIOProcessor::create(IOProcessorCallbacks* callbacks) {
+ std::shared_ptr<HTTPIOProcessor> io(new HTTPIOProcessor());
+ io->_callbacks = callbacks;
+
+ // register at http server
+ std::string path = callbacks->getName();
+ int i = 2;
+ while (!HTTPServer::registerServlet(path, io.get())) {
+ std::stringstream ss;
+ ss << callbacks->getName() << i++;
+ path = ss.str();
+ }
+
+ return io;
+}
+
+Data HTTPIOProcessor::getDataModelVariables() {
+ Data data;
+
+ // we are not connected!
+ if(_url.length() == 0)
+ return data;
+
+ data.compound["location"] = Data(_url, Data::VERBATIM);
+ data.compound["timeout"] = Data(_timeoutS, Data::INTERPRETED);
+
+ URL url(_url);
+ data.compound["host"] = Data(url.host(), Data::VERBATIM);
+ data.compound["port"] = Data(url.port(), Data::VERBATIM);
+ data.compound["path"] = Data(url.path(), Data::VERBATIM);
+ data.compound["scheme"] = Data(url.scheme(), Data::VERBATIM);
+
+ std::list<std::string> pathComps = url.pathComponents();
+ std::list<std::string>::const_iterator pathCompIter = pathComps.begin();
+ while(pathCompIter != pathComps.end()) {
+ data.compound["pathComponents"].array.push_back(Data(*pathCompIter, Data::VERBATIM));
+ pathCompIter++;
+ }
+
+ return data;
+}
+
+bool HTTPIOProcessor::requestFromHTTP(const HTTPServer::Request& req) {
+ Event event = req;
+ event.eventType = Event::EXTERNAL;
+
+ time_t now = std::time(0);
+ _unansweredRequests[req.getUUID()] = std::make_pair(now, req);
+
+ // remove stale requests
+ for (auto reqIter = _unansweredRequests.begin(); reqIter != _unansweredRequests.end();) {
+ if (now > reqIter->second.first + _timeoutS) {
+ evhttp_send_reply(reqIter->second.second.evhttpReq, 504, "Event was not responded to in time", NULL);
+ _unansweredRequests.erase(reqIter++);
+ } else {
+ ++reqIter;
+ }
+ }
+
+ /**
+ * If a single instance of the parameter '_scxmleventname' is present, the
+ * SCXML Processor must use its value as the name of the SCXML event that it
+ * raises.
+ */
+
+ {
+ // if we sent ourself an event it will end up here
+ // this will call the const subscript operator
+ if (req.data.at("content").hasKey("_scxmleventname")) {
+ event.name = req.data.at("content").at("_scxmleventname").atom;
+ }
+ if (req.data.at("content").hasKey("content")) {
+ event.data.atom = req.data.at("content").at("content").atom;
+ }
+ }
+
+ // if we used wget, it will end up here - unify?
+ if (req.data.hasKey("content")) {
+ const Data& data = req.data["content"];
+ for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin();
+ compIter!= data.compound.end(); compIter++) {
+ if (compIter->first == "content") {
+ event.data.atom = compIter->second.atom;
+ } else {
+ event.data[compIter->first] = compIter->second;
+ }
+ }
+ }
+
+ if (req.data.hasKey("header")) {
+ const Data& data = req.data["header"];
+ for(std::map<std::string, Data>::const_iterator compIter = data.compound.begin();
+ compIter!= data.compound.end(); compIter++) {
+ if (compIter->first == "_scxmleventname") {
+ event.name = compIter->second.atom;
+ }
+ }
+ }
+
+ // test 532
+ if (event.name.length() == 0)
+ event.name = "http." + req.data.compound.at("type").atom;
+
+ eventToSCXML(event, USCXML_IOPROC_HTTP_TYPE, req.getUUID());
+
+ // do not reply
+ // evhttp_send_reply(req.evhttpReq, 200, "OK", NULL);
+ return true;
+}
+
+bool HTTPIOProcessor::isValidTarget(const std::string& target) {
+ try {
+ URL url(target);
+ if (url.scheme().compare("http") != 0)
+ return false;
+
+ return true;
+ } catch (ErrorEvent e) {
+ }
+ return false;
+}
+
+void HTTPIOProcessor::eventFromSCXML(const std::string& target, const Event& event) {
+
+ // TODO: is this still needed with isValidTarget()?
+ if (target.length() == 0) {
+ _callbacks->enqueueInternal(Event("error.communication", Event::PLATFORM));
+ return;
+ }
+
+ bool isLocal = target == _url;
+ URL targetURL(target);
+ std::stringstream kvps;
+ std::string kvpSeperator;
+
+ // event name
+ if (event.name.size() > 0) {
+ char* eventNameCStr = evhttp_encode_uri("_scxmleventname");
+ char* eventValueCStr = evhttp_encode_uri(event.name.c_str());
+ kvps << kvpSeperator << eventNameCStr << "=" << eventValueCStr;
+ kvpSeperator = "&";
+ targetURL.addOutHeader("_scxmleventname", eventValueCStr);
+ free(eventNameCStr);
+ free(eventValueCStr);
+ }
+
+ // event namelist
+ if (event.namelist.size() > 0) {
+ std::map<std::string, Data>::const_iterator namelistIter = event.namelist.begin();
+ while (namelistIter != event.namelist.end()) {
+ char* keyCStr = evhttp_encode_uri(namelistIter->first.c_str());
+ // this is simplified - Data might be more elaborate than a simple string atom
+ char* valueCStr = evhttp_encode_uri(namelistIter->second.atom.c_str());
+ kvps << kvpSeperator << keyCStr << "=" << valueCStr;
+ free(keyCStr);
+ free(valueCStr);
+ kvpSeperator = "&";
+ targetURL.addOutHeader(namelistIter->first, namelistIter->second);
+ namelistIter++;
+ }
+ }
+
+ // event params
+ if (event.params.size() > 0) {
+ std::multimap<std::string, Data>::const_iterator paramIter = event.params.begin();
+ while (paramIter != event.params.end()) {
+ char* keyCStr = evhttp_encode_uri(paramIter->first.c_str());
+ // this is simplified - Data might be more elaborate than a simple string atom
+ char* valueCStr = evhttp_encode_uri(paramIter->second.atom.c_str());
+ kvps << kvpSeperator << keyCStr << "=" << valueCStr;
+ free(keyCStr);
+ free(valueCStr);
+ kvpSeperator = "&";
+ targetURL.addOutHeader(paramIter->first, paramIter->second);
+ paramIter++;
+ }
+ }
+
+ // try hard to find actual content
+ char* keyCStr = evhttp_encode_uri("content");
+ if (!event.data.empty()) {
+ char* valueCStr = NULL;
+ if (event.data.atom.length() || event.data.array.size() || event.data.compound.size()) {
+ valueCStr = evhttp_encode_uri(Data::toJSON(event.data).c_str());
+ } else if(event.data.node) {
+ std::stringstream xmlStream;
+ xmlStream << event.data.node;
+ valueCStr = evhttp_encode_uri(xmlStream.str().c_str());
+ } else if(event.data.binary) {
+ valueCStr = evhttp_encode_uri(event.data.binary.base64().c_str());
+ }
+ if (valueCStr != NULL) {
+ kvps << kvpSeperator << keyCStr << "=" << valueCStr;
+ free(valueCStr);
+ kvpSeperator = "&";
+ }
+ }
+ free(keyCStr);
+
+ targetURL.setOutContent(kvps.str());
+ targetURL.addOutHeader("Content-Type", "application/x-www-form-urlencoded");
+
+ targetURL.setRequestType(URLRequestType::POST);
+ targetURL.addMonitor(this);
+
+ _sendRequests[event.sendid] = std::make_pair(targetURL, event);
+ if (isLocal) {
+ // test201 use a blocking request with local communication
+ targetURL.download(true);
+ } else {
+ URLFetcher::fetchURL(targetURL);
+ }
+}
+
+void HTTPIOProcessor::downloadStarted(const URL& url) {}
+
+void HTTPIOProcessor::downloadCompleted(const URL& url) {
+ std::map<std::string, std::pair<URL, Event> >::iterator reqIter = _sendRequests.begin();
+ while(reqIter != _sendRequests.end()) {
+ if (reqIter->second.first == url) {
+ // test513
+ std::string statusCode = url.getStatusCode();
+ if (statusCode.length() > 0) {
+ std::string statusPrefix = statusCode.substr(0,1);
+ std::string statusRest = statusCode.substr(1);
+ Event event;
+ event.data = url;
+ event.name = "HTTP." + statusPrefix + "." + statusRest;
+ eventToSCXML(event, USCXML_IOPROC_HTTP_TYPE, std::string(_url));
+ }
+ _sendRequests.erase(reqIter);
+ return;
+ }
+ reqIter++;
+ }
+ assert(false);
+}
+
+void HTTPIOProcessor::downloadFailed(const URL& url, int errorCode) {
+
+ std::map<std::string, std::pair<URL, Event> >::iterator reqIter = _sendRequests.begin();
+ while(reqIter != _sendRequests.end()) {
+ if (reqIter->second.first == url) {
+ Event failEvent;
+ failEvent.name = "error.communication";
+ eventToSCXML(failEvent, USCXML_IOPROC_HTTP_TYPE, std::string(_url));
+
+ _sendRequests.erase(reqIter);
+ return;
+ }
+ reqIter++;
+ }
+ assert(false);
+
+}
+
+
+}
diff --git a/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h b/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h
new file mode 100644
index 0000000..aefc771
--- /dev/null
+++ b/src/uscxml/plugins/ioprocessor/http/HTTPIOProcessor.h
@@ -0,0 +1,116 @@
+/**
+ * @file
+ * @author 2012-2013 Stefan Radomski (stefan.radomski@cs.tu-darmstadt.de)
+ * @copyright Simplified BSD
+ *
+ * @cond
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the FreeBSD license as published by the FreeBSD
+ * project.
+ *
+ * This program 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.
+ *
+ * You should have received a copy of the FreeBSD license along with this
+ * program. If not, see <http://www.opensource.org/licenses/bsd-license>.
+ * @endcond
+ */
+
+#ifndef HTTPIOPROCESSOR_H_645835
+#define HTTPIOPROCESSOR_H_645835
+
+#include "uscxml/config.h"
+
+extern "C" {
+#include <event2/http.h>
+#include <event2/http_struct.h>
+}
+
+#include <chrono>
+#include <ctime>
+
+// why is it duplicated from Common.h here?
+
+#if defined(_WIN32) && !defined(USCXML_STATIC)
+# if (defined ioprocessor_http_EXPORTS || defined USCXML_EXPORT)
+# define USCXML_PLUGIN_API __declspec(dllexport)
+# else
+# define USCXML_PLUGIN_API __declspec(dllimport)
+# endif
+#else
+# define USCXML_PLUGIN_API
+#endif
+
+#include "uscxml/server/HTTPServer.h"
+#include "uscxml/interpreter/InterpreterImpl.h"
+#include "uscxml/plugins/IOProcessorImpl.h"
+
+#ifndef _WIN32
+#include <sys/time.h>
+#endif
+
+#ifdef BUILD_AS_PLUGINS
+#include "uscxml/plugins/Plugins.h"
+#endif
+
+#define USCXML_IOPROC_HTTP_TYPE "http://www.w3.org/TR/scxml/#HTTPEventProcessor"
+
+namespace uscxml {
+
+/**
+ * @ingroup ioproc
+ * The http I/O processor.
+ */
+class USCXML_PLUGIN_API HTTPIOProcessor : public IOProcessorImpl, public HTTPServlet, public URLMonitor {
+public:
+ HTTPIOProcessor();
+ virtual ~HTTPIOProcessor();
+ virtual std::shared_ptr<IOProcessorImpl> create(uscxml::IOProcessorCallbacks* callbacks);
+
+ virtual std::list<std::string> getNames() {
+ std::list<std::string> names;
+ names.push_back("http");
+ names.push_back(USCXML_IOPROC_HTTP_TYPE);
+ return names;
+ }
+
+ virtual void eventFromSCXML(const std::string& target, const Event& event);
+ virtual bool isValidTarget(const std::string& target);
+
+ Data getDataModelVariables();
+
+ /// HTTPServlet
+ bool requestFromHTTP(const HTTPServer::Request& req);
+ void setURL(const std::string& url) {
+ _url = url;
+ }
+
+ bool canAdaptPath() {
+ return true;
+ }
+
+ // URLMonitor
+ void downloadStarted(const URL& url);
+ void downloadCompleted(const URL& url);
+ void downloadFailed(const URL& url, int errorCode);
+
+ std::map<std::string, std::pair<std::time_t, HTTPServer::Request> >& getUnansweredRequests() {
+ return _unansweredRequests;
+ }
+
+protected:
+ std::string _url;
+ size_t _timeoutS = WITH_IOPROC_HTTP_TIMEOUT;
+ std::map<std::string, std::pair<URL, Event> > _sendRequests;
+ std::map<std::string, std::pair<std::time_t, HTTPServer::Request> > _unansweredRequests;
+
+};
+
+#ifdef BUILD_AS_PLUGINS
+PLUMA_INHERIT_PROVIDER(HTTPIOProcessor, IOProcessorImpl)
+#endif
+
+}
+
+#endif /* end of include guard: HTTPIOPROCESSOR_H_645835 */