Browse Source

fixed seg-fault after read service with a still buggy mockup.

Leon Urbas 11 years ago
parent
commit
573931a136

+ 3 - 3
examples/src/networklayer.c

@@ -116,7 +116,7 @@ void* NL_TCP_reader(NL_Connection *c) {
 		DBG_VERBOSE(printf("NL_TCP_reader - leave read\n"));
 
 		DBG_VERBOSE(printf("NL_TCP_reader - src={%*.s}, ",c->connection.remoteEndpointUrl.length,c->connection.remoteEndpointUrl.data));
-		UA_ByteString_printx("received=",&readBuffer);
+		DBG(UA_ByteString_printx("NL_TCP_reader - received=",&readBuffer));
 
 		if (readBuffer.length  > 0) {
 			TL_Process(&(c->connection),&readBuffer);
@@ -171,8 +171,8 @@ UA_Int32 NL_TCP_writer(struct TL_Connection_T* c, const UA_ByteString** gather_b
 		iov[i].iov_base = gather_buf[i]->data;
 		iov[i].iov_len = gather_buf[i]->length;
 		total_len += gather_buf[i]->length;
-		DBG_VERBOSE(printf("NL_TCP_writer - gather_buf[%i]",i));
-		DBG_VERBOSE(UA_ByteString_printx("=", gather_buf[i]));
+		DBG(printf("NL_TCP_writer - gather_buf[%i]",i));
+		DBG(UA_ByteString_printx("=", gather_buf[i]));
 	}
 
 	struct msghdr message;

+ 1 - 0
include/ua_basictypes.h

@@ -81,6 +81,7 @@ UA_Int32 UA_Array_decodeBinary(UA_ByteString const * src,UA_Int32 noElements, UA
 UA_Int32 UA_Array_delete(void **p,UA_Int32 noElements, UA_Int32 type);
 UA_Int32 UA_Array_init(void **p,UA_Int32 noElements, UA_Int32 type);
 UA_Int32 UA_Array_new(void **p,UA_Int32 noElements, UA_Int32 type);
+UA_Int32 UA_Array_copy(void const * const *src,UA_Int32 noElements, UA_Int32 type, void **dst);
 
 #define UA_TYPE_METHOD_PROTOTYPES(TYPE) \
 UA_Int32 TYPE##_calcSize(TYPE const * ptr);\

+ 19 - 0
src/ua_basictypes.c

@@ -91,6 +91,25 @@ UA_Int32 UA_Array_new(void **p,UA_Int32 noElements, UA_Int32 type) {
 	return retval;
 }
 
+UA_Int32 UA_Array_copy(void const * const * src,UA_Int32 noElements, UA_Int32 type, void **dst) {
+	UA_Int32 retval = UA_SUCCESS;
+	UA_Int32 i;
+	// Get memory for the pointers
+	retval |= UA_Array_new(dst, noElements, type);
+	void const * const a_src = *src;
+	void * a_dst = *dst;
+	for(i=0; i<noElements; i++) {
+		// FIXME: we only have code to do this for strings yet
+		if (type == UA_STRING || type == UA_BYTESTRING) {
+			UA_String_copy(((UA_String **)a_src)[i],((UA_String **)a_dst)[i]);
+		} else {
+			retval = UA_ERR_INVALID_VALUE;
+			break;
+		}
+	}
+	return retval;
+}
+
 UA_Int32 _UA_free(void * ptr,char *pname,char* f,int l){
 	DBG_VERBOSE(printf("UA_free;%p;;%s;;%s;%d\n",ptr,pname,f,l); fflush(stdout));
 	if (UA_NULL != ptr) {

+ 12 - 1
src/ua_services_attribute.c

@@ -108,12 +108,23 @@ static UA_DataValue * service_read_node(Application *app, const UA_ReadValueId *
 		}
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE | UA_DATAVALUE_ENCODINGMASK_VARIANT;
 		v->status = UA_STATUSCODE_GOOD;
+
+		// be careful not to release the node before encoding the message
+
 		UA_VariableNode * vn = (UA_VariableNode*) node;
 		// FIXME: delete will be called later on on on all the members of v, so essentially
 		// the item's data will be removed from the namespace-object. We would need
 		// something like a deep copy function just as we have it for the strings
 		// UA_Variant_copy(UA_Variant* src, UA_Variant* dst);
-		v->value = vn->value; // be careful not to release the node before encoding the message
+
+		// FIXME: mockup code - we know that for 2255 we simply need to copy the array
+		if (node->nodeId.identifier.numeric == 2255) {
+			v->value = vn->value;
+			UA_Array_copy((void const*const*)&(vn->value.data),vn->value.arrayLength,UA_toIndex(vn->value.vt->Id),(void**)&(v->value.data));
+		} else {
+			v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;
+			v->status = UA_STATUSCODE_BADNOTREADABLE;
+		}
 		break;
 	case UA_ATTRIBUTEID_DATATYPE:
 		v->encodingMask = UA_DATAVALUE_ENCODINGMASK_STATUSCODE;

+ 3 - 0
tests/Makefile.am

@@ -20,6 +20,9 @@ check-mem:
 if COVERAGE
 	$(MAKE) cov-report
 endif
+
+check_memory-mem: check_memory
+	$(MAKE) $(AM_MAKEFLAGS) check TESTS="check_memory" TESTS_ENVIRONMENT=$(TESTS_ENVIRONMENT_MEM)
 	
 clean-local:
 	rm -rf coverage || true;

+ 30 - 0
tests/check_memory.c

@@ -24,6 +24,35 @@ START_TEST (newAndEmptyObjectShallBeDeleted)
 }
 END_TEST
 
+START_TEST (arrayCopyShallMakeADeepCopy)
+{
+	// given
+	void **a1; UA_Array_new((void**)&a1,3,UA_STRING);
+	UA_String_copycstring("a",((UA_String **)a1)[0]);
+	UA_String_copycstring("bb",((UA_String **)a1)[1]);
+	UA_String_copycstring("ccc",((UA_String **)a1)[2]);
+	// when
+	void **a2;
+	UA_Int32 retval = UA_Array_copy((void const*const*)&a1,3,UA_STRING,(void**)&a2);
+	// then
+	ck_assert_int_eq(retval,UA_SUCCESS);
+	ck_assert_int_eq(((UA_String **)a1)[0]->length,1);
+	ck_assert_int_eq(((UA_String **)a1)[1]->length,2);
+	ck_assert_int_eq(((UA_String **)a1)[2]->length,3);
+	ck_assert_int_eq(((UA_String **)a1)[0]->length,((UA_String **)a2)[0]->length);
+	ck_assert_int_eq(((UA_String **)a1)[1]->length,((UA_String **)a2)[1]->length);
+	ck_assert_int_eq(((UA_String **)a1)[2]->length,((UA_String **)a2)[2]->length);
+	ck_assert_ptr_ne(((UA_String **)a1)[0]->data,((UA_String **)a2)[0]->data);
+	ck_assert_ptr_ne(((UA_String **)a1)[1]->data,((UA_String **)a2)[1]->data);
+	ck_assert_ptr_ne(((UA_String **)a1)[2]->data,((UA_String **)a2)[2]->data);
+	ck_assert_int_eq(((UA_String **)a1)[0]->data[0],((UA_String **)a2)[0]->data[0]);
+	ck_assert_int_eq(((UA_String **)a1)[1]->data[0],((UA_String **)a2)[1]->data[0]);
+	ck_assert_int_eq(((UA_String **)a1)[2]->data[0],((UA_String **)a2)[2]->data[0]);
+	// finally
+	UA_Array_delete(a1,3,UA_STRING);
+	UA_Array_delete(a2,3,UA_STRING);
+}
+END_TEST
 
 START_TEST (encodeShallYieldDecode)
 {
@@ -93,6 +122,7 @@ int main() {
 	Suite *s = suite_create("testMemoryHandling");
 	TCase *tc = tcase_create("Empty Objects");
 	tcase_add_loop_test(tc, newAndEmptyObjectShallBeDeleted,UA_BOOLEAN,UA_INVALIDTYPE-1);
+	tcase_add_test(tc, arrayCopyShallMakeADeepCopy);
 	tcase_add_loop_test(tc, encodeShallYieldDecode,UA_BOOLEAN,UA_INVALIDTYPE-1);
 	suite_add_tcase(s,tc);
 	tc = tcase_create("Truncated Buffers");