Explorar o código

Add support for Arduino and ESP32

Stefan Profanter %!s(int64=6) %!d(string=hai) anos
pai
achega
05667bbb06

+ 34 - 11
CMakeLists.txt

@@ -51,18 +51,33 @@ if(NOT CMAKE_BUILD_TYPE)
     set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "Choose the type of build" FORCE)
 endif()
 
+
+option(UA_ENABLE_AMALGAMATION "Concatenate the library to a single file open62541.h/.c" OFF)
+set(UA_AMALGAMATION_ARCHITECUTRES "" CACHE STRING "List of architectures to include in amalgamation")
+mark_as_advanced(UA_AMALGAMATION_ARCHITECUTRES)
+
 # Platform. This is at the beginning in case the architecture changes some UA options
 set(UA_ARCHITECTURE "None" CACHE STRING "Architecture to build open62541 on")
 
-if(${UA_ARCHITECTURE} STREQUAL "None")
-  if(UNIX)
-    set(UA_ARCHITECTURE "posix" CACHE STRING "" FORCE)
-  elseif(WIN32)  
-    set(UA_ARCHITECTURE "win32" CACHE STRING ""  FORCE)
-  endif(UNIX)
-endif(${UA_ARCHITECTURE} STREQUAL "None")
+if(UA_ENABLE_AMALGAMATION)
+    if("${UA_AMALGAMATION_ARCHITECUTRES}" STREQUAL "")
+        # select some default architectures which should be included
+        set(UA_AMALGAMATION_ARCHITECUTRES "win32;posix")
+    endif()
+    message(STATUS "Architectures included in amalgamation: ${UA_AMALGAMATION_ARCHITECUTRES}")
+endif()
 
-message(STATUS "The selected architecture is ${UA_ARCHITECTURE}")
+if("${UA_ARCHITECTURE}" STREQUAL "None")
+    if(UNIX)
+        set(UA_ARCHITECTURE "posix" CACHE STRING "" FORCE)
+    elseif(WIN32)
+        set(UA_ARCHITECTURE "win32" CACHE STRING ""  FORCE)
+    endif(UNIX)
+endif()
+
+message(STATUS "The selected architecture is: ${UA_ARCHITECTURE}")
+string(TOUPPER ${UA_ARCHITECTURE} UA_ARCHITECTURE_UPPER)
+add_definitions(-DUA_ARCHITECTURE_${UA_ARCHITECTURE_UPPER})
 
 add_subdirectory(arch)
 
@@ -99,7 +114,6 @@ option(UA_ENABLE_NODEMANAGEMENT "Enable dynamic addition and removal of nodes at
 option(UA_ENABLE_SUBSCRIPTIONS "Enable subscriptions support." ON)
 option(UA_ENABLE_DISCOVERY "Enable Discovery Service (LDS)" ON)
 option(UA_ENABLE_DISCOVERY_MULTICAST "Enable Discovery Service with multicast support (LDS-ME)" OFF)
-option(UA_ENABLE_AMALGAMATION "Concatenate the library to a single file open62541.h/.c" OFF)
 option(UA_ENABLE_COVERAGE "Enable gcov coverage" OFF)
 option(BUILD_SHARED_LIBS "Enable building of shared libraries (dll/so)" OFF)
 
@@ -364,8 +378,17 @@ include_directories(${PROJECT_SOURCE_DIR}/include
                     ${PROJECT_BINARY_DIR}/src_generated
                     ${MBEDTLS_INCLUDE_DIRS})
 
-set(exported_headers ${PROJECT_SOURCE_DIR}/arch/${UA_ARCHITECTURE}/ua_architecture.h
-                     ${PROJECT_BINARY_DIR}/src_generated/ua_config.h
+if(NOT "${UA_AMALGAMATION_ARCHITECUTRES}" STREQUAL "")
+    set(exported_headers)
+    foreach(arch ${UA_AMALGAMATION_ARCHITECUTRES})
+        list(APPEND exported_headers ${PROJECT_SOURCE_DIR}/arch/${arch}/ua_architecture.h)
+    endforeach()
+else()
+    set(exported_headers ${PROJECT_SOURCE_DIR}/arch/${UA_ARCHITECTURE}/ua_architecture.h)
+endif()
+
+set(exported_headers ${exported_headers}
+                     ${PROJECT_BINARY_DIR}/src_generated/ua_config.h 
                      ${PROJECT_SOURCE_DIR}/deps/ms_stdint.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_statuscodes.h
                      ${PROJECT_BINARY_DIR}/src_generated/ua_nodeids.h

+ 2 - 1
README.md

@@ -106,7 +106,8 @@ As an open source project, new contributors are encouraged to help improve open6
 
 ### Example Server Implementation
 Compile the examples with the single-file distribution `open62541.h/.c` header and source file.
-Using the GCC compiler, just run ```gcc -std=c99 <server.c> open62541.c -o server``` (under Windows you may need to add ``` -lws2_32```).
+Using the GCC compiler, just run ```gcc -std=c99 -DUA_ARCHITECTURE_POSIX <server.c> open62541.c -o server``` (under Windows you may need to add ``` -lws2_32``` 
+and change `-DUA_ARCHITECTURE_POSIX` to `-DUA_ARCHITECTURE_WIN32`).
 ```c
 #include <signal.h>
 #include "open62541.h"

+ 10 - 3
arch/arduino/CMakeLists.txt

@@ -1,8 +1,15 @@
 SET(SOURCE_GROUP ${SOURCE_GROUP}\\arduino)
 
-ua_add_architecture("Arduino")
+ua_add_architecture("arduino")
 
-if("${UA_ARCHITECTURE}" STREQUAL "Arduino")
+list (FIND UA_AMALGAMATION_ARCHITECUTRES "arduino" _index)
+if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "arduino")
 
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
 
-endif()
+    if("${UA_ARCHITECTURE}" STREQUAL "arduino")
+        ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+    endif()
+
+endif()

+ 94 - 0
arch/arduino/ua_architecture.h

@@ -0,0 +1,94 @@
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ *    Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ *    Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
+ */
+
+#ifdef UA_ARCHITECTURE_ARDUINO
+
+#ifndef PLUGINS_ARCH_ARDUINO_UA_ARCHITECTURE_H_
+#define PLUGINS_ARCH_ARDUINO_UA_ARCHITECTURE_H_
+
+#define UA_THREAD_LOCAL
+
+#include <stdlib.h>
+#include <string.h>
+
+#define LWIP_TIMEVAL_PRIVATE 0
+//#define LWIP_COMPAT_MUTEX 0
+#define LWIP_POSIX_SOCKETS_IO_NAMES 0
+#ifdef LWIP_COMPAT_SOCKETS
+#undef LWIP_COMPAT_SOCKETS
+#endif
+#define LWIP_COMPAT_SOCKETS 0
+//#define __USE_W32_SOCKETS 1 //needed to avoid redefining of select in sys/select.h
+
+#include <lwip/tcpip.h>
+#include <lwip/netdb.h>
+#define sockaddr_storage sockaddr
+#ifdef BYTE_ORDER
+# undef BYTE_ORDER
+#endif
+#define UA_sleep_ms(X) vTaskDelay(pdMS_TO_TICKS(X))
+
+#define OPTVAL_TYPE int
+
+#include <unistd.h> // read, write, close
+
+#define UA_fd_set(fd, fds) FD_SET((unsigned int)fd, fds)
+#define UA_fd_isset(fd, fds) FD_ISSET((unsigned int)fd, fds)
+
+#define UA_access access
+
+#define UA_IPV6 0
+#define UA_SOCKET int
+#define UA_INVALID_SOCKET -1
+#define UA_ERRNO errno
+#define UA_INTERRUPTED EINTR
+#define UA_AGAIN EAGAIN
+#define UA_EAGAIN EAGAIN
+#define UA_WOULDBLOCK EWOULDBLOCK
+#define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
+
+// No log colors on Arduino
+// #define UA_ENABLE_LOG_COLORS
+
+#define UA_send lwip_send
+#define UA_recv lwip_recv
+#define UA_close lwip_close
+#define UA_select lwip_select
+#define UA_shutdown lwip_shutdown
+#define UA_socket lwip_socket
+#define UA_bind lwip_bind
+#define UA_listen lwip_listen
+#define UA_accept lwip_accept
+#define UA_connect lwip_connect
+#define UA_getsockopt lwip_getsockopt
+#define UA_setsockopt lwip_setsockopt
+#define UA_freeaddrinfo lwip_freeaddrinfo
+#define UA_gethostname gethostname_freertos
+#define UA_getaddrinfo lwip_getaddrinfo
+
+#define UA_free free
+#define UA_malloc malloc
+#define UA_calloc calloc
+#define UA_realloc realloc
+
+#include <stdio.h>
+#define UA_snprintf snprintf
+
+int gethostname_freertos(char* name, size_t len);
+
+#define UA_LOG_SOCKET_ERRNO_WRAP(LOG) { \
+    char *errno_str = ""; \
+    LOG; \
+}
+
+#define UA_LOG_SOCKET_ERRNO_GAI_WRAP UA_LOG_SOCKET_ERRNO_WRAP
+
+#include "../ua_architecture_functions.h"
+
+#endif /* PLUGINS_ARCH_ARDUINO_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_ARDUINO */

+ 39 - 0
arch/arduino/ua_architecture_functions.c

@@ -0,0 +1,39 @@
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
+ *    Copyright 2018 (c) Stefan Profanter, fortiss GmbH
+ */
+
+#ifdef UA_ARCHITECTURE_ARDUINO
+
+#include "ua_types.h"
+
+unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
+  int on = 0;
+  if(lwip_ioctl(sockfd, FIONBIO, &on) < 0)
+    return UA_STATUSCODE_BADINTERNALERROR;
+  return UA_STATUSCODE_GOOD;
+}
+
+unsigned int UA_socket_set_nonblocking(UA_SOCKET sockfd){
+  int on = 1;
+  if(lwip_ioctl(sockfd, FIONBIO, &on) < 0)
+    return UA_STATUSCODE_BADINTERNALERROR;
+  return UA_STATUSCODE_GOOD;
+}
+
+int gethostname_freertos(char* name, size_t len){
+    // use UA_ServerConfig_set_customHostname to set your hostname as the IP
+  return -1;
+}
+
+void UA_initialize_architecture_network(void){
+  return;
+}
+
+void UA_deinitialize_architecture_network(void){
+  return;
+}
+
+#endif /* UA_ARCHITECTURE_ARDUINO */

+ 60 - 0
arch/arduino/ua_clock.c

@@ -0,0 +1,60 @@
+/* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
+ * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
+ *
+ *    Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
+ *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ *    Copyright 2017 (c) Thomas Stalder
+ */
+
+#ifdef UA_ARCHITECTURE_ARDUINO
+
+/* Enable POSIX features */
+#if !defined(_XOPEN_SOURCE)
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _DEFAULT_SOURCE
+# define _DEFAULT_SOURCE
+#endif
+/* On older systems we need to define _BSD_SOURCE.
+ * _DEFAULT_SOURCE is an alias for that. */
+#ifndef _BSD_SOURCE
+# define _BSD_SOURCE
+#endif
+
+#include <time.h>
+#include <sys/time.h>
+
+#include "ua_types.h"
+
+#include <freertos/FreeRTOS.h>
+#include <freertos/task.h>
+
+UA_DateTime UA_DateTime_now(void) {
+    struct timeval tv;
+    gettimeofday(&tv, NULL);
+    return (tv.tv_sec * UA_DATETIME_SEC) + (tv.tv_usec * UA_DATETIME_USEC) + UA_DATETIME_UNIX_EPOCH;
+}
+
+/* Credit to https://stackoverflow.com/questions/13804095/get-the-time-zone-gmt-offset-in-c */
+UA_Int64 UA_DateTime_localTimeUtcOffset(void) {
+    time_t gmt, rawtime = time(NULL);
+    struct tm *ptm;
+    struct tm gbuf;
+    ptm = gmtime_r(&rawtime, &gbuf);
+    // Request that mktime() looksup dst in timezone database
+    ptm->tm_isdst = -1;
+    gmt = mktime(ptm);
+    return (UA_Int64) (difftime(rawtime, gmt) * UA_DATETIME_SEC);
+}
+
+UA_DateTime UA_DateTime_nowMonotonic(void) {
+    portTickType TaskTime = xTaskGetTickCount();
+    UA_DateTimeStruct UATime;
+    UATime.milliSec = (UA_UInt16) TaskTime;
+    struct timespec ts;
+    ts.tv_sec = UATime.milliSec/1000;
+    ts.tv_nsec = (UATime.milliSec % 1000)* 1000000;
+    return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
+}
+
+#endif /* UA_ARCHITECTURE_ARDUINO */

+ 19 - 12
arch/freertos/CMakeLists.txt

@@ -2,18 +2,25 @@ SET(SOURCE_GROUP ${SOURCE_GROUP}\\freertos)
 
 ua_add_architecture("freertos")
 
-if("${UA_ARCHITECTURE}" STREQUAL "freertos")
+list (FIND UA_AMALGAMATION_ARCHITECUTRES "freertos" _index)
+if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "freertos")
 
-    ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
     ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
     ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
-    
-    SET(UA_FREERTOS_INCLUDES "" CACHE STRING "Folders to include from the freeRTOS OS")
-    ua_include_directories(${UA_FREERTOS_INCLUDES})
-    
-    ua_architecture_remove_definitions(-fPIC -Wconversion )
-    ua_architecture_add_definitions(-DUA_FREERTOS -mcpu=cortex-m3 -mthumb -g -Wall -O0 -specs=nano.specs 
-                -ffunction-sections -fdata-sections  -fno-exceptions -fstack-usage -Wno-unused-variable -Wno-format -Wno-format-security -Wno-format-nonliteral)
-    ua_architecture_append_to_library(c m stdc++ supc++)
-
-endif()
+
+    if("${UA_ARCHITECTURE}" STREQUAL "freertos")
+
+        ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+        SET(UA_FREERTOS_INCLUDES "" CACHE STRING "Folders to include from the freeRTOS OS")
+        ua_include_directories(${UA_FREERTOS_INCLUDES})
+
+        ua_architecture_remove_definitions(-fPIC -Wconversion )
+        ua_architecture_add_definitions(-DUA_FREERTOS -mcpu=cortex-m3 -mthumb -g -Wall -O0 -specs=nano.specs
+                    -ffunction-sections -fdata-sections  -fno-exceptions -fstack-usage -Wno-unused-variable -Wno-format -Wno-format-security -Wno-format-nonliteral)
+        ua_architecture_append_to_library(c m stdc++ supc++)
+
+        set(UA_FREERTOS_HOSTNAME "freertos-host" CACHE STRING "Define a custom hostname/ip for the endpoint.")
+        ua_architecture_add_definitions(-DUA_FREERTOS_HOSTNAME="${UA_FREERTOS_HOSTNAME}")
+    endif()
+endif()

+ 10 - 2
arch/freertos/ua_architecture.h

@@ -2,9 +2,12 @@
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  *
  *    Copyright 2016-2017 (c) Julius Pfrommer, Fraunhofer IOSB
- *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
+ *    Copyright 2017-2018 (c) Stefan Profanter, fortiss GmbH
+ *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_FREERTOS
+
 #ifndef PLUGINS_ARCH_FREERTOS_UA_ARCHITECTURE_H_
 #define PLUGINS_ARCH_FREERTOS_UA_ARCHITECTURE_H_
 
@@ -15,7 +18,7 @@
 
 #define AI_PASSIVE 0x01
 
-#define UA_FREERTOS_HOSTNAME "10.200.4.114"
+#define UA_THREAD_LOCAL
 
 #include <stdlib.h>
 #include <string.h>
@@ -56,6 +59,9 @@
 #define UA_WOULDBLOCK EWOULDBLOCK
 #define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
 
+// No log colors on FreeRTOS
+// #define UA_ENABLE_LOG_COLORS
+
 #define UA_send lwip_send
 #define UA_recv lwip_recv
 #define UA_close lwip_close
@@ -91,3 +97,5 @@ int gethostname_freertos(char* name, size_t len);
 #include "../ua_architecture_functions.h"
 
 #endif /* PLUGINS_ARCH_FREERTOS_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_FREERTOS */

+ 6 - 3
arch/freertos/ua_architecture_functions.c

@@ -1,9 +1,11 @@
 /* This work is licensed under a Creative Commons CCZero 1.0 Universal License.
  * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
  *
- *    Copyright 2018 (c) Jose Cabral, fortiss IOSB
+ *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_FREERTOS
+
 #include "ua_types.h"
 
 unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
@@ -29,8 +31,7 @@ int gethostname_freertos(char* name, size_t len){
 
 int UA_getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res){
   if(NULL == node){
-    const char* hostname = UA_FREERTOS_HOSTNAME;
-    return lwip_getaddrinfo(hostname, service, hints, res);
+    return lwip_getaddrinfo(UA_FREERTOS_HOSTNAME, service, hints, res);
   }else{
     return lwip_getaddrinfo(node, service, hints, res);
   }
@@ -43,3 +44,5 @@ void UA_initialize_architecture_network(void){
 void UA_deinitialize_architecture_network(void){
   return;
 }
+
+#endif /* UA_ARCHITECTURE_FREERTOS */

+ 4 - 0
arch/freertos/ua_clock.c

@@ -6,6 +6,8 @@
  *    Copyright 2017 (c) Thomas Stalder
  */
 
+#ifdef UA_ARCHITECTURE_FREERTOS
+
 #include "ua_types.h"
 #include <time.h>
 #include <sys/time.h>
@@ -39,3 +41,5 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
     ts.tv_nsec = (UATime.milliSec % 1000)* 1000000;
     return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
 }
+
+#endif /* UA_ARCHITECTURE_FREERTOS */

+ 11 - 5
arch/posix/CMakeLists.txt

@@ -2,10 +2,16 @@ SET(SOURCE_GROUP ${SOURCE_GROUP}\\posix)
 
 ua_add_architecture("posix")
 
-if("${UA_ARCHITECTURE}" STREQUAL "posix")
+list (FIND UA_AMALGAMATION_ARCHITECUTRES "posix" _index)
+if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "posix")
 
-ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
-ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
 
-endif()
+    if("${UA_ARCHITECTURE}" STREQUAL "posix")
+
+        ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+    endif()
+
+endif()

+ 23 - 0
arch/posix/ua_architecture.h

@@ -5,6 +5,8 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_POSIX
+
 #ifndef PLUGINS_ARCH_POSIX_UA_ARCHITECTURE_H_
 #define PLUGINS_ARCH_POSIX_UA_ARCHITECTURE_H_
 
@@ -47,6 +49,23 @@
 # include <netinet/tcp.h>
 #endif
 
+
+/* Thread-Local Storage
+ * --------------------
+ * Thread-local storage is not required by the main library functionality. It is
+ * only used for some testing strategies. ``UA_THREAD_LOCAL`` is empty if the
+ * feature is not available. */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+# define UA_THREAD_LOCAL _Thread_local /* C11 */
+#elif defined(__cplusplus) && __cplusplus > 199711L
+# define UA_THREAD_LOCAL thread_local /* C++11 */
+#elif defined(__GNUC__)
+# define UA_THREAD_LOCAL __thread /* GNU extension */
+#else
+# define UA_THREAD_LOCAL
+#endif
+
 /* unsigned int for windows and workaround to a glibc bug */
 /* Additionally if GNU_LIBRARY is not defined, it may be using
  * musl libc (e.g. Docker Alpine) */
@@ -73,6 +92,8 @@
 #define UA_WOULDBLOCK EWOULDBLOCK
 #define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
 
+#define UA_ENABLE_LOG_COLORS
+
 #define UA_getnameinfo getnameinfo
 #define UA_send send
 #define UA_recv recv
@@ -111,3 +132,5 @@
 #include "../ua_architecture_functions.h"
 
 #endif /* PLUGINS_ARCH_POSIX_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_POSIX */

+ 4 - 0
arch/posix/ua_architecture_functions.c

@@ -4,6 +4,8 @@
  *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_POSIX
+
 #include "ua_types.h"
 
 unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
@@ -27,3 +29,5 @@ void UA_initialize_architecture_network(void){
 void UA_deinitialize_architecture_network(void){
   return;
 }
+
+#endif /* UA_ARCHITECTURE_POSIX */

+ 4 - 0
arch/posix/ua_clock.c

@@ -6,6 +6,8 @@
  *    Copyright 2017 (c) Thomas Stalder, Blue Time Concept SA
  */
 
+#ifdef UA_ARCHITECTURE_POSIX
+
 #include "ua_types.h"
 #include <time.h>
 #include <sys/time.h>
@@ -52,3 +54,5 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
     return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
 #endif
 }
+
+#endif /* UA_ARCHITECTURE_POSIX */

+ 29 - 0
arch/ua_architecture_functions.h

@@ -38,6 +38,35 @@ void* UA_realloc(void *ptr, size_t new_size);//re-allocate memory in the heap wi
 void UA_free(void* ptr); //de-allocate memory previously allocated with UA_malloc, UA_calloc or UA_realloc
 #endif
 
+/**
+ * Memory Management
+ * -----------------
+ * The default is to use the malloc implementation from ``stdlib.h``. Override
+ * if required. Changing the settings has no effect on a pre-compiled
+ * library. */
+#ifndef UA_alloca
+# if defined(__GNUC__) || defined(__clang__)
+#  define UA_alloca(size) __builtin_alloca (size)
+# elif defined(_WIN32)
+#  define UA_alloca(SIZE) _alloca(SIZE)
+# else
+#  include <alloca.h>
+#  define UA_alloca(SIZE) alloca(SIZE)
+# endif
+#endif
+
+#ifndef UA_STACKARRAY
+/* Stack-allocation of memory. Use C99 variable-length arrays if possible.
+ * Otherwise revert to alloca. Note that alloca is not supported on some
+ * plattforms. */
+# if defined(__GNUC__) || defined(__clang__)
+#  define UA_STACKARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
+# else
+#  define UA_STACKARRAY(TYPE, NAME, SIZE) \
+    TYPE *NAME = (TYPE*)UA_alloca(sizeof(TYPE) * SIZE)
+# endif
+#endif
+
 /*
  * Sleep function
  */

+ 2 - 0
arch/ua_network_tcp.c

@@ -333,6 +333,8 @@ ServerNetworkLayerTCP_start(UA_ServerNetworkLayer *nl, const UA_String *customHo
             du.length = (size_t)UA_snprintf(discoveryUrl, 255, "opc.tcp://%s:%d/",
                                          hostname, layer->port);
             du.data = (UA_Byte*)discoveryUrl;
+        } else {
+            UA_LOG_ERROR(layer->logger, UA_LOGCATEGORY_NETWORK, "Could not get the hostname");
         }
     }
     UA_String_copy(&du, &nl->discoveryUrl);

+ 13 - 7
arch/vxworks/CMakeLists.txt

@@ -2,13 +2,19 @@ SET(SOURCE_GROUP ${SOURCE_GROUP}\\vxworks)
 
 ua_add_architecture("vxworks")
 
-if("${UA_ARCHITECTURE}" STREQUAL "vxworks")
+list (FIND UA_AMALGAMATION_ARCHITECUTRES "vxworks" _index)
+if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "vxworks")
 
-    ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
     ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
     ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
-    
-    ua_architecture_remove_definitions(-Werror -Wpedantic -Wno-static-in-inline -fPIC)
-    ua_architecture_add_definitions(-D_WRS_KERNEL)
-    
-endif()
+
+    if("${UA_ARCHITECTURE}" STREQUAL "vxworks")
+
+        ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+        ua_architecture_remove_definitions(-Werror -Wpedantic -Wno-static-in-inline -fPIC)
+        ua_architecture_add_definitions(-D_WRS_KERNEL)
+
+    endif()
+
+endif()

+ 24 - 0
arch/vxworks/ua_architecture.h

@@ -5,6 +5,8 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_VXWORKS
+
 #ifndef PLUGINS_ARCH_VXWORKS_UA_ARCHITECTURE_H_
 #define PLUGINS_ARCH_VXWORKS_UA_ARCHITECTURE_H_
 
@@ -38,6 +40,24 @@
 #endif
 #define UA_BINARY_OVERLAYABLE_FLOAT 1
 
+
+/* Thread-Local Storage
+ * --------------------
+ * Thread-local storage is not required by the main library functionality. It is
+ * only used for some testing strategies. ``UA_THREAD_LOCAL`` is empty if the
+ * feature is not available. */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+# define UA_THREAD_LOCAL _Thread_local /* C11 */
+#elif defined(__cplusplus) && __cplusplus > 199711L
+# define UA_THREAD_LOCAL thread_local /* C++11 */
+#elif defined(__GNUC__)
+# define UA_THREAD_LOCAL __thread /* GNU extension */
+#else
+# define UA_THREAD_LOCAL
+#endif
+
+
 #define OPTVAL_TYPE int
 
 #include <fcntl.h>
@@ -59,6 +79,8 @@
 #define UA_WOULDBLOCK EWOULDBLOCK
 #define UA_ERR_CONNECTION_PROGRESS EINPROGRESS
 
+#define UA_ENABLE_LOG_COLORS
+
 #define UA_getnameinfo getnameinfo
 #define UA_send send
 #define UA_recv recv
@@ -97,3 +119,5 @@
 #include "../ua_architecture_functions.h"
 
 #endif /* PLUGINS_ARCH_VXWORKS_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_VXWORKS */

+ 4 - 0
arch/vxworks/ua_architecture_functions.c

@@ -4,6 +4,8 @@
  *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_VXWORKS
+
 #include "ua_types.h"
 
 unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
@@ -27,3 +29,5 @@ void UA_initialize_architecture_network(void){
 void UA_deinitialize_architecture_network(void){
   return;
 }
+
+#endif /* UA_ARCHITECTURE_VXWORKS */

+ 5 - 0
arch/vxworks/ua_clock.c

@@ -6,6 +6,8 @@
  *    Copyright 2017 (c) Thomas Stalder
  */
 
+#ifdef UA_ARCHITECTURE_VXWORKS
+
 #ifndef _DEFAULT_SOURCE
 # define _DEFAULT_SOURCE
 #endif
@@ -49,3 +51,6 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
 #endif
   return (ts.tv_sec * UA_DATETIME_SEC) + (ts.tv_nsec / 100);
 }
+
+#endif /* UA_ARCHITECTURE_VXWORKS */
+

+ 10 - 5
arch/win32/CMakeLists.txt

@@ -2,11 +2,16 @@ SET(SOURCE_GROUP ${SOURCE_GROUP}\\win32)
 
 ua_add_architecture("win32")
 
-if("${UA_ARCHITECTURE}" STREQUAL "win32")
+list (FIND UA_AMALGAMATION_ARCHITECUTRES "win32" _index)
+if (${_index} GREATER -1 OR "${UA_ARCHITECTURE}" STREQUAL "win32")
 
-ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
-ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
-ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_clock.c)
+    ua_add_architecture_file(${CMAKE_CURRENT_SOURCE_DIR}/ua_architecture_functions.c)
 
+    if("${UA_ARCHITECTURE}" STREQUAL "win32")
 
-endif()
+        ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+    endif()
+
+endif()

+ 22 - 0
arch/win32/ua_architecture.h

@@ -5,6 +5,8 @@
  *    Copyright 2017 (c) Stefan Profanter, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_WIN32
+
 #ifndef PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
 #define PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_
 
@@ -34,6 +36,21 @@
 # define POP_SLIST_ENTRY
 #endif
 
+/* Thread-Local Storage
+ * --------------------
+ * Thread-local storage is not required by the main library functionality. It is
+ * only used for some testing strategies. ``UA_THREAD_LOCAL`` is empty if the
+ * feature is not available. */
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+# define UA_THREAD_LOCAL _Thread_local /* C11 */
+#elif defined(__cplusplus) && __cplusplus > 199711L
+# define UA_THREAD_LOCAL thread_local /* C++11 */
+#elif defined(_MSC_VER)
+# define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
+#else
+# define UA_THREAD_LOCAL
+#endif
 
 #include <stdlib.h>
 #if defined(_WIN32) && !defined(__clang__)
@@ -75,6 +92,9 @@
 # define errno
 #endif
 
+// Windows does not support ansi colors
+// #define UA_ENABLE_LOG_COLORS
+
 #define UA_IPV6 1
 #define UA_SOCKET int
 #define UA_INVALID_SOCKET -1
@@ -123,3 +143,5 @@
 #include "../ua_architecture_functions.h"
 
 #endif /* PLUGINS_ARCH_WIN32_UA_ARCHITECTURE_H_ */
+
+#endif /* UA_ARCHITECTURE_WIN32 */

+ 4 - 0
arch/win32/ua_architecture_functions.c

@@ -4,6 +4,8 @@
  *    Copyright 2018 (c) Jose Cabral, fortiss GmbH
  */
 
+#ifdef UA_ARCHITECTURE_WIN32
+
 #include "ua_types.h"
 
 unsigned int UA_socket_set_blocking(UA_SOCKET sockfd){
@@ -29,3 +31,5 @@ void UA_initialize_architecture_network(void){
 void UA_deinitialize_architecture_network(void){
   WSACleanup();
 }
+
+#endif /* UA_ARCHITECTURE_WIN32 */

+ 4 - 0
arch/win32/ua_clock.c

@@ -6,6 +6,8 @@
  *    Copyright 2017 (c) Thomas Stalder
  */
 
+#ifdef UA_ARCHITECTURE_WIN32
+
 #ifndef _BSD_SOURCE
 # define _BSD_SOURCE
 #endif
@@ -58,3 +60,5 @@ UA_DateTime UA_DateTime_nowMonotonic(void) {
     UA_Double ticks2dt = UA_DATETIME_SEC / (UA_Double)freq.QuadPart;
     return (UA_DateTime)(ticks.QuadPart * ticks2dt);
 }
+
+#endif /* UA_ARCHITECTURE_WIN32 */

+ 1 - 1
doc/building.rst

@@ -12,7 +12,7 @@ Using the GCC compiler, the following calls build the examples on Linux.
 
    cp /path-to/open62541.* . # copy single-file distribution to the local directory
    cp /path-to/examples/server_variable.c . # copy the example server
-   gcc -std=c99 open62541.c server_variable.c -o server
+   gcc -std=c99 -DUA_ARCHITECTURE_POSIX open62541.c server_variable.c -o server
 
 Building the Library
 --------------------

+ 2 - 10
examples/server_ctt.c

@@ -283,11 +283,7 @@ main(int argc, char **argv) {
         attr.dataType = UA_TYPES[type].typeId;
 #ifndef UA_ENABLE_TYPENAMES
         char name[15];
-#if defined(_WIN32) && !defined(__MINGW32__)
-        sprintf_s(name, 15, "%02d", type);
-#else
-        sprintf(name, "%02d", type);
-#endif
+        UA_snprintf(name, 15, "%02d", type);
         attr.displayName = UA_LOCALIZEDTEXT("en-US", name);
         UA_QualifiedName qualifiedName = UA_QUALIFIEDNAME(1, name);
 #else
@@ -344,11 +340,7 @@ main(int argc, char **argv) {
     id = DEPTHID; // running id in namespace 0 - Start with Matrix NODE
     for(UA_UInt32 i = 1; i <= 20; i++) {
         char name[15];
-#if defined(_WIN32) && !defined(__MINGW32__)
-        sprintf_s(name, 15, "depth%i", i);
-#else
-        sprintf(name, "depth%i", i);
-#endif
+        UA_snprintf(name, 15, "depth%i", i);
         object_attr.description = UA_LOCALIZEDTEXT("en-US", name);
         object_attr.displayName = UA_LOCALIZEDTEXT("en-US", name);
         UA_Server_addObjectNode(server, UA_NODEID_NUMERIC(1, id + i),

+ 0 - 21
include/ua_config.h.in

@@ -104,27 +104,6 @@ extern "C" {
 # define UA_STATIC_ASSERT(cond,msg) typedef char static_assertion_##msg[(cond)?1:-1]
 #endif
 
-/**
- * Memory Management
- * -----------------
- * The default is to use the malloc implementation from ``stdlib.h``. Override
- * if required. Changing the settings has no effect on a pre-compiled
- * library. */
-
-/* Stack-allocation of memory. Use C99 variable-length arrays if possible.
- * Otherwise revert to alloca. Note that alloca is not supported on some
- * plattforms. */
-#if defined(__GNUC__) || defined(__clang__)
-# define UA_STACKARRAY(TYPE, NAME, SIZE) TYPE NAME[SIZE]
-#elif defined(_WIN32)
-# define UA_STACKARRAY(TYPE, NAME, SIZE) \
-    TYPE *NAME = (TYPE*)_alloca(sizeof(TYPE) * SIZE)
-#else
-# include <alloca.h>
-# define UA_STACKARRAY(TYPE, NAME, SIZE) \
-    TYPE *NAME = (TYPE*)alloca(sizeof(TYPE) * SIZE)
-#endif
-
 /**
  * Function Export
  * ---------------

+ 14 - 6
plugins/ua_config_default.c

@@ -283,23 +283,31 @@ createDefaultConfig(void) {
 }
 
 static UA_StatusCode
-addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber) {
+addDefaultNetworkLayers(UA_ServerConfig *conf, UA_UInt16 portNumber, UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize) {
     /* Add a network layer */
     conf->networkLayers = (UA_ServerNetworkLayer *)
         UA_malloc(sizeof(UA_ServerNetworkLayer));
     if(!conf->networkLayers)
         return UA_STATUSCODE_BADOUTOFMEMORY;
 
+    UA_ConnectionConfig config = UA_ConnectionConfig_default;
+    if (sendBufferSize > 0)
+        config.sendBufferSize = sendBufferSize;
+    if (recvBufferSize > 0)
+        config.recvBufferSize = recvBufferSize;
+
     conf->networkLayers[0] =
-        UA_ServerNetworkLayerTCP(UA_ConnectionConfig_default, portNumber, conf->logger);
+        UA_ServerNetworkLayerTCP(config, portNumber, conf->logger);
     conf->networkLayersSize = 1;
 
     return UA_STATUSCODE_GOOD;
 }
 
 UA_ServerConfig *
-UA_ServerConfig_new_minimal(UA_UInt16 portNumber,
-                            const UA_ByteString *certificate) {
+UA_ServerConfig_new_customBuffer(UA_UInt16 portNumber,
+                                 const UA_ByteString *certificate,
+                                 UA_UInt32 sendBufferSize,
+                                 UA_UInt32 recvBufferSize) {
     UA_ServerConfig *conf = createDefaultConfig();
 
     UA_StatusCode retval = UA_Nodestore_default_new(&conf->nodestore);
@@ -308,7 +316,7 @@ UA_ServerConfig_new_minimal(UA_UInt16 portNumber,
         return NULL;
     }
 
-    if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+    if(addDefaultNetworkLayers(conf, portNumber, sendBufferSize, recvBufferSize) != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }
@@ -361,7 +369,7 @@ UA_ServerConfig_new_basic128rsa15(UA_UInt16 portNumber,
         return NULL;
     }
 
-    if(addDefaultNetworkLayers(conf, portNumber) != UA_STATUSCODE_GOOD) {
+    if(addDefaultNetworkLayers(conf, portNumber, 0, 0) != UA_STATUSCODE_GOOD) {
         UA_ServerConfig_delete(conf);
         return NULL;
     }

+ 23 - 2
plugins/ua_config_default.h

@@ -27,6 +27,25 @@ extern const UA_EXPORT UA_ConnectionConfig UA_ConnectionConfig_default;
 /* Default Server Config */
 /*************************/
 
+
+
+/* Creates a new server config with one endpoint and custom buffer size.
+ *
+ * The config will set the tcp network layer to the given port and adds a single
+ * endpoint with the security policy ``SecurityPolicy#None`` to the server. A
+ * server certificate may be supplied but is optional.
+ * Additionally you can define a custom buffer size for send and receive buffer.
+ *
+ * @param portNumber The port number for the tcp network layer
+ * @param certificate Optional certificate for the server endpoint. Can be
+ *        ``NULL``.
+ * @param sendBufferSize The size in bytes for the network send buffer
+ * @param recvBufferSize The size in bytes for the network receive buffer
+ *
+ */
+UA_EXPORT UA_ServerConfig *
+UA_ServerConfig_new_customBuffer(UA_UInt16 portNumber, const UA_ByteString *certificate, UA_UInt32 sendBufferSize, UA_UInt32 recvBufferSize);
+
 /* Creates a new server config with one endpoint.
  * 
  * The config will set the tcp network layer to the given port and adds a single
@@ -36,8 +55,10 @@ extern const UA_EXPORT UA_ConnectionConfig UA_ConnectionConfig_default;
  * @param portNumber The port number for the tcp network layer
  * @param certificate Optional certificate for the server endpoint. Can be
  *        ``NULL``. */
-UA_EXPORT UA_ServerConfig *
-UA_ServerConfig_new_minimal(UA_UInt16 portNumber, const UA_ByteString *certificate);
+static UA_INLINE UA_ServerConfig *
+UA_ServerConfig_new_minimal(UA_UInt16 portNumber, const UA_ByteString *certificate) {
+    return UA_ServerConfig_new_customBuffer(4840, NULL, 0 ,0);
+}
 
 #ifdef UA_ENABLE_ENCRYPTION
 

+ 9 - 9
plugins/ua_log_stdout.c

@@ -13,15 +13,7 @@
 /* ANSI escape sequences for color output taken from here:
  * https://stackoverflow.com/questions/3219393/stdlib-and-colored-output-in-c*/
 
-#ifdef _WIN32
-# define ANSI_COLOR_RED     ""
-# define ANSI_COLOR_GREEN   ""
-# define ANSI_COLOR_YELLOW  ""
-# define ANSI_COLOR_BLUE    ""
-# define ANSI_COLOR_MAGENTA ""
-# define ANSI_COLOR_CYAN    ""
-# define ANSI_COLOR_RESET   ""
-#else
+#ifdef UA_ENABLE_LOG_COLORS
 # define ANSI_COLOR_RED     "\x1b[31m"
 # define ANSI_COLOR_GREEN   "\x1b[32m"
 # define ANSI_COLOR_YELLOW  "\x1b[33m"
@@ -29,6 +21,14 @@
 # define ANSI_COLOR_MAGENTA "\x1b[35m"
 # define ANSI_COLOR_CYAN    "\x1b[36m"
 # define ANSI_COLOR_RESET   "\x1b[0m"
+#else
+# define ANSI_COLOR_RED     ""
+# define ANSI_COLOR_GREEN   ""
+# define ANSI_COLOR_YELLOW  ""
+# define ANSI_COLOR_BLUE    ""
+# define ANSI_COLOR_MAGENTA ""
+# define ANSI_COLOR_CYAN    ""
+# define ANSI_COLOR_RESET   ""
 #endif
 
 #ifdef UA_ENABLE_MULTITHREADING

+ 1 - 7
src/server/ua_mdns.c

@@ -233,14 +233,8 @@ setSrv(UA_Server *server, const struct resource *r,
 
     // todo: malloc may fail: return a statuscode
     char *newUrl = (char*)UA_malloc(10 + srvNameLen + 8);
-    #ifndef _MSC_VER
-    snprintf(newUrl, 10 + srvNameLen + 8, "opc.tcp://%.*s:%d/", (int) srvNameLen,
+    UA_snprintf(newUrl, 10 + srvNameLen + 8, "opc.tcp://%.*s:%d/", (int) srvNameLen,
              r->known.srv.name, r->known.srv.port);
-    #else
-    _snprintf_s(newUrl, 10 + srvNameLen + 8, _TRUNCATE, "opc.tcp://%.*s:%d/", (int) srvNameLen,
-             r->known.srv.name, r->known.srv.port);
-    #endif
-
     UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SERVER,
                 "Multicast DNS: found server: %s", newUrl);
     entry->serverOnNetwork.discoveryUrl = UA_String_fromChars(newUrl);

+ 0 - 18
src/ua_util.h

@@ -26,24 +26,6 @@ extern "C" {
 /* Macro-Expand for MSVC workarounds */
 #define UA_MACRO_EXPAND(x) x
 
-/* Thread-Local Storage
- * --------------------
- * Thread-local storage is not required by the main library functionality. It is
- * only used for some testing strategies. ``UA_THREAD_LOCAL`` is empty if the
- * feature is not available. */
-
-#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
-# define UA_THREAD_LOCAL _Thread_local /* C11 */
-#elif defined(__cplusplus) && __cplusplus > 199711L
-# define UA_THREAD_LOCAL thread_local /* C++11 */
-#elif defined(__GNUC__)
-# define UA_THREAD_LOCAL __thread /* GNU extension */
-#elif defined(_MSC_VER)
-# define UA_THREAD_LOCAL __declspec(thread) /* MSVC extension */
-#else
-# define UA_THREAD_LOCAL
-#endif
-
 /* Integer Shortnames
  * ------------------
  * These are not exposed on the public API, since many user-applications make

+ 2 - 2
tools/travis/travis_linux_script.sh

@@ -175,8 +175,8 @@ else
     echo -e "\r\n== Building the C++ example =="  && echo -en 'travis_fold:start:script.build.example\\r'
     mkdir -p build && cd build
     cp ../../open62541.* .
-    gcc -std=c99 -c open62541.c
-    g++ ../examples/server.cpp -I./ open62541.o -lrt -o cpp-server
+    gcc -std=c99  -DUA_ARCHITECTURE_POSIX  -c open62541.c
+    g++ ../examples/server.cpp -DUA_ARCHITECTURE_POSIX -I./ open62541.o -lrt -o cpp-server
     if [ $? -ne 0 ] ; then exit 1 ; fi
     cd .. && rm build -rf
     echo -en 'travis_fold:end:script.build.example\\r'