Browse Source

Merge branch '0.2'

Julius Pfrommer 8 years ago
parent
commit
f07e55351e
4 changed files with 54 additions and 46 deletions
  1. 43 33
      src/client/ua_client.c
  2. 4 4
      src/server/ua_server_binary.c
  3. 6 8
      src/server/ua_server_worker.c
  4. 1 1
      src/ua_securechannel.c

+ 43 - 33
src/client/ua_client.c

@@ -95,37 +95,42 @@ UA_ClientState UA_EXPORT UA_Client_getState(UA_Client *client) {
 /* Manage the Connection */
 /*************************/
 
+#define UA_MINMESSAGESIZE 8192
+
 static UA_StatusCode HelAckHandshake(UA_Client *client) {
-    UA_TcpMessageHeader messageHeader;
-    messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
+    UA_Connection *conn = client->connection;
+
+    /* Get a buffer */
+    UA_ByteString message;
+    UA_StatusCode retval = client->connection->getSendBuffer(client->connection, UA_MINMESSAGESIZE, &message);
+    if(retval != UA_STATUSCODE_GOOD)
+        return retval;
 
+    /* Prepare the HEL message and encode at offset 8 */
     UA_TcpHelloMessage hello;
     UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */
-
-    UA_Connection *conn = client->connection;
     hello.maxChunkCount = conn->localConf.maxChunkCount;
     hello.maxMessageSize = conn->localConf.maxMessageSize;
     hello.protocolVersion = conn->localConf.protocolVersion;
     hello.receiveBufferSize = conn->localConf.recvBufferSize;
     hello.sendBufferSize = conn->localConf.sendBufferSize;
 
-    UA_ByteString message;
-    UA_StatusCode retval;
-    retval = client->connection->getSendBuffer(client->connection, client->connection->remoteConf.recvBufferSize, &message);
-    if(retval != UA_STATUSCODE_GOOD)
-        return retval;
-
     size_t offset = 8;
-    retval |= UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
+    retval = UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
+    UA_TcpHelloMessage_deleteMembers(&hello);
+
+    /* Encode the message header at offset 0 */
+    UA_TcpMessageHeader messageHeader;
+    messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL;
     messageHeader.messageSize = (UA_UInt32)offset;
     offset = 0;
     retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset);
-    UA_TcpHelloMessage_deleteMembers(&hello);
     if(retval != UA_STATUSCODE_GOOD) {
         client->connection->releaseSendBuffer(client->connection, &message);
         return retval;
     }
 
+    /* Send the HEL message */
     message.length = messageHeader.messageSize;
     retval = client->connection->send(client->connection, &message);
     if(retval != UA_STATUSCODE_GOOD) {
@@ -134,8 +139,9 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
     }
     UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Sent HEL message");
 
-    UA_ByteString reply;
-    UA_ByteString_init(&reply);
+    /* Loop until we have a complete chunk */
+    /* TODO: quit after a total wait time of client->config.timeout */
+    UA_ByteString reply = UA_BYTESTRING_NULL;
     UA_Boolean realloced = false;
     do {
         retval = client->connection->recv(client->connection, &reply, client->config.timeout);
@@ -146,33 +152,37 @@ static UA_StatusCode HelAckHandshake(UA_Client *client) {
         }
     } while(reply.length == 0);
 
+    /* Decode the message */
     offset = 0;
-    UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
     UA_TcpAcknowledgeMessage ackMessage;
-    retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
+    retval = UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader);
+    retval |= UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage);
+
+    /* Free the message buffer */
     if(!realloced)
         client->connection->releaseRecvBuffer(client->connection, &reply);
     else
         UA_ByteString_deleteMembers(&reply);
 
-    if(retval != UA_STATUSCODE_GOOD) {
+    /* Store remote connection settings and adjust local configuration to not exceed the limits */
+    if(retval == UA_STATUSCODE_GOOD) {
+        UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
+        conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount; /* may be zero -> unlimited */
+        conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize; /* may be zero -> unlimited */
+        conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
+        conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
+        if(conn->remoteConf.recvBufferSize < conn->localConf.sendBufferSize)
+            conn->localConf.sendBufferSize = conn->remoteConf.recvBufferSize;
+        conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
+        if(conn->remoteConf.sendBufferSize < conn->localConf.recvBufferSize)
+            conn->localConf.recvBufferSize = conn->remoteConf.sendBufferSize;
+        conn->state = UA_CONNECTION_ESTABLISHED;
+    } else {
         UA_LOG_INFO(client->config.logger, UA_LOGCATEGORY_NETWORK, "Decoding ACK message failed");
-        return retval;
     }
-    UA_LOG_DEBUG(client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message");
-
-    /* TODO: verify that remote and local configurations match, adjust local configuration in the other case */
-    conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount;
-    conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize;
-    conn->remoteConf.protocolVersion = ackMessage.protocolVersion;
-    conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize;
-    conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize;
-    conn->state = UA_CONNECTION_ESTABLISHED;
-    
-    if (conn->remoteConf.recvBufferSize < conn->localConf.sendBufferSize)
-      conn->localConf.sendBufferSize = conn->remoteConf.recvBufferSize;
-    
-    return UA_STATUSCODE_GOOD;
+    UA_TcpAcknowledgeMessage_deleteMembers(&ackMessage);
+
+    return retval;
 }
 
 static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) {
@@ -284,7 +294,7 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     else
         UA_ByteString_deleteMembers(&reply);
 
-    //save the sequence number from server
+    /* save the sequence number from server */
     client->channel->receiveSequenceNumber = seqHeader.sequenceNumber;
 
 

+ 4 - 4
src/server/ua_server_binary.c

@@ -235,16 +235,16 @@ static void processHEL(UA_Connection *connection, const UA_ByteString *msg, size
         return;
     }
 
-    connection->state = UA_CONNECTION_ESTABLISHED;
-    connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount;
-    connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize;
+    connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount; /* may be zero -> unlimited */
+    connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize; /* may be zero -> unlimited */
     connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
     connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize;
     if(connection->localConf.sendBufferSize > helloMessage.receiveBufferSize)
         connection->localConf.sendBufferSize = helloMessage.receiveBufferSize;
+    connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
     if(connection->localConf.recvBufferSize > helloMessage.sendBufferSize)
         connection->localConf.recvBufferSize = helloMessage.sendBufferSize;
-    connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize;
+    connection->state = UA_CONNECTION_ESTABLISHED;
     UA_TcpHelloMessage_deleteMembers(&helloMessage);
 
     /* Build acknowledge response */

+ 6 - 8
src/server/ua_server_worker.c

@@ -22,19 +22,17 @@
  * - Remove the entry from the list
  * - mark it as "dead" with an atomic operation
  * - add a delayed job that frees the memory when all concurrent operations have completed
- * 
+ *
  * This approach to concurrently accessible memory is known as epoch based reclamation [1]. According to
  * [2], it performs competitively well on many-core systems. Our version of EBR does however not require
  * a global epoch. Instead, every worker thread has its own epoch counter that we observe for changes.
- * 
+ *
  * [1] Fraser, K. 2003. Practical lock freedom. Ph.D. thesis. Computer Laboratory, University of Cambridge.
  * [2] Hart, T. E., McKenney, P. E., Brown, A. D., & Walpole, J. (2007). Performance of memory reclamation
  *     for lockless synchronization. Journal of Parallel and Distributed Computing, 67(12), 1270-1285.
- * 
- * 
  */
 
-#define MAXTIMEOUT 500 // max timeout in millisec until the next main loop iteration
+#define MAXTIMEOUT 50 // max timeout in millisec until the next main loop iteration
 #define BATCHSIZE 20 // max number of jobs that are dispatched at once to workers
 
 static void processJobs(UA_Server *server, UA_Job *jobs, size_t jobsSize) {
@@ -94,10 +92,10 @@ static void * workerLoop(UA_Worker *worker) {
     UA_Server *server = worker->server;
     UA_UInt32 *counter = &worker->counter;
     volatile UA_Boolean *running = &worker->running;
-    
+
     /* Initialize the (thread local) random seed with the ram address of worker */
     UA_random_seed((uintptr_t)worker);
-   	rcu_register_thread();
+    rcu_register_thread();
 
     pthread_mutex_t mutex; // required for the condition variable
     pthread_mutex_init(&mutex,0);
@@ -122,7 +120,7 @@ static void * workerLoop(UA_Worker *worker) {
     pthread_mutex_destroy(&mutex);
     UA_ASSERT_RCU_UNLOCKED();
     rcu_barrier(); // wait for all scheduled call_rcu work to complete
-   	rcu_unregister_thread();
+    rcu_unregister_thread();
     return NULL;
 }
 

+ 1 - 1
src/ua_securechannel.c

@@ -139,7 +139,7 @@ UA_SecureChannel_sendChunk(UA_ChunkInfo *ci, UA_ByteString *dst, size_t offset)
     dst->length += UA_SECURE_MESSAGE_HEADER_LENGTH;
     offset += UA_SECURE_MESSAGE_HEADER_LENGTH;
 
-    if(ci->messageSizeSoFar + offset > connection->remoteConf.maxMessageSize)
+    if(ci->messageSizeSoFar + offset > connection->remoteConf.maxMessageSize && connection->remoteConf.maxChunkCount > 0)
         ci->errorCode = UA_STATUSCODE_BADRESPONSETOOLARGE;
     if(++ci->chunksSoFar > connection->remoteConf.maxChunkCount && connection->remoteConf.maxChunkCount > 0)
         ci->errorCode = UA_STATUSCODE_BADRESPONSETOOLARGE;