diff options
author | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2014-08-13 11:48:26 (GMT) |
---|---|---|
committer | Stefan Radomski <radomski@tk.informatik.tu-darmstadt.de> | 2014-08-13 11:48:26 (GMT) |
commit | 02f52d15e7df2500c0c6e96660a43a985add16e8 (patch) | |
tree | d4ccfdd7d1070201f39a9589b35e02a39ec179c8 /src/uscxml | |
parent | c30b602cdb5ede809b960e35fc7e702b7f1f76e2 (diff) | |
download | uscxml-02f52d15e7df2500c0c6e96660a43a985add16e8.zip uscxml-02f52d15e7df2500c0c6e96660a43a985add16e8.tar.gz uscxml-02f52d15e7df2500c0c6e96660a43a985add16e8.tar.bz2 |
Builds for Raspberry and
started VoiceXML HTTP integration
Diffstat (limited to 'src/uscxml')
-rw-r--r-- | src/uscxml/URL.cpp | 11 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp | 135 | ||||
-rw-r--r-- | src/uscxml/plugins/ioprocessor/modality/MMIMessages.h | 15 | ||||
-rw-r--r-- | src/uscxml/server/Socket.cpp | 109 | ||||
-rw-r--r-- | src/uscxml/server/Socket.h | 22 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.cpp | 136 | ||||
-rw-r--r-- | src/uscxml/transform/ChartToFSM.h | 9 |
7 files changed, 277 insertions, 160 deletions
diff --git a/src/uscxml/URL.cpp b/src/uscxml/URL.cpp index 4e97faa..f5ba85c 100644 --- a/src/uscxml/URL.cpp +++ b/src/uscxml/URL.cpp @@ -341,6 +341,7 @@ void URLImpl::setRequestType(const std::string& requestType) { void URLImpl::setOutContent(const std::string& content) { _outContent = content; + _requestType = "POST"; } const std::string URLImpl::getInContent(bool forceReload) { @@ -602,15 +603,17 @@ void URLFetcher::fetchURL(URL& url) { struct curl_slist* headers = NULL; std::map<std::string, std::string>::iterator paramIter = url._impl->_outHeader.begin(); while(paramIter != url._impl->_outHeader.end()) { - char* key = curl_easy_escape(handle, paramIter->first.c_str(), paramIter->first.length()); - char* value = curl_easy_escape(handle, paramIter->second.c_str(), paramIter->second.length()); +// char* key = curl_easy_escape(handle, paramIter->first.c_str(), paramIter->first.length()); +// char* value = curl_easy_escape(handle, paramIter->second.c_str(), paramIter->second.length()); + + const char* value = paramIter->second.c_str(); char* header = (char*)malloc(paramIter->first.size() + strlen(value) + 3); sprintf(header,"%s: %s", paramIter->first.c_str(), value); headers = curl_slist_append(headers, header); - curl_free(key); - curl_free(value); +// curl_free(key); +// curl_free(value); paramIter++; } diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp index 6db5ac4..67a2371 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp +++ b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp @@ -34,6 +34,19 @@ (element.hasAttributeNS(nameSpace, #name) ? element.getAttributeNS(nameSpace, #name) : "") \ ) +#define FIND_EVENT_NODE(node)\ +while (node) {\ + if (node.getNodeType() == Node_base::ELEMENT_NODE) {\ + if (boost::iequals(node.getLocalName(), "MMI")) {\ + node = node.getFirstChild();\ + continue;\ + } else {\ + break;\ + }\ + }\ + node = node.getNextSibling();\ +}\ + namespace uscxml { @@ -42,9 +55,21 @@ using namespace Arabica::DOM; std::string MMIEvent::nameSpace = "http://www.w3.org/2008/04/mmi-arch"; MMIEvent::Type MMIEvent::getType(Arabica::DOM::Node<std::string> node) { - if (!node) + if (!node || node.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) return INVALID; + // MMI container? + if (boost::iequals(node.getLocalName(), "MMI")) { + node = node.getFirstChild(); + if (!node) + return INVALID; + while(node.getNodeType() != Arabica::DOM::Node_base::ELEMENT_NODE) { + node = node.getNextSibling(); + if (!node) + return INVALID; + } + } + if (boost::iequals(node.getLocalName(), "NEWCONTEXTREQUEST")) return NEWCONTEXTREQUEST; if (boost::iequals(node.getLocalName(), "NEWCONTEXTRESPONSE")) @@ -84,32 +109,9 @@ MMIEvent::Type MMIEvent::getType(Arabica::DOM::Node<std::string> node) { return INVALID; } -Arabica::DOM::Node<std::string> MMIEvent::getEventNode(Arabica::DOM::Node<std::string> node) { - if (!node) - return node; - - if (node.getNodeType() == Node_base::DOCUMENT_NODE) - node = Arabica::DOM::Document<std::string>(node).getDocumentElement(); - - // get the first element - while (node && node.getNodeType() != Node_base::ELEMENT_NODE) { - node = node.getNextSibling(); - } - // get the contained message - if (node && getType(node) == INVALID) { - node = node.getFirstChild(); - while (node && node.getNodeType() != Node_base::ELEMENT_NODE && getType(node) == INVALID) { - node = node.getNextSibling(); - } - } - return node; -} - - -Arabica::DOM::Document<std::string> MMIEvent::toXML() const { +Arabica::DOM::Document<std::string> MMIEvent::toXML(bool encapsulateInMMI) const { Arabica::DOM::DOMImplementation<std::string> domFactory = Arabica::SimpleDOM::DOMImplementation<std::string>::getDOMImplementation(); Document<std::string> doc = domFactory.createDocument(nameSpace, "", 0); -// Element<std::string> mmiElem = doc.createElementNS(nameSpace, "mmi"); Element<std::string> msgElem = doc.createElementNS(nameSpace, tagName); msgElem.setAttributeNS(nameSpace, "Source", source); msgElem.setAttributeNS(nameSpace, "Target", target); @@ -136,21 +138,25 @@ Arabica::DOM::Document<std::string> MMIEvent::toXML() const { msgElem.appendChild(dataElem); } -// mmiElem.appendChild(msgElem); -// doc.appendChild(mmiElem); - doc.appendChild(msgElem); + if (encapsulateInMMI) { + Element<std::string> mmiElem = doc.createElementNS(nameSpace, "mmi"); + mmiElem.appendChild(msgElem); + doc.appendChild(mmiElem); + } else { + doc.appendChild(msgElem); + } return doc; } -Arabica::DOM::Document<std::string> ContextualizedRequest::toXML() const { - Document<std::string> doc = MMIEvent::toXML(); +Arabica::DOM::Document<std::string> ContextualizedRequest::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = MMIEvent::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); msgElem.setAttributeNS(nameSpace, "Context", context); return doc; } -Arabica::DOM::Document<std::string> ContentRequest::toXML() const { - Document<std::string> doc = ContextualizedRequest::toXML(); +Arabica::DOM::Document<std::string> ContentRequest::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = ContextualizedRequest::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); if (contentURL.href.size() > 0) { @@ -185,15 +191,15 @@ Arabica::DOM::Document<std::string> ContentRequest::toXML() const { return doc; } -Arabica::DOM::Document<std::string> ExtensionNotification::toXML() const { - Document<std::string> doc = ContextualizedRequest::toXML(); +Arabica::DOM::Document<std::string> ExtensionNotification::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = ContextualizedRequest::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); msgElem.setAttributeNS(nameSpace, "Name", name); return doc; } -Arabica::DOM::Document<std::string> StatusResponse::toXML() const { - Document<std::string> doc = ContextualizedRequest::toXML(); +Arabica::DOM::Document<std::string> StatusResponse::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = ContextualizedRequest::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); if (status == ALIVE) { msgElem.setAttributeNS(nameSpace, "Status", "alive"); @@ -207,8 +213,8 @@ Arabica::DOM::Document<std::string> StatusResponse::toXML() const { return doc; } -Arabica::DOM::Document<std::string> StatusInfoResponse::toXML() const { - Document<std::string> doc = StatusResponse::toXML(); +Arabica::DOM::Document<std::string> StatusInfoResponse::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = StatusResponse::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); Element<std::string> statusInfoElem = doc.createElementNS(nameSpace, "StatusInfo"); @@ -219,8 +225,8 @@ Arabica::DOM::Document<std::string> StatusInfoResponse::toXML() const { return doc; } -Arabica::DOM::Document<std::string> StatusRequest::toXML() const { - Document<std::string> doc = ContextualizedRequest::toXML(); +Arabica::DOM::Document<std::string> StatusRequest::toXML(bool encapsulateInMMI) const { + Document<std::string> doc = ContextualizedRequest::toXML(encapsulateInMMI); Element<std::string> msgElem = Element<std::string>(doc.getDocumentElement().getFirstChild()); if (automaticUpdate) { @@ -234,11 +240,8 @@ Arabica::DOM::Document<std::string> StatusRequest::toXML() const { MMIEvent MMIEvent::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { MMIEvent msg; - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); msg.source = STRING_ATTR_OR_EXPR(msgElem, Source); msg.target = STRING_ATTR_OR_EXPR(msgElem, Target); @@ -281,11 +284,8 @@ MMIEvent::operator Event() const { ContextualizedRequest ContextualizedRequest::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { ContextualizedRequest msg(MMIEvent::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); msg.context = STRING_ATTR_OR_EXPR(msgElem, Context); return msg; @@ -300,11 +300,8 @@ ContextualizedRequest::operator Event() const { ContentRequest ContentRequest::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { ContentRequest msg(ContextualizedRequest::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); Element<std::string> contentElem; @@ -344,11 +341,8 @@ ContentRequest ContentRequest::fromXML(Arabica::DOM::Node<std::string> node, Int ExtensionNotification ExtensionNotification::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { ExtensionNotification msg(ContextualizedRequest::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); msg.name = STRING_ATTR_OR_EXPR(msgElem, Name); msg.type = EXTENSIONNOTIFICATION; @@ -367,11 +361,8 @@ ExtensionNotification::operator Event() const { StatusResponse StatusResponse::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { StatusResponse msg(ContextualizedRequest::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); std::string status = STRING_ATTR_OR_EXPR(msgElem, Status); @@ -390,11 +381,8 @@ StatusResponse StatusResponse::fromXML(Arabica::DOM::Node<std::string> node, Int StatusInfoResponse StatusInfoResponse::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { StatusInfoResponse msg(StatusResponse::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); Element<std::string> statusInfoElem; @@ -424,11 +412,8 @@ StatusInfoResponse StatusInfoResponse::fromXML(Arabica::DOM::Node<std::string> n StatusRequest StatusRequest::fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter) { StatusRequest msg(ContextualizedRequest::fromXML(node, interpreter)); - while (node) { - if (node.getNodeType() == Node_base::ELEMENT_NODE) - break; - node = node.getNextSibling(); - } + FIND_EVENT_NODE(node); + Element<std::string> msgElem(node); std::string autoUpdate = STRING_ATTR_OR_EXPR(msgElem, RequestAutomaticUpdate); diff --git a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h index fc9142e..e4456f8 100644 --- a/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h +++ b/src/uscxml/plugins/ioprocessor/modality/MMIMessages.h @@ -51,9 +51,8 @@ public: }; static Type getType(Arabica::DOM::Node<std::string> node); - static Arabica::DOM::Node<std::string> getEventNode(Arabica::DOM::Node<std::string> node); - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static MMIEvent fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); @@ -107,7 +106,7 @@ public: class ContextualizedRequest : public MMIEvent { public: - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static ContextualizedRequest fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); operator Event() const; @@ -207,7 +206,7 @@ public: tagName = "StatusRequest"; type = STARTREQUEST; } - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static StatusRequest fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); operator Event() const; @@ -224,7 +223,7 @@ public: std::string fetchTimeout; }; - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static ContentRequest fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); operator Event() const; @@ -284,7 +283,7 @@ public: tagName = "ExtensionNotification"; type = EXTENSIONNOTIFICATION; } - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static ExtensionNotification fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); operator Event() const; @@ -307,7 +306,7 @@ public: tagName = "StatusResponse"; type = STATUSRESPONSE; } - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; static StatusResponse fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); Status status; @@ -317,7 +316,7 @@ protected: class StatusInfoResponse : public StatusResponse { public: - virtual Arabica::DOM::Document<std::string> toXML() const; + virtual Arabica::DOM::Document<std::string> toXML(bool encapsulateInMMI = false) const; StatusInfoResponse(const StatusResponse& father) : StatusResponse(father) {} static StatusInfoResponse fromXML(Arabica::DOM::Node<std::string> node, InterpreterImpl* interpreter = NULL); diff --git a/src/uscxml/server/Socket.cpp b/src/uscxml/server/Socket.cpp index 9c844e5..2d474ea 100644 --- a/src/uscxml/server/Socket.cpp +++ b/src/uscxml/server/Socket.cpp @@ -67,10 +67,16 @@ Socket::~Socket() { } void Socket::setupSockAddr(const std::string& address, int port) { + if (address == "*") { _sin.sin_addr.s_addr = 0; } else { - _sin.sin_addr.s_addr = inet_addr(address.c_str()); + struct hostent *he = NULL; + if ( (he = gethostbyname(address.c_str()) ) != NULL ) { + memcpy(&_sin.sin_addr, he->h_addr_list[0], he->h_length); + } else { + _sin.sin_addr.s_addr = inet_addr(address.c_str()); + } if (_sin.sin_addr.s_addr == INADDR_NONE) throw std::runtime_error(std::string("inet_addr: ") + strerror(errno)); } @@ -83,6 +89,34 @@ void Socket::setBlockSizeRead(size_t size) { _blockSizeRead = size; } +void Socket::parseAddress(const std::string& address, std::string& protocol, std::string& hostName, uint16_t& port) { + // tcp://hostname:port + size_t protEnd = address.find("://"); + if (protEnd != std::string::npos) { + protocol = address.substr(0, protEnd); + protEnd += 3; + } else { + protocol = "tcp"; + protEnd = 0; + } + + size_t hostEnd = address.find(":", protEnd); + if (hostEnd != std::string::npos) { + hostName = address.substr(protEnd, hostEnd - protEnd); + hostEnd += 1; + } else { + hostName = "127.0.0.1"; + hostEnd = protEnd; + } + + if (hostEnd < address.size()) { + port = strTo<uint16_t>(address.substr(hostEnd)); + } else { + port = 0; + } +} + + ClientSocket::ClientSocket(int domain, int type, int protocol) : Socket(domain, type, protocol), _clientEvent(NULL) { } @@ -95,7 +129,7 @@ ClientSocket::~ClientSocket() { } void ClientSocket::errorCallback(struct bufferevent *bev, short error, void *ctx) { - ClientSocket* instance = (ClientSocket*)ctx; +// ClientSocket* instance = (ClientSocket*)ctx; // tthread::lock_guard<tthread::recursive_mutex> lock(instance->_mutex); if (error & BEV_EVENT_READING) { @@ -115,6 +149,14 @@ void ClientSocket::errorCallback(struct bufferevent *bev, short error, void *ctx // bufferevent_free(bev); } +void ClientSocket::connect(const std::string& address) { + std::string _prot; + std::string _address; + uint16_t _port; + parseAddress(address, _prot, _address, _port); + connect(_address, _port); +} + void ClientSocket::connect(const std::string& address, int port) { // tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); @@ -123,11 +165,15 @@ void ClientSocket::connect(const std::string& address, int port) { throw std::runtime_error(std::string("connect: ") + strerror(errno)); } - _clientEvent = bufferevent_socket_new(_base->base, _socketFD, 0); //BEV_OPT_THREADSAFE); + _clientEvent = bufferevent_socket_new(_base->base, _socketFD, BEV_OPT_THREADSAFE); //BEV_OPT_THREADSAFE); bufferevent_setcb(_clientEvent, ClientSocket::readCallback, NULL, ClientSocket::errorCallback, this); bufferevent_enable(_clientEvent, EV_READ|EV_WRITE); } +int ClientSocket::write(const std::string& data) { + return write(data.data(), data.size()); +} + int ClientSocket::write(const char* data, size_t size) { // tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); bufferevent_write(_clientEvent, data, size); @@ -138,14 +184,15 @@ void ClientSocket::readCallback(struct bufferevent *bev, void *ctx) { ClientSocket* instance = (ClientSocket*)ctx; // tthread::lock_guard<tthread::recursive_mutex> lock(instance->_mutex); - size_t n; + int n; struct evbuffer* input; char* data = (char*)malloc(instance->_blockSizeRead); input = bufferevent_get_input(bev); - n = evbuffer_remove(input, data, instance->_blockSizeRead); - - instance->readCallback(data, n); + + while((n = evbuffer_remove(input, data, instance->_blockSizeRead)) > 0) { + instance->readCallback(data, n); + } free(data); } @@ -201,7 +248,6 @@ void ServerSocket::errorCallback(struct bufferevent *bev, short error, void *ctx #else close(conn->second.fd); #endif - instance->_connections.erase(conn); } } else if (error & BEV_EVENT_EOF) { @@ -229,9 +275,9 @@ void ServerSocket::readCallback(struct bufferevent *bev, void *ctx) { char* data = (char*)malloc(instance->_blockSizeRead); input = bufferevent_get_input(bev); - n = evbuffer_remove(input, data, instance->_blockSizeRead); - - instance->readCallback(data, n, instance->_connections[bev]); + while((n = evbuffer_remove(input, data, instance->_blockSizeRead)) > 0) { + instance->readCallback(data, n, instance->_connections[bev]); + } free(data); } @@ -241,11 +287,30 @@ void ServerSocket::bind() { } } +void ServerSocket::listen(const std::string& address) { + std::string _prot; + std::string _address; + uint16_t _port; + parseAddress(address, _prot, _address, _port); + listen(_address, _port); +} + void ServerSocket::listen(const std::string& address, int port) { // tthread::lock_guard<tthread::recursive_mutex> lock(_mutex); setupSockAddr(address, port); bind(); + int reuseaddr_on = 1; + setsockopt(_socketFD, SOL_SOCKET, SO_REUSEADDR, &reuseaddr_on, sizeof(reuseaddr_on)); + + int flags = fcntl(_socketFD, F_GETFL); + if (flags >= 0) { + flags |= O_NONBLOCK; + if (fcntl(_socketFD, F_SETFL, flags) < 0) { + // could not set to non-blocj + } + } + _listenerEvent = event_new(_base->base, _socketFD, EV_READ|EV_PERSIST, acceptCallback, (void*)this); /*XXX check it */ event_add(_listenerEvent, NULL); @@ -275,7 +340,7 @@ void ServerSocket::acceptCallback(evutil_socket_t listener, short event, void *c } else { struct bufferevent *bev; evutil_make_socket_nonblocking(fd); - bev = bufferevent_socket_new(instance->_base->base, fd, BEV_OPT_THREADSAFE); + bev = bufferevent_socket_new(instance->_base->base, fd, BEV_OPT_THREADSAFE); //BEV_OPT_THREADSAFE bufferevent_setcb(bev, ServerSocket::readCallback, NULL, ServerSocket::errorCallback, ctx); bufferevent_enable(bev, EV_READ|EV_WRITE); @@ -288,4 +353,24 @@ void ServerSocket::Connection::reply(const char* data, size_t size) { bufferevent_write(bufferEvent, data, size); } +void PacketServerSocket::readCallback(const char* data, size_t size, Connection& conn) { + std::stringstream& fragment = _fragments[conn]; + fragment << std::string(data, size); + + size_t startPos = 0; + size_t endPos; + const std::string& buffer = fragment.str(); + while((endPos = buffer.find(_sep, startPos)) != std::string::npos) { +// std::cout << ">" << buffer.substr(startPos, endPos - startPos) << "<" << std::endl; + readCallback(buffer.substr(startPos, endPos - startPos), conn); + startPos = endPos + _sep.size(); + } + if (startPos != 0 && startPos < buffer.size() + 1) { + std::string rest = buffer.substr(startPos); + fragment.str(std::string()); + fragment.clear(); + fragment << rest; + } +} + } diff --git a/src/uscxml/server/Socket.h b/src/uscxml/server/Socket.h index 5854a46..9330c4b 100644 --- a/src/uscxml/server/Socket.h +++ b/src/uscxml/server/Socket.h @@ -23,6 +23,7 @@ #include "uscxml/Common.h" // for USCXML_API #include "uscxml/concurrency/EventBase.h" #include <string> +#include <sstream> #include <map> #include <set> @@ -49,6 +50,7 @@ public: virtual ~Socket(); void setBlockSizeRead(size_t size); + static void parseAddress(const std::string& address, std::string& protocol, std::string& hostName, uint16_t& port); protected: @@ -67,6 +69,10 @@ class USCXML_API ServerSocket : public Socket { public: class Connection { public: + bool operator<(const Connection& other) const { + return bufferEvent < other.bufferEvent; + } + struct bufferevent* bufferEvent; int fd; @@ -77,6 +83,7 @@ public: virtual ~ServerSocket(); void listen(const std::string& address, int port); + void listen(const std::string& address); virtual void readCallback(const char* data, size_t size, Connection& conn) {}; @@ -93,6 +100,19 @@ protected: }; +class USCXML_API PacketServerSocket : public ServerSocket { +public: + PacketServerSocket(int domain, int type, int protocol, const std::string& sep) : ServerSocket(domain, type, protocol), _sep(sep) {} + virtual ~PacketServerSocket() {} + + void readCallback(const char* data, size_t size, Connection& conn); + virtual void readCallback(const std::string& packet, Connection& conn) = 0; + +protected: + std::string _sep; + std::map<Connection, std::stringstream> _fragments; +}; + class USCXML_API ClientSocket : public Socket { public: ClientSocket(int domain, int type, int protocol); @@ -100,6 +120,8 @@ public: virtual void readCallback(const char* data, size_t size) {}; void connect(const std::string& address, int port); + void connect(const std::string& address); + int write(const std::string& data); int write(const char* data, size_t size); diff --git a/src/uscxml/transform/ChartToFSM.cpp b/src/uscxml/transform/ChartToFSM.cpp index 0a04771..c31853c 100644 --- a/src/uscxml/transform/ChartToFSM.cpp +++ b/src/uscxml/transform/ChartToFSM.cpp @@ -163,9 +163,9 @@ FlatteningInterpreter::~FlatteningInterpreter() { } Document<std::string> FlatteningInterpreter::getDocument() const { -// std::cout << "######################" << std::endl; -// std::cout << _flatDoc << std::endl; -// std::cout << "######################" << std::endl; +// std::cerr << "######################" << std::endl; +// std::cerr << _flatDoc << std::endl; +// std::cerr << "######################" << std::endl; return _flatDoc; } @@ -175,7 +175,7 @@ InterpreterState FlatteningInterpreter::interpret() { setupIOProcessors(); uint64_t complexity = ChartToFSM::stateMachineComplexity(_scxml) + 1; - std::cout << "Approximate Complexity: " << complexity << std::endl; + std::cerr << "Approximate Complexity: " << complexity << std::endl; // initialize the datamodel std::string datamodelName; @@ -227,10 +227,10 @@ InterpreterState FlatteningInterpreter::interpret() { initialTransitions.push_back(transitionElem); } labelTransitions(); - weightTransitions(); +// weightTransitions(); indexTransitions(_scxml); -// std::cout << _scxml << std::endl; +// std::cerr << _scxml << std::endl; GlobalTransition* globalTransition = new GlobalTransition(initialTransitions, _dataModel, this); _start->outgoing[globalTransition->transitionId] = globalTransition; @@ -245,9 +245,9 @@ InterpreterState FlatteningInterpreter::interpret() { for(std::map<std::string, GlobalState*>::iterator globalConfIter = _globalConf.begin(); globalConfIter != _globalConf.end(); globalConfIter++) { - std::cout << globalConfIter->first << std::endl; + std::cerr << globalConfIter->first << std::endl; } - std::cout << _globalConf.size() << std::endl; + std::cerr << _globalConf.size() << std::endl; #endif createDocument(); @@ -263,13 +263,13 @@ InterpreterState FlatteningInterpreter::interpret() { } } - std::cout << "Actual Complexity: " << nrStates << std::endl; + std::cerr << "Actual Complexity: " << nrStates << std::endl; return _state; } void FlatteningInterpreter::executeContent(const Arabica::DOM::Element<std::string>& content, bool rethrow) { -// std::cout << content << std::endl; -// std::cout << TAGNAME(content) << std::endl; +// std::cerr << content << std::endl; +// std::cerr << TAGNAME(content) << std::endl; GlobalTransition::Action action; @@ -306,7 +306,7 @@ void FlatteningInterpreter::internalDoneSend(const Arabica::DOM::Element<std::st if (parentIsScxmlState(state)) return; -// std::cout << "internalDoneSend: " << state << std::endl; +// std::cerr << "internalDoneSend: " << state << std::endl; // create onentry with a raise element Element<std::string> onentry = _flatDoc.createElementNS(_nsInfo.nsURL, "onentry"); @@ -551,23 +551,23 @@ void FlatteningInterpreter::explode() { break; NodeSet<std::string> transitions; -// std::cout << globalState->stateId << " [" << nrElements << "]: " << std::endl; +// std::cerr << globalState->stateId << " [" << nrElements << "]: " << std::endl; for (int i = 1; i <= k; i++) { -// std::cout << stack[i] - 1 << ", "; +// std::cerr << stack[i] - 1 << ", "; transitions.push_back(allTransitions[stack[i] - 1]); } -// std::cout << std::endl; +// std::cerr << std::endl; _perfTotal++; _perfProcessed++; if (tthread::chrono::system_clock::now() - _lastTimeStamp > 1000) { _lastTimeStamp = tthread::chrono::system_clock::now(); -// std::cout << globalState->stateId << " [" << nrElements << "]: " << std::endl; - std::cout << "States: " << _globalConf.size() << " - "; - std::cout << "Tested: " << _perfTotal << " [" << _perfProcessed << "/sec] - "; - std::cout << "Current Complexity: 2**" << nrElements << " = " << pow(2.0, static_cast<double>(nrElements)); - std::cout << std::endl; +// std::cerr << globalState->stateId << " [" << nrElements << "]: " << std::endl; + std::cerr << "States: " << _globalConf.size() << " - "; + std::cerr << "Tested: " << _perfTotal << " [" << _perfProcessed << "/sec] - "; + std::cerr << "Current Complexity: 2**" << nrElements << " = " << pow(2.0, static_cast<double>(nrElements)); + std::cerr << std::endl; _perfProcessed = 0; } @@ -595,11 +595,12 @@ void FlatteningInterpreter::explode() { // two combinations might have projected onto the same conflict-free set if (transitionSets.find(transition->transitionId) != transitionSets.end()) { -// std::cout << "skipping as projected onto existing conflict-free subset" << std::endl; +// std::cerr << "skipping as projected onto existing conflict-free subset" << std::endl; delete transition; continue; } +#if 0 for (int currDepth = 0; currDepth <= maxDepth; currDepth++) { int lowestOrder = std::numeric_limits<int32_t>::max(); int nrDepth = 0; @@ -618,7 +619,7 @@ void FlatteningInterpreter::explode() { transition->firstElemPerLevel.push_back(lowestOrder); transition->prioPerLevel.push_back(prioPerLevel); } - +#endif #if 0 // calculate priority transition->priority = 0; @@ -643,7 +644,7 @@ NEXT_DEPTH: } #endif // remember this conflict-free set -// std::cout << "New conflict-free subset: " << transition->transitionId << ":" << transition->eventDesc << std::endl; +// std::cerr << "New conflict-free subset: " << transition->transitionId << ":" << transition->eventDesc << std::endl; transitionSets[transition->transitionId] = transition; } @@ -746,9 +747,9 @@ void FlatteningInterpreter::createDocument() { int index = 0; for (std::list<Element<std::string> >::reverse_iterator transIter = indexedTransitions.rbegin(); transIter != indexedTransitions.rend(); transIter++) { const Element<std::string>& refTrans = *transIter; - std::cout << index++ << ": " << refTrans << std::endl; + std::cerr << index++ << ": " << refTrans << std::endl; } - std::cout << std::endl; + std::cerr << std::endl; for (std::vector<std::pair<std::string,GlobalState*> >::iterator confIter = sortedStates.begin(); confIter != sortedStates.end(); @@ -766,9 +767,11 @@ template <typename T> bool PtrComp(const T * const & a, const T * const & b) } -bool isRedundantSubset (GlobalTransition* first, GlobalTransition* second) { +/** + * subset only removes transitions without cond -> superset will always be enabled + */ +bool hasUnconditionalSuperset (GlobalTransition* first, GlobalTransition* second) { if (isSuperset(second, first)) { -// std::cout << second->transitions.size() << " / " << first->transitions.size() << std::endl; for (int i = 0; i < first->transitions.size(); i++) { if (!InterpreterImpl::isMember(first->transitions[i], second->transitions)) { if (HAS_ATTR_CAST(first->transitions[i], "cond")) { @@ -781,7 +784,16 @@ bool isRedundantSubset (GlobalTransition* first, GlobalTransition* second) { return false; //second can't be removed } -std::list<GlobalTransition*> filterRedundantSubset(std::list<GlobalTransition*> list) { +bool hasEarlierUnconditionalMatch(GlobalTransition* first, GlobalTransition* second) { + if (first->eventDesc == second->eventDesc) { + if (first->condition.size() == 0) + return true; + } + return false; +} + +// for some reason, unique is not quite up to the task +std::list<GlobalTransition*> reapplyUniquePredicates(std::list<GlobalTransition*> list) { for (std::list<GlobalTransition*>::iterator outerIter = list.begin(); outerIter != list.end(); @@ -796,12 +808,17 @@ std::list<GlobalTransition*> filterRedundantSubset(std::list<GlobalTransition*> GlobalTransition* t1 = *outerIter; GlobalTransition* t2 = *innerIter; - if (isRedundantSubset(t1, t2)) { + if (hasUnconditionalSuperset(t1, t2)) { list.erase(outerIter++); - } else if (isRedundantSubset(t2, t1)) { + continue; + } else if (hasUnconditionalSuperset(t2, t1)) { list.erase(innerIter++); + continue; + } + if (hasEarlierUnconditionalMatch(t1, t2)) { + list.erase(innerIter++); + continue; } - } } @@ -827,9 +844,10 @@ void FlatteningInterpreter::appendGlobalStateNode(GlobalState* globalState) { // transitionList = sortTransitions(transitionList); transitionList.sort(PtrComp<GlobalTransition>); - transitionList.unique(isRedundantSubset); + transitionList.unique(hasUnconditionalSuperset); + transitionList.unique(hasEarlierUnconditionalMatch); // unique is not quite like what we need, but it was a start - transitionList = filterRedundantSubset(transitionList); + transitionList = reapplyUniquePredicates(transitionList); // apend here, for transient state chains to trail the state _scxml.appendChild(state); @@ -854,23 +872,7 @@ Node<std::string> FlatteningInterpreter::globalTransitionToNode(GlobalTransition // transition.setAttribute("ref", globalTransition->index); #if 1 - std::string members; - int index = 0; - std::string seperator; - for (std::list<Element<std::string> >::reverse_iterator transIter = indexedTransitions.rbegin(); transIter != indexedTransitions.rend(); transIter++) { - const Element<std::string>& refTrans = *transIter; - if (isMember(refTrans, globalTransition->transitions)) { - members += seperator + toStr(index); - } else { - members += seperator; - for (int i = 0; i < toStr(index).size(); i++) { - members += " "; - } - } - seperator = " "; - index++; - } - transition.setAttribute("members", members); + transition.setAttribute("members", globalTransition->members); #endif if (!globalTransition->isEventless) { @@ -910,9 +912,9 @@ Node<std::string> FlatteningInterpreter::globalTransitionToNode(GlobalTransition #endif -// std::cout << " firstPerLevel:" << feSS.str() << " " << globalTransition->transitionId << std::endl; -// std::cout << "event: " << globalTransition->eventDesc << " firstPerLevel:" << feSS.str() << " numberPerLevel:" << nrSS.str() << " prioPerLevel:" << prSS.str() << " " << globalTransition->transitionId << std::endl; -// std::cout << globalTransition->transitionId << std::endl; +// std::cerr << " firstPerLevel:" << feSS.str() << " " << globalTransition->transitionId << std::endl; +// std::cerr << "event: " << globalTransition->eventDesc << " firstPerLevel:" << feSS.str() << " numberPerLevel:" << nrSS.str() << " prioPerLevel:" << prSS.str() << " " << globalTransition->transitionId << std::endl; +// std::cerr << globalTransition->transitionId << std::endl; NodeSet<std::string> transientStateChain; @@ -1031,6 +1033,7 @@ Node<std::string> FlatteningInterpreter::globalTransitionToNode(GlobalTransition return transition; } +#if 0 void FlatteningInterpreter::weightTransitions() { maxDepth = 0; maxOrder = 0; @@ -1055,6 +1058,7 @@ void FlatteningInterpreter::weightTransitions() { states = getChildStates(states); } } +#endif void FlatteningInterpreter::labelTransitions() { // put a unique id on each transition @@ -1134,11 +1138,11 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t isEventless = true; #if 0 - std::cout << "################" << std::endl; + std::cerr << "################" << std::endl; for (int i = 0; i < transitions.size(); i++) { - std::cout << transitions[i] << std::endl; + std::cerr << transitions[i] << std::endl; } - std::cout << "################" << std::endl; + std::cerr << "################" << std::endl; #endif std::list<std::string> conditions; @@ -1156,6 +1160,22 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t } transitionId = setId.str(); + int index = 0; + std::string seperator; + for (std::list<Element<std::string> >::iterator transIter = interpreter->indexedTransitions.begin(); transIter != interpreter->indexedTransitions.end(); transIter++) { + const Element<std::string>& refTrans = *transIter; + if (InterpreterImpl::isMember(refTrans, transitions)) { + members += seperator + toStr(index); + } else { + members += seperator; + for (int i = 0; i < toStr(index).size(); i++) { + members += " "; + } + } + seperator = " "; + index++; + } + /** * Can these events event occur together? They can't if: * 1. event / eventless is mixed @@ -1230,11 +1250,13 @@ GlobalTransition::GlobalTransition(const Arabica::XPath::NodeSet<std::string>& t eventDesc = "*"; } - if (conditions.size() > 0) { + if (conditions.size() > 1) { condition = dataModel.andExpressions(conditions); if (condition.size() == 0) { LOG(ERROR) << "Datamodel does not support to conjungate expressions!" << std::endl; } + } else if (conditions.size() == 1) { + condition = conditions.front(); } } diff --git a/src/uscxml/transform/ChartToFSM.h b/src/uscxml/transform/ChartToFSM.h index 923304c..a60985d 100644 --- a/src/uscxml/transform/ChartToFSM.h +++ b/src/uscxml/transform/ChartToFSM.h @@ -77,15 +77,16 @@ public: bool isTargetless; // whether or not all our transitions are eventless bool isSubset; // there is a superset to this set - std::vector<long> firstElemPerLevel; - std::vector<long> nrElemPerLevel; - std::vector<long> prioPerLevel; +// std::vector<long> firstElemPerLevel; +// std::vector<long> nrElemPerLevel; +// std::vector<long> prioPerLevel; Arabica::XPath::NodeSet<std::string> transitions; // constituting transitions std::list<std::string> eventNames; // the list of longest event names that will enable this set std::string eventDesc; // space-seperated eventnames for convenience std::string condition; // conjunction of all the set's conditions + std::string members; // a convenience string listing all constituting transitions // executable content we gathered when we took the transition std::list<Action> actions; @@ -140,7 +141,7 @@ protected: void explode(); void labelTransitions(); - void weightTransitions(); +// void weightTransitions(); void createDocument(); void indexTransitions(const Arabica::DOM::Element<std::string>& root); |