Fix log sorting for good

Unfortunately, this is really hard to split up, so a bunch of stuff
happens at once.

When a message is sent from node A -> node B, add support for sending
that timestamp back from node B to node A for logging.

    {
      "name": "/pi1/aos",
      "type": "aos.message_bridge.Timestamp",
      "source_node": "pi1",
      "frequency": 10,
      "max_size": 200,
      "destination_nodes": [
        {
          "name": "pi2",
          "priority": 1,
          "timestamp_logger": "LOCAL_AND_REMOTE_LOGGER",
          "timestamp_logger_nodes": ["pi1"]
        }
      ]
    },

This gives us a way to log enough information on node A such that
everything is self contained.  We know all the messages we sent to B,
and when they got there, so we can recreate the time offset and replay
the node.

This data is then published over
   { "name": "/aos/remote_timestamps/pi2", "type": ".aos.logger.MessageHeader"}

The logger then treats that channel specially and log the contents
directly as though the message contents were received on the remote
node.

This (among other things) exposes log sorting problems.  Use our fancy
new infinite precision noncausal filter to estimate time precise enough
to actually order events.  This gets us down to 2-3 ns of error due to
integer precision.

Change-Id: Ia843c5176a2c4efc227e669c07d7bb4c7cbe7c91
diff --git a/aos/configuration.h b/aos/configuration.h
index 4ada459..fbd9cff 100644
--- a/aos/configuration.h
+++ b/aos/configuration.h
@@ -57,6 +57,14 @@
                                  const Node *node) {
   return GetChannel(&config.message(), name, type, application_name, node);
 }
+template <typename T>
+inline const Channel *GetChannel(const Configuration *config,
+                                 const std::string_view name,
+                                 const std::string_view application_name,
+                                 const Node *node) {
+  return GetChannel(config, name, T::GetFullyQualifiedName(), application_name,
+                    node);
+}
 // Convenience wrapper for getting a channel from a specified config if you
 // already have the name/type in a Channel object--this is useful if you Channel
 // object you have does not point to memory within config.