Sfoglia il codice sorgente

move sending of servicefaults from securechannel to server.
return UA_STATUSCODE_BADREQUESTTOOLARGE in the client when the message is bigger than the recv buffer of the server.
(no chunking supported so far)

Julius Pfrommer 9 anni fa
parent
commit
b44a64a8fc

+ 5 - 3
examples/networklayer_tcp.c

@@ -67,6 +67,7 @@ static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *respo
         return UA_STATUSCODE_BADOUTOFMEMORY;
     struct timeval tmptv = {0, timeout * 1000};
     if(0 != setsockopt(connection->sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tmptv, sizeof(struct timeval))){
+		UA_free(response->data);
         return UA_STATUSCODE_BADINTERNALERROR;
     }
     int ret = recv(connection->sockfd, (char*)response->data, connection->localConf.recvBufferSize, 0);
@@ -75,16 +76,17 @@ static UA_StatusCode socket_recv(UA_Connection *connection, UA_ByteString *respo
 		connection->close(connection);
 		return UA_STATUSCODE_BADCONNECTIONCLOSED;
 	} else if(ret < 0) {
+        UA_free(response->data);
 #ifdef _WIN32
 		if(WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) {
 #else
 		if (errno == EAGAIN) {
 #endif
             return UA_STATUSCODE_BADCOMMUNICATIONERROR;
+        } else {
+            connection->close(connection);
+            return UA_STATUSCODE_BADCONNECTIONCLOSED;
         }
-		UA_free(response->data);
-		connection->close(connection);
-        return UA_STATUSCODE_BADCONNECTIONCLOSED;
     }
     response->length = ret;
     *response = UA_Connection_completeMessages(connection, *response);

+ 4 - 1
src/client/ua_client.c

@@ -239,7 +239,10 @@ static void synchronousRequest(UA_Client *client, void *request, const UA_DataTy
                                                               request, requestType);
     UA_ResponseHeader *respHeader = (UA_ResponseHeader*)response;
     if(retval) {
-        respHeader->serviceResult = retval;
+        if(retval == UA_STATUSCODE_BADENCODINGERROR)
+            respHeader->serviceResult = UA_STATUSCODE_BADREQUESTTOOLARGE;
+        else
+            respHeader->serviceResult = retval;
         return;
     }
 

+ 17 - 10
src/server/ua_server_binary.c

@@ -148,8 +148,8 @@ static void init_response_header(const UA_RequestHeader *p, UA_ResponseHeader *r
 }
 
 /* The request/response are casted to the header (first element of their struct) */
-static void invoke_service(UA_Server *server, UA_SecureChannel *channel,
-                           UA_UInt32 requestId, UA_RequestHeader *request, const UA_DataType *responseType,
+static void invoke_service(UA_Server *server, UA_SecureChannel *channel, UA_UInt32 requestId,
+                           UA_RequestHeader *request, const UA_DataType *responseType,
                            void (*service)(UA_Server*, UA_Session*, void*, void*)) {
     UA_ResponseHeader *response = UA_alloca(responseType->memSize);
     UA_init(response, responseType);
@@ -170,7 +170,14 @@ static void invoke_service(UA_Server *server, UA_SecureChannel *channel,
         UA_Session_updateLifetime(session);
         service(server, session, request, response);
     }
-    UA_SecureChannel_sendBinaryMessage(channel, requestId, response, responseType);
+    UA_StatusCode retval = UA_SecureChannel_sendBinaryMessage(channel, requestId, response, responseType);
+    if(retval != UA_STATUSCODE_GOOD) {
+        if(retval == UA_STATUSCODE_BADENCODINGERROR)
+            response->serviceResult = UA_STATUSCODE_BADRESPONSETOOLARGE;
+        else
+            response->serviceResult = retval;
+        UA_SecureChannel_sendBinaryMessage(channel, requestId, response, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
+    }
     UA_deleteMembers(response, responseType);
 }
 
@@ -316,20 +323,20 @@ static void processMSG(UA_Connection *connection, UA_Server *server, const UA_By
             UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION, "Unknown request: NodeId(ns=%d, i=%d)",
                         requestType.namespaceIndex, requestType.identifier.numeric);
         UA_RequestHeader p;
-        UA_ServiceFault r;
+        UA_ResponseHeader r;
         if(UA_RequestHeader_decodeBinary(msg, pos, &p) != UA_STATUSCODE_GOOD)
             return;
-        UA_ServiceFault_init(&r);
-        init_response_header(&p, &r.responseHeader);
-        r.responseHeader.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
+        UA_ResponseHeader_init(&r);
+        init_response_header(&p, &r);
+        r.serviceResult = UA_STATUSCODE_BADSERVICEUNSUPPORTED;
 #ifdef EXTENSION_STATELESS
         if(retval != UA_STATUSCODE_GOOD)
             r.serviceResult = retval;
 #endif
+        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId, &r,
+                                           &UA_TYPES[UA_TYPES_SERVICEFAULT]);
         UA_RequestHeader_deleteMembers(&p);
-        UA_SecureChannel_sendBinaryMessage(clientChannel, sequenceHeader.requestId,
-            &r, &UA_TYPES[UA_TYPES_SERVICEFAULT]);
-        UA_ServiceFault_deleteMembers(&r);
+        UA_ResponseHeader_deleteMembers(&r);
         break;
     }
     }

+ 5 - 11
src/ua_securechannel.c

@@ -120,16 +120,9 @@ UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_U
     retval |= UA_NodeId_encodeBinary(&typeId, &message, &messagePos);
     retval |= UA_encodeBinary(content, contentType, &message, &messagePos);
 
-    /* write a failure message if necessary */
     if(retval != UA_STATUSCODE_GOOD) {
-        UA_ServiceFault r;
-        UA_ServiceFault_init(&r);
-        r.responseHeader = *(const UA_ResponseHeader*)content;
-        r.responseHeader.serviceResult = UA_STATUSCODE_BADRESPONSETOOLARGE;
-        size_t messagePos = 24;
-        UA_NodeId_encodeBinary(&UA_TYPES[UA_TYPES_SERVICEFAULT].typeId, &message, &messagePos);
-        UA_encodeBinary(&r, &UA_TYPES[UA_TYPES_SERVICEFAULT], &message, &messagePos);
-        UA_ServiceFault_init(&r);
+        connection->releaseBuffer(connection, &message);
+        return retval;
     }
 
     /* now write the header with the size */
@@ -145,7 +138,8 @@ UA_StatusCode UA_SecureChannel_sendBinaryMessage(UA_SecureChannel *channel, UA_U
     UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symSecHeader, &message, &messagePos);
     UA_SequenceHeader_encodeBinary(&seqHeader, &message, &messagePos);
     
-    if(connection->write(connection, &message, respHeader.messageHeader.messageSize) != UA_STATUSCODE_GOOD)
+    retval = connection->write(connection, &message, respHeader.messageHeader.messageSize);
+    if(retval != UA_STATUSCODE_GOOD)
         connection->releaseBuffer(connection, &message);
-    return UA_STATUSCODE_GOOD;
+    return retval;
 }