Leon Urbas 11 years ago
parent
commit
21b3005e28

+ 1 - 1
Makefile.am

@@ -1,6 +1,6 @@
 AM_CFLAGS = -std=c99 -pedantic -pipe -fPIC -fno-exceptions -fstack-protector -Wl,-z,relro -Wl,-z,now -fvisibility=hidden -W -Wall -Wno-unused-parameter -Wno-unused-function -Wno-unused-label -Wpointer-arith -Wformat -Wreturn-type -Wsign-compare -Wmultichar -Wformat-nonliteral -Winit-self -Wuninitialized -Wno-deprecated -Wformat-security -Werror
 if DEBUG
-AM_CFLAGS += -g3 -O0  
+AM_CFLAGS += -g3 -O0 -DDEBUG=1 -DVERBOSE=1
 else
 AM_CFLAGS += -O2 
 endif

+ 119 - 124
examples/src/networklayer.c

@@ -10,8 +10,8 @@
 #include <memory.h> // memset
 #include <fcntl.h> // fcntl
 
+#define VERBOSE 1
 #include "networklayer.h"
-#include "ua_transportLayer.h"
 
 NL_Description NL_Description_TcpBinary  = {
 		NL_THREADINGTYPE_SINGLE,
@@ -20,13 +20,10 @@ NL_Description NL_Description_TcpBinary  = {
 		{-1,8192,8192,16384,1}
 };
 
-// TODO: We currently need a variable global to the module!
-NL_data theNL;
-
-_Bool connectionComparer(void *p1, void* p2) {
-	UA_TL_connection* c1 = (UA_TL_connection*) p1;
-	UA_TL_connection* c2 = (UA_TL_connection*) p2;
-	return (c1->connectionHandle == c2->connectionHandle);
+_Bool NL_connectionComparer(void *p1, void* p2) {
+	NL_connection* c1 = (NL_connection*) p1;
+	NL_connection* c2 = (NL_connection*) p2;
+	return (c1->connection.connectionHandle == c2->connection.connectionHandle);
 }
 
 int NL_TCP_SetNonBlocking(int sock) {
@@ -43,64 +40,64 @@ int NL_TCP_SetNonBlocking(int sock) {
 	return 0;
 }
 
+void NL_connection_printf(void* payload) {
+  NL_connection* c = (NL_connection*) payload;
+  printf("ListElement connectionHandle = %d\n",c->connection.connectionHandle);
+}
+
 /** the tcp reader thread - single shot if single-threaded, looping until CLOSE if multi-threaded
  */
-void* NL_TCP_reader(UA_TL_connection *c) {
+void* NL_TCP_reader(NL_connection *c) {
 
 	UA_ByteString readBuffer;
-	UA_alloc((void**)&(readBuffer.data),c->localConf.recvBufferSize);
+	UA_alloc((void**)&(readBuffer.data),c->connection.localConf.recvBufferSize);
 
-	if (c->connectionState != connectionState_CLOSE) {
+	if (c->connection.connectionState != connectionState_CLOSE) {
 		do {
-			printf("NL_TCP_reader - enter read\n");
-			readBuffer.length = read(c->connectionHandle, readBuffer.data, c->localConf.recvBufferSize);
-			printf("NL_TCP_reader - leave read\n");
+			DBG_VERBOSE(printf("NL_TCP_reader - enter read\n"));
+			readBuffer.length = read(c->connection.connectionHandle, readBuffer.data, c->connection.localConf.recvBufferSize);
+			DBG_VERBOSE(printf("NL_TCP_reader - leave read\n"));
 
-			printf("NL_TCP_reader - %*.s ",c->remoteEndpointUrl.length,c->remoteEndpointUrl.data);
+			DBG_VERBOSE(printf("NL_TCP_reader - src={%*.s}, ",c->connection.remoteEndpointUrl.length,c->connection.remoteEndpointUrl.data));
 			UA_ByteString_printx("received=",&readBuffer);
 
 			if (readBuffer.length  > 0) {
-				TL_process(c,&readBuffer);
+				TL_process(&(c->connection),&readBuffer);
 			} else {
-				c->connectionState = connectionState_CLOSE;
+				c->connection.connectionState = connectionState_CLOSE;
 				perror("ERROR reading from socket1");
 			}
-		} while (c->connectionState != connectionState_CLOSE && theNL.threaded == NL_THREADINGTYPE_PTHREAD);
+		} while (c->connection.connectionState != connectionState_CLOSE && c->networkLayer->threaded == NL_THREADINGTYPE_PTHREAD);
 	}
-	if (c->connectionState == connectionState_CLOSE) {
-		// clean up: socket, buffer, connection
-		// free resources allocated with socket
-		if (theNL.threaded == NL_THREADINGTYPE_SINGLE) {
-			printf("UA_TL_TCP_reader - remove handle=%d from fd_set\n",c->connectionHandle);
-			// FD_CLR(c->connectionHandle,&(theTL.readerHandles));
-		}
-		printf("NL_TCP_reader - enter shutdown\n");
-		shutdown(c->connectionHandle,2);
-		printf("NL_TCP_reader - enter close\n");
-		close(c->connectionHandle);
-		printf("NL_TCP_reader - leave close\n");
-		c->connectionState = connectionState_CLOSED;
+	if (c->connection.connectionState == connectionState_CLOSE) {
+		DBG_VERBOSE(printf("NL_TCP_reader - enter shutdown\n"));
+		shutdown(c->connection.connectionHandle,2);
+		DBG_VERBOSE(printf("NL_TCP_reader - enter close\n"));
+		close(c->connection.connectionHandle);
+		DBG_VERBOSE(printf("NL_TCP_reader - leave close\n"));
+		c->connection.connectionState = connectionState_CLOSED;
 
 		UA_ByteString_deleteMembers(&readBuffer);
-		printf("NL_TCP_reader - search element to remove\n");
-		UA_list_Element* lec = UA_list_search(&theNL.connections,connectionComparer,c);
-		printf("NL_TCP_reader - remove handle=%d\n",((UA_TL_connection*)lec->payload)->connectionHandle);
+		DBG_VERBOSE(printf("NL_TCP_reader - search element to remove\n"));
+		UA_list_Element* lec = UA_list_search(&(c->networkLayer->connections),NL_connectionComparer,c);
+		DBG_VERBOSE(printf("NL_TCP_reader - remove connection for handle=%d\n",((NL_connection*)lec->payload)->connection.connectionHandle));
 		UA_list_removeElement(lec,UA_NULL);
+		DBG_VERBOSE(UA_list_iteratePayload(&(c->networkLayer->connections),NL_connection_printf));
 		UA_free(c);
 	}
 	return UA_NULL;
 }
 
 /** write to a tcp transport layer connection */
-UA_Int32 NL_TCP_writer(struct T_TL_connection* c, UA_ByteString* msg) {
-	UA_ByteString_printx("write data:", msg);
+UA_Int32 NL_TCP_writer(UA_TL_connection* c, UA_ByteString* msg) {
+	DBG_VERBOSE(UA_ByteString_printx("NL_TCP_writer - msg=", msg));
 	int nWritten = 0;
 	while (nWritten < msg->length) {
 		int n=0;
 		do {
-			printf("NL_TCP_writer - enter write\n");
+			DBG_VERBOSE(printf("NL_TCP_writer - enter write\n"));
 			n = write(c->connectionHandle, &(msg->data[nWritten]), msg->length-nWritten);
-			printf("NL_TCP_writer - leave write with n=%d,errno=%d\n",n,errno);
+			DBG_VERBOSE(printf("NL_TCP_writer - leave write with n=%d,errno={%d,%s}\n",n,errno,strerror(errno)));
 		} while (n == -1L && errno == EINTR);
 		if (n >= 0) {
 			nWritten += n;
@@ -111,47 +108,62 @@ UA_Int32 NL_TCP_writer(struct T_TL_connection* c, UA_ByteString* msg) {
 	return UA_SUCCESS;
 }
 
+void* NL_Connection_init(NL_connection* c, NL_data* tld, UA_Int32 connectionHandle, NL_reader reader, UA_TL_writer writer)
+{
+	// connection layer of UA stack
+	c->connection.connectionHandle = connectionHandle;
+	c->connection.connectionState = connectionState_CLOSED;
+	c->connection.writerCallback = writer;
+	memcpy(&(c->connection.localConf),&(tld->tld->localConf),sizeof(TL_buffer));
+	memset(&(c->connection.remoteConf),0,sizeof(TL_buffer));
+	UA_String_copy(&(tld->endpointUrl), &(c->connection.localEndpointUrl));
+
+	// network layer
+	c->reader = reader;
+	c->readerThreadHandle = -1;
+	c->networkLayer = tld;
+	return UA_NULL;
+}
+
+
 /** the tcp listener routine.
  *  does a single shot if single threaded, runs forever if multithreaded
  */
-void* NL_TCP_listen(void *p) {
-	NL_data* tld = (NL_data*) p;
+void* NL_TCP_listen(NL_connection* c) {
+	NL_data* tld = c->networkLayer;
 
-	UA_String_printf("open62541-server at ",&(tld->endpointUrl));
+	// UA_String_printf("open62541-server listening at endpoint ",&(tld->endpointUrl));
 	do {
-		printf("NL_TCP_listen - enter listen\n");
-		int retval = listen(tld->listenerHandle, tld->tld->maxConnections);
-		printf("NL_TCP_listen - leave listen, retval=%d\n",retval);
+		DBG_VERBOSE(printf("NL_TCP_listen - enter listen\n"));
+		int retval = listen(c->connection.connectionHandle, tld->tld->maxConnections);
+		DBG_VERBOSE(printf("NL_TCP_listen - leave listen, retval=%d\n",retval));
 
 		if (retval < 0) {
 			// TODO: Error handling
-			printf("NL_TCP_listen retval=%d, errno=%d\n",retval,errno);
+			perror("NL_TCP_listen");
+			DBG_ERR(printf("NL_TCP_listen retval=%d, errno={%d,%s}\n",retval,errno,strerror(errno)));
 		} else if (tld->tld->maxConnections == -1 || tld->connections.size < tld->tld->maxConnections) {
-			// accept only if not max number of connections exceede
+			// accept only if not max number of connections exceeded
 			struct sockaddr_in cli_addr;
 			socklen_t cli_len = sizeof(cli_addr);
-			printf("NL_TCP_listen - enter accept\n");
-			int newsockfd = accept(tld->listenerHandle, (struct sockaddr *) &cli_addr, &cli_len);
-			printf("NL_TCP_listen - leave accept\n");
+			DBG_VERBOSE(printf("NL_TCP_listen - enter accept\n"));
+			int newsockfd = accept(c->connection.connectionHandle, (struct sockaddr *) &cli_addr, &cli_len);
+			DBG_VERBOSE(printf("NL_TCP_listen - leave accept\n"));
 			if (newsockfd < 0) {
-				printf("UA_TL_TCP_listen - accept returns errno=%d\n",errno);
+				DBG_ERR(printf("UA_TL_TCP_listen - accept returns errno={%d,%s}\n",errno,strerror(errno)));
 				perror("ERROR on accept");
 			} else {
-				printf("NL_TCP_listen - new connection on %d\n",newsockfd);
-				UA_TL_connection* c;
+				DBG_VERBOSE(printf("NL_TCP_listen - new connection on %d\n",newsockfd));
+				NL_connection* cclient;
 				UA_Int32 retval = UA_SUCCESS;
-				retval |= UA_alloc((void**)&c,sizeof(UA_TL_connection));
-				TL_Connection_init(c, tld);
-				c->connectionHandle = newsockfd;
-				c->writerCallback = NL_TCP_writer;
-				c->readerCallback = NL_TCP_reader;
-				// add to list
-				UA_list_addPayloadToBack(&(tld->connections),c);
+				retval |= UA_alloc((void**)&cclient,sizeof(NL_connection));
+				NL_Connection_init(cclient, tld, newsockfd, NL_TCP_reader, NL_TCP_writer);
+				UA_list_addPayloadToBack(&(tld->connections),cclient);
 				if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
 					// TODO: handle retval of pthread_create
-					pthread_create( &(c->readerThread), NULL, (void*(*)(void*)) NL_TCP_reader, (void*) c);
+					pthread_create( &(cclient->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_reader, (void*) cclient);
 				} else {
-					NL_TCP_SetNonBlocking(c->connectionHandle);
+					NL_TCP_SetNonBlocking(cclient->connection.connectionHandle);
 				}
 			}
 		} else {
@@ -162,64 +174,56 @@ void* NL_TCP_listen(void *p) {
 }
 
 
-int maxHandle;
-void NL_addHandleToSet(UA_Int32 handle) {
-	FD_SET(handle, &(theNL.readerHandles));
-	maxHandle = (handle > maxHandle) ? handle : maxHandle;
+void NL_addHandleToSet(UA_Int32 handle, NL_data* nl) {
+	FD_SET(handle, &(nl->readerHandles));
+	nl->maxReaderHandle = (handle > nl->maxReaderHandle) ? handle : nl->maxReaderHandle;
 }
 void NL_setFdSet(void* payload) {
-  UA_TL_connection* c = (UA_TL_connection*) payload;
-  NL_addHandleToSet(c->connectionHandle);
+  NL_connection* c = (NL_connection*) payload;
+  NL_addHandleToSet(c->connection.connectionHandle, c->networkLayer);
 }
 void NL_checkFdSet(void* payload) {
-  UA_TL_connection* c = (UA_TL_connection*) payload;
-  if (FD_ISSET(c->connectionHandle, &(theNL.readerHandles))) {
-	  c->readerCallback((void*)c);
+  NL_connection* c = (NL_connection*) payload;
+  if (FD_ISSET(c->connection.connectionHandle, &(c->networkLayer->readerHandles))) {
+	  c->reader((void*)c);
   }
 }
 
-
-UA_Int32 NL_msgLoop(struct timeval *tv, UA_Int32(*worker)(void*), void *arg)  {
+UA_Int32 NL_msgLoop(NL_data* nl, struct timeval *tv, UA_Int32(*worker)(void*), void *arg)  {
 	UA_Int32 result;
 	while (UA_TRUE) {
 		// determine the largest handle
-		maxHandle = 0;
-		UA_list_iteratePayload(&theNL.connections,NL_setFdSet);
-		NL_addHandleToSet(theNL.listenerHandle);
-		printf("UA_Stack_msgLoop - maxHandle=%d\n", maxHandle);
+		nl->maxReaderHandle = 0;
+		UA_list_iteratePayload(&(nl->connections),NL_setFdSet);
+		DBG_VERBOSE(printf("UA_Stack_msgLoop - maxHandle=%d\n", nl->maxReaderHandle));
 
 		// copy tv, some unixes do overwrite and return the remaining time
 		struct timeval tmptv;
 		memcpy(&tmptv,tv,sizeof(struct timeval));
 
 		// and wait
-		printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec);
-		result = select(maxHandle + 1, &(theNL.readerHandles), UA_NULL, UA_NULL,&tmptv);
-		printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec);
+		DBG_VERBOSE(printf("UA_Stack_msgLoop - enter select sec=%d,usec=%d\n",(UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
+		result = select(nl->maxReaderHandle + 1, &(nl->readerHandles), UA_NULL, UA_NULL,&tmptv);
+		DBG_VERBOSE(printf("UA_Stack_msgLoop - leave select result=%d,sec=%d,usec=%d\n",result, (UA_Int32) tmptv.tv_sec, (UA_Int32) tmptv.tv_usec));
 		if (result == 0) {
 			int err = errno;
 			switch (err) {
 			case EBADF:
-				printf("UA_Stack_msgLoop - result=bad file\n"); //FIXME: handle
-				break;
 			case EINTR:
-				printf("UA_Stack_msgLoop - result=interupted\n"); //FIXME: handle
-				break;
 			case EINVAL:
-				printf("UA_Stack_msgLoop - result=bad arguments\n"); //FIXME: handle
+				//FIXME: handle errors
+				DBG_ERR(printf("UA_Stack_msgLoop - errno={%d,%s}\n", errno, strerror(errno)));
 				break;
 			case EAGAIN:
-				printf("UA_Stack_msgLoop - result=do it again\n");
 			default:
-				printf("UA_Stack_msgLoop - result=%d\n",err);
+				DBG_VERBOSE(printf("UA_Stack_msgLoop - errno={%d,%s}\n", errno, strerror(errno)));
+				DBG_VERBOSE(printf("UA_Stack_msgLoop - call worker\n"));
 				worker(arg);
+				DBG_VERBOSE(printf("UA_Stack_msgLoop - return from worker\n"));
 			}
-		} else if (FD_ISSET(theNL.listenerHandle,&theNL.readerHandles)) { // activity on listener port
-			printf("UA_Stack_msgLoop - connection request\n");
-			NL_TCP_listen((void*)&theNL);
-		} else { // activity on client ports
-			printf("UA_Stack_msgLoop - activities on %d handles\n",result);
-			UA_list_iteratePayload(&theNL.connections,NL_checkFdSet);
+		} else { // activity on listener or client ports
+			DBG_VERBOSE(printf("UA_Stack_msgLoop - activities on %d handles\n",result));
+			UA_list_iteratePayload(&(nl->connections),NL_checkFdSet);
 		}
 	}
 	return UA_SUCCESS;
@@ -228,13 +232,14 @@ UA_Int32 NL_msgLoop(struct timeval *tv, UA_Int32(*worker)(void*), void *arg)  {
 UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
 	UA_Int32 retval = UA_SUCCESS;
 	// socket variables
+	int newsockfd;
 	int optval = 1;
 	struct sockaddr_in serv_addr;
 
 
 	// create socket for listening to incoming connections
-	tld->listenerHandle = socket(PF_INET, SOCK_STREAM, 0);
-	if (tld->listenerHandle < 0) {
+	newsockfd = socket(PF_INET, SOCK_STREAM, 0);
+	if (newsockfd < 0) {
 		perror("ERROR opening socket");
 		retval = UA_ERROR;
 	} else {
@@ -243,58 +248,48 @@ UA_Int32 NL_TCP_init(NL_data* tld, UA_Int32 port) {
 		serv_addr.sin_family = AF_INET;
 		serv_addr.sin_addr.s_addr = INADDR_ANY;
 		serv_addr.sin_port = htons(port);
-		if (setsockopt(tld->listenerHandle, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1 ) {
+		if (setsockopt(newsockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1 ) {
 			perror("setsockopt");
 			retval = UA_ERROR;
 		} else {
 			// bind to port
-			if (bind(tld->listenerHandle, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+			if (bind(newsockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 				perror("ERROR on binding");
 				retval = UA_ERROR;
 			} else {
-				// TODO: implement
-				// UA_String_sprintf("opc.tpc://localhost:%d", &(tld->endpointUrl), port);
-				UA_String_copycstring("opc.tpc://localhost:16664/", &(tld->endpointUrl));
+				UA_String_copyprintf("opc.tcp://localhost:%d/", &(tld->endpointUrl), port);
 			}
 		}
 	}
 	// finally
 	if (retval == UA_SUCCESS) {
+		DBG_VERBOSE(printf("NL_TCP_init - new listener on %d\n",newsockfd));
+		NL_connection* c;
+		UA_Int32 retval = UA_SUCCESS;
+		retval |= UA_alloc((void**)&c,sizeof(NL_connection));
+		NL_Connection_init(c, tld, newsockfd, NL_TCP_listen, (UA_TL_writer) UA_NULL);
+		UA_list_addPayloadToBack(&(tld->connections),c);
 		if (tld->threaded == NL_THREADINGTYPE_PTHREAD) {
 			// TODO: handle retval of pthread_create
-			pthread_create( &tld->listenerThreadHandle, NULL, NL_TCP_listen, (void*) tld);
+			pthread_create( &(c->readerThreadHandle), NULL, (void*(*)(void*)) NL_TCP_listen, (void*) c);
 		} else {
-			NL_TCP_SetNonBlocking(tld->listenerHandle);
-			FD_ZERO(&(tld->readerHandles));
+			NL_TCP_SetNonBlocking(c->connection.connectionHandle);
 		}
 	}
 	return retval;
 }
 
-UA_Int32 TL_Connection_init(UA_TL_connection* c, NL_data* tld)
-{
-	c->connectionHandle = -1;
-	c->connectionState = connectionState_CLOSED;
-	c->readerThread = -1;
-	c->writerCallback = UA_NULL;
-	c->readerCallback = UA_NULL;
-	memcpy(&(c->localConf),&(tld->tld->localConf),sizeof(TL_buffer));
-	memset(&(c->remoteConf),0,sizeof(TL_buffer));
-	UA_String_copy(&(tld->endpointUrl), &(c->localEndpointUrl));
-	return UA_SUCCESS;
-}
-
 
 /** checks arguments and dispatches to worker or refuses to init */
-UA_Int32 NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded) {
-	UA_Int32 retval = UA_SUCCESS;
+NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded) {
+	NL_data* nl = UA_NULL;
 	if (tlDesc->connectionType == NL_CONNECTIONTYPE_TCPV4 && tlDesc->encoding == NL_UA_ENCODING_BINARY) {
-		theNL.tld = tlDesc;
-		theNL.threaded = threaded;
-		UA_list_init(&theNL.connections);
-		retval |= NL_TCP_init(&theNL,port);
-	} else {
-		retval = UA_ERR_NOT_IMPLEMENTED;
+		UA_alloc((void**)&nl,sizeof(NL_data));
+		nl->tld = tlDesc;
+		nl->threaded = threaded;
+		FD_ZERO(&(nl->readerHandles));
+		UA_list_init(&(nl->connections));
+		NL_TCP_init(nl,port);
 	}
-	return retval;
+	return nl;
 }

+ 13 - 3
examples/src/networklayer.h

@@ -10,6 +10,7 @@
 
 #include "opcua.h"
 #include "ua_connection.h"
+#include "ua_transportLayer.h"
 #include "ua_list.h"
 
 #include <pthread.h> // pthreadcreate, pthread_t
@@ -44,12 +45,21 @@ typedef struct T_NL_data {
 	UA_String endpointUrl;
 	int listenerHandle;
 	pthread_t listenerThreadHandle;
-	UA_list_List connections;
 	UA_Int32 threaded;	// NL_THREADINGTYPE_enum
+	UA_list_List connections;
 	fd_set readerHandles;
+	int maxReaderHandle;
 } NL_data;
 
+struct T_NL_connection;
+typedef void* (*NL_reader)(struct T_NL_connection *c);
+typedef struct T_NL_connection {
+	UA_TL_connection connection;
+	NL_reader reader;
+	pthread_t 	readerThreadHandle;
+	NL_data*    networkLayer;
+} NL_connection;
 
-UA_Int32 NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded);
-UA_Int32 NL_msgLoop(struct timeval* tv,UA_Int32 (*timeoutCallBack)(void*),void *arg);
+NL_data* NL_init(NL_Description* tlDesc, UA_Int32 port, UA_Int32 threaded);
+UA_Int32 NL_msgLoop(NL_data* nl, struct timeval* tv,UA_Int32 (*timeoutCallBack)(void*),void *arg);
 #endif /* NETWORKLAYER_H_ */

+ 2 - 2
examples/src/opcuaServer.c

@@ -26,7 +26,7 @@ int pthread_create(pthread_t* newthread, const pthread_attr_t* attr, void *(*sta
 }
 
 int main(int argc, char** argv) {
+	NL_data* nl = NL_init(&NL_Description_TcpBinary,16664,NL_THREADINGTYPE_SINGLE);
 	struct timeval tv = {2, 0}; // 2 seconds
-	NL_init(&NL_Description_TcpBinary,16664,NL_THREADINGTYPE_SINGLE);
-	NL_msgLoop(&tv,serverCallback,argv[0]);
+	NL_msgLoop(nl, &tv,serverCallback,argv[0]);
 }

+ 4 - 4
include/ua_basictypes.h

@@ -65,11 +65,11 @@ UA_ByteString;
 /* heap memory functions */
 #define UA_NULL ((void*)0)
 extern void const * UA_alloc_lastptr;
-#define UA_free(ptr) _UA_free(ptr,__FILE__,__LINE__)
-UA_Int32 _UA_free(void * ptr,char*,int);
+#define UA_free(ptr) _UA_free(ptr,#ptr,__FILE__,__LINE__)
+UA_Int32 _UA_free(void * ptr,char*,char*,int);
 UA_Int32 UA_memcpy(void *dst, void const *src, int size);
-#define UA_alloc(ptr,size) _UA_alloc(ptr,size,__FILE__,__LINE__)
-UA_Int32 _UA_alloc(void ** dst, int size,char*,int);
+#define UA_alloc(ptr,size) _UA_alloc(ptr,size,#ptr,#size,__FILE__,__LINE__)
+UA_Int32 _UA_alloc(void ** dst, int size,char*,char*,char*,int);
 
 /* Array operations */
 UA_Int32 UA_Array_calcSize(UA_Int32 noElements, UA_Int32 type, void const ** const ptr);

+ 4 - 4
src/ua_basictypes.c

@@ -90,8 +90,8 @@ UA_Int32 UA_Array_new(void **p,UA_Int32 noElements, UA_Int32 type) {
 	return retval;
 }
 
-UA_Int32 _UA_free(void * ptr,char* f,int l){
-	DBG_VERBOSE(printf("UA_free;%p;;%s;%d\n",ptr,f,l); fflush(stdout));
+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) {
 		free(ptr);
 	}
@@ -99,10 +99,10 @@ UA_Int32 _UA_free(void * ptr,char* f,int l){
 }
 
 void const * UA_alloc_lastptr;
-UA_Int32 _UA_alloc(void ** ptr, int size,char* f,int l){
+UA_Int32 _UA_alloc(void ** ptr, int size,char*pname,char*sname,char* f,int l){
 	if(ptr == UA_NULL) return UA_ERR_INVALID_VALUE;
+	DBG_VERBOSE(printf("UA_alloc;%p;%d;%s;%s;%s;%d\n",*ptr,size,pname,sname,f,l); fflush(stdout));
 	UA_alloc_lastptr = *ptr = malloc(size);
-	DBG_VERBOSE(printf("UA_alloc;%p;%d;%s;%d\n",*ptr,size,f,l); fflush(stdout));
 	if(*ptr == UA_NULL) return UA_ERR_NO_MEMORY;
 	return UA_SUCCESS;
 }

+ 1 - 0
src/util/ua_list.c

@@ -112,6 +112,7 @@ UA_Int32 UA_list_removeLast(UA_list_List* list, UA_list_PayloadVisitor visitor){
 		list->size--;
 		if(list->size == 1){
 			list->first = temp;
+			list->first->next = UA_NULL;
 		}else if(list->size==0){
 			list->first = UA_NULL;
 		}