コード例 #1
0
    void handleAllocation(const ReceivedDataStructure<Allocation>& msg)
    {
        trace(TraceAllocationActivity, msg.getSrcNodeID().get());

        if (!msg.isAnonymousTransfer())
        {
            return;         // This is a response from another allocator, ignore
        }

        /*
         * Reset the expected stage on timeout
         */
        if (msg.getMonotonicTimestamp() > (last_message_timestamp_ + stage_timeout_))
        {
            UAVCAN_TRACE("AllocationRequestManager", "Stage timeout, reset");
            current_unique_id_.clear();
            trace(TraceAllocationFollowupTimeout, (msg.getMonotonicTimestamp() - last_message_timestamp_).toUSec());
        }

        /*
         * Checking if request stage matches the expected stage
         */
        const uint8_t request_stage = detectRequestStage(msg);
        if (request_stage == InvalidStage)
        {
            trace(TraceAllocationBadRequest, msg.unique_id.size());
            return;             // Malformed request - ignore without resetting
        }

        const uint8_t expected_stage = getExpectedStage();
        if (expected_stage == InvalidStage)
        {
            UAVCAN_ASSERT(0);
            return;
        }

        if (request_stage != expected_stage)
        {
            trace(TraceAllocationUnexpectedStage, request_stage);
            return;             // Ignore - stage mismatch
        }

        const uint8_t max_expected_bytes =
            static_cast<uint8_t>(current_unique_id_.capacity() - current_unique_id_.size());
        UAVCAN_ASSERT(max_expected_bytes > 0);
        if (msg.unique_id.size() > max_expected_bytes)
        {
            trace(TraceAllocationBadRequest, msg.unique_id.size());
            return;             // Malformed request
        }

        /*
         * Updating the local state
         */
        for (uint8_t i = 0; i < msg.unique_id.size(); i++)
        {
            current_unique_id_.push_back(msg.unique_id[i]);
        }

        trace(TraceAllocationRequestAccepted, current_unique_id_.size());

        /*
         * Proceeding with allocation if possible
         * Note that single-frame CAN FD allocation requests will be delivered to the server even if it's not leader.
         */
        if (current_unique_id_.size() == current_unique_id_.capacity())
        {
            UAVCAN_TRACE("AllocationRequestManager", "Allocation request received; preferred node ID: %d",
                         int(msg.node_id));

            UniqueID unique_id;
            copy(current_unique_id_.begin(), current_unique_id_.end(), unique_id.begin());
            current_unique_id_.clear();

            {
                uint64_t event_agrument = 0;
                for (uint8_t i = 0; i < 8; i++)
                {
                    event_agrument |= static_cast<uint64_t>(unique_id[i]) << (56U - i * 8U);
                }
                trace(TraceAllocationExchangeComplete, static_cast<int64_t>(event_agrument));
            }

            handler_.handleAllocationRequest(unique_id, msg.node_id);
        }
        else
        {
            if (handler_.canPublishFollowupAllocationResponse())
            {
                publishFollowupAllocationResponse();
            }
            else
            {
                trace(TraceAllocationFollowupDenied, 0);
                current_unique_id_.clear();
            }
        }

        /*
         * It is super important to update timestamp only if the request has been processed successfully.
         */
        last_message_timestamp_ = msg.getMonotonicTimestamp();
    }
コード例 #2
0
void DynamicNodeIDClient::handleAllocation(const ReceivedDataStructure<protocol::dynamic_node_id::Allocation>& msg)
{
    /*
     * TODO This method can blow the stack easily
     */
    UAVCAN_ASSERT(preferred_node_id_.isValid());
    if (isAllocationComplete())
    {
        UAVCAN_ASSERT(0);
        terminate();
        return;
    }

    startPeriodic(getPeriod()); // Restarting the timer - Rule C
    UAVCAN_TRACE("DynamicNodeIDClient", "Request timer reset because of Allocation message from %d",
                 static_cast<int>(msg.getSrcNodeID().get()));

    // Rule D
    if (!msg.isAnonymousTransfer() &&
        msg.unique_id.size() > 0 &&
        msg.unique_id.size() < msg.unique_id.capacity() &&
        equal(msg.unique_id.begin(), msg.unique_id.end(), unique_id_))
    {
        // Filling the response message
        const uint8_t size_of_unique_id_in_response =
            min(protocol::dynamic_node_id::Allocation::MAX_LENGTH_OF_UNIQUE_ID_IN_REQUEST,
                static_cast<uint8_t>(msg.unique_id.capacity() - msg.unique_id.size()));

        protocol::dynamic_node_id::Allocation second_stage;
        second_stage.node_id = preferred_node_id_.get();
        second_stage.first_part_of_unique_id = false;

        second_stage.unique_id.resize(size_of_unique_id_in_response);

        copy(unique_id_ + msg.unique_id.size(),
             unique_id_ + msg.unique_id.size() + size_of_unique_id_in_response,
             second_stage.unique_id.begin());

        UAVCAN_ASSERT(equal(second_stage.unique_id.begin(),
                            second_stage.unique_id.end(),
                            unique_id_ + msg.unique_id.size()));

        // Broadcasting the response
        UAVCAN_TRACE("DynamicNodeIDClient", "Broadcasting 2nd stage: preferred ID: %d, size of unique ID: %d",
                     static_cast<int>(preferred_node_id_.get()), static_cast<int>(second_stage.unique_id.size()));
        const int res = dnida_pub_.broadcast(second_stage);
        if (res < 0)
        {
            dnida_pub_.getNode().registerInternalFailure("DynamicNodeIDClient request failed");
        }
    }

    // Rule E
    if (!msg.isAnonymousTransfer() &&
        msg.unique_id.size() == msg.unique_id.capacity() &&
        equal(msg.unique_id.begin(), msg.unique_id.end(), unique_id_) &&
        msg.node_id > 0)
    {
        allocated_node_id_ = msg.node_id;
        allocator_node_id_ = msg.getSrcNodeID();
        UAVCAN_TRACE("DynamicNodeIDClient", "Allocation complete, node ID %d provided by %d",
                     static_cast<int>(allocated_node_id_.get()), static_cast<int>(allocator_node_id_.get()));
        terminate();
        UAVCAN_ASSERT(isAllocationComplete());
    }
}