Пример #1
0
/*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;
}
Пример #2
0
/* 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);
        }
    }
}
Пример #3
0
/**
 * 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);
}
Пример #4
0
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);
}
Пример #5
0
/**
 * 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;
}
Пример #6
0
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;
}
Пример #7
0
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;
		}
}