This adds support for two serialization formats for complex data types:
- Protobuf for complex objects with variable length internals that need forward and backward wire compatibility (lower speed, more flexible)
- Raw struct (ByteBuffer-style) for fixed-length objects (higher speed, less flexible)
Deserialization can be done either by creating a new object (for immutable objects) or overwriting the contents of an existing object (for mutable objects).
Implementing classes should provide inner classes that implement the Protobuf or Struct interface (in Java) or specialize the wpi::Protobuf or wpi::Struct struct (in C++). It is possible for classes to implement both. If the class itself does not implement serialization, it's possible for third parties/users to provide an implementation instead.
Uses the Google protobuf implementation for C++ and the QuickBuffers alternative protobuf implementation for Java.
The object was being destroyed due to the error handling path.
Instead, defer to the next loop cycle using a one-shot timer.
Properly handle error return values from Send functions.
Fix UB in accessing one past the end of a vector.
std::remove_if() is destructive--it can assume the removed elements are
not used, but NetworkOutgoingQueue needs them to stay intact to be moved
to a different queue. Use std::stable_partition() instead.
- Utilize TrySend to properly backpressure network traffic
- Split updates into reasonable sized frames using WS fragmentation
- Use WS pings for network aliveness (requires 4.1 protocol revision)
- Measure RTT only at start of connection, rather than periodically
(this avoids them being affected by other network traffic)
- Refactor network queue
- Refactor network ping, ping from server as well
- Improve meta topic performance
- Implement unified approach for network value updates (currently client and server use very different approaches) that respects requested subscriber update frequency
This adds a new protocol version (4.1) due to WS bugs in prior versions.
Previously this was unlimited, which could result in holding on to a
large amount of memory if the connection got backlogged or a burst of
data transmission occurred.
The algorithm being used for scanning outgoing messages was O(n^2)
because it did a full linear search and then appended. This scan is
performed for each client. If there is a burst of outgoing changes, the
outgoing queue can get quite deep all at once and this scan can be very
slow. Replacing with a map fixes this.
There's a spec difference between NT4 and datalog for integers; NT4 uses
"int", datalog uses "int64". We were using "int" for datalog as well.
Also add backwards compatibility support to datalogtool for treating
"int" as "int64".
Previously the timeout was 10 times the update rate, so with low update
rates it could be as small as 50 ms, causing spurious disconnects when
large or many topics were published.
Previously, a setDefault() on the server could override a client doing a
real set() if the time offset between client and server was negative,
resulting in a negative timestamp from the client. This is a not
uncommon situation with robot code, as the robot code always starts at
time 0, so any clients that set values earlier (in real time) would have
negative timestamps.
Also improve special casing of 0 in the transmit side to make sure a
normal timestamp will never get sent as 0.