Explorar el Código

should be buildable now

Leon Urbas hace 11 años
padre
commit
a0c69382db

+ 1 - 1
examples/src/Makefile.am

@@ -3,7 +3,7 @@ bin_PROGRAMS= $(top_builddir)/bin/exampleServer $(top_builddir)/bin/simpleTest
 #__top_builddir__bin_exampleServer_LDFLAGS = -all-static
 __top_builddir__bin_exampleServer_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_exampleServer_SOURCES = opcuaServer.c
-__top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a
+__top_builddir__bin_exampleServer_LDADD= $(top_builddir)/lib/libopen62541.a -lpthread
 
 __top_builddir__bin_simpleTest_CFLAGS = -I$(top_builddir)/src -I$(top_builddir)/include
 __top_builddir__bin_simpleTest_SOURCES = simpleTest.c

+ 43 - 0
include/UA_stack.h

@@ -0,0 +1,43 @@
+/*
+ * UA_stack.h
+ *
+ *  Created on: 04.04.2014
+ *      Author: mrt
+ */
+
+#ifndef UA_STACK_H_
+#define UA_STACK_H_
+
+#include "opcua.h"
+#include "UA_connection.h"
+#include "UA_list.h"
+
+#define UA_TL_MAXCONNECTIONS_DEFAULT 1
+
+enum UA_TRANSPORTLAYERDESCRIPTION_ENCODING_enum {
+	UA_TL_ENCODING_BINARY = 0,
+	UA_TL_ENCODING_XML = 1,
+};
+enum UA_TRANSPORTLAYERDESCRIPTION_CONNECTION_enum {
+	UA_TL_CONNECTIONTYPE_TCPV4 = 0,
+	UA_TL_CONNECTIONTYPE_TCPV6 = 1,
+};
+typedef struct T_UA_TL_Description {
+	UA_Int32 encoding;
+	UA_Int32 connectionType;
+	UA_Int32 maxConnections;
+	TL_buffer localConf;
+} UA_TL_Description;
+
+extern UA_TL_Description UA_TransportLayerDescriptorTcpBinary;
+
+typedef struct T_UA_TL_data {
+	UA_TL_Description* tld;
+	UA_String endpointUrl;
+	int listenerHandle;
+	pthread_t listenerThreadHandle;
+	UA_list_List connections;
+} UA_TL_data;
+
+UA_Int32 UA_Stack_init(UA_TL_Description* tlDesc, UA_Int32 port);
+#endif /* UA_STACK_H_ */

+ 2 - 2
src/UA_connection.h

@@ -55,7 +55,7 @@ typedef struct T_TL_connection
 	UA_Int32 (*UA_TL_writer)(struct T_TL_connection* c, UA_ByteString* msg);
 	TL_buffer remoteConf;
 	UA_String endpointUrl;
-} TL_connection;
+} UA_TL_connection;
 
 
 /* Secure Layer Channel */
@@ -75,7 +75,7 @@ typedef struct T_SL_Channel
 
 	SL_ChannelSecurityToken securityToken;
 	UA_UInt32 requestId; // request Id of the current request
-	TL_connection* tlc;
+	UA_TL_connection* tlc;
 } UA_SL_Channel;
 
 struct SS_connection

+ 176 - 0
src/UA_stack.c

@@ -0,0 +1,176 @@
+/*
+ * UA_stack.c
+ *
+ *  Created on: 04.04.2014
+ *      Author: mrt
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/socketvar.h>
+
+#include <errno.h> // errno, EINTR
+
+#include <pthread.h>
+
+#include "UA_stack.h"
+
+UA_TL_Description UA_TransportLayerDescriptorTcpBinary  = {
+		UA_TL_ENCODING_BINARY,
+		UA_TL_CONNECTIONTYPE_TCPV4,
+		UA_TL_MAXCONNECTIONS_DEFAULT,
+		{-1,8192,8192,16384,1}
+};
+
+// TODO: do we really need a variable global to the module?
+UA_TL_data theTL;
+
+
+/** checks arguments and dispatches to worker or refuses to init */
+UA_Int32 UA_TL_init(UA_TL_Description* tlDesc, UA_Int32 port) {
+	UA_Int32 retval = UA_SUCCESS;
+	if (tlDesc->connectionType == UA_TL_CONNECTIONTYPE_TCPV4 && tlDesc->encoding == UA_TL_ENCODING_BINARY) {
+		theTL.tld = &tlDesc;
+		UA_list_init(&theTL.connections);
+		retval |= UA_TL_TCP_init(theTL,port);
+	} else {
+		retval = UA_ERR_NOT_IMPLEMENTED;
+	}
+	return retval;
+}
+
+
+/** the tcp reader thread **/
+void* UA_TL_TCP_reader(void *p) {
+	UA_TL_connection* c = (UA_TL_connection*) p;
+
+	UA_ByteString readBuffer;
+	UA_alloc(&(readBuffer.data),c->localConf.recvBufferSize);
+
+	while (c->connectionState != connectionState_CLOSE) {
+		readBuffer.length = read(c->socket, readBuffer.data, c->localConf.recvBufferSize);
+
+		UA_ByteString_printx("server_run - received=",&readBuffer);
+
+		if (readBuffer.length  > 0) {
+			TL_process(&c,&readBuffer);
+		} else if (readBuffer.length < 0) {
+			perror("ERROR reading from socket1");
+			break;
+		}
+	}
+	// clean up: socket, buffer, connection
+	// not really necessary?
+	c->connectionState = connectionState_CLOSE;
+	// free resources allocated with socket
+	close(c->socket);
+	UA_ByteString_deleteMembers(&readBuffer);
+	// FIXME: C has no lambdas, we need a matcher with two arguments
+	// UA_list_Element* lec = UA_list_findFirst(theTL,c,compare);
+	// TODO: can we get get rid of reference to theTL?
+	UA_list_Element* lec = UA_list_find(&theTL.connections,UA_NULL);
+	UA_list_removeElement(lec,UA_NULL);
+	UA_free(lec->payload);
+	return UA_NULL;
+}
+
+/** write to a tcp transport layer connection */
+void* UA_TL_TCP_write(UA_TL_connection* c, UA_ByteString* msg) {
+	UA_ByteString_printx("write data:", msg);
+	int nWritten = 0;
+	while (nWritten < msg->length) {
+		int n;
+		do {
+			n = write(c->socket, &(msg->data[n]), msg->length-n);
+		} while (n == -1L && errno == EINTR);
+		if (n >= 0) {
+			nWritten += n;
+		} else {
+			// TODO: error handling
+		}
+	}
+	return UA_NULL;
+}
+
+/** the tcp listener thread **/
+void* UA_TL_TCP_listen(void *p) {
+	UA_TL_data* tld = (UA_TL_data*) p;
+
+	UA_String_printf("open62541-server at ",&(tld->endpointUrl));
+	while (UA_TRUE) {
+		listen(tld->listenerHandle, tld->tld->maxConnections);
+
+		// accept only if not max number of connections exceeded
+		if (tld->tld->maxConnections == -1 || tld->connections.size < tld->tld->maxConnections) {
+			struct sockaddr_in cli_addr;
+			int cli_len = sizeof(cli_addr);
+			int newsockfd = accept(tld->listenerHandle, (struct sockaddr *) &cli_addr, &cli_len);
+			if (newsockfd < 0) {
+				perror("ERROR on accept");
+			} else {
+				UA_TL_connection* c;
+				UA_Int32 retval = UA_SUCCESS;
+				retval |= UA_alloc(&c,sizeof(UA_TL_connection));
+				TL_Connection_init(c, tld);
+				c->socket = newsockfd;
+				c->UA_TL_writer = UA_TL_TCP_write;
+				// add to list
+				UA_list_addPayloadToBack(&(tld->connections),c);
+				// TODO: handle retval of pthread_create
+				pthread_create( &(c->readerThread), NULL, UA_TL_TCP_reader, (void*) c);
+			}
+		} else {
+			// no action necessary to reject connection
+		}
+	}
+	return UA_NULL;
+}
+
+UA_Int32 UA_TL_TCP_init(UA_TL_data* tld, UA_Int32 port) {
+	UA_Int32 retval = UA_SUCCESS;
+	// socket variables
+	int sockfd;
+	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) {
+		perror("ERROR opening socket");
+		retval = UA_ERROR;
+	} else {
+		// set port number, options and bind
+		memset((void *) &serv_addr, sizeof(serv_addr),1);
+		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) {
+			perror("setsockopt");
+			retval = UA_ERROR;
+		} else {
+			// bind to port
+			if (bind(sockfd, (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);
+			}
+		}
+	}
+	// finally
+	if (retval == UA_SUCCESS) {
+		// TODO: handle retval of pthread_create
+		pthread_create( &tld->listenerThreadHandle, NULL, UA_TL_TCP_listen, (void*) tld);
+	}
+	return retval;
+}
+
+/** checks arguments and dispatches to worker or refuses to init */
+UA_Int32 UA_Stack_init(UA_TL_Description* tlDesc, UA_Int32 port) {
+	UA_Int32 retval = UA_SUCCESS;
+	retval = UA_TL_init(tlDesc,port);
+	return retval;
+}

+ 1 - 1
src/opcua_secureLayer.c

@@ -428,7 +428,7 @@ UA_Int32 SL_processMessage(UA_SL_Channel *sc, UA_ByteString* msg) {
 UA_SL_Channel slc;
 
 /** process data as we've got it from the transport layer */
-void SL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType) {
+void SL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType) {
 	UA_SecureConversationMessageHeader secureConvHeader;
 	UA_AsymmetricAlgorithmSecurityHeader asymAlgSecHeader;
 	UA_SequenceHeader sequenceHeader;

+ 1 - 1
src/opcua_secureLayer.h

@@ -27,6 +27,6 @@ UA_Int32 SL_initConnectionObject(UA_SL_Channel *connection);
 UA_Int32 SL_openSecureChannel_responseMessage_get(UA_SL_Channel *connection,
 UA_SL_Response *response, UA_Int32* sizeInOut);
 
-void SL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType);
+void SL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 messageType);
 
 #endif /* OPCUA_SECURECHANNELLAYER_H_ */

+ 4 - 4
src/opcua_transportLayer.c

@@ -10,7 +10,7 @@
 #include "opcua_transportLayer.h"
 
 
-UA_Int32 TL_Connection_init(TL_connection *c, UA_TL_Description* tld)
+UA_Int32 TL_Connection_init(UA_TL_connection *c, UA_TL_Description* tld)
 {
 	c->socket = -1;
 	c->connectionState = connectionState_CLOSED;
@@ -22,7 +22,7 @@ UA_Int32 TL_Connection_init(TL_connection *c, UA_TL_Description* tld)
 	return UA_SUCCESS;
 }
 
-UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg, int checkLocal)
+UA_Int32 TL_check(UA_TL_connection *connection, UA_ByteString* msg, int checkLocal)
 {
 	UA_Int32 retval = UA_SUCCESS;
 
@@ -46,7 +46,7 @@ UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg, int checkLocal)
 
 #define Cmp3Byte(data,pos,a,b,c) (*((Int32*) ((data)+(pos))) & 0xFFFFFF) == (Int32)(((Byte)(a))|((Byte)(b))<<8|((Byte)(c))<<16)
 
-UA_Int32 TL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 packetType, UA_Int32 *pos)
+UA_Int32 TL_process(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 packetType, UA_Int32 *pos)
 {
 	UA_Int32 retval = UA_SUCCESS;
 	UA_Int32 tmpPos = 0;
@@ -140,7 +140,7 @@ UA_Int32 TL_process(TL_connection *connection, UA_ByteString* msg, UA_Int32 pack
 	return retval;
 }
 /** respond to client request */
-UA_Int32 TL_send(TL_connection* connection, UA_ByteString* msg)
+UA_Int32 TL_send(UA_TL_connection* connection, UA_ByteString* msg)
 {
 	UA_Int32 retval = UA_SUCCESS;
 	DBG_VERBOSE_printf("TL_send - entered \n");

+ 4 - 4
src/opcua_transportLayer.h

@@ -93,16 +93,16 @@ enum UA_TL_CHECK_enum {
 	UA_TL_CHECK_LOCAL = 0,
 	UA_TL_CHECK_REMOTE = 1
 };
-UA_Int32 TL_check(TL_connection *connection, UA_ByteString* msg, UA_Int32 local);
+UA_Int32 TL_check(UA_TL_connection *connection, UA_ByteString* msg, UA_Int32 local);
 /**
  *
  * @param connection
  * @param TL_message
  */
-UA_Int32 TL_receive(TL_connection *connection,UA_ByteString *packet);
-UA_Int32 TL_send(TL_connection *connection, UA_ByteString *packet);
+UA_Int32 TL_receive(UA_TL_connection *connection,UA_ByteString *packet);
+UA_Int32 TL_send(UA_TL_connection *connection, UA_ByteString *packet);
 UA_Int32 TL_getPacketType(UA_ByteString *packet, UA_Int32 *pos);
-UA_Int32 TL_process(TL_connection *connection, UA_ByteString *packet, UA_Int32 packetType, UA_Int32 *pos);
+UA_Int32 TL_process(UA_TL_connection *connection, UA_ByteString *packet, UA_Int32 packetType, UA_Int32 *pos);
 
 
 #endif /* OPCUA_TRANSPORTLAYER_H_ */