sping
Program for measuring asymmetric latencies.
This is a reimplementation in Ruby of the reference implementation of the sping protocol in Go. The program provides both the client and server part to measure asymmetric latencies and asymmetric packet loss between two peers.
Protocol
The protocol consists of three phases:
- A TCP handshake
- A UDP handshake
- Sending the pings
The TCP handshake is performed first. Here the peers negotiate a session ID. To do this, the client sends a request to the server and then invites it to a session. If the server accepts the invitation, it sends a session ID to the client. This is used to uniquely identify the connection between the peers. For example, a peer may change its port or IP address. The session ID is used so that the peers can continue to identify each other. The session is activated at the end of the TCP handshake.
A UDP handshake is then performed. In this, the client sends a UDP packet, which is encoded with MessagePack, to the server. The server sends the packet back to the client for confirmation. One of the purposes of this is to punch a hole in a firewall so that it allows UDP packets between the peers. After a successful UDP handshake, the session is double activated. Only then does the sending of ping packets begin.
Finally, the peers send pings to each other (in this case UDP packets containing time messages). These time messages contain, among other things, the time at which the message was sent, but also the last 32 time messages received from the peer. This information can be used to determine both the asymmetric latency and the asymmetric packet loss.