|
@@ -0,0 +1,224 @@
|
|
|
|
+/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
+
|
|
|
|
+#ifndef UA_PLUGIN_NETWORK_H_
|
|
|
|
+#define UA_PLUGIN_NETWORK_H_
|
|
|
|
+
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
+extern "C" {
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#include "ua_types.h"
|
|
|
|
+#include "ua_log.h"
|
|
|
|
+
|
|
|
|
+/* Forward declarations */
|
|
|
|
+struct UA_Connection;
|
|
|
|
+typedef struct UA_Connection UA_Connection;
|
|
|
|
+
|
|
|
|
+struct UA_SecureChannel;
|
|
|
|
+typedef struct UA_SecureChannel UA_SecureChannel;
|
|
|
|
+
|
|
|
|
+struct UA_Server;
|
|
|
|
+typedef struct UA_Server UA_Server;
|
|
|
|
+
|
|
|
|
+struct UA_ServerNetworkLayer;
|
|
|
|
+typedef struct UA_ServerNetworkLayer UA_ServerNetworkLayer;
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * .. _networking:
|
|
|
|
+ *
|
|
|
|
+ * Networking Plugin API
|
|
|
|
+ * =====================
|
|
|
|
+ *
|
|
|
|
+ * Connection
|
|
|
|
+ * ----------
|
|
|
|
+ * Client-server connections are represented by a `UA_Connection`. The
|
|
|
|
+ * connection is stateful and stores partially received messages, and so on. In
|
|
|
|
+ * addition, the connection contains function pointers to the underlying
|
|
|
|
+ * networking implementation. An example for this is the `send` function. So the
|
|
|
|
+ * connection encapsulates all the required networking functionality. This lets
|
|
|
|
+ * users on embedded (or otherwise exotic) systems implement their own
|
|
|
|
+ * networking plugins with a clear interface to the main open62541 library. */
|
|
|
|
+
|
|
|
|
+typedef struct {
|
|
|
|
+ UA_UInt32 protocolVersion;
|
|
|
|
+ UA_UInt32 sendBufferSize;
|
|
|
|
+ UA_UInt32 recvBufferSize;
|
|
|
|
+ UA_UInt32 maxMessageSize;
|
|
|
|
+ UA_UInt32 maxChunkCount;
|
|
|
|
+} UA_ConnectionConfig;
|
|
|
|
+
|
|
|
|
+typedef enum {
|
|
|
|
+ UA_CONNECTION_OPENING, /* The socket is open, but the HEL/ACK handshake
|
|
|
|
+ * is not done */
|
|
|
|
+ UA_CONNECTION_ESTABLISHED, /* The socket is open and the connection
|
|
|
|
+ * configured */
|
|
|
|
+ UA_CONNECTION_CLOSED, /* The socket has been closed and the connection
|
|
|
|
+ * will be deleted */
|
|
|
|
+} UA_ConnectionState;
|
|
|
|
+
|
|
|
|
+struct UA_Connection {
|
|
|
|
+ UA_ConnectionState state;
|
|
|
|
+ UA_ConnectionConfig localConf;
|
|
|
|
+ UA_ConnectionConfig remoteConf;
|
|
|
|
+ UA_SecureChannel *channel; /* The securechannel that is attached to
|
|
|
|
+ * this connection */
|
|
|
|
+ UA_Int32 sockfd; /* Most connectivity solutions run on
|
|
|
|
+ * sockets. Having the socket id here
|
|
|
|
+ * simplifies the design. */
|
|
|
|
+ void *handle; /* A pointer to internal data */
|
|
|
|
+ UA_ByteString incompleteMessage; /* A half-received message (TCP is a
|
|
|
|
+ * streaming protocol) is stored here */
|
|
|
|
+
|
|
|
|
+ /* Get a buffer for sending */
|
|
|
|
+ UA_StatusCode (*getSendBuffer)(UA_Connection *connection, size_t length,
|
|
|
|
+ UA_ByteString *buf);
|
|
|
|
+
|
|
|
|
+ /* Release the send buffer manually */
|
|
|
|
+ void (*releaseSendBuffer)(UA_Connection *connection, UA_ByteString *buf);
|
|
|
|
+
|
|
|
|
+ /* Sends a message over the connection. The message buffer is always freed,
|
|
|
|
+ * even if sending fails.
|
|
|
|
+ *
|
|
|
|
+ * @param connection The connection
|
|
|
|
+ * @param buf The message buffer
|
|
|
|
+ * @return Returns an error code or UA_STATUSCODE_GOOD. */
|
|
|
|
+ UA_StatusCode (*send)(UA_Connection *connection, UA_ByteString *buf);
|
|
|
|
+
|
|
|
|
+ /* Receive a message from the remote connection
|
|
|
|
+ *
|
|
|
|
+ * @param connection The connection
|
|
|
|
+ * @param response The response string. It is allocated by the connection
|
|
|
|
+ * and needs to be freed with connection->releaseBuffer
|
|
|
|
+ * @param timeout Timeout of the recv operation in milliseconds
|
|
|
|
+ * @return Returns UA_STATUSCODE_BADCOMMUNICATIONERROR if the recv operation
|
|
|
|
+ * can be repeated, UA_STATUSCODE_GOOD if it succeeded and
|
|
|
|
+ * UA_STATUSCODE_BADCONNECTIONCLOSED if the connection was
|
|
|
|
+ * closed. */
|
|
|
|
+ UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response,
|
|
|
|
+ UA_UInt32 timeout);
|
|
|
|
+
|
|
|
|
+ /* Release the buffer of a received message */
|
|
|
|
+ void (*releaseRecvBuffer)(UA_Connection *connection, UA_ByteString *buf);
|
|
|
|
+
|
|
|
|
+ /* Close the connection. The network layer closes the socket, removes
|
|
|
|
+ * internal pointers to the connection and calls
|
|
|
|
+ * UA_Server_removeConnection. */
|
|
|
|
+ void (*close)(UA_Connection *connection);
|
|
|
|
+
|
|
|
|
+ /* To be called only from within the server (and not the network layer).
|
|
|
|
+ * Frees up the connection's memory. */
|
|
|
|
+ void (*free)(UA_Connection *connection);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/* Cleans up half-received messages, and so on. Called from connection->free. */
|
|
|
|
+void UA_EXPORT
|
|
|
|
+UA_Connection_deleteMembers(UA_Connection *connection);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Server Network Layer
|
|
|
|
+ * --------------------
|
|
|
|
+ * The server exposes two functions to interact with remote clients:
|
|
|
|
+ * `processBinaryMessage` and `removeConnection`. These functions are called by
|
|
|
|
+ * the server network layer.
|
|
|
|
+ *
|
|
|
|
+ * It is the job of the server network layer to listen on a TCP socket, to
|
|
|
|
+ * accept new connections, to call the server with received messages and to
|
|
|
|
+ * signal closed connections to the server.
|
|
|
|
+ *
|
|
|
|
+ * The network layer is part of the server config. So users can provide a custom
|
|
|
|
+ * implementation if the provided example does not fit their architecture. The
|
|
|
|
+ * network layer is invoked only from the server's main loop. So the network
|
|
|
|
+ * layer does not need to be thread-safe. If the networklayer receives a
|
|
|
|
+ * positive duration for blocking listening, the server's main loop will block
|
|
|
|
+ * until a message is received or the duration times out. */
|
|
|
|
+
|
|
|
|
+/* Process a binary message (TCP packet). The message can contain partial
|
|
|
|
+ * chunks. (TCP is a streaming protocol and packets may be split/merge during
|
|
|
|
+ * transport.) After processing, the message is freed with
|
|
|
|
+ * connection->releaseRecvBuffer. */
|
|
|
|
+void UA_EXPORT
|
|
|
|
+UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection,
|
|
|
|
+ UA_ByteString *message);
|
|
|
|
+
|
|
|
|
+/* The server internally cleans up the connection and then calls
|
|
|
|
+ * connection->free. */
|
|
|
|
+void UA_EXPORT
|
|
|
|
+UA_Server_removeConnection(UA_Server *server, UA_Connection *connection);
|
|
|
|
+
|
|
|
|
+struct UA_ServerNetworkLayer {
|
|
|
|
+ void *handle; /* Internal data */
|
|
|
|
+ UA_String discoveryUrl;
|
|
|
|
+
|
|
|
|
+ /* Start listening on the networklayer.
|
|
|
|
+ *
|
|
|
|
+ * @param nl The network layer
|
|
|
|
+ * @param logger The logger
|
|
|
|
+ * @return Returns UA_STATUSCODE_GOOD or an error code. */
|
|
|
|
+ UA_StatusCode (*start)(UA_ServerNetworkLayer *nl, UA_Logger logger);
|
|
|
|
+
|
|
|
|
+ /* Listen for new and closed connections and arriving packets. Calls
|
|
|
|
+ * UA_Server_processBinaryMessage for the arriving packets. Calls
|
|
|
|
+ * UA_Server_removeConnection for closed connections.
|
|
|
|
+ *
|
|
|
|
+ * @param nl The network layer
|
|
|
|
+ * @param server The server for processing the incoming packets and for
|
|
|
|
+ * closing connections.
|
|
|
|
+ * @param timeout The timeout during which an event must arrive in
|
|
|
|
+ * milliseconds
|
|
|
|
+ * @return A statuscode for the status of the network layer. */
|
|
|
|
+ UA_StatusCode (*listen)(UA_ServerNetworkLayer *nl, UA_Server *server,
|
|
|
|
+ UA_UInt16 timeout);
|
|
|
|
+
|
|
|
|
+ /* Close the network socket and all open connections. Afterwards, the
|
|
|
|
+ * network layer can be safely deleted.
|
|
|
|
+ *
|
|
|
|
+ * @param nl The network layer
|
|
|
|
+ * @param server The server that processes the incoming packets and for
|
|
|
|
+ * closing connections before deleting them.
|
|
|
|
+ * @return A statuscode for the status of the closing operation. */
|
|
|
|
+ void (*stop)(UA_ServerNetworkLayer *nl, UA_Server *server);
|
|
|
|
+
|
|
|
|
+ /* Deletes the network layer context. Call only after stopping. */
|
|
|
|
+ void (*deleteMembers)(UA_ServerNetworkLayer *nl);
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Client Network Layer
|
|
|
|
+ * --------------------
|
|
|
|
+ * The client has only a single connection. The connection is used for both
|
|
|
|
+ * sending and receiving binary messages. */
|
|
|
|
+
|
|
|
|
+typedef UA_Connection
|
|
|
|
+(*UA_ConnectClientConnection)(UA_ConnectionConfig localConf,
|
|
|
|
+ const char *endpointUrl, UA_Logger logger);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * Endpoint URL Parser
|
|
|
|
+ * -------------------
|
|
|
|
+ * The endpoint URL parser is generally useful for the implementation of network
|
|
|
|
+ * layer plugins. */
|
|
|
|
+
|
|
|
|
+/* Split the given endpoint url into hostname, port and path. All arguments must
|
|
|
|
+ * be non-NULL. EndpointUrls have the form "opc.tcp://hostname:port/path", port
|
|
|
|
+ * and path may be omitted (together with the prefix colon and slash).
|
|
|
|
+ *
|
|
|
|
+ * @param endpointUrl The endpoint URL.
|
|
|
|
+ * @param outHostname Set to the parsed hostname. The string points into the
|
|
|
|
+ * original endpointUrl, so no memory is allocated. If an IPv6 address is
|
|
|
|
+ * given, hostname contains e.g. '[2001:0db8:85a3::8a2e:0370:7334]'
|
|
|
|
+ * @param outPort Set to the port of the url or left unchanged.
|
|
|
|
+ * @param outPath Set to the path if one is present in the endpointUrl.
|
|
|
|
+ * Starting or trailing '/' are NOT included in the path. The string
|
|
|
|
+ * points into the original endpointUrl, so no memory is allocated.
|
|
|
|
+ * @return Returns UA_STATUSCODE_BADTCPENDPOINTURLINVALID if parsing failed. */
|
|
|
|
+UA_StatusCode UA_EXPORT
|
|
|
|
+UA_parseEndpointUrl(const UA_String *endpointUrl, UA_String *outHostname,
|
|
|
|
+ UA_UInt16 *outPort, UA_String *outPath);
|
|
|
|
+
|
|
|
|
+#ifdef __cplusplus
|
|
|
|
+} // extern "C"
|
|
|
|
+#endif
|
|
|
|
+
|
|
|
|
+#endif /* UA_PLUGIN_NETWORK_H_ */
|