summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-12-20 00:56:45 (GMT)
committerStefan Radomski <radomski@tk.informatik.tu-darmstadt.de>2013-12-20 00:56:45 (GMT)
commit0388c7ac478187ff8d264b6e0275a4c4a43796b9 (patch)
tree7e62439ebf72b6369ee7b1daa370e6251c06b7e0 /src
parent22e22bfd0965e01fea041e053873d352387805f6 (diff)
downloaduscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.zip
uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.gz
uscxml-0388c7ac478187ff8d264b6e0275a4c4a43796b9.tar.bz2
Performance and bugfix for WebSockets
Diffstat (limited to 'src')
-rw-r--r--src/bindings/swig/php/uscxmlNativePHP.php18
-rw-r--r--src/uscxml/Convenience.h12
-rw-r--r--src/uscxml/Interpreter.cpp58
-rw-r--r--src/uscxml/Interpreter.h8
-rw-r--r--src/uscxml/Message.cpp58
-rw-r--r--src/uscxml/Message.h4
-rw-r--r--src/uscxml/interpreter/InterpreterDraft6.cpp5
-rw-r--r--src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp15
-rw-r--r--src/uscxml/server/HTTPServer.cpp31
-rw-r--r--src/uscxml/util/Base64.h5
-rw-r--r--src/uscxml/util/Base64.hpp14
-rw-r--r--src/uscxml/util/MD5.c1
12 files changed, 161 insertions, 68 deletions
diff --git a/src/bindings/swig/php/uscxmlNativePHP.php b/src/bindings/swig/php/uscxmlNativePHP.php
index d7bb3d0..3aba5be 100644
--- a/src/bindings/swig/php/uscxmlNativePHP.php
+++ b/src/bindings/swig/php/uscxmlNativePHP.php
@@ -2,12 +2,12 @@
/* ----------------------------------------------------------------------------
* This file was automatically generated by SWIG (http://www.swig.org).
- * Version 2.0.9
- *
- * This file is not intended to be easily readable and contains a number of
+ * Version 2.0.11
+ *
+ * This file is not intended to be easily readable and contains a number of
* coding conventions designed to improve portability and efficiency. Do not make
- * changes to this file unless you know what you are doing--modify the SWIG
- * interface file instead.
+ * changes to this file unless you know what you are doing--modify the SWIG
+ * interface file instead.
* ----------------------------------------------------------------------------- */
// Try to load our extension if it's not already loaded.
@@ -1030,13 +1030,7 @@ class Interpreter {
}
static function tokenizeIdRefs($idRefs) {
- $r=Interpreter_tokenizeIdRefs($idRefs);
- if (is_resource($r)) {
- $c=substr(get_resource_type($r), (strpos(get_resource_type($r), '__') ? strpos(get_resource_type($r), '__') + 2 : 3));
- if (class_exists($c)) return new $c($r);
- return new StringVector($r);
- }
- return $r;
+ return Interpreter_tokenizeIdRefs($idRefs);
}
static function spaceNormalize($text) {
diff --git a/src/uscxml/Convenience.h b/src/uscxml/Convenience.h
index 9f4c1a1..0177476 100644
--- a/src/uscxml/Convenience.h
+++ b/src/uscxml/Convenience.h
@@ -49,7 +49,7 @@ inline bool isNumeric( const char* pszInput, int nNumberBase) {
}
inline bool iequals(const std::string& a, const std::string& b) {
- // this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml
+ // this impementation beats boost::iequals 2700ms vs 2100ms for test-performance.scxml - we don't care for non-ascii yet
unsigned int size = a.size();
if (b.size() != size)
return false;
@@ -59,6 +59,16 @@ inline bool iequals(const std::string& a, const std::string& b) {
return true;
}
+inline bool equals(const std::string& a, const std::string& b) {
+ unsigned int size = a.size();
+ if (b.size() != size)
+ return false;
+ for (unsigned int i = 0; i < size; ++i)
+ if (a[i] != b[i])
+ return false;
+ return true;
+}
+
// see http://www.cplusplus.com/forum/general/27544/
// Little-endian operating systems:
diff --git a/src/uscxml/Interpreter.cpp b/src/uscxml/Interpreter.cpp
index 1314986..dfd9311 100644
--- a/src/uscxml/Interpreter.cpp
+++ b/src/uscxml/Interpreter.cpp
@@ -912,11 +912,11 @@ void InterpreterImpl::send(const Arabica::DOM::Node<std::string>& element) {
// namelist
if (HAS_ATTR(element, "namelist")) {
if (_dataModel) {
- std::vector<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
- for (int i = 0; i < names.size(); i++) {
- Data namelistValue = _dataModel.getStringAsData(names[i]);
- sendReq.namelist[names[i]] = namelistValue;
- sendReq.data.compound[names[i]] = namelistValue;
+ std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
+ for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+ Data namelistValue = _dataModel.getStringAsData(*nameIter);
+ sendReq.namelist[*nameIter] = namelistValue;
+ sendReq.data.compound[*nameIter] = namelistValue;
}
} else {
LOG(ERROR) << "Namelist attribute at send requires datamodel to be defined";
@@ -1054,9 +1054,9 @@ void InterpreterImpl::invoke(const Arabica::DOM::Node<std::string>& element) {
// namelist
if (HAS_ATTR(element, "namelist")) {
- std::vector<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
- for (int i = 0; i < names.size(); i++) {
- invokeReq.namelist[names[i]] = _dataModel.evalAsString(names[i]);
+ std::list<std::string> names = tokenizeIdRefs(ATTR(element, "namelist"));
+ for (std::list<std::string>::const_iterator nameIter = names.begin(); nameIter != names.end(); nameIter++) {
+ invokeReq.namelist[*nameIter] = _dataModel.evalAsString(*nameIter);
}
}
@@ -1235,10 +1235,11 @@ bool InterpreterImpl::hasConditionMatch(const Arabica::DOM::Node<std::string>& c
void InterpreterImpl::executeContent(const NodeList<std::string>& content, bool rethrow) {
for (unsigned int i = 0; i < content.getLength(); i++) {
- if (content.item(i).getNodeType() != Node_base::ELEMENT_NODE)
+ const Arabica::DOM::Node<std::string>& node = content.item(i);
+ if (node.getNodeType() != Node_base::ELEMENT_NODE)
continue;
try {
- executeContent(content.item(i), true);
+ executeContent(node, true);
}
CATCH_AND_DISTRIBUTE2("Error when executing content", content.item(i));
}
@@ -1246,10 +1247,11 @@ void InterpreterImpl::executeContent(const NodeList<std::string>& content, bool
void InterpreterImpl::executeContent(const NodeSet<std::string>& content, bool rethrow) {
for (unsigned int i = 0; i < content.size(); i++) {
- if (content[i].getNodeType() != Node_base::ELEMENT_NODE)
+ const Arabica::DOM::Node<std::string>& node = content[i];
+ if (node.getNodeType() != Node_base::ELEMENT_NODE)
continue;
try {
- executeContent(content[i], true);
+ executeContent(node, true);
}
CATCH_AND_DISTRIBUTE2("Error when executing content", content[i]);
}
@@ -1598,9 +1600,9 @@ NEXT_ANCESTOR:
return ancestor;
}
-Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::vector<std::string>& stateIds) {
+Arabica::XPath::NodeSet<std::string> InterpreterImpl::getStates(const std::list<std::string>& stateIds) {
Arabica::XPath::NodeSet<std::string> states;
- std::vector<std::string>::const_iterator tokenIter = stateIds.begin();
+ std::list<std::string>::const_iterator tokenIter = stateIds.begin();
while(tokenIter != stateIds.end()) {
states.push_back(getState(*tokenIter));
tokenIter++;
@@ -1717,18 +1719,32 @@ NodeSet<std::string> InterpreterImpl::getTargetStates(const Arabica::DOM::Node<s
}
std::string targetId = ((Arabica::DOM::Element<std::string>)transition).getAttribute("target");
-
- std::vector<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target"));
- for (int i = 0; i < targetIds.size(); i++) {
- Arabica::DOM::Node<std::string> state = getState(targetIds[i]);
+ std::list<std::string> targetIds = InterpreterImpl::tokenizeIdRefs(ATTR(transition, "target"));
+ for (std::list<std::string>::const_iterator targetIter = targetIds.begin(); targetIter != targetIds.end(); targetIter++) {
+ Arabica::DOM::Node<std::string> state = getState(*targetIter);
assert(HAS_ATTR(state, "id"));
targetStates.push_back(state);
}
return targetStates;
}
-std::vector<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) {
- std::vector<std::string> ids;
+std::list<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRefs) {
+ std::list<std::string> ids;
+
+ // appr. 3x faster than stringstream
+ size_t start = 0;
+ for (int i = 0; i < idRefs.size(); i++) {
+ if (isspace(idRefs[i])) {
+ if (i > 0 && start < i - 1) {
+ ids.push_back(idRefs.substr(start, i - start));
+ }
+ while(isspace(idRefs[++i])); // skip whitespaces
+ start = i;
+ } else if (i + 1 == idRefs.size()) {
+ ids.push_back(idRefs.substr(start, i + 1 - start));
+ }
+ }
+
#if 0
if (idRefs.length() > 0) {
@@ -1740,11 +1756,13 @@ std::vector<std::string> InterpreterImpl::tokenizeIdRefs(const std::string& idRe
}
#endif
+#if 0
// this version is somewhat fatser than the one above
std::stringstream ss (idRefs);
std::string item;
while(ss >> item)
ids.push_back(item);
+#endif
return ids;
}
diff --git a/src/uscxml/Interpreter.h b/src/uscxml/Interpreter.h
index 5cc9053..d2e63e9 100644
--- a/src/uscxml/Interpreter.h
+++ b/src/uscxml/Interpreter.h
@@ -236,7 +236,7 @@ public:
}
Arabica::DOM::Node<std::string> getState(const std::string& stateId);
- Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds);
+ Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds);
Arabica::DOM::Document<std::string>& getDocument() {
return _document;
@@ -286,7 +286,7 @@ public:
static bool isCompound(const Arabica::DOM::Node<std::string>& state);
static bool isDescendant(const Arabica::DOM::Node<std::string>& s1, const Arabica::DOM::Node<std::string>& s2);
- static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs);
+ static std::list<std::string> tokenizeIdRefs(const std::string& idRefs);
static std::string spaceNormalize(const std::string& text);
bool isInEmbeddedDocument(const Arabica::DOM::Node<std::string>& node);
@@ -540,7 +540,7 @@ public:
Arabica::DOM::Node<std::string> getState(const std::string& stateId) {
return _impl->getState(stateId);
}
- Arabica::XPath::NodeSet<std::string> getStates(const std::vector<std::string>& stateIds) {
+ Arabica::XPath::NodeSet<std::string> getStates(const std::list<std::string>& stateIds) {
return _impl->getStates(stateIds);
}
@@ -628,7 +628,7 @@ public:
return InterpreterImpl::isDescendant(s1, s2);
}
- static std::vector<std::string> tokenizeIdRefs(const std::string& idRefs) {
+ static std::list<std::string> tokenizeIdRefs(const std::string& idRefs) {
return InterpreterImpl::tokenizeIdRefs(idRefs);
}
static std::string spaceNormalize(const std::string& text) {
diff --git a/src/uscxml/Message.cpp b/src/uscxml/Message.cpp
index c79e08a..26cf640 100644
--- a/src/uscxml/Message.cpp
+++ b/src/uscxml/Message.cpp
@@ -61,6 +61,64 @@ Blob::Blob(void* _data, size_t _size, const std::string& _mimeType, bool adopt)
size = _size;
}
+#if 0
+// there used to work base64 encoded images in a browser - can't check extensively just now
+static const std::string base64_chars =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "abcdefghijklmnopqrstuvwxyz"
+ "0123456789+/";
+
+std::string Blob::base64() {
+
+ int in_len = size;
+ char const* bytes_to_encode = data;
+
+ std::string ret;
+ int i = 0;
+ int j = 0;
+ unsigned char char_array_3[3];
+ unsigned char char_array_4[4];
+
+ while (in_len--) {
+ char_array_3[i++] = *(bytes_to_encode++);
+ if (i == 3) {
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for(i = 0; (i <4) ; i++)
+ ret += base64_chars[char_array_4[i]];
+ i = 0;
+ }
+ }
+
+ if (i) {
+ for(j = i; j < 3; j++)
+ char_array_3[j] = '\0';
+
+ char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
+ char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
+ char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
+ char_array_4[3] = char_array_3[2] & 0x3f;
+
+ for (j = 0; (j < i + 1); j++)
+ ret += base64_chars[char_array_4[j]];
+
+ while((i++ < 3))
+ ret += '=';
+
+ }
+
+ return ret;
+
+}
+#else
+std::string Blob::base64() {
+ return base64Encode((char* const)data, size);
+}
+#endif
+
Data::Data(const char* _data, size_t _size, const std::string& mimeType, bool adopt) {
binary = boost::shared_ptr<Blob>(new Blob((void*)_data, _size, mimeType, adopt));
}
diff --git a/src/uscxml/Message.h b/src/uscxml/Message.h
index 5de9a56..5f6703e 100644
--- a/src/uscxml/Message.h
+++ b/src/uscxml/Message.h
@@ -55,9 +55,7 @@ public:
return uscxml::md5(data, size);
}
- std::string base64() {
- return base64Encode((char* const)data, size);
- }
+ std::string base64();
Blob* fromBase64(const std::string base64) {
std::string decoded = base64Decode(base64);
diff --git a/src/uscxml/interpreter/InterpreterDraft6.cpp b/src/uscxml/interpreter/InterpreterDraft6.cpp
index c9c00ef..772ad96 100644
--- a/src/uscxml/interpreter/InterpreterDraft6.cpp
+++ b/src/uscxml/interpreter/InterpreterDraft6.cpp
@@ -467,9 +467,8 @@ bool InterpreterDraft6::isEnabledTransition(const Node<std::string>& transition,
return false;
}
- std::vector<std::string> eventNames = tokenizeIdRefs(eventName);
-
- std::vector<std::string>::iterator eventIter = eventNames.begin();
+ std::list<std::string> eventNames = tokenizeIdRefs(eventName);
+ std::list<std::string>::iterator eventIter = eventNames.begin();
while(eventIter != eventNames.end()) {
if(nameMatch(*eventIter, event) && hasConditionMatch(transition)) {
return true;
diff --git a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
index 947c0c2..9827b91 100644
--- a/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
+++ b/src/uscxml/plugins/datamodel/ecmascript/JavaScriptCore/JSCDataModel.cpp
@@ -400,9 +400,10 @@ Data JSCDataModel::getValueAsData(const JSValueRef value) {
if (!isNumeric(property.c_str(), 10))
isArray = false;
propertySet.insert(property);
- JSStringRelease(stringValue);
+ //JSStringRelease(stringValue); // JSPropertyNameArrayRelease does the job it seems
free(buf);
}
+ JSPropertyNameArrayRelease(properties);
std::set<std::string>::iterator propIter = propertySet.begin();
while(propIter != propertySet.end()) {
if (isArray) {
@@ -537,14 +538,14 @@ void JSCDataModel::assign(const Element<std::string>& assignElem,
throw Event("error.execution", Event::PLATFORM);
// flags on attribute are ignored?
- if (key.compare("_sessionid") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_sessionid") == 0) // test 322
+ throw Event("error.execution", Event::PLATFORM);
if (key.compare("_name") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
- if (key.compare("_ioprocessors") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ throw Event("error.execution", Event::PLATFORM);
+ if (key.compare("_ioprocessors") == 0) // test 326
+ throw Event("error.execution", Event::PLATFORM);
if (key.compare("_invokers") == 0)
- return; //throw Event("error.execution", Event::PLATFORM);
+ throw Event("error.execution", Event::PLATFORM);
if (HAS_ATTR(assignElem, "expr")) {
evalAsValue(key + " = " + ATTR(assignElem, "expr"));
diff --git a/src/uscxml/server/HTTPServer.cpp b/src/uscxml/server/HTTPServer.cpp
index 358c819..6b24cd8 100644
--- a/src/uscxml/server/HTTPServer.cpp
+++ b/src/uscxml/server/HTTPServer.cpp
@@ -92,17 +92,24 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
evhttp_set_allowed_methods(_http, allowedMethods); // allow all methods
- if (_port > 0)
+ if (_port > 0) {
_httpHandle = evhttp_bind_socket_with_handle(_http, INADDR_ANY, _port);
- if (_httpHandle)
- LOG(INFO) << "HTTP server listening on tcp/" << _port;
+ if (_httpHandle) {
+ LOG(INFO) << "HTTP server listening on tcp/" << _port;
+ } else {
+ LOG(ERROR) << "HTTP server cannot bind to tcp/" << _wsPort;
+ }
+ }
_wsPort = wsPort;
- if (_wsPort > 0)
+ if (_wsPort > 0) {
_wsHandle = evws_bind_socket(_evws, _wsPort);
- if (_wsHandle)
- LOG(INFO) << "WebSocket server listening on tcp/" << _wsPort;
-
+ if (_wsHandle) {
+ LOG(INFO) << "WebSocket server listening on tcp/" << _wsPort;
+ } else {
+ LOG(ERROR) << "WebSocket server cannot bind to tcp/" << _wsPort;
+ }
+ }
#if (defined EVENT_SSL_FOUND && defined OPENSSL_FOUND && defined OPENSSL_HAS_ELIPTIC_CURVES)
_sslHandle = NULL;
_https = NULL;
@@ -136,11 +143,15 @@ HTTPServer::HTTPServer(unsigned short port, unsigned short wsPort, SSLConfig* ss
evhttp_set_bevcb(_https, sslBufferEventCallback, ctx);
evhttp_set_gencb(_https, sslGeneralBufferEventCallback, NULL);
- if (_sslPort > 0)
+ if (_sslPort > 0) {
_sslHandle = evhttp_bind_socket_with_handle(_https, INADDR_ANY, _sslPort);
- if (_sslHandle)
- LOG(INFO) << "HTTPS server listening on tcp/" << _wsPort;
+ if (_sslHandle) {
+ LOG(INFO) << "HTTPS server listening on tcp/" << _wsPort;
+ } else {
+ LOG(ERROR) << "HTTPS server cannot bind to tcp/" << _wsPort;
+ }
+ }
}
#endif
diff --git a/src/uscxml/util/Base64.h b/src/uscxml/util/Base64.h
index 7dfc83c..a07d24e 100644
--- a/src/uscxml/util/Base64.h
+++ b/src/uscxml/util/Base64.h
@@ -36,9 +36,7 @@ extern "C" {
} base64_decodestate;
USCXML_API void base64_init_decodestate(base64_decodestate* state_in);
-
USCXML_API int base64_decode_value(char value_in);
-
USCXML_API int base64_decode_block(const char* code_in, const int length_in, char* plaintext_out, base64_decodestate* state_in);
/// ENDCODE
@@ -54,11 +52,8 @@ extern "C" {
} base64_encodestate;
USCXML_API void base64_init_encodestate(base64_encodestate* state_in);
-
USCXML_API char base64_encode_value(char value_in);
-
USCXML_API int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in);
-
USCXML_API int base64_encode_blockend(char* code_out, base64_encodestate* state_in);
#ifdef __cplusplus
diff --git a/src/uscxml/util/Base64.hpp b/src/uscxml/util/Base64.hpp
index a106a12..e3cbe03 100644
--- a/src/uscxml/util/Base64.hpp
+++ b/src/uscxml/util/Base64.hpp
@@ -12,7 +12,7 @@ extern "C" {
namespace uscxml {
-USCXML_API inline std::string base64Encode(const char* data, unsigned int len) {
+USCXML_API inline std::string base64Encode(const char* data, unsigned int len, bool withBlockEnd = true) {
base64_encodestate* ctx = (base64_encodestate*)malloc(sizeof(base64_encodestate));
base64_init_encodestate(ctx);
@@ -22,10 +22,15 @@ USCXML_API inline std::string base64Encode(const char* data, unsigned int len) {
* be approximated with this formula:
*/
+ int written = 0;
char* out = (char*)malloc(len * 1.4 + 814);
- base64_encode_block(data, len, out, ctx);
+ written += base64_encode_block(data, len, out, ctx);
+ if (withBlockEnd) {
+ written += base64_encode_blockend(out + written, ctx);
+ written--; // drop the newline
+ }
+ std::string result(out, written);
free(ctx);
- std::string result(out);
free(out);
return result;
}
@@ -42,5 +47,8 @@ USCXML_API inline std::string base64Decode(const std::string& data) {
return result;
}
+// USCXML_API std::string base64Decode(const std::string& data);
+// USCXML_API std::string base64Encode(const char* data, unsigned int len);
+
}
#endif /* end of include guard: BASE64_H_5FKG12HF */
diff --git a/src/uscxml/util/MD5.c b/src/uscxml/util/MD5.c
index 1bf05e4..f553c9c 100644
--- a/src/uscxml/util/MD5.c
+++ b/src/uscxml/util/MD5.c
@@ -52,6 +52,7 @@
*/
#include "MD5.h"
+#include <string.h>
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
#ifdef ARCH_IS_BIG_ENDIAN