Browse Source

Merge branch 'master' into dev

Conflicts:
	src/ua_types_encoding_binary.c
Julius Pfrommer 9 years ago
parent
commit
a1a8487afb

+ 71 - 25
examples/networklayer_tcp.c

@@ -38,25 +38,26 @@
 /* Generic Socket Functions */
 /****************************/
 
-static UA_StatusCode socket_write(UA_Connection *connection, const UA_ByteString *buf) {
-    if(buf->length < 0)
-        return UA_STATUSCODE_BADINTERNALERROR;
-    UA_Int32 nWritten = 0;
-    while (nWritten < buf->length) {
+static UA_StatusCode socket_write(UA_Connection *connection, UA_ByteString *buf, size_t buflen) {
+    size_t nWritten = 0;
+    while (nWritten < buflen) {
         UA_Int32 n = 0;
         do {
 #ifdef _WIN32
-            n = send((SOCKET)connection->sockfd, (const char*)buf->data, buf->length, 0);
+            n = send((SOCKET)connection->sockfd, (const char*)buf->data, buflen, 0);
             if(n < 0 && WSAGetLastError() != WSAEINTR && WSAGetLastError() != WSAEWOULDBLOCK)
                 return UA_STATUSCODE_BADCONNECTIONCLOSED;
 #else
-            n = send(connection->sockfd, (const char*)buf->data, buf->length, MSG_NOSIGNAL);
+            n = send(connection->sockfd, (const char*)buf->data, buflen, MSG_NOSIGNAL);
             if(n == -1L && errno != EINTR && errno != EAGAIN)
                 return UA_STATUSCODE_BADCONNECTIONCLOSED;
 #endif
         } while (n == -1L);
         nWritten += n;
     }
+#ifdef UA_MULTITHREADING
+    UA_ByteString_deleteMembers(buf);
+#endif
     return UA_STATUSCODE_GOOD;
 }
 
@@ -111,18 +112,6 @@ static UA_StatusCode socket_set_nonblocking(UA_Int32 sockfd) {
     return UA_STATUSCODE_GOOD;
 }
 
-/*****************************/
-/* Generic Buffer Management */
-/*****************************/
-
-static UA_StatusCode GetMallocedBuffer(UA_Connection *connection, UA_ByteString *buf, size_t minSize) {
-    return UA_ByteString_newMembers(buf, minSize);
-}
-
-static void ReleaseMallocedBuffer(UA_Connection *connection, UA_ByteString *buf) {
-    UA_ByteString_deleteMembers(buf);
-}
-
 /***************************/
 /* Server NetworkLayer TCP */
 /***************************/
@@ -166,6 +155,10 @@ typedef struct {
     UA_String discoveryUrl;
     UA_ConnectionConfig conf; /* todo: rename to localconf. */
 
+#ifndef UA_MULTITHREADING
+    UA_ByteString buffer; // message buffer that is reused
+#endif
+
     /* open sockets and connections */
     fd_set fdset;
     UA_Int32 serversockfd;
@@ -183,6 +176,22 @@ typedef struct {
     } *deletes;
 } ServerNetworkLayerTCP;
 
+static UA_StatusCode ServerNetworkLayerGetBuffer(UA_Connection *connection, UA_ByteString *buf, size_t minSize) {
+#ifdef UA_MULTITHREADING
+    return UA_ByteStringnewMembers(buf, minSize);
+#else
+    ServerNetworkLayerTCP *layer = connection->handle;
+    *buf = layer->buffer;
+    return UA_STATUSCODE_GOOD;
+#endif
+}
+
+static void ServerNetworkLayerReleaseBuffer(UA_Connection *connection, UA_ByteString *buf) {
+#ifdef UA_MULTITHREADING
+    UA_ByteString_deleteMembers(buf);
+#endif
+}
+
 /* after every select, we need to reset the sockets we want to listen on */
 static void setFDSet(ServerNetworkLayerTCP *layer) {
     FD_ZERO(&layer->fdset);
@@ -243,8 +252,8 @@ static UA_StatusCode ServerNetworkLayerTCP_add(ServerNetworkLayerTCP *layer, UA_
     c->localConf = layer->conf;
     c->write = socket_write;
     c->close = ServerNetworkLayerTCP_closeConnection;
-    c->getBuffer = GetMallocedBuffer;
-    c->releaseBuffer = ReleaseMallocedBuffer;
+    c->getBuffer = ServerNetworkLayerGetBuffer;
+    c->releaseBuffer = ServerNetworkLayerReleaseBuffer;
     c->state = UA_CONNECTION_OPENING;
     struct ConnectionMapping *nm =
         realloc(layer->mappings, sizeof(struct ConnectionMapping)*(layer->mappingsSize+1));
@@ -453,6 +462,9 @@ static void ServerNetworkLayerTCP_delete(ServerNetworkLayerTCP *layer) {
     UA_String_deleteMembers(&layer->discoveryUrl);
     removeMappings(layer, layer->deletes);
     freeConnections(NULL, layer->deletes);
+#ifndef UA_MULTITHREADING
+    UA_ByteString_deleteMembers(&layer->buffer);
+#endif
     for(size_t i = 0; i < layer->mappingsSize; i++)
         free(layer->mappings[i].connection);
     free(layer->mappings);
@@ -482,6 +494,10 @@ UA_ServerNetworkLayer ServerNetworkLayerTCP_new(UA_ConnectionConfig conf, UA_UIn
     gethostname(hostname, 255);
     UA_String_copyprintf("opc.tcp://%s:%d", &layer->discoveryUrl, hostname, port);
 
+#ifndef UA_MULTITHREADING
+    layer->buffer = (UA_ByteString){.length = conf.maxMessageSize, .data = malloc(conf.maxMessageSize)};
+#endif
+
     nl.nlHandle = layer;
     nl.start = (UA_StatusCode (*)(void*, UA_Logger *logger))ServerNetworkLayerTCP_start;
     nl.getJobs = (UA_Int32 (*)(void*, UA_Job**, UA_UInt16))ServerNetworkLayerTCP_getJobs;
@@ -495,9 +511,39 @@ UA_ServerNetworkLayer ServerNetworkLayerTCP_new(UA_ConnectionConfig conf, UA_UIn
 /* Client NetworkLayer TCP */
 /***************************/
 
-UA_Connection ClientNetworkLayerTCP_connect(char *endpointUrl, UA_Logger *logger) {
+static UA_StatusCode ClientNetworkLayerGetBuffer(UA_Connection *connection, UA_ByteString *buf, size_t minSize) {
+#ifdef UA_MULTITHREADING
+    *buf = *(UA_ByteString*)connection->handle;
+    return UA_STATUSCODE_GOOD;
+#else
+    return UA_ByteString_newMembers(buf, minSize);
+#endif
+}
+
+static void ClientNetworkLayerReleaseBuffer(UA_Connection *connection, UA_ByteString *buf) {
+#ifdef UA_MULTITHREADING
+    UA_ByteString_deleteMembers(buf);
+#endif
+}
+
+static void ClientNetworkLayerClose(UA_Connection *connection) {
+    socket_close(connection);
+#ifndef UA_MULTITHREADING
+    UA_ByteString_delete(connection->handle);
+#endif
+}
+
+/* we have no networklayer. instead, attach the reusable buffer to the handle */
+UA_Connection ClientNetworkLayerTCP_connect(UA_ConnectionConfig localConf, char *endpointUrl,
+                                            UA_Logger *logger) {
     UA_Connection connection;
     UA_Connection_init(&connection);
+    connection.localConf = localConf;
+
+#ifndef UA_MULTITHREADING
+    connection.handle = UA_ByteString_new();
+    UA_ByteString_newMembers(connection.handle, localConf.maxMessageSize);
+#endif
 
     size_t urlLength = strlen(endpointUrl);
     if(urlLength < 11 || urlLength >= 512) {
@@ -556,8 +602,8 @@ UA_Connection ClientNetworkLayerTCP_connect(char *endpointUrl, UA_Logger *logger
     //socket_set_nonblocking(connection.sockfd);
     connection.write = socket_write;
     connection.recv = socket_recv;
-    connection.close = socket_close;
-    connection.getBuffer = GetMallocedBuffer;
-    connection.releaseBuffer = ReleaseMallocedBuffer;
+    connection.close = ClientNetworkLayerClose;
+    connection.getBuffer = ClientNetworkLayerGetBuffer;
+    connection.releaseBuffer = ClientNetworkLayerReleaseBuffer;
     return connection;
 }

+ 2 - 1
examples/networklayer_tcp.h

@@ -19,7 +19,8 @@ extern "C" {
 
 /** @brief Create the TCP networklayer and listen to the specified port */
 UA_EXPORT UA_ServerNetworkLayer ServerNetworkLayerTCP_new(UA_ConnectionConfig conf, UA_UInt32 port);
-UA_EXPORT UA_Connection ClientNetworkLayerTCP_connect(char *endpointUrl, UA_Logger *logger);
+UA_EXPORT UA_Connection ClientNetworkLayerTCP_connect(UA_ConnectionConfig conf, char *endpointUrl,
+                                                      UA_Logger *logger);
 
 #ifdef __cplusplus
 } // extern "C"

+ 1 - 1
examples/server.c

@@ -192,7 +192,7 @@ static void stopHandler(int sign) {
 static UA_ByteString loadCertificate(void) {
 	UA_ByteString certificate = UA_STRING_NULL;
 	FILE *fp = NULL;
-	//FIXME: a potiential bug of locating the certificate, we need to get the path from the server's config
+	//FIXME: a potential bug of locating the certificate, we need to get the path from the server's config
 	fp=fopen("server_cert.der", "rb");
 
 	if(!fp) {

+ 2 - 1
include/ua_client.h

@@ -18,7 +18,8 @@ typedef struct UA_Client UA_Client;
  * The client networklayer is defined by a single function that fills a UA_Connection struct after
  * successfully connecting.
  */
-typedef UA_Connection (*UA_ConnectClientConnection)(char *endpointUrl, UA_Logger *logger);
+typedef UA_Connection (*UA_ConnectClientConnection)(UA_ConnectionConfig localConf, char *endpointUrl,
+                                                    UA_Logger *logger);
 
 typedef struct UA_ClientConfig {
     UA_Int32 timeout; //sync response timeout

+ 9 - 2
include/ua_connection.h

@@ -65,8 +65,15 @@ struct UA_Connection {
     void *handle; ///> A pointer to the networklayer
     UA_ByteString incompleteMessage; ///> Half-received messages (tcp is a streaming protocol) get stored here
     UA_StatusCode (*getBuffer)(UA_Connection *connection, UA_ByteString *buf, size_t minSize); ///> Attach the data array to the buffer. Fails if minSize is larger than remoteConf allows
-    void (*releaseBuffer)(UA_Connection *connection, UA_ByteString *buf); ///> Release the buffer
-    UA_StatusCode (*write)(UA_Connection *connection, const UA_ByteString *buf); ///> The bytestrings cannot be reused after sending!
+    void (*releaseBuffer)(UA_Connection *connection, UA_ByteString *buf); ///> Release the buffer manually
+    /**
+     * Sends a message over the connection.
+     * @param connection The connection
+     * @param buf The message buffer is potentially reused (or freed) internally if sending succeeds.
+     * @param buflen Since the buffer is potentially reused, we provide a separate content length.
+     * @return Returns an error code or UA_STATUSCODE_GOOD.
+     */
+    UA_StatusCode (*write)(UA_Connection *connection, UA_ByteString *buf, size_t buflen);
    /**
      * Receive a message from the remote connection
 	 * @param connection The connection

+ 9 - 6
src/client/ua_client.c

@@ -93,8 +93,9 @@ static UA_StatusCode HelAckHandshake(UA_Client *c) {
     UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset);
     UA_TcpHelloMessage_deleteMembers(&hello);
 
-    retval = c->connection.write(&c->connection, &message);
-    c->connection.releaseBuffer(&c->connection, &message);
+    retval = c->connection.write(&c->connection, &message, messageHeader.messageSize);
+    if(retval != UA_STATUSCODE_GOOD)
+        c->connection.releaseBuffer(&c->connection, &message);
     if(retval)
         return retval;
 
@@ -178,8 +179,10 @@ static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew)
     UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
     UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq);
 
-    retval = client->connection.write(&client->connection, &message);
-    client->connection.releaseBuffer(&client->connection, &message);
+    retval = client->connection.write(&client->connection, &message,
+                                      messageHeader.messageHeader.messageSize);
+    if(retval != UA_STATUSCODE_GOOD)
+        client->connection.releaseBuffer(&client->connection, &message);
     if(retval)
         return retval;
 
@@ -456,7 +459,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
     retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset);
     retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], &message, &offset);
     if(retval == UA_STATUSCODE_GOOD)
-        retval = client->connection.write(&client->connection, &message);
+        retval = client->connection.write(&client->connection, &message, msgHeader.messageHeader.messageSize);
     client->connection.releaseBuffer(&client->connection, &message);
     return retval;
 }
@@ -466,7 +469,7 @@ static UA_StatusCode CloseSecureChannel(UA_Client *client) {
 /*************************/
 
 UA_StatusCode UA_Client_connect(UA_Client *client, UA_ConnectClientConnection connectFunc, char *endpointUrl) {
-    client->connection = connectFunc(endpointUrl, &client->logger);
+    client->connection = connectFunc(UA_ConnectionConfig_standard, endpointUrl, &client->logger);
     if(client->connection.state != UA_CONNECTION_OPENING)
         return UA_STATUSCODE_BADCONNECTIONCLOSED;
 

+ 7 - 4
src/server/ua_server_binary.c

@@ -50,8 +50,8 @@ static void processHEL(UA_Connection *connection, const UA_ByteString *msg, size
     size_t tmpPos = 0;
     UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos);
     UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos);
-    connection->write(connection, &ack_msg);
-    connection->releaseBuffer(connection, &ack_msg);
+    if(connection->write(connection, &ack_msg, ackHeader.messageSize) != UA_STATUSCODE_GOOD)
+        connection->releaseBuffer(connection, &ack_msg);
 }
 
 static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg,
@@ -133,8 +133,9 @@ static void processOPN(UA_Connection *connection, UA_Server *server, const UA_By
     UA_OpenSecureChannelResponse_deleteMembers(&p);
     UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader);
 
-    connection->write(connection, &resp_msg);
-    connection->releaseBuffer(connection, &resp_msg);
+    if(connection->write(connection, &resp_msg,
+                         respHeader.messageHeader.messageSize) != UA_STATUSCODE_GOOD)
+        connection->releaseBuffer(connection, &resp_msg);
 }
 
 static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r) {
@@ -389,6 +390,7 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
         case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff:
             processCLO(connection, server, msg, &pos);
             connection->close(connection);
+            UA_ByteString_deleteMembers(msg);
             return;
         }
 
@@ -399,4 +401,5 @@ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection
             pos = targetpos;
         }
     } while(msg->length > (UA_Int32)pos);
+    UA_ByteString_deleteMembers(msg);
 }

+ 2 - 2
src/ua_securechannel.c

@@ -137,7 +137,7 @@ UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_U
     UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
     UA_encodeBinary(content, contentType, &message, &messagePos);
     
-    connection->write(connection, &message);
-    connection->releaseBuffer(connection, &message);
+    if(connection->write(connection, &message, respHeader.messageHeader.messageSize) != UA_STATUSCODE_GOOD)
+        connection->releaseBuffer(connection, &message);
     return UA_STATUSCODE_GOOD;
 }

+ 4 - 4
src/ua_types_encoding_binary.c

@@ -172,7 +172,7 @@ UA_StatusCode UA_UInt16_decodeBinary(UA_ByteString const *src, size_t *UA_RESTRI
     if((UA_Int32)(*offset + sizeof(UA_UInt16)) > src->length)
         return UA_STATUSCODE_BADDECODINGERROR;
     UA_UInt16 value = *((UA_UInt16*)&src->data[*offset]);
-#ifndef UA_NON_LITTLEENDIAN_ARCHITECTURE
+#ifdef UA_NON_LITTLEENDIAN_ARCHITECTURE
     value = le16toh(value);
 #endif
     *dst = value;
@@ -189,7 +189,7 @@ UA_StatusCode UA_UInt32_encodeBinary(UA_UInt32 const *src, UA_ByteString * dst,
     if((UA_Int32)(*offset + sizeof(UA_UInt32)) > dst->length )
         return UA_STATUSCODE_BADENCODINGERROR;
     UA_UInt32 *dst_ptr = (UA_UInt32*)&dst->data[*offset];
-#ifndef UA_NON_LITTLEENDIAN_ARCHITECTURE
+#ifdef UA_NON_LITTLEENDIAN_ARCHITECTURE
     *dst_ptr = htole32(*src);
 #else
     *dst_ptr = *src;
@@ -219,7 +219,7 @@ UA_StatusCode UA_UInt64_encodeBinary(UA_UInt64 const *src, UA_ByteString *dst, s
     if((UA_Int32)(*offset + sizeof(UA_UInt64)) > dst->length )
         return UA_STATUSCODE_BADENCODINGERROR;
     UA_UInt64 *dst_ptr = (UA_UInt64*)&dst->data[*offset];
-#ifndef UA_NON_LITTLEENDIAN_ARCHITECTURE
+#ifdef UA_NON_LITTLEENDIAN_ARCHITECTURE
     *dst_ptr = htole64(*src);
 #else
     *dst_ptr = *src;
@@ -232,7 +232,7 @@ UA_StatusCode UA_UInt64_decodeBinary(UA_ByteString const *src, size_t *UA_RESTRI
     if((UA_Int32)(*offset + sizeof(UA_UInt64)) > src->length)
         return UA_STATUSCODE_BADDECODINGERROR;
     UA_UInt64 value = *((UA_UInt64*)&src->data[*offset]);
-#ifndef UA_NON_LITTLEENDIAN_ARCHITECTURE
+#ifdef UA_NON_LITTLEENDIAN_ARCHITECTURE
     value = le64toh(value);
 #endif
     *dst = value;

+ 1 - 1
src/ua_util.h

@@ -87,7 +87,7 @@
     # define UA_alloca(SIZE) _alloca(SIZE)
 #else
  #ifdef __GNUC__
-    # define UA_alloca(size)   __builtin_alloca (size)
+    # define UA_alloca(size) __builtin_alloca (size)
  #else
     # include <alloca.h>
     # define UA_alloca(SIZE) alloca(SIZE)