Browse Source

Stack: Remove experimental UDP transport (for client/server) (#2272)

Julius Pfrommer 5 years ago
parent
commit
102b7dc693
7 changed files with 1 additions and 334 deletions
  1. 0 7
      CMakeLists.txt
  2. 1 1
      arch/CMakeLists.txt
  3. 0 252
      arch/ua_network_udp.c
  4. 0 28
      arch/ua_network_udp.h
  5. 0 2
      doc/building.rst
  6. 0 43
      examples/server_udp.c
  7. 0 1
      include/ua_config.h.in

+ 0 - 7
CMakeLists.txt

@@ -248,9 +248,6 @@ mark_as_advanced(UA_ENABLE_DISCOVERY_SEMAPHORE)
 option(UA_ENABLE_UNIT_TESTS_MEMCHECK "Use Valgrind (Linux) or DrMemory (Windows) to detect memory leaks when running the unit tests" OFF)
 mark_as_advanced(UA_ENABLE_UNIT_TESTS_MEMCHECK)
 
-option(UA_ENABLE_NONSTANDARD_UDP "Enable udp extension (non-standard)" OFF)
-mark_as_advanced(UA_ENABLE_NONSTANDARD_UDP)
-
 option(UA_ENABLE_UNIT_TEST_FAILURE_HOOKS
        "Add hooks to force failure modes for additional unit tests. Not for production use!" OFF)
 mark_as_advanced(UA_ENABLE_UNIT_TEST_FAILURE_HOOKS)
@@ -626,10 +623,6 @@ if(UA_DEBUG_DUMP_PKGS)
     list(APPEND lib_sources ${PROJECT_SOURCE_DIR}/plugins/ua_debug_dump_pkgs.c)
 endif()
 
-if(UA_ENABLE_NONSTANDARD_UDP)
-    list(APPEND exported_headers ${PROJECT_SOURCE_DIR}/arch/ua_network_udp.h)
-endif()
-
 if(UA_ENABLE_DISCOVERY_MULTICAST)
     # prepend in list, otherwise it complains that winsock2.h has to be included before windows.h
     set(internal_headers ${PROJECT_BINARY_DIR}/src_generated/mdnsd_config.h

+ 1 - 1
arch/CMakeLists.txt

@@ -1,6 +1,6 @@
 SET(SOURCE_GROUP ${SOURCE_GROUP}\\arch)
 
-ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) #to have access to ua_network_tcp.h and udp.h
+ua_include_directories(${CMAKE_CURRENT_SOURCE_DIR}) #to have access to ua_network_tcp.h
 
 add_subdirectory(posix)
 add_subdirectory(win32)

+ 0 - 252
arch/ua_network_udp.c

@@ -1,252 +0,0 @@
-/* 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) Fraunhofer IOSB (Author: Julius Pfrommer)
- *    Copyright 2016-2017 (c) Stefan Profanter, fortiss GmbH
- */
-
-#include "ua_network_udp.h"
-#include <stdio.h>
-#include <string.h> // memset
-
-/* with a space so amalgamation does not remove the includes */
-# include <errno.h> // errno, EINTR
-# include <fcntl.h> // fcntl
-# include <strings.h> //bzero
-
-#if defined(UA_FREERTOS)
- # include <lwip/udp.h>
- # include <lwip/tcpip.h>
-#else
-# ifndef _WRS_KERNEL
-#  include <sys/select.h>
-# else
-#  include <selectLib.h>
-# endif
-#  include <netinet/in.h>
-#  include <netinet/tcp.h>
-#  include <sys/socketvar.h>
-#  include <sys/ioctl.h>
-#  include <unistd.h> // read, write, close
-#  include <arpa/inet.h>
-#endif
-#ifdef __QNX__
-#include <sys/socket.h>
-#endif
-#if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__))
-# include <sys/param.h>
-# if defined(BSD)
-#  include<sys/socket.h>
-# endif
-#endif
-# define CLOSESOCKET(S) close(S)
-
-#define MAXBACKLOG 100
-
-#ifdef _WIN32
-# error udp not yet implemented for windows
-#endif
-
-/*****************************/
-/* Generic Buffer Management */
-/*****************************/
-
-static UA_StatusCode GetMallocedBuffer(UA_Connection *connection, size_t length, UA_ByteString *buf) {
-    if(length > connection->remoteConf.recvBufferSize)
-        return UA_STATUSCODE_BADCOMMUNICATIONERROR;
-    return UA_ByteString_allocBuffer(buf, connection->remoteConf.recvBufferSize);
-}
-
-static void ReleaseMallocedBuffer(UA_Connection *connection, UA_ByteString *buf) {
-    UA_ByteString_deleteMembers(buf);
-}
-
-/*********************/
-/* UDP Network Layer */
-/*********************/
-
-/* Forwarded to the server as a (UA_Connection) and used for callbacks back into
-   the networklayer */
-typedef struct {
-    UA_Connection connection;
-    struct sockaddr from;
-    socklen_t fromlen;
-} UDPConnection;
-
-typedef struct {
-    UA_ConnectionConfig conf;
-    UA_UInt16 port;
-    fd_set fdset;
-    UA_Int32 serversockfd;
-
-    UA_Logger logger; // Set during start
-} ServerNetworkLayerUDP;
-
-/** Accesses only the sockfd in the handle. Can be run from parallel threads. */
-static UA_StatusCode sendUDP(UA_Connection *connection, UA_ByteString *buf) {
-    UDPConnection *udpc = (UDPConnection*)connection;
-    ServerNetworkLayerUDP *layer = (ServerNetworkLayerUDP*)connection->handle;
-    long nWritten = 0;
-    struct sockaddr_in *sin = NULL;
-
-    if (udpc->from.sa_family == AF_INET) {
-#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
-#endif
-        sin = (struct sockaddr_in *) &udpc->from;
-#if ((__GNUC__ == 4 && __GNUC_MINOR__ >= 6) || __GNUC__ > 4 || defined(__clang__))
-#pragma GCC diagnostic pop
-#endif
-    } else {
-        UA_ByteString_deleteMembers(buf);
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-
-    while (nWritten < (long)buf->length) {
-        long n = sendto(layer->serversockfd, buf->data, buf->length, 0,
-                            (struct sockaddr*)sin, sizeof(struct sockaddr_in));
-        if(n == -1L) {
-            UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "UDP send error %i", errno);
-            UA_ByteString_deleteMembers(buf);
-            return UA_STATUSCODE_BADINTERNALERROR;
-        }
-        nWritten += n;
-    }
-    UA_ByteString_deleteMembers(buf);
-    return UA_STATUSCODE_GOOD;
-}
-
-static void setFDSet(ServerNetworkLayerUDP *layer) {
-    FD_ZERO(&layer->fdset);
-    FD_SET(layer->serversockfd, &layer->fdset);
-}
-
-static void closeConnectionUDP(UA_Connection *handle) {
-    UA_free(handle);
-}
-
-static UA_StatusCode ServerNetworkLayerUDP_start(UA_ServerNetworkLayer *nl, UA_Logger logger) {
-    ServerNetworkLayerUDP *layer = nl->handle;
-    layer->logger = logger;
-    layer->serversockfd = socket(AF_INET6, SOCK_DGRAM, 0);
-    if(layer->serversockfd < 0) {
-        UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Error opening socket");
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-    struct sockaddr_in6 serv_addr;
-    memset(&serv_addr, 0, sizeof(serv_addr));
-    serv_addr.sin6_family = AF_INET6;
-    serv_addr.sin6_port = htons(layer->port);
-    serv_addr.sin6_addr = in6addr_any;
-    int optval = 1;
-    if(setsockopt(layer->serversockfd, SOL_SOCKET,
-                  SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
-        UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Could not setsockopt");
-        CLOSESOCKET(layer->serversockfd);
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-    if(bind(layer->serversockfd, (const struct sockaddr *)&serv_addr,
-            sizeof(serv_addr)) < 0) {
-        UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Could not bind the socket");
-        CLOSESOCKET(layer->serversockfd);
-        return UA_STATUSCODE_BADINTERNALERROR;
-    }
-    UA_socket_set_nonblocking(layer->serversockfd);
-    UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "Listening for UDP connections on %s:%d",
-                   inet_ntoa(serv_addr.sin_addr), ntohs(serv_addr.sin_port));
-    return UA_STATUSCODE_GOOD;
-}
-
-static size_t ServerNetworkLayerUDP_getJobs(UA_ServerNetworkLayer *nl, UA_Job **jobs, UA_UInt16 timeout) {
-    ServerNetworkLayerUDP *layer = nl->handle;
-    UA_Job *items = NULL;
-    setFDSet(layer);
-    struct timeval tmptv = {0, timeout};
-    int resultsize = select(layer->serversockfd+1, &layer->fdset, NULL, NULL, &tmptv);
-    if(resultsize <= 0 || !FD_ISSET(layer->serversockfd, &layer->fdset)) {
-        *jobs = items;
-        return 0;
-    }
-    items = UA_malloc(sizeof(UA_Job)*(unsigned long)resultsize);
-    // read from established sockets
-    size_t j = 0;
-    UA_ByteString buf = {0, NULL};
-    if(!buf.data) {
-        buf.data = UA_malloc(sizeof(UA_Byte) * layer->conf.recvBufferSize);
-        if(!buf.data)
-            UA_LOG_WARNING(layer->logger, UA_LOGCATEGORY_NETWORK, "malloc failed");
-    }
-    struct sockaddr sender;
-    socklen_t sendsize = sizeof(sender);
-    bzero(&sender, sizeof(sender));
-    ssize_t rec_result = recvfrom(layer->serversockfd, buf.data, layer->conf.recvBufferSize, 0, &sender, &sendsize);
-    if (rec_result > 0) {
-        buf.length = (size_t)rec_result;
-        UDPConnection *c = UA_malloc(sizeof(UDPConnection));
-        if(!c){
-                UA_free(items);
-            return UA_STATUSCODE_BADINTERNALERROR;
-        }
-        UA_Connection_init(&c->connection);
-        c->from = sender;
-        c->fromlen = sendsize;
-        // c->sockfd = newsockfd;
-        c->connection.getSendBuffer = GetMallocedBuffer;
-        c->connection.releaseSendBuffer = ReleaseMallocedBuffer;
-        c->connection.releaseRecvBuffer = ReleaseMallocedBuffer;
-        c->connection.handle = layer;
-        c->connection.send = sendUDP;
-        c->connection.close = closeConnectionUDP;
-        c->connection.localConf = layer->conf;
-        c->connection.state = UA_CONNECTION_OPENING;
-
-        items[j].type = UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER;
-        items[j].job.binaryMessage.message = buf;
-        items[j].job.binaryMessage.connection = (UA_Connection*)c;
-        buf.data = NULL;
-        j++;
-        *jobs = items;
-    } else {
-        UA_free(items);
-        *jobs = NULL;
-    }
-    if(buf.data)
-        UA_free(buf.data);
-    return j;
-}
-
-static size_t ServerNetworkLayerUDP_stop(UA_ServerNetworkLayer *nl, UA_Job **jobs) {
-    ServerNetworkLayerUDP *layer = nl->handle;
-    UA_LOG_INFO(layer->logger, UA_LOGCATEGORY_NETWORK,
-                "Shutting down the UDP network layer");
-    CLOSESOCKET(layer->serversockfd);
-    return 0;
-}
-
-static void ServerNetworkLayerUDP_deleteMembers(UA_ServerNetworkLayer *nl) {
-    ServerNetworkLayerUDP *layer = nl->handle;
-    UA_free(layer);
-    UA_String_deleteMembers(&nl->discoveryUrl);
-}
-
-UA_ServerNetworkLayer
-UA_ServerNetworkLayerUDP(UA_ConnectionConfig conf, UA_UInt16 port) {
-    UA_ServerNetworkLayer nl;
-    memset(&nl, 0, sizeof(UA_ServerNetworkLayer));
-
-    ServerNetworkLayerUDP *layer = UA_malloc(sizeof(ServerNetworkLayerUDP));
-    if(!layer)
-        return nl;
-    memset(layer, 0, sizeof(ServerNetworkLayerUDP));
-
-    layer->conf = conf;
-    layer->port = port;
-
-    nl.handle = layer;
-    nl.start = ServerNetworkLayerUDP_start;
-    nl.getJobs = ServerNetworkLayerUDP_getJobs;
-    nl.stop = ServerNetworkLayerUDP_stop;
-    nl.deleteMembers = ServerNetworkLayerUDP_deleteMembers;
-    return nl;
-}

+ 0 - 28
arch/ua_network_udp.h

@@ -1,28 +0,0 @@
-/* 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 (c) Fraunhofer IOSB (Author: Julius Pfrommer)
- */
-
-#ifndef UA_NETWORK_UDP_H_
-#define UA_NETWORK_UDP_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "ua_server.h"
-#include "ua_client.h"
-
-/* Create the UDP networklayer and listen to the specified port */
-UA_ServerNetworkLayer UA_EXPORT
-UA_ServerNetworkLayerUDP(UA_ConnectionConfig conf, UA_UInt16 port);
-
-UA_Connection UA_EXPORT
-UA_ClientConnectionUDP(UA_ConnectionConfig conf, const char *endpointUrl, UA_Logger logger);
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
-
-#endif /* UA_NETWORK_UDP_H_ */

+ 0 - 2
doc/building.rst

@@ -230,8 +230,6 @@ be visible in the cmake GUIs.
 **UA_ENABLE_FULL_NS0**
    Use the full NS0 instead of a minimal Namespace 0 nodeset
    ``UA_FILE_NS0`` is used to specify the file for NS0 generation from namespace0 folder. Default value is ``Opc.Ua.NodeSet2.xml``
-**UA_ENABLE_NONSTANDARD_UDP**
-   Enable udp extension
 
 Debug Build Options
 ^^^^^^^^^^^^^^^^^^^

+ 0 - 43
examples/server_udp.c

@@ -1,43 +0,0 @@
-/*
- * This work is licensed under a Creative Commons CCZero 1.0 Universal License.
- * See http://creativecommons.org/publicdomain/zero/1.0/ for more information.
- */
-#include "open62541.h"
-#include <signal.h>
-
-UA_Boolean running = 1;
-static void stopHandler(int sign) {
-    printf("Received Ctrl-C\n");
-    running = 0;
-}
-
-int main(int argc, char** argv) {
-    signal(SIGINT,  stopHandler);
-    signal(SIGTERM, stopHandler);
-
-    UA_ServerConfig config = UA_ServerConfig_standard;
-    UA_ServerNetworkLayer nl;
-    nl = UA_ServerNetworkLayerUDP(UA_ConnectionConfig_standard, 4840);
-    config.networkLayers = &nl;
-    config.networkLayersSize = 1;
-    UA_Server *server = UA_Server_new(config);
-
-    // add a variable node to the adresspace
-    UA_VariableAttributes attr = UA_VariableAttributes_default;
-    UA_Int32 myInteger = 42;
-    UA_Variant_setScalar(&attr.value, &myInteger, &UA_TYPES[UA_TYPES_INT32]);
-    attr.description = UA_LOCALIZEDTEXT("en-US","the answer");
-    attr.displayName = UA_LOCALIZEDTEXT("en-US","the answer");
-    UA_NodeId myIntegerNodeId = UA_NODEID_STRING(1, "the.answer");
-    UA_QualifiedName myIntegerName = UA_QUALIFIEDNAME(1, "the answer");
-    UA_NodeId parentNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_OBJECTSFOLDER);
-    UA_NodeId parentReferenceNodeId = UA_NODEID_NUMERIC(0, UA_NS0ID_ORGANIZES);
-    UA_Server_addVariableNode(server, myIntegerNodeId, parentNodeId,
-                              parentReferenceNodeId, myIntegerName,
-                              UA_NODEID_NULL, attr, NULL, NULL);
-
-    UA_StatusCode retval = UA_Server_run(server, &running);
-    UA_Server_delete(server);
-
-    return (int) retval;
-}

+ 0 - 1
include/ua_config.h.in

@@ -44,7 +44,6 @@
 #cmakedefine UA_ENABLE_TYPENAMES
 #cmakedefine UA_ENABLE_NODESET_COMPILER_DESCRIPTIONS
 #cmakedefine UA_ENABLE_DETERMINISTIC_RNG
-#cmakedefine UA_ENABLE_NONSTANDARD_UDP
 #cmakedefine UA_ENABLE_DISCOVERY
 #cmakedefine UA_ENABLE_DISCOVERY_MULTICAST
 #cmakedefine UA_ENABLE_QUERY