Browse Source

make UA_Connection_completeMessages an internal function

Julius Pfrommer 8 years ago
parent
commit
3946886130

+ 30 - 53
include/ua_connection.h

@@ -21,13 +21,10 @@ extern "C" {
 #endif
 
 #include "ua_types.h"
-#include "ua_job.h"
 
-typedef enum UA_ConnectionState {
-    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;
+/* Forward declaration */
+struct UA_SecureChannel;
+typedef struct UA_SecureChannel UA_SecureChannel;
 
 typedef struct UA_ConnectionConfig {
     UA_UInt32 protocolVersion;
@@ -39,9 +36,14 @@ typedef struct UA_ConnectionConfig {
 
 extern const UA_EXPORT UA_ConnectionConfig UA_ConnectionConfig_standard;
 
-/* Forward declaration */
-struct UA_SecureChannel;
-typedef struct UA_SecureChannel UA_SecureChannel;
+typedef enum UA_ConnectionState {
+    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;
+typedef struct UA_Connection UA_Connection;
 
 /**
  * The connection to a single client (or server). The connection is defined independent of the
@@ -52,73 +54,48 @@ struct UA_Connection {
     UA_ConnectionState state;
     UA_ConnectionConfig localConf;
     UA_ConnectionConfig remoteConf;
-    UA_SecureChannel *channel; ///< The securechannel that is attached to this connection (or null)
-    UA_Int32 sockfd; ///< Most connectivity solutions run on sockets. Having the socket id here
-                     ///  simplifies the design.
-    void *handle; ///< A pointer to the networklayer
-    UA_ByteString incompleteMessage; ///< A half-received message (TCP is a streaming protocol) is stored here
-
-    /** Get a buffer for sending */
+    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 the networklayer */
+    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 */
+    /* Release the send buffer manually */
     void (*releaseSendBuffer)(UA_Connection *connection, UA_ByteString *buf);
 
-    /**
-     * Sends a message over the connection.
+    /* 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 is always released (freed) internally
-     * @return Returns an error code or UA_STATUSCODE_GOOD.
-     */
+     * @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
+    /* 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.
-	 */
+     *         connection was closed. */
     UA_StatusCode (*recv)(UA_Connection *connection, UA_ByteString *response, UA_UInt32 timeout);
 
-    /** Release the buffer of a received message */
+    /* Release the buffer of a received message */
     void (*releaseRecvBuffer)(UA_Connection *connection, UA_ByteString *buf);
 
-    /** Close the connection */
+    /* Close the connection */
     void (*close)(UA_Connection *connection);
 };
 
 void UA_EXPORT UA_Connection_init(UA_Connection *connection);
 void UA_EXPORT UA_Connection_deleteMembers(UA_Connection *connection);
 
-void UA_EXPORT UA_Connection_detachSecureChannel(UA_Connection *connection);
-void UA_EXPORT UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel);
-
-/**
- * The network layer may receive chopped up messages since TCP is a streaming
- * protocol. Furthermore, the networklayer may operate on ringbuffers or
- * statically assigned memory.
- *
- * If an entire message is received, it is forwarded directly. But the memory
- * needs to be freed with the networklayer-specific mechanism. If a half message
- * is received, we copy it into a local buffer. Then, the stack-specific free
- * needs to be used.
- *
- * @param connection The connection
- * @param message The received message. The content may be overwritten when a
- *        previsouly received buffer is completed.
- * @param realloced The Boolean value is set to true if the outgoing message has
- *        been reallocated from the network layer.
- * @return Returns UA_STATUSCODE_GOOD or an error code. When an error occurs, the ingoing message
- *         and the current buffer in the connection are freed.
- */
-UA_StatusCode UA_EXPORT
-UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString * UA_RESTRICT message,
-                               UA_Boolean * UA_RESTRICT realloced);
-
 #ifdef __cplusplus
 } // extern "C"
 #endif

+ 2 - 3
include/ua_job.h

@@ -16,13 +16,12 @@
 #ifndef UA_JOB_H_
 #define UA_JOB_H_
 
+#include "ua_connection.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-struct UA_Connection;
-typedef struct UA_Connection UA_Connection;
-
 struct UA_Server;
 typedef struct UA_Server UA_Server;
 

+ 1 - 8
plugins/networklayer_tcp.c

@@ -429,16 +429,9 @@ ServerNetworkLayerTCP_getJobs(UA_ServerNetworkLayer *nl, UA_Job **jobs, UA_UInt1
             continue;
         UA_StatusCode retval = socket_recv(layer->mappings[i].connection, &buf, 0);
         if(retval == UA_STATUSCODE_GOOD) {
-            UA_Boolean realloced = false;
-            retval = UA_Connection_completeMessages(layer->mappings[i].connection, &buf, &realloced);
-            if(retval != UA_STATUSCODE_GOOD || buf.length == 0)
-                continue;
             js[j].job.binaryMessage.connection = layer->mappings[i].connection;
             js[j].job.binaryMessage.message = buf;
-            if(!realloced)
-                js[j].type = UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER;
-            else
-                js[j].type = UA_JOBTYPE_BINARYMESSAGE_ALLOCATED;
+            js[j].type = UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER;
             j++;
         } else if (retval == UA_STATUSCODE_BADCONNECTIONCLOSED) {
             UA_Connection *c = layer->mappings[i].connection;

+ 1 - 0
src/client/ua_client.c

@@ -2,6 +2,7 @@
 #include "ua_client.h"
 #include "ua_client_highlevel.h"
 #include "ua_client_internal.h"
+#include "ua_connection_internal.h"
 #include "ua_types_generated.h"
 #include "ua_nodeids.h"
 #include "ua_types_encoding_binary.h"

+ 2 - 1
src/server/ua_server_binary.c

@@ -435,7 +435,8 @@ processMSG(UA_Connection *connection, UA_Server *server, const UA_ByteString *ms
             LIST_REMOVE(ch, pointers);
             UA_free(ch);
         } else {
-            UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL, "Received MSGA on an unknown request");
+            UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_SECURECHANNEL,
+                        "Received MSGA on an unknown request");
         }
 
         return;

+ 1 - 0
src/server/ua_server_internal.h

@@ -4,6 +4,7 @@
 #include "ua_util.h"
 #include "ua_server.h"
 #include "ua_server_external_ns.h"
+#include "ua_connection_internal.h"
 #include "ua_session_manager.h"
 #include "ua_securechannel_manager.h"
 #include "ua_nodestore.h"

+ 31 - 5
src/server/ua_server_worker.c

@@ -590,6 +590,26 @@ UA_StatusCode UA_Server_run_startup(UA_Server *server) {
     return result;
 }
 
+static void completeMessages(UA_Server *server, UA_Job *job) {
+    UA_Boolean realloced = UA_FALSE;
+    UA_StatusCode retval = UA_Connection_completeMessages(job->job.binaryMessage.connection,
+                                                          &job->job.binaryMessage.message, &realloced);
+    if(retval != UA_STATUSCODE_GOOD) {
+        if(retval == UA_STATUSCODE_BADOUTOFMEMORY)
+            UA_LOG_WARNING(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                           "Lost message(s) from Connection %i as memory could not be allocated",
+                           job->job.binaryMessage.connection->sockfd);
+        else if(retval != UA_STATUSCODE_GOOD)
+            UA_LOG_INFO(server->config.logger, UA_LOGCATEGORY_NETWORK,
+                        "Could not merge half-received messages on Connection %i with error 0x%08x",
+                        job->job.binaryMessage.connection->sockfd, retval);
+        job->type = UA_JOBTYPE_NOTHING;
+        return;
+    }
+    if(realloced)
+        job->type = UA_JOBTYPE_BINARYMESSAGE_ALLOCATED;
+}
+
 UA_UInt16 UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
 #ifdef UA_ENABLE_MULTITHREADING
     /* Run work assigned for the main thread */
@@ -614,15 +634,21 @@ UA_UInt16 UA_Server_run_iterate(UA_Server *server, UA_Boolean waitInternal) {
         else
             jobsSize = nl->getJobs(nl, &jobs, 0);
 
-#ifdef UA_ENABLE_MULTITHREADING
-        /* Filter out delayed work */
         for(size_t k = 0; k < jobsSize; k++) {
-            if(jobs[k].type != UA_JOBTYPE_METHODCALL_DELAYED)
+#ifdef UA_ENABLE_MULTITHREADING
+            /* Filter out delayed work */
+            if(jobs[k].type == UA_JOBTYPE_METHODCALL_DELAYED) {
+                addDelayedJob(server, &jobs[k]);
+                jobs[k].type = UA_JOBTYPE_NOTHING;
                 continue;
-            addDelayedJob(server, &jobs[k]);
-            jobs[k].type = UA_JOBTYPE_NOTHING;
+            }
+#endif
+            /* Merge half-received messages */
+            if(jobs[k].type == UA_JOBTYPE_BINARYMESSAGE_NETWORKLAYER)
+                completeMessages(server, &jobs[k]);
         }
 
+#ifdef UA_ENABLE_MULTITHREADING
         dispatchJobs(server, jobs, jobsSize);
         /* Wake up worker threads */
         if(jobsSize > 0)

+ 1 - 1
src/ua_connection.c

@@ -1,5 +1,5 @@
 #include "ua_util.h"
-#include "ua_connection.h"
+#include "ua_connection_internal.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_types_generated_encoding_binary.h"
 #include "ua_securechannel.h"

+ 31 - 0
src/ua_connection_internal.h

@@ -0,0 +1,31 @@
+#ifndef UA_CONNECTION_INTERNAL_H_
+#define UA_CONNECTION_INTERNAL_H_
+
+#include "ua_connection.h"
+
+/**
+ * The network layer may receive chopped up messages since TCP is a streaming
+ * protocol. Furthermore, the networklayer may operate on ringbuffers or
+ * statically assigned memory.
+ *
+ * If an entire message is received, it is forwarded directly. But the memory
+ * needs to be freed with the networklayer-specific mechanism. If a half message
+ * is received, we copy it into a local buffer. Then, the stack-specific free
+ * needs to be used.
+ *
+ * @param connection The connection
+ * @param message The received message. The content may be overwritten when a
+ *        previsouly received buffer is completed.
+ * @param realloced The Boolean value is set to true if the outgoing message has
+ *        been reallocated from the network layer.
+ * @return Returns UA_STATUSCODE_GOOD or an error code. When an error occurs, the ingoing message
+ *         and the current buffer in the connection are freed.
+ */
+UA_StatusCode
+UA_Connection_completeMessages(UA_Connection *connection, UA_ByteString * UA_RESTRICT message,
+                               UA_Boolean * UA_RESTRICT realloced);
+
+void UA_EXPORT UA_Connection_detachSecureChannel(UA_Connection *connection);
+void UA_EXPORT UA_Connection_attachSecureChannel(UA_Connection *connection, UA_SecureChannel *channel);
+
+#endif /* UA_CONNECTION_INTERNAL_H_ */

+ 1 - 8
src/ua_securechannel.h

@@ -4,13 +4,7 @@
 #include "queue.h"
 #include "ua_types.h"
 #include "ua_transport_generated.h"
-#include "ua_connection.h"
-
-/**
- *  @ingroup communication
- *
- * @{
- */
+#include "ua_connection_internal.h"
 
 struct UA_Session;
 typedef struct UA_Session UA_Session;
@@ -54,6 +48,5 @@ UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_U
                                                   const void *content, const UA_DataType *contentType);
 
 void UA_SecureChannel_revolveTokens(UA_SecureChannel *channel);
-/** @} */
 
 #endif /* UA_SECURECHANNEL_H_ */