/*receives hello ack, opens secure channel*/ UA_StatusCode processACKResponseAsync(void *application, UA_Connection *connection, UA_ByteString *chunk) { UA_Client *client = (UA_Client*)application; /* Decode the message */ size_t offset = 0; UA_TcpMessageHeader messageHeader; UA_TcpAcknowledgeMessage ackMessage; client->connectStatus = UA_TcpMessageHeader_decodeBinary (chunk, &offset, &messageHeader); client->connectStatus |= UA_TcpAcknowledgeMessage_decodeBinary( chunk, &offset, &ackMessage); if (client->connectStatus != UA_STATUSCODE_GOOD) { UA_LOG_INFO(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Decoding ACK message failed"); return client->connectStatus; } UA_LOG_DEBUG(&client->config.logger, UA_LOGCATEGORY_NETWORK, "Received ACK message"); client->connectStatus = UA_Connection_processHELACK(connection, &client->config.localConnectionConfig, (const UA_ConnectionConfig*)&ackMessage); if(client->connectStatus != UA_STATUSCODE_GOOD) return client->connectStatus; client->state = UA_CLIENTSTATE_CONNECTED; /* Open a SecureChannel. TODO: Select with endpoint */ client->channel.connection = &client->connection; client->connectStatus = openSecureChannelAsync(client/*, false*/); return client->connectStatus; }
/* Takes the raw message from the network layer */ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *message) { UA_SecureChannel *channel = connection->channel; if(channel) { /* Assemble chunks in the securechannel and process complete messages */ UA_StatusCode retval = UA_SecureChannel_processChunks(channel, message, (UA_ProcessMessageCallback*)UA_Server_processSecureChannelMessage, server); if(retval != UA_STATUSCODE_GOOD) UA_LOG_TRACE_CHANNEL(server->config.logger, channel, "Procesing chunkgs resulted in error code 0x%08x", retval); } else { /* Process messages without a channel and no chunking */ size_t offset = 0; UA_TcpMessageHeader tcpMessageHeader; UA_StatusCode retval = UA_TcpMessageHeader_decodeBinary(message, &offset, &tcpMessageHeader); if(retval != UA_STATUSCODE_GOOD) { connection->close(connection); return; } /* Dispatch according to the message type */ switch(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) { case UA_MESSAGETYPE_HEL: UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK, "Connection %i | Process HEL message", connection->sockfd); processHEL(connection, message, &offset); break; case UA_MESSAGETYPE_OPN: { UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK, "Connection %i | Process OPN message", connection->sockfd); UA_UInt32 channelId = 0; retval = UA_UInt32_decodeBinary(message, &offset, &channelId); if(retval != UA_STATUSCODE_GOOD) connection->close(connection); UA_ByteString offsetMessage = (UA_ByteString){ .data = message->data + 12, .length = message->length - 12}; processOPN(server, connection, channelId, &offsetMessage); break; } case UA_MESSAGETYPE_MSG: UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK, "Connection %i | Processing a MSG message not possible " "without a SecureChannel", connection->sockfd); connection->close(connection); break; case UA_MESSAGETYPE_CLO: UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK, "Connection %i | Processing a CLO message not possible " "without a SecureChannel", connection->sockfd); connection->close(connection); break; default: UA_LOG_TRACE(server->config.logger, UA_LOGCATEGORY_NETWORK, "Connection %i | Unknown message type", connection->sockfd); connection->close(connection); } } }
/** * process binary message received from Connection * dose not modify UA_ByteString you have to free it youself. * use of connection->getSendBuffer() and connection->sent() to answer Message */ void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, const UA_ByteString *msg) { size_t pos = 0; UA_TcpMessageHeader tcpMessageHeader; do { if(UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader)) { UA_LOG_INFO(server->logger, UA_LOGCATEGORY_NETWORK, "Decoding of message header failed"); connection->close(connection); break; } size_t targetpos = pos - 8 + tcpMessageHeader.messageSize; switch(tcpMessageHeader.messageTypeAndFinal & 0xffffff) { case UA_MESSAGETYPEANDFINAL_HELF & 0xffffff: processHEL(connection, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_OPNF & 0xffffff: processOPN(connection, server, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_MSGF & 0xffffff: #ifndef EXTENSION_STATELESS if(connection->state != UA_CONNECTION_ESTABLISHED) { connection->close(connection); return; } #endif processMSG(connection, server, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff: processCLO(connection, server, msg, &pos); connection->close(connection); return; default: UA_LOG_INFO(server->logger, UA_LOGCATEGORY_NETWORK, "Unknown request type on Connection %i", connection->sockfd); } UA_TcpMessageHeader_deleteMembers(&tcpMessageHeader); if(pos != targetpos) { UA_LOG_INFO(server->logger, UA_LOGCATEGORY_NETWORK, "Message on Connection %i was not entirely processed. " "Arrived at position %i, skip after the announced length to position %i", connection->sockfd, pos, targetpos); pos = targetpos; } } while(msg->length > pos); }
void UA_Server_processBinaryMessage(UA_Server *server, UA_Connection *connection, UA_ByteString *msg) { if(msg->length <= 0) return; size_t pos = 0; UA_TcpMessageHeader tcpMessageHeader; do { if(UA_TcpMessageHeader_decodeBinary(msg, &pos, &tcpMessageHeader)) { UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION, "Decoding of message header failed"); connection->close(connection); break; } size_t targetpos = pos - 8 + tcpMessageHeader.messageSize; switch(tcpMessageHeader.messageTypeAndFinal & 0xffffff) { case UA_MESSAGETYPEANDFINAL_HELF & 0xffffff: processHEL(connection, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_OPNF & 0xffffff: processOPN(connection, server, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_MSGF & 0xffffff: #ifndef EXTENSION_STATELESS if(connection->state != UA_CONNECTION_ESTABLISHED) connection->close(connection); else #endif processMSG(connection, server, msg, &pos); break; case UA_MESSAGETYPEANDFINAL_CLOF & 0xffffff: processCLO(connection, server, msg, &pos); connection->close(connection); return; } UA_TcpMessageHeader_deleteMembers(&tcpMessageHeader); if(pos != targetpos) { UA_LOG_INFO(server->logger, UA_LOGCATEGORY_COMMUNICATION, "The message was not entirely processed, skipping to the end"); pos = targetpos; } } while(msg->length > (UA_Int32)pos); }
/** * We need to decode the given binary message to get the name of the called service. * This method is used if the connection has no channel yet. */ static UA_StatusCode UA_debug_dump_setName_withoutChannel(UA_Server *server, UA_Connection *connection, UA_ByteString *message, struct UA_dump_filename* dump_filename) { size_t offset = 0; UA_TcpMessageHeader tcpMessageHeader; UA_StatusCode retval = UA_TcpMessageHeader_decodeBinary(message, &offset, &tcpMessageHeader); if(retval != UA_STATUSCODE_GOOD) return retval; dump_filename->messageType = UA_debug_dumpGetMessageTypePrefix(tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff); if ((tcpMessageHeader.messageTypeAndChunkType & 0x00ffffff) == UA_MESSAGETYPE_MSG) { // this should not happen in normal operation UA_LOG_ERROR(&server->config.logger, UA_LOGCATEGORY_SERVER, "Got MSG package without channel."); return UA_STATUSCODE_BADUNEXPECTEDERROR; } return UA_STATUSCODE_GOOD; }
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; }
static int ua_client_connectUA(char* ipaddress,int port, UA_String *endpointUrl, ConnectionInfo *connectionInfo, UA_Boolean stateless, UA_Boolean udp) { UA_ByteString reply; UA_ByteString_newMembers(&reply, 65536); int sock; struct sockaddr_in server; //Create socket if(udp==UA_TRUE){ sock = socket(AF_INET, SOCK_DGRAM, 0); }else{ sock = socket(AF_INET, SOCK_STREAM, 0); } if(sock == -1) { printf("Could not create socket"); return 1; } server.sin_addr.s_addr = inet_addr(ipaddress); server.sin_family = AF_INET; server.sin_port = htons(port); if(connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) { perror("connect failed. Error"); return 1; } connectionInfo->socket = sock; if(stateless){ UA_NodeId_init(&connectionInfo->authenticationToken); connectionInfo->channelId=0; UA_SequenceHeader_init(&connectionInfo->sequenceHdr); connectionInfo->tokenId=0; return 0; }else{ sendHello(sock, endpointUrl); recv(sock, reply.data, reply.length, 0); sendOpenSecureChannel(sock); recv(sock, reply.data, reply.length, 0); size_t recvOffset = 0; UA_TcpMessageHeader msghdr; UA_TcpMessageHeader_decodeBinary(&reply, &recvOffset, &msghdr); UA_AsymmetricAlgorithmSecurityHeader asymHeader; UA_NodeId rspType; UA_OpenSecureChannelResponse openSecChannelRsp; UA_UInt32_decodeBinary(&reply, &recvOffset, &connectionInfo->channelId); UA_AsymmetricAlgorithmSecurityHeader_decodeBinary(&reply,&recvOffset,&asymHeader); UA_AsymmetricAlgorithmSecurityHeader_deleteMembers(&asymHeader); UA_SequenceHeader_decodeBinary(&reply,&recvOffset,&connectionInfo->sequenceHdr); UA_NodeId_decodeBinary(&reply,&recvOffset,&rspType); UA_OpenSecureChannelResponse_decodeBinary(&reply,&recvOffset,&openSecChannelRsp); connectionInfo->tokenId = openSecChannelRsp.securityToken.tokenId; sendCreateSession(sock, connectionInfo->channelId, openSecChannelRsp.securityToken.tokenId, 52, 2, endpointUrl); recv(sock, reply.data, reply.length, 0); UA_NodeId messageType; recvOffset = 24; UA_NodeId_decodeBinary(&reply,&recvOffset,&messageType); UA_CreateSessionResponse createSessionResponse; UA_CreateSessionResponse_decodeBinary(&reply,&recvOffset,&createSessionResponse); connectionInfo->authenticationToken = createSessionResponse.authenticationToken; sendActivateSession(sock, connectionInfo->channelId, connectionInfo->tokenId, 53, 3, connectionInfo->authenticationToken); recv(sock, reply.data, reply.length, 0); UA_OpenSecureChannelResponse_deleteMembers(&openSecChannelRsp); UA_String_deleteMembers(&reply); UA_CreateSessionResponse_deleteMembers(&createSessionResponse); return 0; } }