Browse Source

make binary connection work

Julius Pfrommer 10 years ago
parent
commit
ae856629fa

+ 17 - 24
examples/networklayer_tcp.c

@@ -86,6 +86,7 @@ UA_Int32 NetworklayerTCP_remove(NetworklayerTCP *layer, UA_Int32 sockfd) {
 void NetworklayerTCP_delete(NetworklayerTCP *layer) {
 void NetworklayerTCP_delete(NetworklayerTCP *layer) {
 	for(UA_UInt32 index = 0;index < layer->connectionsSize;index++) {
 	for(UA_UInt32 index = 0;index < layer->connectionsSize;index++) {
 		shutdown(layer->connections[index].sockfd, 2);
 		shutdown(layer->connections[index].sockfd, 2);
+        UA_Connection_deleteMembers(&layer->connections[index].connection);
 		CLOSESOCKET(layer->connections[index].sockfd);
 		CLOSESOCKET(layer->connections[index].sockfd);
 	}
 	}
 	UA_free(layer->connections);
 	UA_free(layer->connections);
@@ -93,14 +94,14 @@ void NetworklayerTCP_delete(NetworklayerTCP *layer) {
 }
 }
 
 
 /** Callback function */
 /** Callback function */
-void closeHandle(TCPConnectionHandle *handle) {
+void closeCallback(TCPConnectionHandle *handle) {
 	shutdown(handle->sockfd,2);
 	shutdown(handle->sockfd,2);
 	CLOSESOCKET(handle->sockfd);
 	CLOSESOCKET(handle->sockfd);
 	NetworklayerTCP_remove(handle->layer, handle->sockfd);
 	NetworklayerTCP_remove(handle->layer, handle->sockfd);
 }
 }
 
 
 /** Callback function */
 /** Callback function */
-UA_Int32 writeHandle(TCPConnectionHandle *handle, UA_ByteStringArray gather_buf) {
+UA_Int32 writeCallback(TCPConnectionHandle *handle, UA_ByteStringArray gather_buf) {
 	UA_UInt32 total_len = 0;
 	UA_UInt32 total_len = 0;
 	UA_UInt32 nWritten = 0;
 	UA_UInt32 nWritten = 0;
 #ifdef WIN32
 #ifdef WIN32
@@ -151,19 +152,17 @@ UA_Int32 writeHandle(TCPConnectionHandle *handle, UA_ByteStringArray gather_buf)
 }
 }
 
 
 UA_Int32 NetworklayerTCP_add(NetworklayerTCP *layer, UA_Int32 newsockfd) {
 UA_Int32 NetworklayerTCP_add(NetworklayerTCP *layer, UA_Int32 newsockfd) {
-	layer->connections = realloc(layer->connections,
-								 sizeof(TCPConnection) * layer->connectionsSize);
-	TCPConnection *newconnection = &layer->connections[layer->connectionsSize];
+    layer->connectionsSize++;
+	layer->connections = realloc(layer->connections, sizeof(TCPConnection) * layer->connectionsSize);
+	TCPConnection *newconnection = &layer->connections[layer->connectionsSize-1];
 	newconnection->sockfd = newsockfd;
 	newconnection->sockfd = newsockfd;
-	layer->connectionsSize++;
 
 
 	struct TCPConnectionHandle *callbackhandle;
 	struct TCPConnectionHandle *callbackhandle;
 	UA_alloc((void**)&callbackhandle, sizeof(struct TCPConnectionHandle));
 	UA_alloc((void**)&callbackhandle, sizeof(struct TCPConnectionHandle));
 	callbackhandle->layer = layer;
 	callbackhandle->layer = layer;
 	callbackhandle->sockfd = newsockfd;
 	callbackhandle->sockfd = newsockfd;
 	UA_Connection_init(&newconnection->connection, layer->localConf, callbackhandle,
 	UA_Connection_init(&newconnection->connection, layer->localConf, callbackhandle,
-					   (UA_Int32 (*)(void*))closeHandle,
-					   (UA_Int32 (*)(void*, UA_ByteStringArray*))writeHandle);
+					   (UA_Connection_closeCallback)closeCallback, (UA_Connection_writeCallback)writeCallback);
 	return UA_SUCCESS;
 	return UA_SUCCESS;
 }
 }
 
 
@@ -242,54 +241,48 @@ void setFDSet(NetworklayerTCP *layer) {
 		if(layer->connections[i].sockfd > layer->highestfd)
 		if(layer->connections[i].sockfd > layer->highestfd)
 			layer->highestfd = layer->connections[i].sockfd;
 			layer->highestfd = layer->connections[i].sockfd;
 	}
 	}
+    layer->highestfd++;
 }
 }
 
 
 UA_Int32 NetworkLayerTCP_run(NetworklayerTCP *layer, UA_Server *server, struct timeval tv,
 UA_Int32 NetworkLayerTCP_run(NetworklayerTCP *layer, UA_Server *server, struct timeval tv,
 							   void(*worker)(UA_Server*), UA_Boolean *running) {
 							   void(*worker)(UA_Server*), UA_Boolean *running) {
-	struct sockaddr_in serv_addr;
-	//UA_String_copyprintf("opc.tcp://localhost:%d/", &(tld->endpointUrl), port);
-
 #ifdef WIN32
 #ifdef WIN32
-	unsigned int newsockfd;
 	WORD wVersionRequested;
 	WORD wVersionRequested;
 	WSADATA wsaData;
 	WSADATA wsaData;
 	wVersionRequested = MAKEWORD(2, 2);
 	wVersionRequested = MAKEWORD(2, 2);
 	WSAStartup(wVersionRequested, &wsaData);
 	WSAStartup(wVersionRequested, &wsaData);
-	newsockfd = socket(PF_INET, SOCK_STREAM,0);
-	if (newsockfd == INVALID_SOCKET) {
+	if((layer->serversockfd = socket(PF_INET, SOCK_STREAM,0)) == INVALID_SOCKET) {
 		printf("ERROR opening socket, code: %d\n", WSAGetLastError());
 		printf("ERROR opening socket, code: %d\n", WSAGetLastError());
 		return UA_ERROR;
 		return UA_ERROR;
 	}
 	}
 #else
 #else
-	int newsockfd;
-	newsockfd = socket(PF_INET, SOCK_STREAM, 0);
-	if (newsockfd < 0) {
+    if((layer->serversockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
 		perror("ERROR opening socket");
 		perror("ERROR opening socket");
 		return UA_ERROR;
 		return UA_ERROR;
 	} 
 	} 
 #endif
 #endif
+	struct sockaddr_in serv_addr;
 	memset((void *)&serv_addr, sizeof(serv_addr), 1);
 	memset((void *)&serv_addr, sizeof(serv_addr), 1);
 	serv_addr.sin_family = AF_INET;
 	serv_addr.sin_family = AF_INET;
 	serv_addr.sin_addr.s_addr = INADDR_ANY;
 	serv_addr.sin_addr.s_addr = INADDR_ANY;
 	serv_addr.sin_port = htons(layer->port);
 	serv_addr.sin_port = htons(layer->port);
 
 
 	int optval = 1;
 	int optval = 1;
-	if(setsockopt(newsockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval,
-				  sizeof(optval)) == -1) {
+	if(setsockopt(layer->serversockfd, SOL_SOCKET, SO_REUSEADDR, (const char *)&optval, sizeof(optval)) == -1) {
 		perror("setsockopt");
 		perror("setsockopt");
-		close(newsockfd);
+		close(layer->serversockfd);
 		return UA_ERROR;
 		return UA_ERROR;
 	}
 	}
 		
 		
-	if(bind(newsockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+	if(bind(layer->serversockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 		perror("binding");
 		perror("binding");
-		close(newsockfd);
+		close(layer->serversockfd);
 		return UA_ERROR;
 		return UA_ERROR;
 	}
 	}
 
 
 #define MAXBACKLOG 10
 #define MAXBACKLOG 10
-	setNonBlocking(newsockfd);
-	listen(newsockfd, MAXBACKLOG);
+	setNonBlocking(layer->serversockfd);
+	listen(layer->serversockfd, MAXBACKLOG);
 
 
 	while (*running) {
 	while (*running) {
 		setFDSet(layer);
 		setFDSet(layer);

+ 8 - 3
src/server/ua_securechannel_manager.c

@@ -88,6 +88,8 @@ UA_Int32 UA_SecureChannelManager_open(UA_SecureChannelManager           *cm,
     UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
     UA_ByteString_copy(&entry->channel.serverNonce, &response->serverNonce);
     UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
     UA_ChannelSecurityToken_copy(&entry->channel.securityToken, &response->securityToken);
 
 
+    conn->channel = &entry->channel;
+
     return UA_SUCCESS;
     return UA_SUCCESS;
 }
 }
 
 
@@ -100,12 +102,15 @@ UA_Int32 UA_SecureChannelManager_renew(UA_SecureChannelManager           *cm,
     if(channel == UA_NULL)
     if(channel == UA_NULL)
         return UA_ERROR;
         return UA_ERROR;
 
 
-
-    // TODO write response
-
+    channel->securityToken.tokenId         = cm->lastTokenId++;
     channel->securityToken.createdAt       = UA_DateTime_now(); // todo: is wanted?
     channel->securityToken.createdAt       = UA_DateTime_now(); // todo: is wanted?
     channel->securityToken.revisedLifetime = request->requestedLifetime > cm->maxChannelLifetime ?
     channel->securityToken.revisedLifetime = request->requestedLifetime > cm->maxChannelLifetime ?
                                              cm->maxChannelLifetime : request->requestedLifetime;
                                              cm->maxChannelLifetime : request->requestedLifetime;
+
+    UA_SecureChannel_generateNonce(&channel->serverNonce);
+    UA_ByteString_copy(&channel->serverNonce, &response->serverNonce);
+    UA_ChannelSecurityToken_copy(&channel->securityToken, &response->securityToken);
+
     return UA_SUCCESS;
     return UA_SUCCESS;
 }
 }
 
 

+ 88 - 62
src/server/ua_server_binary.c

@@ -4,16 +4,11 @@
 
 
 static void processHello(UA_Connection *connection, const UA_ByteString *msg,
 static void processHello(UA_Connection *connection, const UA_ByteString *msg,
                          UA_UInt32 *pos) {
                          UA_UInt32 *pos) {
-    UA_UInt32 tmpPos = 0;
     UA_OPCUATcpHelloMessage helloMessage;
     UA_OPCUATcpHelloMessage helloMessage;
-
-    if(connection->state != UA_CONNECTION_OPENING) {
-        // multiple HEL are not allowed
+    if(UA_OPCUATcpHelloMessage_decodeBinary(msg, pos, &helloMessage) != UA_SUCCESS) {
         connection->close(connection->callbackHandle);
         connection->close(connection->callbackHandle);
         return;
         return;
     }
     }
-
-    UA_OPCUATcpHelloMessage_decodeBinary(msg, pos, &helloMessage);
     connection->remoteConf.maxChunkCount   = helloMessage.maxChunkCount;
     connection->remoteConf.maxChunkCount   = helloMessage.maxChunkCount;
     connection->remoteConf.maxMessageSize  = helloMessage.maxMessageSize;
     connection->remoteConf.maxMessageSize  = helloMessage.maxMessageSize;
     connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
     connection->remoteConf.protocolVersion = helloMessage.protocolVersion;
@@ -23,10 +18,6 @@ static void processHello(UA_Connection *connection, const UA_ByteString *msg,
     connection->state = UA_CONNECTION_ESTABLISHED;
     connection->state = UA_CONNECTION_ESTABLISHED;
 
 
     // build acknowledge response
     // build acknowledge response
-    UA_OPCUATcpMessageHeader ackHeader;
-    ackHeader.messageType = UA_MESSAGETYPE_ACK;
-    ackHeader.isFinal     = 'F';
-
     UA_OPCUATcpAcknowledgeMessage ackMessage;
     UA_OPCUATcpAcknowledgeMessage ackMessage;
     ackMessage.protocolVersion   = connection->localConf.protocolVersion;
     ackMessage.protocolVersion   = connection->localConf.protocolVersion;
     ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
     ackMessage.receiveBufferSize = connection->localConf.recvBufferSize;
@@ -34,42 +25,82 @@ static void processHello(UA_Connection *connection, const UA_ByteString *msg,
     ackMessage.maxMessageSize    = connection->localConf.maxMessageSize;
     ackMessage.maxMessageSize    = connection->localConf.maxMessageSize;
     ackMessage.maxChunkCount     = connection->localConf.maxChunkCount;
     ackMessage.maxChunkCount     = connection->localConf.maxChunkCount;
 
 
+    UA_OPCUATcpMessageHeader ackHeader;
+    ackHeader.messageType = UA_MESSAGETYPE_ACK;
+    ackHeader.isFinal     = 'F';
     ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(&ackMessage) +
     ackHeader.messageSize = UA_OPCUATcpAcknowledgeMessage_calcSizeBinary(&ackMessage) +
                             UA_OPCUATcpMessageHeader_calcSizeBinary(&ackHeader);
                             UA_OPCUATcpMessageHeader_calcSizeBinary(&ackHeader);
-    UA_ByteString *ack_msg;
-    UA_alloc((void **)&ack_msg, sizeof(UA_ByteString));
-    UA_ByteString_newMembers(ack_msg, ackHeader.messageSize);
-    tmpPos = 0;
-    UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader, ack_msg, &tmpPos);
-    UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage, ack_msg, &tmpPos);
-    UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = ack_msg };
-    connection->write(connection->callbackHandle, &answer_buf);
-    UA_ByteString_delete(ack_msg);
+
+    UA_ByteString ack_msg;
+    UA_UInt32 tmpPos = 0;
+    UA_ByteString_newMembers(&ack_msg, ackHeader.messageSize);
+    UA_OPCUATcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos);
+    UA_OPCUATcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos);
+    UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &ack_msg };
+    connection->write(connection->callbackHandle, answer_buf);
+    UA_ByteString_deleteMembers(&ack_msg);
 }
 }
 
 
 static void processOpen(UA_Connection *connection, UA_Server *server,
 static void processOpen(UA_Connection *connection, UA_Server *server,
                         const UA_ByteString *msg, UA_UInt32 *pos) {
                         const UA_ByteString *msg, UA_UInt32 *pos) {
-    UA_UInt32 secureChannelId;
     if(connection->state != UA_CONNECTION_ESTABLISHED) {
     if(connection->state != UA_CONNECTION_ESTABLISHED) {
+        // was hello exchanged before?
         if(connection->state == UA_CONNECTION_OPENING)
         if(connection->state == UA_CONNECTION_OPENING)
             connection->close(connection->callbackHandle);
             connection->close(connection->callbackHandle);
         return;
         return;
     }
     }
 
 
+    UA_UInt32 secureChannelId;
     UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
     UA_UInt32_decodeBinary(msg, pos, &secureChannelId);
-    // needs asym encoding for returning
-    // call the service!!!!
-    /* if(connection->channel != UA_NULL) { */
-    /*  //create new channel */
-    /*  SL_Channel *newChannel; */
-    /*  retval |= SL_ChannelManager_generateChannel(cm, ) */
-    /*  retval |= SL_ProcessOpenChannel(newChannel, server, msg, pos); */
-    /*  retval |= SL_Channel_bind(newChannel, connection); */
-    /*  return retval; */
-    /* } */
-    /* // channel already exists, renew token? */
-    /* retval |= SL_ProcessOpenChannel(channel, server, msg, pos); */
-    /* return retval; */
+
+    UA_AsymmetricAlgorithmSecurityHeader asymHeader;
+    UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader);
+
+    UA_SequenceHeader seqHeader;
+    UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader);
+
+    UA_ExpandedNodeId requestType;
+    UA_ExpandedNodeId_decodeBinary(msg, pos, &requestType);
+
+    if(requestType.nodeId.identifier.numeric != 446) {
+        // todo: handle error
+    }
+
+    UA_OpenSecureChannelRequest r;
+    UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r);
+
+    // perform request
+    UA_OpenSecureChannelResponse p;
+    UA_OpenSecureChannelResponse_init(&p);
+    Service_OpenSecureChannel(server, connection, &r, &p);
+
+    // response
+    UA_OPCUATcpMessageHeader respHeader;
+    respHeader.messageType = UA_MESSAGETYPE_OPN;
+    respHeader.isFinal     = 'F';
+    respHeader.messageSize = 8+4; //header + securechannelid
+
+    UA_ExpandedNodeId responseType;
+    NS0EXPANDEDNODEID(responseType, 449);
+
+    respHeader.messageSize += UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader);
+    respHeader.messageSize += UA_SequenceHeader_calcSizeBinary(&seqHeader);
+    respHeader.messageSize += UA_ExpandedNodeId_calcSizeBinary(&responseType);
+    respHeader.messageSize += UA_OpenSecureChannelResponse_calcSizeBinary(&p);
+
+    UA_ByteString resp_msg;
+    UA_UInt32 tmpPos = 0;
+    UA_ByteString_newMembers(&resp_msg, respHeader.messageSize);
+    UA_OPCUATcpMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos);
+    UA_UInt32_encodeBinary(&p.securityToken.channelId, &resp_msg, &tmpPos);
+    UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back
+    UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back
+    UA_ExpandedNodeId_encodeBinary(&responseType, &resp_msg, &tmpPos);
+    UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos);
+    
+    UA_ByteStringArray answer_buf = { .stringsSize = 1, .strings = &resp_msg };
+    connection->write(connection->callbackHandle, answer_buf);
+    UA_ByteString_deleteMembers(&resp_msg);
 }
 }
 
 
 static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r) {
 static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r) {
@@ -89,14 +120,11 @@ static void init_response_header(UA_RequestHeader const *p, UA_ResponseHeader *r
 #define INVOKE_SERVICE(TYPE) do {                                                                         \
 #define INVOKE_SERVICE(TYPE) do {                                                                         \
         UA_##TYPE##Request p;                                                                             \
         UA_##TYPE##Request p;                                                                             \
         UA_##TYPE##Response r;                                                                            \
         UA_##TYPE##Response r;                                                                            \
-        UA_Session *session = UA_NULL;                                                                    \
         CHECK_PROCESS(UA_##TYPE##Request_decodeBinary(msg, pos, &p),; );                                  \
         CHECK_PROCESS(UA_##TYPE##Request_decodeBinary(msg, pos, &p),; );                                  \
         UA_##TYPE##Response_init(&r);                                                                     \
         UA_##TYPE##Response_init(&r);                                                                     \
         init_response_header(&p.requestHeader, &r.responseHeader);                                        \
         init_response_header(&p.requestHeader, &r.responseHeader);                                        \
-        UA_SessionManager_getSessionByToken(server->sessionManager, &p.requestHeader.authenticationToken, \
-                                            &session);                                                    \
         DBG_VERBOSE(printf("Invoke Service: %s\n", # TYPE));                                              \
         DBG_VERBOSE(printf("Invoke Service: %s\n", # TYPE));                                              \
-        Service_##TYPE(server, session, &p, &r);                                                          \
+        Service_##TYPE(server, channel->session, &p, &r);                                                 \
         DBG_VERBOSE(printf("Finished Service: %s\n", # TYPE));                                            \
         DBG_VERBOSE(printf("Finished Service: %s\n", # TYPE));                                            \
         UA_ByteString_newMembers(&responseBuf.strings[1], UA_##TYPE##Response_calcSizeBinary(&r));        \
         UA_ByteString_newMembers(&responseBuf.strings[1], UA_##TYPE##Response_calcSizeBinary(&r));        \
         UA_##TYPE##Response_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);                       \
         UA_##TYPE##Response_encodeBinary(&r, &responseBuf.strings[1], &sendOffset);                       \
@@ -118,6 +146,10 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
     UA_UInt32_decodeBinary(msg, pos, &tokenId);
     UA_UInt32_decodeBinary(msg, pos, &tokenId);
     UA_SequenceHeader sequenceHeader;
     UA_SequenceHeader sequenceHeader;
     CHECK_PROCESS(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader),; );
     CHECK_PROCESS(UA_SequenceHeader_decodeBinary(msg, pos, &sequenceHeader),; );
+
+    channel->sequenceNumber = sequenceHeader.sequenceNumber;
+    channel->requestId = sequenceHeader.requestId;
+    // todo
     //UA_SecureChannel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
     //UA_SecureChannel_checkSequenceNumber(channel,sequenceHeader.sequenceNumber);
     //UA_SecureChannel_checkRequestId(channel,sequenceHeader.requestId);
     //UA_SecureChannel_checkRequestId(channel,sequenceHeader.requestId);
 
 
@@ -136,8 +168,7 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
     //subtract 2 for binary encoding
     //subtract 2 for binary encoding
     UA_UInt32 sendOffset = 0;
     UA_UInt32 sendOffset = 0;
     switch(requestType.nodeId.identifier.numeric - 2) {
     switch(requestType.nodeId.identifier.numeric - 2) {
-    case UA_GETENDPOINTSREQUEST_NS0:
-    {
+    case UA_GETENDPOINTSREQUEST_NS0: {
         UA_GetEndpointsRequest  p;
         UA_GetEndpointsRequest  p;
         UA_GetEndpointsResponse r;
         UA_GetEndpointsResponse r;
         CHECK_PROCESS(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p),; );
         CHECK_PROCESS(UA_GetEndpointsRequest_decodeBinary(msg, pos, &p),; );
@@ -153,8 +184,7 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
         break;
         break;
     }
     }
 
 
-    case UA_CREATESESSIONREQUEST_NS0:
-    {
+    case UA_CREATESESSIONREQUEST_NS0: {
         UA_CreateSessionRequest  p;
         UA_CreateSessionRequest  p;
         UA_CreateSessionResponse r;
         UA_CreateSessionResponse r;
         CHECK_PROCESS(UA_CreateSessionRequest_decodeBinary(msg, pos, &p),; );
         CHECK_PROCESS(UA_CreateSessionRequest_decodeBinary(msg, pos, &p),; );
@@ -206,8 +236,7 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
         INVOKE_SERVICE(SetPublishingMode);
         INVOKE_SERVICE(SetPublishingMode);
         break;
         break;
 
 
-    default:
-    {
+    default: {
         printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
         printf("SL_processMessage - unknown request, namespace=%d, request=%d\n",
                requestType.nodeId.namespaceIndex, requestType.nodeId.identifier.numeric);
                requestType.nodeId.namespaceIndex, requestType.nodeId.identifier.numeric);
         UA_RequestHeader  p;
         UA_RequestHeader  p;
@@ -221,12 +250,10 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
         UA_RequestHeader_deleteMembers(&p);
         UA_RequestHeader_deleteMembers(&p);
         UA_ResponseHeader_deleteMembers(&r);
         UA_ResponseHeader_deleteMembers(&r);
         responseType = UA_RESPONSEHEADER_NS0 + 2;
         responseType = UA_RESPONSEHEADER_NS0 + 2;
-    }
+        }
     }
     }
 
 
     // 5) Build the header
     // 5) Build the header
-#define SIZE_SECURECHANNEL_HEADER 12
-#define SIZE_SEQHEADER_HEADER 8
     UA_NodeId response_nodeid = { .namespaceIndex     = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
     UA_NodeId response_nodeid = { .namespaceIndex     = 0, .identifierType = UA_NODEIDTYPE_NUMERIC,
                                   .identifier.numeric = responseType }; // add 2 for binary encoding
                                   .identifier.numeric = responseType }; // add 2 for binary encoding
 
 
@@ -234,19 +261,17 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
                              8 + 16 + // normal header + 4*32bit secure channel information
                              8 + 16 + // normal header + 4*32bit secure channel information
                              UA_NodeId_calcSizeBinary(&response_nodeid));
                              UA_NodeId_calcSizeBinary(&response_nodeid));
 
 
-    // sizePadding = 0;
-    // sizeSignature = 0;
     UA_ByteString *header = &responseBuf.strings[0];
     UA_ByteString *header = &responseBuf.strings[0];
+    UA_UInt32 rpos = 0;
 
 
-    // secure conversation message header
-    header->data[0] = 'M';
-    header->data[1] = 'S';
-    header->data[2] = 'G';
-    header->data[3] = 'F';
-    UA_UInt32 rpos       = 4;
+    // header
+    UA_OPCUATcpMessageHeader respHeader;
+    respHeader.messageType = UA_MESSAGETYPE_MSG;
+    respHeader.isFinal     = 'F';
+    respHeader.messageSize = header->length + responseBuf.strings[1].length;
+    UA_OPCUATcpMessageHeader_encodeBinary(&respHeader, header, &rpos);
 
 
-    UA_Int32  packetSize = header->length + responseBuf.strings[0].length;
-    UA_Int32_encodeBinary(&packetSize, header, &rpos);
+    // channel id
     UA_UInt32_encodeBinary(&channel->securityToken.channelId, header, &rpos);
     UA_UInt32_encodeBinary(&channel->securityToken.channelId, header, &rpos);
 
 
     // algorithm security header
     // algorithm security header
@@ -264,7 +289,7 @@ static void processMessage(UA_Connection *connection, UA_Server *server,
     // encrypt data
     // encrypt data
 
 
     // 6) Send it over the wire.
     // 6) Send it over the wire.
-    connection->write(connection->callbackHandle, &responseBuf);
+    connection->write(connection->callbackHandle, responseBuf);
 
 
 clean_up:
 clean_up:
     UA_ExpandedNodeId_deleteMembers(&requestType);
     UA_ExpandedNodeId_deleteMembers(&requestType);
@@ -278,8 +303,7 @@ close_connection:
     return;
     return;
 }
 }
 
 
-static void processClose(UA_Connection *connection, UA_Server *server,
-                         const UA_ByteString *msg, UA_UInt32 *pos) {
+static void processClose(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, UA_UInt32 *pos) {
     // just read in the sequenceheader
     // just read in the sequenceheader
 
 
 }
 }
@@ -289,6 +313,7 @@ UA_Int32 UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connec
     UA_Int32  retval = UA_SUCCESS;
     UA_Int32  retval = UA_SUCCESS;
     UA_UInt32 pos    = 0;
     UA_UInt32 pos    = 0;
     UA_OPCUATcpMessageHeader tcpMessageHeader;
     UA_OPCUATcpMessageHeader tcpMessageHeader;
+    // todo: test how far pos advanced must be equal to what is said in the messageheader
     do {
     do {
         retval = UA_OPCUATcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader);
         retval = UA_OPCUATcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader);
         if(retval == UA_SUCCESS) {
         if(retval == UA_SUCCESS) {
@@ -314,15 +339,16 @@ UA_Int32 UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connec
                 connection->state = UA_CONNECTION_CLOSING;
                 connection->state = UA_CONNECTION_CLOSING;
                 processClose(connection, server, msg, &pos);
                 processClose(connection, server, msg, &pos);
                 connection->close(connection->callbackHandle);
                 connection->close(connection->callbackHandle);
-                break;
+                return retval;
             }
             }
+            UA_OPCUATcpMessageHeader_deleteMembers(&tcpMessageHeader);
         } else {
         } else {
             printf("TL_Process - ERROR: decoding of header failed \n");
             printf("TL_Process - ERROR: decoding of header failed \n");
             connection->state = UA_CONNECTION_CLOSING;
             connection->state = UA_CONNECTION_CLOSING;
-            processClose(connection, server, msg, &pos);
+            //processClose(connection, server, msg, &pos);
             connection->close(connection->callbackHandle);
             connection->close(connection->callbackHandle);
         }
         }
-        UA_OPCUATcpMessageHeader_deleteMembers(&tcpMessageHeader);
+        // todo: more than one message at once..
     } while(msg->length > (UA_Int32)pos);
     } while(msg->length > (UA_Int32)pos);
     return retval;
     return retval;
 }
 }

+ 9 - 13
src/server/ua_services_discovery.c

@@ -3,39 +3,35 @@
 UA_Int32 Service_GetEndpoints(UA_Server                    *server,
 UA_Int32 Service_GetEndpoints(UA_Server                    *server,
                               const UA_GetEndpointsRequest *request,
                               const UA_GetEndpointsRequest *request,
                               UA_GetEndpointsResponse      *response) {
                               UA_GetEndpointsResponse      *response) {
+    UA_GetEndpointsResponse_init(response);
     response->endpointsSize = 1;
     response->endpointsSize = 1;
-    UA_Array_new((void **)&response->endpoints, response->endpointsSize,
-                 &UA_.types[UA_ENDPOINTDESCRIPTION]);
+    UA_Array_new((void **)&response->endpoints, response->endpointsSize, &UA_.types[UA_ENDPOINTDESCRIPTION]);
 
 
-    //FIXME hard-coded code
+    // security policy
     response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
     response->endpoints[0].securityMode = UA_MESSAGESECURITYMODE_NONE;
     UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",
     UA_String_copycstring("http://opcfoundation.org/UA/SecurityPolicy#None",
                           &response->endpoints[0].securityPolicyUri);
                           &response->endpoints[0].securityPolicyUri);
     UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
     UA_String_copycstring("http://opcfoundation.org/UA-Profile/Transport/uatcp-uasc-uabinary",
                           &response->endpoints[0].transportProfileUri);
                           &response->endpoints[0].transportProfileUri);
 
 
+    // usertoken policy
     response->endpoints[0].userIdentityTokensSize = 1;
     response->endpoints[0].userIdentityTokensSize = 1;
     UA_Array_new((void **)&response->endpoints[0].userIdentityTokens,
     UA_Array_new((void **)&response->endpoints[0].userIdentityTokens,
-                 response->endpoints[0].userIdentityTokensSize,
-                 &UA_.types[UA_USERTOKENPOLICY]);
+                 response->endpoints[0].userIdentityTokensSize, &UA_.types[UA_USERTOKENPOLICY]);
     UA_UserTokenPolicy *token = &response->endpoints[0].userIdentityTokens[0];
     UA_UserTokenPolicy *token = &response->endpoints[0].userIdentityTokens[0];
+    UA_UserTokenPolicy_init(token);
     UA_String_copycstring("my-anonymous-policy", &token->policyId); // defined per server
     UA_String_copycstring("my-anonymous-policy", &token->policyId); // defined per server
     token->tokenType         = UA_USERTOKENTYPE_ANONYMOUS;
     token->tokenType         = UA_USERTOKENTYPE_ANONYMOUS;
-    token->issuerEndpointUrl = (UA_String ) {-1, UA_NULL };
-    token->issuedTokenType   = (UA_String ) {-1, UA_NULL };
-    token->securityPolicyUri = (UA_String ) {-1, UA_NULL };
 
 
+    // server description
     UA_String_copy(&request->endpointUrl, &response->endpoints[0].endpointUrl);
     UA_String_copy(&request->endpointUrl, &response->endpoints[0].endpointUrl);
-    UA_String_copycstring("http://open62541.info/product/release",
-                          &(response->endpoints[0].server.productUri));
+    UA_String_copycstring("http://open62541.info/product/release", &(response->endpoints[0].server.productUri));
     // FIXME: This information should be provided by the application, preferably in the address space
     // FIXME: This information should be provided by the application, preferably in the address space
     UA_String_copycstring("http://open62541.info/applications/4711",
     UA_String_copycstring("http://open62541.info/applications/4711",
                           &(response->endpoints[0].server.applicationUri));
                           &(response->endpoints[0].server.applicationUri));
-    UA_LocalizedText_copycstring("The open62541 application",
-                                 &(response->endpoints[0].server.applicationName));
+    UA_LocalizedText_copycstring("The open62541 application", &(response->endpoints[0].server.applicationName));
     // FIXME: This should be a feature of the application and an enum
     // FIXME: This should be a feature of the application and an enum
     response->endpoints[0].server.applicationType = UA_APPLICATIONTYPE_SERVER;
     response->endpoints[0].server.applicationType = UA_APPLICATIONTYPE_SERVER;
-    // all the other strings are empty by initialization
 
 
     return UA_SUCCESS;
     return UA_SUCCESS;
 }
 }

+ 0 - 0
src/tokenType


+ 2 - 6
src/ua_connection.c

@@ -21,15 +21,11 @@ UA_Int32 UA_ByteStringArray_deleteMembers(UA_ByteStringArray *stringarray) {
         return UA_ERROR;
         return UA_ERROR;
     for(UA_UInt32 i = 0;i < stringarray->stringsSize;i++)
     for(UA_UInt32 i = 0;i < stringarray->stringsSize;i++)
         UA_String_deleteMembers(&stringarray->strings[i]);
         UA_String_deleteMembers(&stringarray->strings[i]);
-    UA_free(stringarray);
     return UA_SUCCESS;
     return UA_SUCCESS;
 }
 }
 
 
-UA_Int32 UA_Connection_init(UA_Connection *connection,
-                            UA_ConnectionConfig localConf,
-                            void *callbackHandle,
-                            UA_Int32 (*close)(void *handle),
-                            UA_Int32 (*write)(void *handle, UA_ByteStringArray *buf)) {
+UA_Int32 UA_Connection_init(UA_Connection *connection, UA_ConnectionConfig localConf, void *callbackHandle,
+                            UA_Connection_closeCallback close, UA_Connection_writeCallback write) {
     connection->state          = UA_CONNECTION_OPENING;
     connection->state          = UA_CONNECTION_OPENING;
     connection->localConf      = localConf;
     connection->localConf      = localConf;
     connection->channel        = UA_NULL;
     connection->channel        = UA_NULL;

+ 3 - 4
src/ua_connection.h

@@ -33,7 +33,7 @@ extern UA_ConnectionConfig UA_ConnectionConfig_standard;
 struct UA_SecureChannel;
 struct UA_SecureChannel;
 typedef struct UA_SecureChannel UA_SecureChannel;
 typedef struct UA_SecureChannel UA_SecureChannel;
 
 
-typedef UA_Int32 (*UA_Connection_writeCallback)(void *handle, UA_ByteStringArray *buf);
+typedef UA_Int32 (*UA_Connection_writeCallback)(void *handle, UA_ByteStringArray buf);
 typedef UA_Int32 (*UA_Connection_closeCallback)(void *handle);
 typedef UA_Int32 (*UA_Connection_closeCallback)(void *handle);
 
 
 typedef struct UA_Connection {
 typedef struct UA_Connection {
@@ -46,9 +46,8 @@ typedef struct UA_Connection {
     UA_Connection_closeCallback close;
     UA_Connection_closeCallback close;
 } UA_Connection;
 } UA_Connection;
 
 
-UA_Int32 UA_Connection_init(UA_Connection *connection, UA_ConnectionConfig localConf,
-                            void *callbackHandle, UA_Int32 (*close)(void *handle),
-                            UA_Int32 (*write)(void *handle, UA_ByteStringArray *buf));
+UA_Int32 UA_Connection_init(UA_Connection *connection, UA_ConnectionConfig localConf, void *callbackHandle,
+                            UA_Connection_closeCallback close, UA_Connection_writeCallback write);
 UA_Int32 UA_Connection_deleteMembers(UA_Connection *connection);
 UA_Int32 UA_Connection_deleteMembers(UA_Connection *connection);
 
 
 // todo: closing a binaryconnection that was closed on the network level
 // todo: closing a binaryconnection that was closed on the network level

+ 0 - 6
src/ua_types.c

@@ -14,10 +14,6 @@
 #include "ua_types_encoding_binary.h"
 #include "ua_types_encoding_binary.h"
 #include "ua_namespace_0.h"
 #include "ua_namespace_0.h"
 
 
-/************/
-/* Built-In */
-/************/
-
 /* Boolean */
 /* Boolean */
 UA_Int32 UA_Boolean_init(UA_Boolean *p) {
 UA_Int32 UA_Boolean_init(UA_Boolean *p) {
     if(p == UA_NULL) return UA_ERROR;
     if(p == UA_NULL) return UA_ERROR;
@@ -65,8 +61,6 @@ void UA_Int16_print(const UA_Int16 *p, FILE *stream) {
 }
 }
 #endif
 #endif
 
 
-
-
 /* UInt16 */
 /* UInt16 */
 UA_TYPE_DEFAULT(UA_UInt16)
 UA_TYPE_DEFAULT(UA_UInt16)
 #ifdef DEBUG
 #ifdef DEBUG