Kaynağa Gözat

added encode_builtInDatatypeArray w/ tests, completed
encodeResponseHeader and fixed some uninitialized pointer bugs in
SL_openSecureChannel

Leon Urbas 11 yıl önce
ebeveyn
işleme
be8fcc93af

+ 23 - 88
src/opcua_binaryEncDec.c

@@ -430,92 +430,26 @@ Int32 decoder_decodeBuiltInDatatype(char const * srcBuf, Int32 type, Int32 *pos,
  }
 
 
- /* not tested */
-/*needs to be reimplemented */
-Int32 encode_builtInDatatypeArray(void *data, Int32 size, Int32 type,
+/* not tested, needs to be reimplemented */
+Int32 encode_builtInDatatypeArray(void* data[], Int32 size, Int32 type,
 		Int32 *pos, char *dstBuf) {
 	int i;
-	void * pItem;
-	encoder_encodeBuiltInDatatype((void*) (size), INT32, pos, dstBuf);
-	for (i = 0; i < size;) {
-		encoder_encodeBuiltInDatatype(pItem, type, pos, dstBuf);
-		switch (type) {
-		case BOOLEAN:
-			pItem = (Boolean*) (data) + 1;
-			break;
-		case SBYTE:
-			pItem = (SByte*) (data) + 1;
-			break;
-		case BYTE:
-			pItem = (Byte*) (data) + 1;
-			break;
-		case INT16:
-			pItem = (Int16*) (data) + 1;
-			break;
-		case UINT16:
-			pItem = (UInt16*) (data) + 1;
-			break;
-		case INT32:
-			pItem = (Int32*) (data) + 1;
-			break;
-		case UINT32:
-			pItem = (UInt32*) (data) + 1;
-			break;
-		case INT64:
-			pItem = (Int64*) (data) + 1;
-			break;
-		case UINT64:
-			pItem = (UInt64*) (data) + 1;
-			break;
-		case FLOAT:
-			pItem = (Float*) (data) + 1;
-			break;
-		case DOUBLE:
-			pItem = (Double*) (data) + 1;
-			break;
-		case STRING:
-			pItem = (UA_String*) (data) + 1;
-			break;
-		case DATE_TIME:
-			pItem = (UA_DateTime*) (data) + 1;
-			break;
-		case GUID:
-			pItem = (UA_Guid*) (data) + 1;
-			break;
-		case BYTE_STRING:
-			pItem = (UA_ByteString*) (data) + 1;
-			break;
-		case XML_ELEMENT:
-			pItem = (UA_XmlElement*) (data) + 1;
-			break;
-		case NODE_ID:
-			pItem = (UA_NodeId*) (data) + 1;
-			break;
-		case EXPANDED_NODE_ID:
-			pItem = (UA_ExpandedNodeId*) (data) + 1;
-			break;
-		case STATUS_CODE:
-			pItem = (UA_StatusCode*) (data) + 1;
-			break;
-		case QUALIFIED_NAME:
-			pItem = (UA_QualifiedName*) (data) + 1;
-			break;
-		case LOCALIZED_TEXT:
-			pItem = (UA_LocalizedText*) (data) + 1;
-			break;
-		case EXTENSION_OBJECT:
-			pItem = (UA_ExtensionObject*) (data) + 1;
-			break;
-		case DATA_VALUE:
-			pItem = (UA_DataValue*) (data) + 1;
-			break;
-		case VARIANT:
-			pItem = (UA_Variant*) (data) + 1;
-			break;
-		case DIAGNOSTIC_INFO:
-			pItem = (UA_DiagnosticInfo*) (data) + 1;
-			break;
+
+	printf("encode_builtInDatatypeArray - size=%d, data=%p\n", size, data);
+
+	// encode length of array
+	encodeUInt32(size, pos, dstBuf);
+
+	// now iterate over array
+	for (i = 0; i < size; i++) {
+		printf("encode_builtInDatatypeArray - pItem=%p", data[i]);
+		if (type == BYTE_STRING) {
+			UA_ByteString* p = (UA_ByteString*) data[i];
+			printf(", item={l=%d,m=%.*s\n}", p->Length, p->Length, p->Data);
+		} else {
+			printf("\n");
 		}
+		encoder_encodeBuiltInDatatype(data[i], type, pos, dstBuf);
 	}
 	return UA_NO_ERROR;
 }
@@ -1351,13 +1285,13 @@ Int32 decodeDiagnosticInfo(char const * buf, Int32 *pos,
 Int32 encodeDiagnosticInfo(UA_DiagnosticInfo *diagnosticInfo, Int32 *pos,
 		char *dstbuf) {
 	Byte mask;
-	mask = 0;
+	int i;
 
 	encoder_encodeBuiltInDatatype((void*) (&(diagnosticInfo->EncodingMask)),
 			BYTE, pos, dstbuf);
-	for (mask = 1; mask <= 0x40; mask = mask << 2) {
+	for (i = 0; i < 7; i++) {
 
-		switch (mask & (diagnosticInfo->EncodingMask)) {
+		switch ( (0x01 << i) & diagnosticInfo->EncodingMask)  {
 		case DIEMT_SYMBOLIC_ID:
 			//	puts("diagnosticInfo symbolic id");
 			encoder_encodeBuiltInDatatype((void*) &(diagnosticInfo->SymbolicId),
@@ -1480,8 +1414,9 @@ Int32 encodeResponseHeader(UA_AD_ResponseHeader const * responseHeader,
 	encodeUADateTime(responseHeader->timestamp, pos, dstBuf->Data);
 	encodeIntegerId(responseHeader->requestHandle, pos, dstBuf->Data);
 	encodeUInt32(responseHeader->serviceResult, pos, dstBuf->Data);
-	//Kodieren von String Datentypen
-
+	encodeDiagnosticInfo(responseHeader->serviceDiagnostics, pos, dstBuf->Data);
+	encode_builtInDatatypeArray(responseHeader->stringTable, responseHeader->noOfStringTable, BYTE_STRING, pos, dstBuf->Data);
+	encodeExtensionObject(responseHeader->additionalHeader,pos, dstBuf->Data);
 	return 0;
 }
 Int32 extensionObject_calcSize(UA_ExtensionObject *extensionObject) {

+ 2 - 0
src/opcua_builtInDatatypes.c

@@ -8,6 +8,7 @@
 #include <stdio.h>
 
 UA_ExtensionObject the_empty_UA_ExtensionObject = { { NIEVT_TWO_BYTE, 0 }, NO_BODY_IS_ENCODED};
+UA_DiagnosticInfo the_empty_UA_DiagnosticInfo = { 0x00 };
 
 Int32 UA_String_compare(UA_String *string1, UA_String *string2) {
 	Int32 i;
@@ -46,6 +47,7 @@ void UA_ByteString_printx(char* label, UA_ByteString* string) {
 	if (string->Length > 0) {
 		for (i = 0; i < string->Length; i++) {
 			printf("%c%d", i == 0 ? '{' : ',', (string->Data)[i]);
+			if (i > 0 && !(i%20)) { printf("\n\t"); }
 		}
 	} else {
 		printf("{");

+ 1 - 0
src/opcua_builtInDatatypes.h

@@ -327,6 +327,7 @@ typedef struct UA_DiagnosticInfo
 	struct UA_DiagnosticInfo* InnerDiagnosticInfo;
 }
 UA_DiagnosticInfo;
+extern UA_DiagnosticInfo the_empty_UA_DiagnosticInfo;
 
 typedef enum UA_DiagnosticInfoEncodingMaskType
 {

+ 25 - 21
src/opcua_secureChannelLayer.c

@@ -12,18 +12,20 @@ Int32 SL_send(UA_connection *connection, UA_ByteString responseMessage, Int32 ty
 {
 	UInt32 sequenceNumber;
 	UInt32 requestId;
-	//TODO: fill with valid information
 	char securityPolicy[] = "http://opcfoundation.org/UA/SecurityPolicy#None";
+	SL_AsymmetricAlgorithmSecurityHeader AAS_header;
 
 	//sequence header
 	sequenceNumber = connection->secureLayer.sequenceNumber;
 	requestId = connection->secureLayer.requestId;
 
 
-
 	if(type == 449) //openSecureChannelResponse -> asymmetric algorithm
 	{
-		//TODO add Asymmetric Security Header
+		AAS_header.SecurityPolicyUri.Length = strlen(securityPolicy);
+		AAS_header.SecurityPolicyUri.Data = securityPolicy;
+		AAS_header.SenderCertificate.Length = -1;
+		AAS_header.ReceiverThumbprint.Length = -1;
 	}
 	else
 	{
@@ -48,11 +50,12 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	Int32 sizeSecurityToken;
 	UA_ByteString response;
 	UInt32 serverProtocolVersion;
-	Int32 *pos;
+	Int32 pos = 0;
 
 	/*--------------type ----------------------*/
 	//Four Bytes Encoding
 	responseType.EncodingByte = NIEVT_FOUR_BYTE;
+	responseType.Namespace = 0;
 	responseType.Identifier.Numeric = 449;
 
 	/*--------------responseHeader-------------*/
@@ -81,8 +84,6 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	// no additional header
 	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;
 
-	//calculate the size
-	sizeRespHeader = responseHeader_calcSize(&responseHeader);
 
 	/*--------------responseMessage-------------*/
 	/* 	Res-2) UInt32 ServerProtocolVersion
@@ -92,9 +93,7 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	//                  secureChannelId + TokenId + CreatedAt + RevisedLifetime
 	sizeSecurityToken = sizeof(UInt32) + sizeof(UInt32) + sizeof(UA_DateTime) + sizeof(Int32);
 
-	//ignore server nonce
-	serverNonce.Length = -1;
-	serverNonce.Data = NULL;
+	serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
 
 	//fill toke structure with default server information
 	securityToken.secureChannelId = connection->secureLayer.securityToken.secureChannelId;
@@ -102,27 +101,32 @@ Int32 SL_openSecureChannel(UA_connection *connection, IntegerId requestHandle, U
 	securityToken.createdAt = opcua_getTime();
 	securityToken.revisedLifetime = connection->secureLayer.securityToken.revisedLifetime;
 
-	serverProtocolVersion = connection->transportLayer.localConf.protocolVersion;
+	// server nonce
+	serverNonce.Length = -1;
 
+	//calculate the size
+	sizeRespHeader = responseHeader_calcSize(&responseHeader);
 	//                ProtocolVersion + SecurityToken + Nonce
-	sizeRespMessage = sizeof(UInt32) + sizeSecurityToken + UAByteString_calcSize(&serverNonce) + sizeof(Int32) + sizeSecurityToken;
+	sizeRespMessage = sizeof(Int32) + sizeSecurityToken + UAByteString_calcSize(&serverNonce);
 
 	//get memory for response
-	response.Data = (char*)opcua_malloc(nodeId_calcSize(responseType) + sizeRespHeader + sizeRespMessage);
-	*pos = 0;
+	response.Length = nodeId_calcSize(&responseType) + sizeRespHeader + sizeRespMessage;
+	response.Data = (char*) opcua_malloc(response.Length);
+
 	//encode responseType (NodeId)
-	encoder_encodeBuiltInDatatype(responseType,NODE_ID,pos,response.Data);
+	encoder_encodeBuiltInDatatype(&responseType,NODE_ID,&pos,response.Data);
 	//encode header
-	encodeResponseHeader(&responseHeader,pos, &response);
+	encodeResponseHeader(&responseHeader,&pos, &response);
 	//encode message
-	encoder_encodeBuiltInDatatype(serverProtocolVersion, UINT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.secureChannelId, UINT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.tokenId, INT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.createdAt, DATE_TIME, pos,response.Data);
-	encoder_encodeBuiltInDatatype(securityToken.revisedLifetime, INT32, pos,response.Data);
-	encoder_encodeBuiltInDatatype(serverNonce, BYTE_STRING, pos,response.Data);
+	encoder_encodeBuiltInDatatype(&serverProtocolVersion, UINT32, &pos,response.Data);
+	encoder_encodeBuiltInDatatype(&securityToken.secureChannelId, UINT32, &pos,response.Data);
+	encoder_encodeBuiltInDatatype(&securityToken.tokenId, INT32, &pos,response.Data);
+	encoder_encodeBuiltInDatatype(&securityToken.createdAt, DATE_TIME, &pos,response.Data);
+	encoder_encodeBuiltInDatatype(&securityToken.revisedLifetime, INT32, &pos,response.Data);
+	encoder_encodeBuiltInDatatype(&serverNonce, BYTE_STRING, &pos,response.Data);
 
 	//449 = openSecureChannelResponse
+	UA_ByteString_printx("SL_processMessage - response=", &response);
 	SL_send(connection,response,449);
 
 	return UA_NO_ERROR;

+ 50 - 11
tests/check_stack.c

@@ -460,12 +460,11 @@ START_TEST(diagnosticInfo_calcSize_test)
 	diagnosticInfo.AdditionalInfo.Data = "OPCUA";
 	diagnosticInfo.AdditionalInfo.Length = 5;
 
-	valcalc = diagnosticInfo_calcSize(&diagnosticInfo);
-	valreal = 26;
-	ck_assert_int_eq(valcalc,valreal);
-
+	ck_assert_int_eq(diagnosticInfo_calcSize(&diagnosticInfo),26);
+	ck_assert_int_eq(diagnosticInfo_calcSize(&the_empty_UA_DiagnosticInfo),1);
 }
 END_TEST
+
 START_TEST(extensionObject_calcSize_test)
 {
 
@@ -475,23 +474,19 @@ START_TEST(extensionObject_calcSize_test)
 	UA_ExtensionObject extensionObject;
 
 	// empty ExtensionObject
-	valcalc = extensionObject_calcSize(&the_empty_UA_ExtensionObject);
-	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+	ck_assert_int_eq(extensionObject_calcSize(&the_empty_UA_ExtensionObject), 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);
-	ck_assert_int_eq(valcalc, 1 + 1 + 1);
+	ck_assert_int_eq(extensionObject_calcSize(&extensionObject), 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);
-	ck_assert_int_eq(valcalc, 3 + 4 + 3);
+	ck_assert_int_eq(extensionObject_calcSize(&extensionObject), 3 + 4 + 3);
 
 }
 END_TEST
@@ -520,6 +515,9 @@ START_TEST(responseHeader_calcSize_test)
 
 	responseHeader.additionalHeader = &the_empty_UA_ExtensionObject;	//		    3
 	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+26+4+3);
+
+	responseHeader.serviceDiagnostics = &the_empty_UA_DiagnosticInfo;
+	ck_assert_int_eq(responseHeader_calcSize(&responseHeader),16+1+4+3);
 }
 END_TEST
 
@@ -602,6 +600,32 @@ START_TEST(DataValue_calcSize_test)
 }
 END_TEST
 
+START_TEST(encode_builtInDatatypeArray_test_String)
+{
+	Int32 noElements = 2;
+	UA_ByteString s1 = { 6, "OPC UA" };
+	UA_ByteString s2 = { -1, NULL };
+	UA_ByteString* array[] = { &s1, &s2	};
+	Int32 pos = 0, i;
+	char buf[256];
+	char result[] = {
+			0x02, 0x00, 0x00, 0x00,		// noElements
+			0x06, 0x00, 0x00, 0x00,		// s1.Length
+			'O', 'P', 'C', ' ', 'U', 'A', // s1.Data
+			0xFF, 0xFF, 0xFF, 0xFF		// s2.Length
+	};
+
+	encode_builtInDatatypeArray(array, noElements, BYTE_STRING, &pos, buf);
+
+	// check size
+	ck_assert_int_eq(pos, 4 + 4 + 6 + 4);
+	// check result
+	for (i=0; i< sizeof(result); i++) {
+		ck_assert_int_eq(buf[i],result[i]);
+	}
+}
+END_TEST
+
 Suite *testSuite_getPacketType(void)
 {
 	Suite *s = suite_create("getPacketType");
@@ -787,6 +811,15 @@ Suite* testSuite_encodeDataValue()
 	return s;
 }
 
+Suite* testSuite_encode_builtInDatatypeArray()
+{
+	Suite *s = suite_create("encode_builtInDatatypeArray");
+	TCase *tc_core = tcase_create("Core");
+	tcase_add_test(tc_core, encode_builtInDatatypeArray_test_String);
+	suite_add_tcase(s,tc_core);
+	return s;
+}
+
 Suite* testSuite_expandedNodeId_calcSize(void)
 {
 	Suite *s = suite_create("expandedNodeId_calcSize");
@@ -977,6 +1010,12 @@ int main (void)
 	number_failed += srunner_ntests_failed(sr);
 	srunner_free(sr);
 
+	s = testSuite_encode_builtInDatatypeArray();
+	sr = srunner_create(s);
+	srunner_run_all(sr,CK_NORMAL);
+	number_failed += srunner_ntests_failed(sr);
+	srunner_free(sr);
+
 	s = testSuite_expandedNodeId_calcSize();
 	sr = srunner_create(s);
 	srunner_run_all(sr,CK_NORMAL);