Przeglądaj źródła

Merge branch 'master' into inline_setattribute

Conflicts:
	src/server/ua_server_addressspace.c
	src/server/ua_services_attribute.c
Julius Pfrommer 9 lat temu
rodzic
commit
991246bb9a

+ 13 - 86
.travis.yml

@@ -2,6 +2,10 @@ language: c
 compiler:
 - gcc
 - clang
+os:
+- linux
+- osx
+sudo: true
 env:
   global:
   - secure: nSunY54Wp5HkQCHHbKwlwpbaKyqRVIu/0EnhaoJSwhM1wqerQV/E5d/2JelO9/tZgbungAO7wk/fjutRMVc7d378RTIPwS8vHpvZfEoGhCFsLoTOlqESzsZFBup2H5t1lpQ23jRHDOxlLdJy2lz5U+zd1YnYgDXqdDFjegsIYdo=
@@ -15,94 +19,17 @@ addons:
     build_command_prepend: mkdir build && cd build && cmake ..
     build_command: make
     branch_pattern: coverity_scan
+matrix:
+  # This excludes OSX GCC builds.
+  exclude:
+    - os: osx
+      compiler: gcc
 before_install:
-- sudo apt-get install binutils-mingw-w64-i686 gcc-mingw-w64-i686 mingw-w64
-- sudo add-apt-repository ppa:kalakris/cmake -y
-- sudo apt-get update -qq
-- sudo apt-get install -qq --no-install-recommends build-essential cmake python-lxml gcc-multilib graphviz doxygen wget zip
-- sudo apt-get install libsubunit-dev #for check_0.10.0
-- wget http://ftp.de.debian.org/debian/pool/main/c/check/check_0.10.0-2_amd64.deb
-- sudo dpkg -i check_0.10.0-2_amd64.deb
-- wget https://launchpad.net/ubuntu/+source/liburcu/0.8.5-1ubuntu1/+build/6513813/+files/liburcu2_0.8.5-1ubuntu1_amd64.deb
-- wget https://launchpad.net/ubuntu/+source/liburcu/0.8.5-1ubuntu1/+build/6513813/+files/liburcu-dev_0.8.5-1ubuntu1_amd64.deb
-- sudo dpkg -i liburcu2_0.8.5-1ubuntu1_amd64.deb
-- sudo dpkg -i liburcu-dev_0.8.5-1ubuntu1_amd64.deb
-- sudo pip install cpp-coveralls
-- sudo pip install Pygments
-- sudo pip install sphinx
-- sudo pip install breathe
-- sudo pip install sphinx_rtd_theme
+- "if [ ${TRAVIS_OS_NAME} == 'linux' ]; then . ./tools/travis_linux_before_install.sh; fi"
+- "if [ ${TRAVIS_OS_NAME} == 'osx' ]; then . ./tools/travis_osx_before_install.sh; fi"
 script:
-- echo "Checking the applicability of patches"
-- # ./tools/.checkPorts.sh
-- echo "Documentation and certificate build"
-- mkdir -p build
-- cd build
-- cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=ON -DGENERATE_SELFSIGNED=ON ..
-- make doc
-- make selfsigned
-- cp -r doc ..
-- cp server_cert.der ..
-- echo "Testing builds"
-- cd .. && rm build -rf && mkdir -p build && cd build
-- echo "Cross compile release build for MinGW 32 bit"
-- cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make 
-- cp ../README.md .
-- cp ../LICENSE .
-- cp ../AUTHORS .
-- cp -r ../doc .
-- cp ../server_cert.der .
-- zip -r open62541-win32.zip doc server_cert.der LICENSE AUTHORS README.md server_static.exe server.exe client.exe client_static.exe libopen62541.dll libopen62541.dll.a open62541.h open62541.c
-- cp open62541-win32.zip ..
-- cd .. && rm build -rf && mkdir -p build && cd build
-- echo "Cross compile release build for MinGW 64 bit"
-- cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw64.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make 
-- cp ../README.md .
-- cp ../LICENSE .
-- cp ../AUTHORS .
-- cp -r ../doc .
-- cp ../server_cert.der .
-- zip -r open62541-win64.zip doc server_cert.der LICENSE AUTHORS README.md server_static.exe server.exe client.exe client_static.exe libopen62541.dll libopen62541.dll.a open62541.h open62541.c
-- cp open62541-win64.zip ..
-- cd .. && rm build -rf && mkdir -p build && cd build
-- echo "Cross compile release build for 32-bit linux"
-- cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-gcc-m32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make 
-- tar -pczf open62541-linux32.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
-- cp open62541-linux32.tar.gz ..
-- cd .. && rm build -rf && mkdir -p build && cd build
-- echo "Compile release build for 64-bit linux"
-- cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_AMALGAMATION=ON -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
-- make 
-- tar -pczf open62541-linux64.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
-- cp open62541-linux64.tar.gz ..
-- cp open62541.h .. #copy single file-release
-- cp open62541.c .. #copy single file-release
-- echo "Upgrade to gcc 4.8"
-- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
-- sudo apt-get update -qq
-- sudo apt-get install -qq gcc-4.8 g++-4.8 valgrind
-- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20
-- sudo update-alternatives --config gcc
-- echo "Compile multithreaded version"
-- echo "Building the C++ example"
-- gcc -std=c99 -c open62541.c
-- g++-4.8 ../examples/server.cpp -I./ open62541.o -o cpp-server
-- cd .. && rm build -rf && mkdir -p build && cd build
-- cmake -DENABLE_MULTITHREADING=ON -DBUILD_EXAMPLESERVER=ON ..
-- make 
-- cd .. && rm build -rf && mkdir -p build && cd build
-- echo "Debug build and unit tests (64 bit)"
-- cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_DEMO_NODESET=ON -DBUILD_UNIT_TESTS=ON -DBUILD_EXAMPLESERVER=ON -DENABLE_COVERAGE=ON ..
-- make && make test
-- echo "Run valgrind to see if the server leaks memory (just starting up and closing..)"
-- if [[ ! ( ${TRAVIS_OS_NAME} == "linux" && ${CC} == "clang") ]]; then
-  (valgrind --error-exitcode=3 ./server & export pid=$!; sleep 2; kill -INT $pid; wait $pid);
-  (coveralls --gcov /usr/bin/gcov-4.8 -E '.*\.h' -E '.*CMakeCXXCompilerId\.cpp' -E '.*CMakeCCompilerId\.c' -r ../ ; exit 0);
-  fi
-- cd .. 
+- "if [ ${TRAVIS_OS_NAME} == 'linux' ]; then . ./tools/travis_linux_script.sh; fi"
+- "if [ ${TRAVIS_OS_NAME} == 'osx' ]; then . ./tools/travis_osx_script.sh; fi"
 after_success:
 - if [[ ( ${TRAVIS_OS_NAME} == "linux" && ${CC} == "gcc" && ${TRAVIS_BRANCH} == "master") ]]; then ./tools/.deployGH.sh; fi
 - if [[ ( ${TRAVIS_OS_NAME} == "linux" && ${CC} == "gcc" && ${TRAVIS_BRANCH} == "master") ]]; then ./tools/.coverity.sh; fi

+ 9 - 2
CMakeLists.txt

@@ -247,6 +247,9 @@ if(EXTENSION_UDP)
   endif()
 endif()
 
+option(LEGACY "Enable LEGACY code" OFF)
+mark_as_advanced(LEGACY)
+
 option(EXTENSION_STATELESS "Enable stateless extension" OFF)
 if(EXTENSION_STATELESS)
 	message(STATUS "Extensions: enabling stateless")
@@ -368,12 +371,16 @@ if(BUILD_EXAMPLECLIENT)
         target_link_libraries(client_static urcu-cds urcu urcu-common pthread)
         target_link_libraries(client urcu-cds urcu urcu-common pthread)
     endif()
-    if(EXTENSION_STATELESS)
+    if(EXTENSION_STATELESS AND NOT ENABLE_AMALGAMATION)
         add_executable(client_stateless examples/client_stateless.c ${client_source})
         if(ENABLE_MULTITHREADING)
             target_link_libraries(client_stateless urcu-cds urcu urcu-common pthread)
         endif()
     endif()
+    if(LEGACY AND NOT ENABLE_AMALGAMATION)
+    	add_executable(client_legacy ${PROJECT_SOURCE_DIR}/examples/client_legacy.c $<TARGET_OBJECTS:open62541-object>)
+		target_link_libraries(client_legacy ${LIBS})
+	endif()
 endif()
 
 # build unit tests
@@ -401,7 +408,7 @@ if(BUILD_EXAMPLES)
 	if(ENABLE_MULTITHREADING)
 		list(APPEND LIBS urcu-cds urcu urcu-common)
 	endif(ENABLE_MULTITHREADING)
-
+	
     add_executable(server_variable ${PROJECT_SOURCE_DIR}/examples/server_variable.c $<TARGET_OBJECTS:open62541-object>)
 	target_link_libraries(server_variable ${LIBS})
 

+ 60 - 27
examples/client_legacy.c

@@ -11,13 +11,10 @@
 #include <unistd.h> // for close
 #include <stdlib.h> // pulls in declaration of malloc, free
 
-#ifdef NOT_AMALGATED
-    #include "ua_transport_generated.h"
-    #include "ua_types_encoding_binary.h"
-    #include "ua_util.h"
-#else
-    #include "open62541.h"
-#endif
+//this legacy stuff can not be build with amalgamation options, since it need internal APIs
+#include "ua_util.h"
+#include "ua_transport_generated_encoding_binary.h"
+#include "ua_types_generated_encoding_binary.h"
 
 typedef struct ConnectionInfo {
 	UA_Int32 socket;
@@ -25,6 +22,7 @@ typedef struct ConnectionInfo {
 	UA_SequenceHeader sequenceHdr;
 	UA_NodeId authenticationToken;
 	UA_UInt32 tokenId;
+	UA_UInt32 reqestHandle;
 } ConnectionInfo;
 
 static UA_Int32 sendHello(UA_Int32 sock, UA_String *endpointURL) {
@@ -40,14 +38,17 @@ static UA_Int32 sendHello(UA_Int32 sock, UA_String *endpointURL) {
 	hello.receiveBufferSize = 65536;
 	hello.sendBufferSize = 65536;
 
-	messageHeader.messageSize = UA_TcpHelloMessage_calcSizeBinary((UA_TcpHelloMessage const*) &hello) +
-                                UA_TcpMessageHeader_calcSizeBinary((UA_TcpMessageHeader const*) &messageHeader);
 	UA_ByteString message;
-	UA_ByteString_newMembers(&message, messageHeader.messageSize);
+	UA_ByteString_newMembers(&message, 1024);
 
 	size_t offset = 0;
 	UA_TcpMessageHeader_encodeBinary((UA_TcpMessageHeader const*) &messageHeader, &message, &offset);
 	UA_TcpHelloMessage_encodeBinary((UA_TcpHelloMessage const*) &hello, &message, &offset);
+    messageHeader.messageSize = offset;
+
+	offset = 0;
+    UA_TcpMessageHeader_encodeBinary((UA_TcpMessageHeader const*) &messageHeader, &message, &offset);
+    UA_TcpHelloMessage_encodeBinary((UA_TcpHelloMessage const*) &hello, &message, &offset);
 
 	UA_Int32 sendret = send(sock, message.data, offset, 0);
 
@@ -112,7 +113,7 @@ static int sendOpenSecureChannel(UA_Int32 sock) {
 	UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset);
 
     UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
-	UA_String_deleteMembers(&securityPolicy);
+	//UA_String_deleteMembers(&securityPolicy);
 
 	UA_Int32 sendret = send(sock, message.data, offset, 0);
 	UA_ByteString_deleteMembers(&message);
@@ -154,8 +155,13 @@ static UA_Int32 sendCreateSession(UA_Int32 sock, UA_UInt32 channelId, UA_UInt32
 	rq.requestedSessionTimeout = 1200000;
 	rq.maxResponseMessageSize = UA_INT32_MAX;
 
-	msghdr.messageSize = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) +
-                         UA_CreateSessionRequest_calcSizeBinary(&rq);
+	//workaround to get length calculated
+	offset = 0;
+	UA_CreateSessionRequest_encodeBinary(&rq, &message, &offset);
+	UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
+	UA_NodeId_encodeBinary(&type, &message, &offset);
+	msghdr.messageSize = 16 + offset;
+	offset = 0;
 
 	UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
 	UA_UInt32_encodeBinary(&tmpChannelId, &message, &offset);
@@ -167,7 +173,8 @@ static UA_Int32 sendCreateSession(UA_Int32 sock, UA_UInt32 channelId, UA_UInt32
 
 	UA_Int32 sendret = send(sock, message.data, offset, 0);
 	UA_ByteString_deleteMembers(&message);
-	UA_CreateSessionRequest_deleteMembers(&rq);
+	//fixme: potential leak
+	//UA_CreateSessionRequest_deleteMembers(&rq);
 	if (sendret < 0) {
 		printf("send opensecurechannel failed");
 		return 1;
@@ -184,12 +191,10 @@ static UA_Int32 closeSession(ConnectionInfo *connectionInfo) {
 	UA_CloseSessionRequest rq;
     UA_CloseSessionRequest_init(&rq);
 
-	rq.requestHeader.requestHandle = 1;
+	rq.requestHeader.requestHandle = connectionInfo->reqestHandle++;
 	rq.requestHeader.timestamp = UA_DateTime_now();
 	rq.requestHeader.timeoutHint = 10000;
-	rq.requestHeader.authenticationToken.identifier.numeric = 10;
-	rq.requestHeader.authenticationToken.identifierType = UA_NODEIDTYPE_NUMERIC;
-	rq.requestHeader.authenticationToken.namespaceIndex = 10;
+	rq.requestHeader.authenticationToken = connectionInfo->authenticationToken;
     rq.deleteSubscriptions = UA_TRUE;
 
 	UA_TcpMessageHeader msghdr;
@@ -200,13 +205,20 @@ static UA_Int32 closeSession(ConnectionInfo *connectionInfo) {
 	type.identifierType = UA_NODEIDTYPE_NUMERIC;
 	type.namespaceIndex = 0;
 
-	msghdr.messageSize = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) +
-                         UA_CloseSessionRequest_calcSizeBinary(&rq);
+    //workaround to get length calculated
+    offset = 0;
+    UA_CloseSessionRequest_encodeBinary(&rq, &message, &offset);
+    UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
+    UA_NodeId_encodeBinary(&type, &message, &offset);
+    msghdr.messageSize = 16 + offset;
+    offset = 0;
 
 	UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
 	UA_UInt32_encodeBinary(&connectionInfo->channelId, &message, &offset);
 	UA_UInt32_encodeBinary(&connectionInfo->tokenId, &message, &offset);
+	connectionInfo->sequenceHdr.sequenceNumber++;
 	UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.sequenceNumber, &message, &offset);
+	connectionInfo->sequenceHdr.requestId++;
 	UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.requestId, &message, &offset);
 	UA_NodeId_encodeBinary(&type, &message, &offset);
 	UA_CloseSessionRequest_encodeBinary(&rq, &message, &offset);
@@ -241,8 +253,12 @@ static UA_Int32 closeSecureChannel(ConnectionInfo *connectionInfo) {
 	UA_TcpMessageHeader msghdr;
 	msghdr.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF;
 
-	msghdr.messageSize = 4 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) +
-                         UA_CloseSecureChannelRequest_calcSizeBinary(&rq);
+	//workaround to get length calculated
+	offset = 0;
+	UA_CloseSecureChannelRequest_encodeBinary(&rq, &message, &offset);
+	UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
+	msghdr.messageSize = 4 + offset;
+	offset = 0;
 
 	UA_TcpMessageHeader_encodeBinary(&msghdr, &message, &offset);
 	UA_UInt32_encodeBinary(&connectionInfo->channelId, &message, &offset);
@@ -282,8 +298,13 @@ static UA_Int32 sendActivateSession(UA_Int32 sock, UA_UInt32 channelId, UA_UInt3
 	rq.requestHeader.timestamp = UA_DateTime_now();
 	rq.requestHeader.timeoutHint = 10000;
     
-	msghdr.messageSize  = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) +
-                          UA_ActivateSessionRequest_calcSizeBinary(&rq);
+    //workaround to get length calculated
+    offset = 0;
+    UA_ActivateSessionRequest_encodeBinary(&rq, message, &offset);
+    UA_TcpMessageHeader_encodeBinary(&msghdr, message, &offset);
+    UA_NodeId_encodeBinary(&type, message, &offset);
+    msghdr.messageSize = 16 + offset;
+    offset = 0;
 
 	UA_TcpMessageHeader_encodeBinary(&msghdr, message, &offset);
 	UA_UInt32_encodeBinary(&tmpChannelId, message, &offset);
@@ -337,15 +358,22 @@ static UA_Int64 sendReadRequest(ConnectionInfo *connectionInfo, UA_Int32 nodeIds
 	rq.requestHeader.timestamp = UA_DateTime_now();
 	rq.requestHeader.authenticationToken = connectionInfo->authenticationToken;
 	rq.timestampsToReturn = 0x03;
-	rq.requestHeader.requestHandle = 1 + connectionInfo->sequenceHdr.requestId;
+	rq.requestHeader.requestHandle = connectionInfo->reqestHandle++;
 
-	msghdr.messageSize = 16 + UA_TcpMessageHeader_calcSizeBinary(&msghdr) + UA_NodeId_calcSizeBinary(&type) +
-                         UA_ReadRequest_calcSizeBinary(&rq);
+    //workaround to get length calculated
+    offset = 0;
+    UA_ReadRequest_encodeBinary(&rq, message, &offset);
+    UA_TcpMessageHeader_encodeBinary(&msghdr, message, &offset);
+    UA_NodeId_encodeBinary(&type, message, &offset);
+    msghdr.messageSize = 16 + offset;
+    offset = 0;
 
 	UA_TcpMessageHeader_encodeBinary(&msghdr,message,&offset);
 	UA_UInt32_encodeBinary(&tmpChannelId, message, &offset);
 	UA_UInt32_encodeBinary(&connectionInfo->tokenId, message, &offset);
+	connectionInfo->sequenceHdr.sequenceNumber++;
 	UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.sequenceNumber, message, &offset);
+	connectionInfo->sequenceHdr.requestId++;
 	UA_UInt32_encodeBinary(&connectionInfo->sequenceHdr.requestId, message, &offset);
 	UA_NodeId_encodeBinary(&type,message,&offset);
 	UA_ReadRequest_encodeBinary(&rq, message, &offset);
@@ -393,6 +421,7 @@ static int ua_client_connectUA(char* ipaddress,int port, UA_String *endpointUrl,
 			connectionInfo->channelId=0;
 			UA_SequenceHeader_init(&connectionInfo->sequenceHdr);
 			connectionInfo->tokenId=0;
+			connectionInfo->reqestHandle = 1;
 			return 0;
 		}else{
 			sendHello(sock, endpointUrl);
@@ -428,6 +457,10 @@ static int ua_client_connectUA(char* ipaddress,int port, UA_String *endpointUrl,
 					connectionInfo->authenticationToken);
 			recv(sock, reply.data, reply.length, 0);
 
+			connectionInfo->sequenceHdr.requestId = 3;
+			connectionInfo->sequenceHdr.sequenceNumber = 53;
+			connectionInfo->reqestHandle = 3;
+
 			UA_OpenSecureChannelResponse_deleteMembers(&openSecChannelRsp);
 
 			UA_String_deleteMembers(&reply);

+ 4 - 2
examples/client_stateless.c

@@ -8,9 +8,11 @@
 #include <unistd.h> // for close
 #include <stdlib.h> // pulls in declaration of malloc, free
 
+//this stuff can not be build with amalgamation options, since it need internal APIs
 #include "ua_util.h"
-#include "ua_types_encoding_binary.h"
-#include "ua_transport_generated.h"
+#include "ua_transport_generated_encoding_binary.h"
+#include "ua_types_generated_encoding_binary.h"
+
 
 int main(int argc , char *argv[])
 {

+ 8 - 0
examples/logger_stdout.h

@@ -9,7 +9,15 @@
 #include "ua_types.h"
 #include "ua_log.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /** Initialises the logger for the current thread. */
 UA_EXPORT UA_Logger Logger_Stdout_new(void);
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* LOGGER_STDOUT_H_ */

+ 6 - 2
examples/networklayer_tcp.c

@@ -56,7 +56,8 @@ static UA_StatusCode socket_write(UA_Connection *connection, UA_ByteString *buf,
         do {
 #ifdef _WIN32
             n = send((SOCKET)connection->sockfd, (const char*)buf->data, buflen, 0);
-            if(n < 0 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK){
+            const int last_error = WSAGetLastError();
+            if(n < 0 && last_error != WSAEINTR && last_error != WSAEWOULDBLOCK){
                 connection->close(connection);
                 socket_close(connection);
                 return UA_STATUSCODE_BADCONNECTIONCLOSED;
@@ -100,7 +101,8 @@ static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *respo
         free(response->data);
         UA_ByteString_init(response);
 #ifdef _WIN32
-		if(WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) {
+        const int last_error = WSAGetLastError();
+        if(last_error == WSAEINTR || last_error == WSAEWOULDBLOCK) {
 #else
 		if(errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK) {
 #endif
@@ -450,6 +452,8 @@ UA_ServerNetworkLayer ServerNetworkLayerTCP_new(UA_ConnectionConfig conf, UA_UIn
 
 static UA_StatusCode ClientNetworkLayerGetBuffer(UA_Connection *connection, UA_ByteString *buf) {
 #ifndef UA_MULTITHREADING
+    if(connection->state == UA_CONNECTION_CLOSED)
+        return UA_STATUSCODE_BADCONNECTIONCLOSED;
     *buf = *(UA_ByteString*)connection->handle;
     return UA_STATUSCODE_GOOD;
 #else

+ 1 - 1
include/ua_types.h

@@ -327,7 +327,7 @@ UA_StatusCode UA_EXPORT UA_String_copyprintf(char const fmt[], UA_String *dst, .
 
 /* DateTime */
 UA_DateTime UA_EXPORT * UA_DateTime_new(void);
-static UA_INLINE void UA_DateTime_init(UA_DateTime *p) { *p = 0.0f; }
+static UA_INLINE void UA_DateTime_init(UA_DateTime *p) { *p = (UA_DateTime)0.0f; }
 void UA_EXPORT UA_DateTime_delete(UA_DateTime *p);
 static UA_INLINE void UA_DateTime_deleteMembers(UA_DateTime *p) { }
 static UA_INLINE UA_StatusCode UA_DateTime_copy(const UA_DateTime *src, UA_DateTime *dst) { *dst = *src; return UA_STATUSCODE_GOOD; }

+ 8 - 2
src/client/ua_client.c

@@ -372,8 +372,14 @@ static UA_StatusCode ActivateSession(UA_Client *client) {
     request.userIdentityToken.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
     request.userIdentityToken.typeId = UA_TYPES[UA_TYPES_ANONYMOUSIDENTITYTOKEN].typeId;
     request.userIdentityToken.typeId.identifier.numeric+=UA_ENCODINGOFFSET_BINARY;
-
-    UA_ByteString_newMembers(&request.userIdentityToken.body, identityToken.policyId.length+4);
+    
+    if (identityToken.policyId.length >= 0)
+      UA_ByteString_newMembers(&request.userIdentityToken.body, identityToken.policyId.length+4);
+    else {
+      identityToken.policyId.length = -1;
+      UA_ByteString_newMembers(&request.userIdentityToken.body, 4);
+    }
+    
     size_t offset = 0;
     UA_ByteString_encodeBinary(&identityToken.policyId,&request.userIdentityToken.body,&offset);
 

+ 1 - 1
src/server/ua_server.c

@@ -96,7 +96,7 @@ UA_UInt16 UA_Server_addNamespace(UA_Server *server, const char* name) {
     server->namespaces = UA_realloc(server->namespaces, sizeof(UA_String) * (server->namespacesSize+1));
     server->namespaces[server->namespacesSize] = UA_STRING_ALLOC(name);
     server->namespacesSize++;
-    return server->namespacesSize-1;
+    return ((UA_UInt16)server->namespacesSize - 1);
 }
 
 /*****************/

+ 15 - 9
src/server/ua_server_binary.c

@@ -157,6 +157,18 @@ static void invoke_service(UA_Server *server, UA_SecureChannel *channel, UA_UInt
     init_response_header(request, response);
     /* try to get the session from the securechannel first */
     UA_Session *session = UA_SecureChannel_getSession(channel, &request->authenticationToken);
+#ifdef EXTENSION_STATELESS
+    if(request->authenticationToken.namespaceIndex == 0
+            && request->authenticationToken.identifierType == UA_NODEIDTYPE_NUMERIC
+            && request->authenticationToken.identifier.numeric == 0
+    && (responseType->typeIndex == UA_TYPES_READRESPONSE
+            || responseType->typeIndex == UA_TYPES_WRITERESPONSE
+            || responseType->typeIndex == UA_TYPES_BROWSERESPONSE)
+    ){
+        session = &anonymousSession;
+        service(server, session, request, response);
+    }else{
+#endif
     if(!session || session->channel != channel) {
         response->serviceResult = UA_STATUSCODE_BADSESSIONIDINVALID;
     } else if(session->activated == UA_FALSE) {
@@ -167,6 +179,9 @@ static void invoke_service(UA_Server *server, UA_SecureChannel *channel, UA_UInt
         UA_Session_updateLifetime(session);
         service(server, session, request, response);
     }
+#ifdef EXTENSION_STATELESS
+    }
+#endif
     UA_StatusCode retval = UA_SecureChannel_sendBinaryMessage(channel, requestId, response, responseType);
     if(retval != UA_STATUSCODE_GOOD) {
         if(retval == UA_STATUSCODE_BADENCODINGLIMITSEXCEEDED)
@@ -202,9 +217,6 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         UA_SecureChannel_init(&anonymousChannel);
         anonymousChannel.connection = connection;
         clientChannel = &anonymousChannel;
-#ifdef EXTENSION_STATELESS
-        UA_SecureChannel_attachSession(&anonymousChannel, &anonymousSession);
-#endif
     }
 
     /* Read the security header */
@@ -374,10 +386,6 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
         UA_ServiceFault_init(&r);
         init_response_header(&p, &r.responseHeader);
         r.responseHeader.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
-#ifdef EXTENSION_STATELESS
-        if(retval != UA_STATUSCODE_GOOD)
-            r.responseHeader.serviceResult = retval;
-#endif
         UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
                                            &UA_TYPES[UA_TYPES_SERVICEFAULT]);
         UA_RequestHeader_deleteMembers(&p);
@@ -397,8 +405,6 @@ static void processCLO(UA_Connection *connection, UA_Server *server, const UA_By
 }
 
 void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, UA_ByteString *msg) {
-    if(msg->length <= 0)
-        return;
     size_t pos = 0;
     UA_TcpMessageHeader tcpMessageHeader;
     do {

+ 10 - 10
src/server/ua_services_attribute.c

@@ -163,7 +163,8 @@ static UA_StatusCode getVariableNodeArrayDimensions(const UA_VariableNode *vn, U
 }
 
 static const UA_String binEncoding = {sizeof("DefaultBinary")-1, (UA_Byte*)"DefaultBinary"};
-static const UA_String xmlEncoding = {sizeof("DefaultXml")-1, (UA_Byte*)"DefaultXml"};
+/* clang complains about unused variables */
+// static const UA_String xmlEncoding = {sizeof("DefaultXml")-1, (UA_Byte*)"DefaultXml"};
 
 /** Reads a single attribute from a node in the nodestore. */
 void Service_Read_single(UA_Server *server, UA_Session *session, const UA_TimestampsToReturn timestamps,
@@ -365,12 +366,11 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 		/* expiry header */
 		UA_ExtensionObject additionalHeader;
 		UA_ExtensionObject_init(&additionalHeader);
+		additionalHeader.typeId = UA_TYPES[UA_TYPES_VARIANT].typeId;
 		additionalHeader.encoding = UA_EXTENSIONOBJECT_ENCODINGMASK_BODYISBYTESTRING;
 
 		UA_Variant variant;
 		UA_Variant_init(&variant);
-		variant.type = &UA_TYPES[UA_TYPES_DATETIME];
-		variant.arrayLength = request->nodesToReadSize;
 
 		UA_DateTime* expireArray = UA_NULL;
 		expireArray = UA_Array_new(&UA_TYPES[UA_TYPES_DATETIME], request->nodesToReadSize);
@@ -380,17 +380,17 @@ void Service_Read(UA_Server *server, UA_Session *session, const UA_ReadRequest *
 		for(UA_Int32 i = 0;i < response->resultsSize;i++) {
 			expireArray[i] = UA_DateTime_now() + 20 * 100 * 1000 * 1000;
 		}
+		UA_Variant_setArray(&variant, expireArray, request->nodesToReadSize, &UA_TYPES[UA_TYPES_DATETIME]);
+
 		size_t offset = 0;
-        UA_Connection *c = UA_NULL;
-        UA_SecureChannel *sc = session->channel;
-        if(!sc) {
-            response->responseHeader.serviceResult = UA_STATUSCODE_BADINTERNALERROR;
-            return;
-        }
 		UA_ByteString str;
-        UA_ByteString_newMembers(&str, c->remoteConf.maxMessageSize);
+        UA_ByteString_newMembers(&str, 65536);
 		UA_Variant_encodeBinary(&variant, &str, &offset);
+
+        UA_Array_delete(expireArray, &UA_TYPES[UA_TYPES_DATETIME], request->nodesToReadSize);
+
 		additionalHeader.body = str;
+		additionalHeader.body.length = offset;
 		response->responseHeader.additionalHeader = additionalHeader;
     }
 #endif

+ 1 - 1
src/server/ua_services_session.c

@@ -22,7 +22,7 @@ void Service_CreateSession(UA_Server *server, UA_SecureChannel *channel,
     //TODO get maxResponseMessageSize internally
     newSession->maxResponseMessageSize = request->maxResponseMessageSize;
     response->sessionId = newSession->sessionId;
-    response->revisedSessionTimeout = newSession->timeout;
+    response->revisedSessionTimeout = (UA_Double)newSession->timeout;
     response->authenticationToken = newSession->authenticationToken;
     response->responseHeader.serviceResult = UA_String_copy(&request->sessionName, &newSession->sessionName);
     if(server->endpointDescriptions)

+ 1 - 1
src/server/ua_session_manager.c

@@ -65,7 +65,7 @@ UA_StatusCode UA_SessionManager_createSession(UA_SessionManager *sessionManager,
     newentry->session.authenticationToken = UA_NODEID_GUID(1, UA_Guid_random(&randSeed));
     if(request->requestedSessionTimeout <= sessionManager->maxSessionLifeTime &&
        request->requestedSessionTimeout > 0)
-        newentry->session.timeout = request->requestedSessionTimeout;
+        newentry->session.timeout = (UA_Int64)request->requestedSessionTimeout;
     else
         newentry->session.timeout = sessionManager->maxSessionLifeTime; // todo: remove when the CTT is fixed
     UA_Session_updateLifetime(&newentry->session);

+ 13 - 2
src/ua_types.c

@@ -5,6 +5,10 @@
 
 #include "pcg_basic.h"
 
+#ifdef _MSC_VER
+#include <strsafe.h>
+#endif
+
 /*****************/
 /* Helper Macros */
 /*****************/
@@ -228,8 +232,15 @@ UA_StatusCode UA_DateTime_toString(UA_DateTime atime, UA_String *timeString) {
     timeString->length = 31;
 
     UA_DateTimeStruct tSt = UA_DateTime_toStruct(atime);
-    sprintf((char*)timeString->data, "%02d/%02d/%04d %02d:%02d:%02d.%03d.%03d.%03d", tSt.month, tSt.day, tSt.year,
-            tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
+#ifdef _MSC_VER
+    StringCchPrintf((char*)timeString->data, (size_t)timeString->length,
+        "%02d/%02d/%04d %02d:%02d:%02d.%03d.%03d.%03d",
+        tSt.month, tSt.day, tSt.year, tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
+#else
+    sprintf((char*)timeString->data,
+        "%02d/%02d/%04d %02d:%02d:%02d.%03d.%03d.%03d", 
+        tSt.month, tSt.day, tSt.year, tSt.hour, tSt.min, tSt.sec, tSt.milliSec, tSt.microSec, tSt.nanoSec);
+#endif
     return UA_STATUSCODE_GOOD;
 }
 

+ 2 - 2
tests/CMakeLists.txt

@@ -8,9 +8,9 @@ find_package(Threads REQUIRED)
 
 set(LIBS ${CHECK_LIBRARIES})
 if(NOT WIN32)
-  list(APPEND LIBS pthread m subunit)
+  list(APPEND LIBS pthread m)
   if (NOT APPLE)
-    list(APPEND LIBS rt)
+    list(APPEND LIBS rt subunit)
   endif()
 else()
     list(APPEND LIBS ws2_32)

+ 17 - 0
tools/travis_linux_before_install.sh

@@ -0,0 +1,17 @@
+#!/bin/bash
+set -ev
+sudo apt-get install binutils-mingw-w64-i686 gcc-mingw-w64-i686 mingw-w64
+sudo add-apt-repository ppa:kalakris/cmake -y
+sudo apt-get update -qq
+sudo apt-get install -qq --no-install-recommends build-essential cmake python-lxml gcc-multilib graphviz doxygen wget zip
+sudo apt-get install libsubunit-dev #for check_0.10.0
+wget http://ftp.de.debian.org/debian/pool/main/c/check/check_0.10.0-2_amd64.deb
+sudo dpkg -i check_0.10.0-2_amd64.deb
+wget https://launchpad.net/ubuntu/+source/liburcu/0.8.5-1ubuntu1/+build/6513813/+files/liburcu2_0.8.5-1ubuntu1_amd64.deb
+wget https://launchpad.net/ubuntu/+source/liburcu/0.8.5-1ubuntu1/+build/6513813/+files/liburcu-dev_0.8.5-1ubuntu1_amd64.deb
+sudo dpkg -i liburcu2_0.8.5-1ubuntu1_amd64.deb
+sudo dpkg -i liburcu-dev_0.8.5-1ubuntu1_amd64.deb
+sudo pip install cpp-coveralls
+sudo pip install sphinx
+sudo pip install breathe
+sudo pip install sphinx_rtd_theme

+ 72 - 0
tools/travis_linux_script.sh

@@ -0,0 +1,72 @@
+#!/bin/bash
+set -ev
+echo "Checking the applicability of patches"
+# ./tools/.checkPorts.sh
+echo "Documentation and certificate build"
+mkdir -p build
+cd build
+cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=ON -DGENERATE_SELFSIGNED=ON ..
+make doc
+make selfsigned
+cp -r doc ..
+cp server_cert.der ..
+echo "Testing builds"
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Cross compile release build for MinGW 32 bit"
+cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
+make
+cp ../README.md .
+cp ../LICENSE .
+cp ../AUTHORS .
+cp -r ../doc .
+cp ../server_cert.der .
+zip -r open62541-win32.zip doc server_cert.der LICENSE AUTHORS README.md server_static.exe server.exe client.exe client_static.exe libopen62541.dll libopen62541.dll.a open62541.h open62541.c
+cp open62541-win32.zip ..
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Cross compile release build for MinGW 64 bit"
+cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-mingw64.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
+make
+cp ../README.md .
+cp ../LICENSE .
+cp ../AUTHORS .
+cp -r ../doc .
+cp ../server_cert.der .
+zip -r open62541-win64.zip doc server_cert.der LICENSE AUTHORS README.md server_static.exe server.exe client.exe client_static.exe libopen62541.dll libopen62541.dll.a open62541.h open62541.c
+cp open62541-win64.zip ..
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Cross compile release build for 32-bit linux"
+cmake -DCMAKE_TOOLCHAIN_FILE=../cmake/Toolchain-gcc-m32.cmake -DENABLE_AMALGAMATION=ON -DCMAKE_BUILD_TYPE=Release -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
+make
+tar -pczf open62541-linux32.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
+cp open62541-linux32.tar.gz ..
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Compile release build for 64-bit linux"
+cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_AMALGAMATION=ON -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
+make
+tar -pczf open62541-linux64.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.so open62541.h open62541.c
+cp open62541-linux64.tar.gz ..
+cp open62541.h .. #copy single file-release
+cp open62541.c .. #copy single file-release
+echo "Upgrade to gcc 4.8"
+sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+sudo apt-get update -qq
+sudo apt-get install -qq gcc-4.8 g++-4.8 valgrind
+sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 20
+sudo update-alternatives --config gcc
+echo "Building the C++ example"
+gcc -std=c99 -c open62541.c
+g++-4.8 ../examples/server.cpp -I./ open62541.o -o cpp-server
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Compile multithreaded version"
+cmake -DENABLE_MULTITHREADING=ON -DBUILD_EXAMPLESERVER=ON ..
+make
+cd .. && rm build -rf && mkdir -p build && cd build
+echo "Debug build and unit tests (64 bit)"
+cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_DEMO_NODESET=ON -DBUILD_UNIT_TESTS=ON -DBUILD_EXAMPLESERVER=ON -DENABLE_COVERAGE=ON ..
+make && make test
+echo "Run valgrind to see if the server leaks memory (just starting up and closing..)"
+if [[ ! ( ${TRAVIS_OS_NAME} == "linux" && ${CC} == "clang") ]]; then
+  (valgrind --error-exitcode=3 ./server & export pid=$!; sleep 2; kill -INT $pid; wait $pid);
+  (coveralls --gcov /usr/bin/gcov-4.8 -E '.*\.h' -E '.*CMakeCXXCompilerId\.cpp' -E '.*CMakeCCompilerId\.c' -r ../ ; exit 0);
+fi
+cd ..

+ 14 - 0
tools/travis_osx_before_install.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+set -ev
+brew install cmake
+brew install check
+brew install libxml2
+brew install userspace-rcu
+brew install graphviz
+brew install doxygen
+brew install swig
+brew install --HEAD valgrind
+
+sudo pip install lxml
+sudo pip install sphinx
+sudo pip install breathe

+ 30 - 0
tools/travis_osx_script.sh

@@ -0,0 +1,30 @@
+#!/bin/bash
+set -ev
+echo "Documentation and certificate build"
+mkdir -p build
+cd build
+cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_DOCUMENTATION=ON -DGENERATE_SELFSIGNED=ON ..
+make doc
+make selfsigned
+cp -r doc ..
+cp server_cert.der ..
+echo "Testing builds"
+cd .. && rm -rf build && mkdir -p build && cd build
+echo "Compile release build for OS X"
+cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_AMALGAMATION=ON -DBUILD_EXAMPLESERVER=ON -DBUILD_EXAMPLECLIENT=ON ..
+make
+tar -pczf open62541-osx.tar.gz ../doc ../server_cert.der ../LICENSE ../AUTHORS ../README.md server_static server client_static client libopen62541.dylib open62541.h open62541.c
+cp open62541-osx.tar.gz ..
+cp open62541.h .. #copy single file-release
+cp open62541.c .. #copy single file-release
+cd .. && rm -rf build && mkdir -p build && cd build
+echo "Compile multithreaded version"
+cmake -DENABLE_MULTITHREADING=ON -DBUILD_EXAMPLESERVER=ON ..
+make
+cd .. && rm -rf build && mkdir -p build && cd build
+echo "Debug build and unit tests (64 bit)"
+cmake -DCMAKE_BUILD_TYPE=Debug -DBUILD_DEMO_NODESET=ON -DBUILD_UNIT_TESTS=ON -DBUILD_EXAMPLESERVER=ON -DENABLE_COVERAGE=ON ..
+make && make test
+echo "Run valgrind to see if the server leaks memory (just starting up and closing..)"
+(valgrind --error-exitcode=3 ./server & export pid=$!; sleep 2; kill -INT $pid; wait $pid);
+cd ..