Explorar o código

M diagnosticInfo_calcSize: bugfix size of ADDITIONAL_INFO
+ the_empty_UA_ExtensionObject: for convenience
M SL_openSecureChannel: bugfix additionalHeader
M SL_processMessage: removed code that duplicates SL_openSecureChannel

Leon Urbas %!s(int64=10) %!d(string=hai) anos
pai
achega
f56add1fe6

+ 1 - 0
.gitignore

@@ -42,3 +42,4 @@ libtool
 coverage_report
 .project
 .cproject
+/INSTALL

+ 28 - 20
src/opcua_binaryEncDec.c

@@ -1397,15 +1397,12 @@ Int32 encodeDiagnosticInfo(UA_DiagnosticInfo *diagnosticInfo, Int32 *pos,
 	return UA_NO_ERROR;
 }
 Int32 diagnosticInfo_calcSize(UA_DiagnosticInfo *diagnosticInfo) {
-	Int32 minimumLength = 1;
-	Int32 length = minimumLength;
+	Int32 length = 0;
 	Byte mask;
-	Int32 j = 0;
-	mask = 0;
-	//puts("diagnosticInfo called");
-	//printf("with this mask %u", diagnosticInfo->EncodingMask);
-	for (mask = 1; mask <= 0x40; mask *= 2) {
-		j++;
+
+	length += sizeof(Byte);	// EncodingMask
+
+	for (mask = 0x01; mask <= 0x40; mask *= 2) {
 		switch (mask & (diagnosticInfo->EncodingMask)) {
 
 		case DIEMT_SYMBOLIC_ID:
@@ -1422,8 +1419,7 @@ Int32 diagnosticInfo_calcSize(UA_DiagnosticInfo *diagnosticInfo) {
 			length += sizeof(Int32);
 			break;
 		case DIEMT_ADDITIONAL_INFO:
-			length += diagnosticInfo->AdditionalInfo.Length;
-			length += sizeof(Int32);
+			length += UAString_calcSize(&(diagnosticInfo->AdditionalInfo));
 			break;
 		case DIEMT_INNER_STATUS_CODE:
 			length += sizeof(UA_StatusCode);
@@ -1496,25 +1492,37 @@ Int32 extensionObject_calcSize(UA_ExtensionObject *extensionObject) {
 
 	if (extensionObject->Encoding == BODY_IS_BYTE_STRING
 			|| extensionObject->Encoding == BODY_IS_XML_ELEMENT) {
-		length += sizeof(Int32) + extensionObject->Body.Length;
+		length += UAByteString_calcSize(&(extensionObject->Body));
 	}
 	return length;
 }
 
 Int32 responseHeader_calcSize(UA_AD_ResponseHeader *responseHeader) {
-	Int32 minimumLength = 20; // summation of all simple types
-	Int32 i, length;
-	length += minimumLength;
+	Int32 i;
+	Int32 length = 0;
 
-	for (i = 0; i < responseHeader->noOfStringTable; i++) {
-		length += responseHeader->stringTable[i].Length;
-		length += sizeof(UInt32); // length of the encoded length field
-	}
+	// UtcTime timestamp	8
+	length += sizeof(UA_DateTime);
+
+	// IntegerId requestHandle	4
+	length += sizeof(UA_AD_IntegerId);
+
+	// StatusCode serviceResult	4
+	length += sizeof(UA_StatusCode);
 
+	// DiagnosticInfo serviceDiagnostics
 	length += diagnosticInfo_calcSize(responseHeader->serviceDiagnostics);
-	//ToDo
-	length += extensionObject_calcSize(&(responseHeader->additionalHeader));
 
+	// String stringTable[], see 62541-6 § 5.2.4
+	length += sizeof(Int32); // Length of Stringtable always
+	if (responseHeader->noOfStringTable > 0) {
+		for (i = 0; i < responseHeader->noOfStringTable; i++) {
+			length += UAString_calcSize(responseHeader->stringTable[i]);
+		}
+	}
+
+	// ExtensibleObject additionalHeader
+	length += extensionObject_calcSize(responseHeader->additionalHeader);
 	return length;
 }
 

+ 2 - 1
src/opcua_builtInDatatypes.c

@@ -4,10 +4,11 @@
  *  Created on: Dec 19, 2013
  *      Author: opcua
  */
-
 #include "opcua_builtInDatatypes.h"
 #include <stdio.h>
 
+UA_ExtensionObject the_empty_UA_ExtensionObject = { { NIEVT_TWO_BYTE, 0 }, NO_BODY_IS_ENCODED};
+
 Int32 UA_String_compare(UA_String *string1, UA_String *string2) {
 	Int32 i;
 	Boolean equal;

+ 3 - 0
src/opcua_builtInDatatypes.h

@@ -400,6 +400,9 @@ typedef enum UA_ExtensionObjectEncodingMaskType
 }
 UA_ExtensionObjectEncodingMaskType;
 
+// the empty extensionobject
+extern UA_ExtensionObject the_empty_UA_ExtensionObject;
+
 typedef UA_VariantUnion;
 /**
 * VariantBinaryEncoding

+ 12 - 49
src/opcua_secureChannelLayer.c

@@ -34,12 +34,10 @@ Int32 SL_send(UA_connection *connection, UA_ByteString responseMessage, Int32 ty
 /*
  * opens a secure channel
  */
-Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, UA_StatusCode serviceResult, UA_AD_DiagnosticInfo *serviceDiagnostics)
+Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, UA_StatusCode serviceResult, UA_DiagnosticInfo *serviceDiagnostics)
 {
-
-
-
 	UA_AD_ResponseHeader responseHeader;
+	UA_ExtensionObject additionalHeader;
 	SL_ChannelSecurityToken securityToken;
 	UA_ByteString serverNonce;
 	UA_NodeId responseType;
@@ -55,7 +53,6 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	/*--------------type ----------------------*/
 	//Four Bytes Encoding
 	responseType.EncodingByte = NIEVT_FOUR_BYTE;
-	//openSecureChannelResponse = 449
 	responseType.Identifier.Numeric = 449;
 
 	/*--------------responseHeader-------------*/
@@ -74,18 +71,15 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	responseHeader.requestHandle = requestHandle;
 	// StatusCode which informs client about quality of response
 	responseHeader.serviceResult = serviceResult;
-	//retrive diagnosticInfo if client demands
+	//retrieve diagnosticInfo if client demands
 	responseHeader.serviceDiagnostics = serviceDiagnostics;
 
 	//text of fields defined in the serviceDiagnostics
 	responseHeader.noOfStringTable = 0;
 	responseHeader.stringTable = NULL;
 
-
 	// no additional header
-	responseHeader.additionalHeader->Encoding = 0;
-	responseHeader.additionalHeader->TypeId.EncodingByte = 0;
-	responseHeader.additionalHeader->TypeId.Identifier.Numeric = 0;
+	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;
 
 	//calculate the size
 	sizeRespHeader = responseHeader_calcSize(&responseHeader);
@@ -99,7 +93,7 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	sizeSecurityToken = sizeof(UInt32) + sizeof(UInt32) + sizeof(UA_DateTime) + sizeof(Int32);
 
 	//ignore server nonce
-	serverNonce.Length = 0;
+	serverNonce.Length = -1;
 	serverNonce.Data = NULL;
 
 	//fill toke structure with default server information
@@ -111,7 +105,7 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
 
 	//                ProtocolVersion + SecurityToken + Nonce
-	sizeRespMessage = sizeof(UInt32) + sizeSecurityToken + serverNonce.Length + sizeof(Int32) + sizeSecurityToken;
+	sizeRespMessage = sizeof(UInt32) + sizeSecurityToken + UAByteString_calcSize(&serverNonce) + sizeof(Int32) + sizeSecurityToken;
 
 	//get memory for response
 	response.Data = (char*)opcua_malloc(nodeId_calcSize(responseType) + sizeRespHeader + sizeRespMessage);
@@ -147,10 +141,14 @@ Int32 SL_createSecurityToken(UA_connection *connection, Int32 lifeTime) {
 }
 
 Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
+	UA_DiagnosticInfo serviceDiagnostics;
+
 	Int32 pos = 0;
 	// Every Message starts with a NodeID which names the serviceRequestType
 	UA_NodeId serviceRequestType;
 
+
+
 	decoder_decodeBuiltInDatatype(message.Data, NODE_ID, &pos,
 			&serviceRequestType);
 	UA_NodeId_printf("SL_processMessage - serviceRequestType=",
@@ -255,47 +253,12 @@ Int32 SL_processMessage(UA_connection *connection, UA_ByteString message) {
 		printf("SL_processMessage - requestedLifeTime=%d\n", requestedLifetime);
 		//TODO process requestedLifetime
 
-		{
-			// Res-0) NodeId typeID
-			UA_NodeId typeID;
-			// Res-1) ResponseHeader responseHeader
-			UA_AD_ResponseHeader responseHeader;
-			// Res-2) UInt32 ServerProtocolVersion
-			UInt32 serverProtocolVersion;
-			// Res-3) SecurityToken channelSecurityToken
-			SL_ChannelSecurityToken securityToken;
-			// Res-4) ByteString ServerNonce
-			UA_ByteString serverNonce;
-
-			// Res-1) ResponseHeader responseHeader
-			responseHeader.timestamp = opcua_getTime();
-			// 62541-4 §7.27 "The requestHandle given by the Client to the request."
-			responseHeader.requestHandle = requestHeader.requestHandle;
-			responseHeader.serviceResult = SC_Good;
-			// 62541-4 §7.27 "This parameter is empty if diagnostics information was not requested in the request header"
-			responseHeader.serviceDiagnostics = NULL;
-			responseHeader.stringTable = NULL;
-			responseHeader.additionalHeader.TypeId.EncodingByte = 0;
-			responseHeader.additionalHeader.TypeId.Identifier.Numeric = 0;
-			responseHeader.additionalHeader.Encoding = NO_BODY_IS_ENCODED;
-
-			// Res-2) UInt32 ServerProtocolVersion
-			// 62541-6 §6.4.4 "Implementations that have not been certified shall set the protocol version to 0"
-			serverProtocolVersion = 0;
-
-			// Res-3) SecurityToken channelSecurityToken
-			securityToken.secureChannelId = 666; // TODO: create
-			securityToken.tokenId = 42; // TODO: create
-			securityToken.createdAt = opcua_getTime();
-			securityToken.revisedLifetime = requestHeader.timeoutHint;
-			// Res-4) ByteString ServerNonce
-			serverNonce.Length = -1;
-		}
+		// 62541-4 §7.27 "The requestHandle given by the Client to the request."
+		return SL_openSecureChannel(connection, requestHeader.requestHandle, SC_Good, &serviceDiagnostics);
 	} else {
 		printf("SL_processMessage - unknown service request");
 		//TODO change error code
 		return UA_ERROR;
-
 	}
 	return UA_NO_ERROR;
 }

+ 2 - 2
src/opcua_types.h

@@ -806,8 +806,8 @@ typedef struct UA_AD_ResponseHeader
 	UA_AD_IntegerId requestHandle;
 	UA_StatusCode serviceResult;
 	UA_DiagnosticInfo *serviceDiagnostics;
-	UInt16 noOfStringTable;
-	UA_String* stringTable;
+	Int16 noOfStringTable;		// Unsigned: -1 == Empty Array
+	UA_String** stringTable;	//  this is an array of strings, i.e. String** or String* ... []
 	UA_ExtensionObject *additionalHeader;
 }
 UA_AD_ResponseHeader;

+ 50 - 45
tests/check_stack.c

@@ -24,12 +24,11 @@ START_TEST(test_getPacketType_validParameter)
 
 	char buf[] = {'C','L','O'};
 	Int32 pos = 0;
-	AD_RawMessage rawMessage;
-	rawMessage.message = buf;
-	rawMessage.length = 3;
-
-	ck_assert_int_eq(TL_getPacketType(&pos,&rawMessage),packetType_CLO);
+	UA_ByteString msg;
+	msg.Data = buf;
+	msg.Length = 3;
 
+	ck_assert_int_eq(TL_getPacketType(&msg, &pos),packetType_CLO);
 }
 END_TEST
 
@@ -78,7 +77,7 @@ START_TEST(decodeRequestHeader_test_validParameter)
 END_TEST
 */
 
-START_TEST(decodeInt16_test)
+START_TEST(decodeInt16_test_positives)
 {
 	Int32 p = 0;
 	Int16 val;
@@ -88,13 +87,11 @@ START_TEST(decodeInt16_test)
 			0x01,0x00,	// 1
 			0xFF,0x00,	// 255
 			0x00,0x01,	// 256
-			0xFF,0xFF,	// -1
-			0x00,0x80,	// -32768
 	};
 
 	rawMessage.message = mem;
 	rawMessage.length = sizeof(mem);
-	ck_assert_int_eq(rawMessage.length,12);
+	ck_assert_int_eq(rawMessage.length,8);
 
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,0);
@@ -104,12 +101,29 @@ START_TEST(decodeInt16_test)
 	ck_assert_int_eq(val,255);
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,256);
+}
+END_TEST
+START_TEST(decodeInt16_test_negatives)
+{
+	Int32 p = 0;
+	Int16 val;
+	AD_RawMessage rawMessage;
+	char mem[] = {
+			0xFF,0xFF,	// -1
+			0x00,0x80,	// -32768
+	};
+
+	rawMessage.message = mem;
+	rawMessage.length = sizeof(mem);
+	ck_assert_int_eq(rawMessage.length,4);
+
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,-1);
 	decoder_decodeBuiltInDatatype(rawMessage.message,INT16,&p,&val);
 	ck_assert_int_eq(val,-32768);
 }
 END_TEST
+
 START_TEST(encodeInt16_test)
 {
 
@@ -461,61 +475,51 @@ START_TEST(extensionObject_calcSize_test)
 	UA_ExtensionObject extensionObject;
 
 	// empty ExtensionObject
-	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;; // Numeric TWO BYTES
+	valcalc = extensionObject_calcSize(&the_empty_UA_ExtensionObject);
+	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+
+	// empty ExtensionObject, handcoded
+	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;
 	extensionObject.TypeId.Identifier.Numeric = 0;
 	extensionObject.Encoding = NO_BODY_IS_ENCODED;
 
 	valcalc = extensionObject_calcSize(&extensionObject);
-	valreal = 3;
-	ck_assert_int_eq(valcalc, valreal);
+	ck_assert_int_eq(valcalc, 1 + 1 + 1);
 
 	// ExtensionObject with ByteString-Body
 	extensionObject.Encoding = BODY_IS_BYTE_STRING;
 	extensionObject.Body.Data = data;
 	extensionObject.Body.Length = 3;
 	valcalc = extensionObject_calcSize(&extensionObject);
-	valreal = 3 + 4 + 3;
-	ck_assert_int_eq(valcalc, valreal);
+	ck_assert_int_eq(valcalc, 3 + 4 + 3);
 
 }
 END_TEST
 
 START_TEST(responseHeader_calcSize_test)
 {
-	Int32 valreal = 1;
-	Int32 valcalc = 0;
-	fail();//ToDo: needs to be adjusted: just to see this needs to be adjusted
-	//ToDo: needs to be adjusted: T_ResponseHeader responseHeader;
+	UA_AD_ResponseHeader responseHeader;
 	UA_DiagnosticInfo diagnosticInfo;
 	UA_ExtensionObject extensionObject;
 
-	//Should have the size of 16 Bytes
-	//ToDo: needs to be adjusted: responseHeader.timestamp = 150014;
-	//ToDo: needs to be adjusted: responseHeader.requestHandle = 514;
-	//ToDo: needs to be adjusted: responseHeader.serviceResult = 504;
-
 	//Should have the size of 26 Bytes
-	diagnosticInfo.EncodingMask = 0x01 | 0x02 | 0x04 | 0x08 | 0x10;
-	diagnosticInfo.SymbolicId = 30;
-	diagnosticInfo.NamespaceUri = 25;
-	diagnosticInfo.LocalizedText = 22;
-	diagnosticInfo.AdditionalInfo.Data = "OPCUA";
-	diagnosticInfo.AdditionalInfo.Length = 5;
-	//ToDo: needs to be adjusted: responseHeader.serviceDiagnostics = &diagnosticInfo;
-	//Should have the size of 4 Bytes
-	//ToDo: needs to be adjusted: responseHeader.noOfStringTable = 0;
-	//Should have the size of 3 Bytes
-	extensionObject.TypeId.EncodingByte = NIEVT_TWO_BYTE;
-	extensionObject.TypeId.Identifier.Numeric = 0;
-	extensionObject.Encoding = 0x00; //binaryBody = false, xmlBody = false
-	//ToDo: needs to be adjusted: responseHeader.additionalHeader = extensionObject;
-
-	//ToDo: needs to be adjusted: valcalc = responseHeader_calcSize(&responseHeader);
-	fail(); //ToDo: needs to be adjusted: Just to see that this needs to be adjusted
-	valreal = 49;
-
-	ck_assert_int_eq(valcalc,valreal);
-
+	diagnosticInfo.EncodingMask = DIEMT_SYMBOLIC_ID | DIEMT_NAMESPACE | DIEMT_LOCALIZED_TEXT | DIEMT_LOCALE | DIEMT_ADDITIONAL_INFO;		// Byte:   1
+	// Indices into to Stringtable of the responseHeader (62541-6 §5.5.12 )
+	diagnosticInfo.SymbolicId = -1;										// Int32:  4
+	diagnosticInfo.NamespaceUri = -1;									// Int32:  4
+	diagnosticInfo.LocalizedText = -1;									// Int32:  4
+	diagnosticInfo.Locale = -1;											// Int32:  4
+	// Additional Info
+	diagnosticInfo.AdditionalInfo.Length = 5;							// Int32:  4
+	diagnosticInfo.AdditionalInfo.Data = "OPCUA";						// Byte[]: 5
+	responseHeader.serviceDiagnostics = &diagnosticInfo;
+	ck_assert_int_eq(diagnosticInfo_calcSize(&diagnosticInfo),1+(4+4+4+4)+(4+5));
+
+	responseHeader.noOfStringTable = -1;								// Int32:	4
+	responseHeader.stringTable = NULL;
+
+	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;	//		    3
+	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+26+4+3);
 }
 END_TEST
 
@@ -621,7 +625,8 @@ Suite *testSuite_decodeInt16(void)
 {
 	Suite *s = suite_create("decodeInt16_test");
 	TCase *tc_core = tcase_create("Core");
-	tcase_add_test(tc_core, decodeInt16_test);
+	tcase_add_test(tc_core, decodeInt16_test_positives);
+	tcase_add_test(tc_core, decodeInt16_test_negatives);
 	suite_add_tcase(s,tc_core);
 	return s;
 }