/* HEL -> Open up the connection */ static void processHEL(UA_Connection *connection, const UA_ByteString *msg, size_t *offset) { UA_TcpHelloMessage helloMessage; if(UA_TcpHelloMessage_decodeBinary(msg, offset, &helloMessage) != UA_STATUSCODE_GOOD) { connection->close(connection); return; } /* Parameterize the connection */ connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount; /* zero -> unlimited */ connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize; /* zero -> unlimited */ connection->remoteConf.protocolVersion = helloMessage.protocolVersion; connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize; if(connection->localConf.sendBufferSize > helloMessage.receiveBufferSize) connection->localConf.sendBufferSize = helloMessage.receiveBufferSize; connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize; if(connection->localConf.recvBufferSize > helloMessage.sendBufferSize) connection->localConf.recvBufferSize = helloMessage.sendBufferSize; connection->state = UA_CONNECTION_ESTABLISHED; UA_TcpHelloMessage_deleteMembers(&helloMessage); /* Build acknowledge response */ UA_TcpAcknowledgeMessage ackMessage; ackMessage.protocolVersion = connection->localConf.protocolVersion; ackMessage.receiveBufferSize = connection->localConf.recvBufferSize; ackMessage.sendBufferSize = connection->localConf.sendBufferSize; ackMessage.maxMessageSize = connection->localConf.maxMessageSize; ackMessage.maxChunkCount = connection->localConf.maxChunkCount; UA_TcpMessageHeader ackHeader; ackHeader.messageTypeAndChunkType = UA_MESSAGETYPE_ACK + UA_CHUNKTYPE_FINAL; ackHeader.messageSize = 8 + 20; /* ackHeader + ackMessage */ /* Get the send buffer from the network layer */ UA_ByteString ack_msg; UA_ByteString_init(&ack_msg); UA_StatusCode retval = connection->getSendBuffer(connection, connection->localConf.sendBufferSize, &ack_msg); if(retval != UA_STATUSCODE_GOOD) return; /* Encode and send the response */ size_t tmpPos = 0; UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos); UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos); ack_msg.length = ackHeader.messageSize; connection->send(connection, &ack_msg); }
static UA_StatusCode sendHELMessage(UA_Client *client) { /* Get a buffer */ UA_ByteString message; UA_Connection *conn = &client->connection; UA_StatusCode retval = conn->getSendBuffer(conn, UA_MINMESSAGESIZE, &message); if(retval != UA_STATUSCODE_GOOD) return retval; /* Prepare the HEL message and encode at offset 8 */ UA_TcpHelloMessage hello; UA_String_copy(&client->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */ memcpy(&hello, &client->config.localConnectionConfig, sizeof(UA_ConnectionConfig)); /* same struct layout */ UA_Byte *bufPos = &message.data[8]; /* skip the header */ const UA_Byte *bufEnd = &message.data[message.length]; client->connectStatus = UA_TcpHelloMessage_encodeBinary(&hello, &bufPos, bufEnd); UA_TcpHelloMessage_deleteMembers (&hello); /* Encode the message header at offset 0 */ UA_TcpMessageHeader messageHeader; messageHeader.messageTypeAndChunkType = UA_CHUNKTYPE_FINAL + UA_MESSAGETYPE_HEL; messageHeader.messageSize = (UA_UInt32) ((uintptr_t)bufPos - (uintptr_t)message.data); bufPos = message.data; retval = UA_TcpMessageHeader_encodeBinary(&messageHeader, &bufPos, bufEnd); if(retval != UA_STATUSCODE_GOOD) { conn->releaseSendBuffer(conn, &message); return retval; } /* Send the HEL message */ message.length = messageHeader.messageSize; retval = conn->send (conn, &message); if(retval == UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Sent HEL message"); } else { UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Sending HEL failed"); } return retval; }
static void processHEL(UA_Connection *connection, const UA_ByteString *msg, size_t *pos) { UA_TcpHelloMessage helloMessage; if(UA_TcpHelloMessage_decodeBinary(msg, pos, &helloMessage) != UA_STATUSCODE_GOOD) { connection->close(connection); return; } connection->remoteConf.maxChunkCount = helloMessage.maxChunkCount; connection->remoteConf.maxMessageSize = helloMessage.maxMessageSize; connection->remoteConf.protocolVersion = helloMessage.protocolVersion; connection->remoteConf.recvBufferSize = helloMessage.receiveBufferSize; if(connection->localConf.sendBufferSize > helloMessage.receiveBufferSize) connection->localConf.sendBufferSize = helloMessage.receiveBufferSize; if(connection->localConf.recvBufferSize > helloMessage.sendBufferSize) connection->localConf.recvBufferSize = helloMessage.sendBufferSize; connection->remoteConf.sendBufferSize = helloMessage.sendBufferSize; connection->state = UA_CONNECTION_ESTABLISHED; UA_TcpHelloMessage_deleteMembers(&helloMessage); // build acknowledge response UA_TcpAcknowledgeMessage ackMessage; ackMessage.protocolVersion = connection->localConf.protocolVersion; ackMessage.receiveBufferSize = connection->localConf.recvBufferSize; ackMessage.sendBufferSize = connection->localConf.sendBufferSize; ackMessage.maxMessageSize = connection->localConf.maxMessageSize; ackMessage.maxChunkCount = connection->localConf.maxChunkCount; UA_TcpMessageHeader ackHeader; ackHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_ACKF; ackHeader.messageSize = UA_TcpMessageHeader_calcSizeBinary(&ackHeader) + UA_TcpAcknowledgeMessage_calcSizeBinary(&ackMessage); UA_ByteString ack_msg; if(connection->getBuffer(connection, &ack_msg, ackHeader.messageSize) != UA_STATUSCODE_GOOD) return; size_t tmpPos = 0; UA_TcpMessageHeader_encodeBinary(&ackHeader, &ack_msg, &tmpPos); UA_TcpAcknowledgeMessage_encodeBinary(&ackMessage, &ack_msg, &tmpPos); connection->write(connection, &ack_msg); connection->releaseBuffer(connection, &ack_msg); }
static UA_StatusCode HelAckHandshake(UA_Client *c) { UA_TcpMessageHeader messageHeader; messageHeader.messageTypeAndFinal = UA_MESSAGETYPEANDFINAL_HELF; UA_TcpHelloMessage hello; UA_String_copy(&c->endpointUrl, &hello.endpointUrl); /* must be less than 4096 bytes */ UA_Connection *conn = &c->connection; hello.maxChunkCount = conn->localConf.maxChunkCount; hello.maxMessageSize = conn->localConf.maxMessageSize; hello.protocolVersion = conn->localConf.protocolVersion; hello.receiveBufferSize = conn->localConf.recvBufferSize; hello.sendBufferSize = conn->localConf.sendBufferSize; UA_ByteString message; UA_StatusCode retval; retval = c->connection.getSendBuffer(&c->connection, c->connection.remoteConf.recvBufferSize, &message); if(retval != UA_STATUSCODE_GOOD) return retval; size_t offset = 8; retval |= UA_TcpHelloMessage_encodeBinary(&hello, &message, &offset); messageHeader.messageSize = offset; offset = 0; retval |= UA_TcpMessageHeader_encodeBinary(&messageHeader, &message, &offset); UA_TcpHelloMessage_deleteMembers(&hello); if(retval != UA_STATUSCODE_GOOD) { c->connection.releaseSendBuffer(&c->connection, &message); return retval; } message.length = messageHeader.messageSize; retval = c->connection.send(&c->connection, &message); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Sending HEL failed"); return retval; } UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Sent HEL message"); UA_ByteString reply; UA_ByteString_init(&reply); do { retval = c->connection.recv(&c->connection, &reply, c->config.timeout); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Receiving ACK message failed"); return retval; } } while(!reply.data); offset = 0; UA_TcpMessageHeader_decodeBinary(&reply, &offset, &messageHeader); UA_TcpAcknowledgeMessage ackMessage; retval = UA_TcpAcknowledgeMessage_decodeBinary(&reply, &offset, &ackMessage); UA_ByteString_deleteMembers(&reply); if(retval != UA_STATUSCODE_GOOD) { UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Decoding ACK message failed"); return retval; } UA_LOG_DEBUG(c->logger, UA_LOGCATEGORY_NETWORK, "Received ACK message"); conn->remoteConf.maxChunkCount = ackMessage.maxChunkCount; conn->remoteConf.maxMessageSize = ackMessage.maxMessageSize; conn->remoteConf.protocolVersion = ackMessage.protocolVersion; conn->remoteConf.recvBufferSize = ackMessage.receiveBufferSize; conn->remoteConf.sendBufferSize = ackMessage.sendBufferSize; conn->state = UA_CONNECTION_ESTABLISHED; return UA_STATUSCODE_GOOD; }