summaryrefslogtreecommitdiffstats
path: root/src/uscxml
diff options
context:
space:
mode:
Diffstat (limited to 'src/uscxml')
-rw-r--r--src/uscxml/URL.cpp11
-rw-r--r--src/uscxml/plugins/ioprocessor/modality/MMIMessages.cpp135
-rw-r--r--src/uscxml/plugins/ioprocessor/modality/MMIMessages.h15
-rw-r--r--src/uscxml/server/Socket.cpp109
-rw-r--r--src/uscxml/server/Socket.h22
-rw-r--r--src/uscxml/transform/ChartToFSM.cpp136
-rw-r--r--src/uscxml/transform/ChartToFSM.h9
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);