static UA_StatusCode CloseSecureChannel(UA_Client *client) { UA_SecureChannel *channel = &client->channel; UA_CloseSecureChannelRequest request; UA_CloseSecureChannelRequest_init(&request); request.requestHeader.requestHandle = 1; //TODO: magic number? request.requestHeader.timestamp = UA_DateTime_now(); request.requestHeader.timeoutHint = 10000; request.requestHeader.authenticationToken = client->authenticationToken; UA_SecureConversationMessageHeader msgHeader; msgHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_CLOF; msgHeader.secureChannelId = client->channel.securityToken.channelId; UA_SymmetricAlgorithmSecurityHeader symHeader; symHeader.tokenId = channel->securityToken.tokenId; UA_SequenceHeader seqHeader; seqHeader.sequenceNumber = ++channel->sequenceNumber; seqHeader.requestId = ++client->requestId; UA_NodeId typeId = UA_NODEID_NUMERIC(0, UA_NS0ID_CLOSESECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY); UA_ByteString message; UA_Connection *c = &client->connection; UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message); if(retval != UA_STATUSCODE_GOOD) return retval; size_t offset = 12; retval |= UA_SymmetricAlgorithmSecurityHeader_encodeBinary(&symHeader, &message, &offset); retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset); retval |= UA_NodeId_encodeBinary(&typeId, &message, &offset); retval |= UA_encodeBinary(&request, &UA_TYPES[UA_TYPES_CLOSESECURECHANNELREQUEST], &message, &offset); msgHeader.messageHeader.messageSize = offset; offset = 0; retval |= UA_SecureConversationMessageHeader_encodeBinary(&msgHeader, &message, &offset); if(retval != UA_STATUSCODE_GOOD) { client->connection.releaseSendBuffer(&client->connection, &message); return retval; } message.length = msgHeader.messageHeader.messageSize; retval = client->connection.send(&client->connection, &message); return retval; }
static UA_StatusCode SecureChannelHandshake(UA_Client *client, UA_Boolean renew) { /* Check if sc is still valid */ if(renew && client->scExpiresAt - UA_DateTime_now() > client->config.timeToRenewSecureChannel * 10000) return UA_STATUSCODE_GOOD; UA_SecureConversationMessageHeader messageHeader; messageHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; messageHeader.secureChannelId = 0; UA_SequenceHeader seqHeader; seqHeader.sequenceNumber = ++client->channel.sequenceNumber; seqHeader.requestId = ++client->requestId; UA_AsymmetricAlgorithmSecurityHeader asymHeader; UA_AsymmetricAlgorithmSecurityHeader_init(&asymHeader); asymHeader.securityPolicyUri = UA_STRING_ALLOC("http://opcfoundation.org/UA/SecurityPolicy#None"); /* id of opensecurechannelrequest */ UA_NodeId requestType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELREQUEST + UA_ENCODINGOFFSET_BINARY); UA_OpenSecureChannelRequest opnSecRq; UA_OpenSecureChannelRequest_init(&opnSecRq); opnSecRq.requestHeader.timestamp = UA_DateTime_now(); opnSecRq.requestHeader.authenticationToken = client->authenticationToken; opnSecRq.requestedLifetime = client->config.secureChannelLifeTime; if(renew) { opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_RENEW; UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Requesting to renew the SecureChannel"); } else { opnSecRq.requestType = UA_SECURITYTOKENREQUESTTYPE_ISSUE; UA_ByteString_init(&client->channel.clientNonce); UA_ByteString_copy(&client->channel.clientNonce, &opnSecRq.clientNonce); opnSecRq.securityMode = UA_MESSAGESECURITYMODE_NONE; UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Requesting to open a SecureChannel"); } UA_ByteString message; UA_Connection *c = &client->connection; UA_StatusCode retval = c->getSendBuffer(c, c->remoteConf.recvBufferSize, &message); if(retval != UA_STATUSCODE_GOOD) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq); return retval; } size_t offset = 12; retval = UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &message, &offset); retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &message, &offset); retval |= UA_NodeId_encodeBinary(&requestType, &message, &offset); retval |= UA_OpenSecureChannelRequest_encodeBinary(&opnSecRq, &message, &offset); messageHeader.messageHeader.messageSize = offset; offset = 0; retval |= UA_SecureConversationMessageHeader_encodeBinary(&messageHeader, &message, &offset); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_OpenSecureChannelRequest_deleteMembers(&opnSecRq); if(retval != UA_STATUSCODE_GOOD) { client->connection.releaseSendBuffer(&client->connection, &message); return retval; } message.length = messageHeader.messageHeader.messageSize; retval = client->connection.send(&client->connection, &message); if(retval != UA_STATUSCODE_GOOD) return retval; UA_ByteString reply; UA_ByteString_init(&reply); do { retval = client->connection.recv(&client->connection, &reply, client->config.timeout); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Receiving OpenSecureChannelResponse failed"); return retval; } } while(!reply.data); offset = 0; UA_SecureConversationMessageHeader_decodeBinary(&reply, &offset, &messageHeader); UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply, &offset, &asymHeader); UA_SequenceHeader_decodeBinary(&reply, &offset, &seqHeader); UA_NodeId_decodeBinary(&reply, &offset, &requestType); UA_NodeId expectedRequest = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE + UA_ENCODINGOFFSET_BINARY); if(!UA_NodeId_equal(&requestType, &expectedRequest)) { UA_ByteString_deleteMembers(&reply); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_NodeId_deleteMembers(&requestType); UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_CLIENT, "Reply answers the wrong request. Expected OpenSecureChannelResponse."); return UA_STATUSCODE_BADINTERNALERROR; } UA_OpenSecureChannelResponse response; UA_OpenSecureChannelResponse_init(&response); retval = UA_OpenSecureChannelResponse_decodeBinary(&reply, &offset, &response); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "Decoding OpenSecureChannelResponse failed"); UA_ByteString_deleteMembers(&reply); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_OpenSecureChannelResponse_init(&response); response.responseHeader.serviceResult = retval; return retval; } client->scExpiresAt = UA_DateTime_now() + response.securityToken.revisedLifetime * 10000; UA_ByteString_deleteMembers(&reply); retval = response.responseHeader.serviceResult; if(retval != UA_STATUSCODE_GOOD) UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel could not be opened / renewed"); else if(!renew) { UA_ChannelSecurityToken_copy(&response.securityToken, &client->channel.securityToken); /* if the handshake is repeated, replace the old nonce */ UA_ByteString_deleteMembers(&client->channel.serverNonce); UA_ByteString_copy(&response.serverNonce, &client->channel.serverNonce); UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel opened"); } else UA_LOG_DEBUG(client->logger, UA_LOGCATEGORY_SECURECHANNEL, "SecureChannel renewed"); UA_OpenSecureChannelResponse_deleteMembers(&response); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return retval; }
/* OPN -> Open up/renew the securechannel */ static void processOPN(UA_Server *server, UA_Connection *connection, UA_UInt32 channelId, const UA_ByteString *msg) { UA_StatusCode retval = UA_STATUSCODE_GOOD; /* Called before HEL */ if(connection->state != UA_CONNECTION_ESTABLISHED) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Opening up a channel with a channelid already set */ if(!connection->channel && channelId != 0) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Renew a channel with the wrong channelid */ if(connection->channel && channelId != connection->channel->securityToken.channelId) retval = UA_STATUSCODE_BADCOMMUNICATIONERROR; /* Decode the request */ UA_AsymmetricAlgorithmSecurityHeader asymHeader; UA_SequenceHeader seqHeader; UA_NodeId requestType; UA_OpenSecureChannelRequest r; size_t offset = 0; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, &offset, &asymHeader); retval |= UA_SequenceHeader_decodeBinary(msg, &offset, &seqHeader); retval |= UA_NodeId_decodeBinary(msg, &offset, &requestType); retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, &offset, &r); /* Error occured */ if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } /* Call the service */ UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); /* Opening the channel failed */ UA_SecureChannel *channel = connection->channel; if(!channel) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Set the starting sequence number */ channel->receiveSequenceNumber = seqHeader.sequenceNumber; /* Allocate the return message */ UA_ByteString resp_msg; UA_ByteString_init(&resp_msg); retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &resp_msg); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Encode the message after the secureconversationmessageheader */ size_t tmpPos = 12; /* skip the header */ seqHeader.sequenceNumber = UA_atomic_add(&channel->sendSequenceNumber, 1); retval |= UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_TYPES[UA_TYPES_OPENSECURECHANNELRESPONSE].binaryEncodingId); retval |= UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); retval |= UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); if(retval != UA_STATUSCODE_GOOD) { connection->releaseSendBuffer(connection, &resp_msg); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->close(connection); return; } /* Encode the secureconversationmessageheader (cannot fail) and send */ UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndChunkType = UA_MESSAGETYPE_OPN + UA_CHUNKTYPE_FINAL; respHeader.messageHeader.messageSize = (UA_UInt32)tmpPos; respHeader.secureChannelId = p.securityToken.channelId; tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); resp_msg.length = respHeader.messageHeader.messageSize; connection->send(connection, &resp_msg); /* Clean up */ UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); }
static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) { if(connection->state != UA_CONNECTION_ESTABLISHED) { connection->close(connection); return; } UA_UInt32 secureChannelId; UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId); UA_AsymmetricAlgorithmSecurityHeader asymHeader; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader); UA_SequenceHeader seqHeader; retval |= UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader); UA_NodeId requestType; retval |= UA_NodeId_decodeBinary(msg, pos, &requestType); UA_OpenSecureChannelRequest r; retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r); if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_deleteMembers(&seqHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); UA_SecureChannel *channel = connection->channel; if(!channel) { connection->close(connection); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } /* send the response with an asymmetric security header */ seqHeader.sequenceNumber = channel->sequenceNumber; UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; respHeader.messageHeader.messageSize = 0; respHeader.secureChannelId = p.securityToken.channelId; UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE + UA_ENCODINGOFFSET_BINARY); respHeader.messageHeader.messageSize = UA_SecureConversationMessageHeader_calcSizeBinary(&respHeader) + UA_AsymmetricAlgorithmSecurityHeader_calcSizeBinary(&asymHeader) + UA_SequenceHeader_calcSizeBinary(&seqHeader) + UA_NodeId_calcSizeBinary(&responseType) + UA_OpenSecureChannelResponse_calcSizeBinary(&p); UA_ByteString resp_msg; retval = connection->getBuffer(connection, &resp_msg, respHeader.messageHeader.messageSize); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } size_t tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); connection->write(connection, &resp_msg); connection->releaseBuffer(connection, &resp_msg); }
int main(int argc , char *argv[]) { int sock; struct sockaddr_in server; UA_ByteString message; message.data = (UA_Byte*)malloc(1000*sizeof(UA_Byte)); message.length = 1000; //UA_UInt32 messageEncodedLength = 0; UA_Byte server_reply[2000]; unsigned int messagepos = 0; //Create socket #ifdef UA_ENABLE_NONSTANDARD_UDP sock = socket(AF_INET , SOCK_DGRAM , 0); #else sock = socket(AF_INET , SOCK_STREAM , 0); #endif if(sock == -1) { printf("Could not create socket"); } server.sin_addr.s_addr = inet_addr("127.0.0.1"); server.sin_family = AF_INET; server.sin_port = htons( 16664 ); //Connect to remote server if(connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } UA_TcpMessageHeader reqTcpHeader; UA_UInt32 reqSecureChannelId = 0; UA_UInt32 reqTokenId = 0; UA_SequenceHeader reqSequenceHeader; UA_NodeId reqRequestType; UA_ReadRequest req; UA_RequestHeader reqHeader; UA_NodeId reqHeaderAuthToken; UA_ExtensionObject reqHeaderAdditionalHeader; UA_NodeId_init(&reqRequestType); reqRequestType.identifierType = UA_NODEIDTYPE_NUMERIC; reqRequestType.identifier.numeric = 631; //read request UA_SequenceHeader_init(&reqSequenceHeader); reqSequenceHeader.sequenceNumber = 42; UA_ReadRequest_init(&req); req.requestHeader = reqHeader; UA_RequestHeader_init(&(req.requestHeader)); req.requestHeader.authenticationToken = reqHeaderAuthToken; UA_NodeId_init(&(req.requestHeader.authenticationToken)); req.requestHeader.additionalHeader = reqHeaderAdditionalHeader; UA_ExtensionObject_init(&(req.requestHeader.additionalHeader)); req.nodesToRead= UA_Array_new(&UA_TYPES[UA_TYPES_READVALUEID], 1); req.nodesToReadSize = 1; UA_ReadValueId_init(&(req.nodesToRead[0])); req.nodesToRead[0].attributeId = 13; //UA_ATTRIBUTEID_VALUE UA_NodeId_init(&(req.nodesToRead[0].nodeId)); req.nodesToRead[0].nodeId.identifierType = UA_NODEIDTYPE_NUMERIC; req.nodesToRead[0].nodeId.identifier.numeric = 2255; UA_QualifiedName_init(&(req.nodesToRead[0].dataEncoding)); /**messageEncodedLength = UA_TcpMessageHeader_calcSizeBinary(&reqTcpHeader) + UA_UInt32_calcSizeBinary(&reqSecureChannelId)+ UA_UInt32_calcSizeBinary(&reqTokenId)+ UA_SequenceHeader_calcSizeBinary(&reqSequenceHeader)+ UA_NodeId_calcSizeBinary(&reqRequestType) + UA_ReadRequest_calcSizeBinary(&req);**/ UA_TcpMessageHeader_init(&reqTcpHeader); reqTcpHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_MSGF; UA_TcpMessageHeader_encodeBinary(&reqTcpHeader, &message, &messagepos); UA_UInt32_encodeBinary(&reqSecureChannelId, &message, &messagepos); UA_UInt32_encodeBinary(&reqTokenId, &message, &messagepos); UA_SequenceHeader_encodeBinary(&reqSequenceHeader, &message, &messagepos); UA_NodeId_encodeBinary(&reqRequestType, &message, &messagepos); UA_ReadRequest_encodeBinary(&req, &message, &messagepos); reqTcpHeader.messageSize = messagepos; messagepos=0; UA_TcpMessageHeader_encodeBinary(&reqTcpHeader, &message, &messagepos); UA_UInt32_encodeBinary(&reqSecureChannelId, &message, &messagepos); UA_UInt32_encodeBinary(&reqTokenId, &message, &messagepos); UA_SequenceHeader_encodeBinary(&reqSequenceHeader, &message, &messagepos); UA_NodeId_encodeBinary(&reqRequestType, &message, &messagepos); UA_ReadRequest_encodeBinary(&req, &message, &messagepos); //Send some data if(send(sock , message.data, messagepos , 0) < 0) { puts("Send failed"); return 1; } //Receive a reply from the server int received = recv(sock , server_reply , 2000 , 0); if(received < 0) { puts("recv failed"); return 1; } for(int i=0;i<received;i++) { //show only printable ascii if(server_reply[i] >= 32 && server_reply[i]<= 126) printf("%c",server_reply[i]); } printf("\n"); close(sock); return 0; }
static void processOPN(UA_Connection *connection, UA_Server *server, const UA_ByteString *msg, size_t *pos) { if(connection->state != UA_CONNECTION_ESTABLISHED) { connection->close(connection); return; } UA_UInt32 secureChannelId; UA_StatusCode retval = UA_UInt32_decodeBinary(msg, pos, &secureChannelId); UA_AsymmetricAlgorithmSecurityHeader asymHeader; retval |= UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(msg, pos, &asymHeader); UA_SequenceHeader seqHeader; retval |= UA_SequenceHeader_decodeBinary(msg, pos, &seqHeader); UA_NodeId requestType; retval |= UA_NodeId_decodeBinary(msg, pos, &requestType); UA_OpenSecureChannelRequest r; retval |= UA_OpenSecureChannelRequest_decodeBinary(msg, pos, &r); if(retval != UA_STATUSCODE_GOOD || requestType.identifier.numeric != 446) { UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_deleteMembers(&seqHeader); UA_NodeId_deleteMembers(&requestType); UA_OpenSecureChannelRequest_deleteMembers(&r); connection->close(connection); return; } UA_OpenSecureChannelResponse p; UA_OpenSecureChannelResponse_init(&p); Service_OpenSecureChannel(server, connection, &r, &p); UA_OpenSecureChannelRequest_deleteMembers(&r); UA_SecureChannel *channel = connection->channel; if(!channel) { connection->close(connection); UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } /* send the response with an asymmetric security header */ #ifndef UA_MULTITHREADING seqHeader.sequenceNumber = ++channel->sequenceNumber; #else seqHeader.sequenceNumber = uatomic_add_return(&channel->sequenceNumber, 1); #endif UA_SecureConversationMessageHeader respHeader; respHeader.messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_OPNF; respHeader.messageHeader.messageSize = 0; respHeader.secureChannelId = p.securityToken.channelId; UA_NodeId responseType = UA_NODEID_NUMERIC(0, UA_NS0ID_OPENSECURECHANNELRESPONSE + UA_ENCODINGOFFSET_BINARY); UA_ByteString resp_msg; retval = connection->getSendBuffer(connection, connection->remoteConf.recvBufferSize, &resp_msg); if(retval != UA_STATUSCODE_GOOD) { UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); return; } size_t tmpPos = 12; /* skip the secureconversationmessageheader for now */ retval |= UA_AsymmetricAlgorithmSecurityHeader_encodeBinary(&asymHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_SequenceHeader_encodeBinary(&seqHeader, &resp_msg, &tmpPos); // just mirror back retval |= UA_NodeId_encodeBinary(&responseType, &resp_msg, &tmpPos); retval |= UA_OpenSecureChannelResponse_encodeBinary(&p, &resp_msg, &tmpPos); if(retval != UA_STATUSCODE_GOOD) { connection->releaseSendBuffer(connection, &resp_msg); connection->close(connection); } else { respHeader.messageHeader.messageSize = tmpPos; tmpPos = 0; UA_SecureConversationMessageHeader_encodeBinary(&respHeader, &resp_msg, &tmpPos); resp_msg.length = respHeader.messageHeader.messageSize; connection->send(connection, &resp_msg); } UA_OpenSecureChannelResponse_deleteMembers(&p); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); }