Type 28 handler logic: /* Aries_base+0x6780 */ void PerformanceCounter::Initialize(TimingContext *timing_ctx, const uint8_t *aries_payload) { debug_print("PerformanceCounter::Initialize"); timing_ctx->histogram_width = aries_payload[0]; timing_ctx->unknown1 = aries_payload[1]; timing_ctx->unknown2 = aries_payload[2]; timing_ctx->bin_width = timing_ctx->histogram_width / 10; if (timing_ctx->timing_initialized) { send_timing_report(); memset(timing_ctx, 0, sizeof(*timing_ctx)); } timing_ctx->timing_initialized = (timing_ctx->histogram_width != 0 && timing_ctx->unknown1 != 0 && timing_ctx->unknown2 != 0); } Type 27 handler logic: /* Aries_base+0x64e0 */ void PerformanceCounter::ProcessTimingPing(TimingContext *timing_ctx, const uint8_t *aries_payload) { unsigned elapsed_time, divisor, bin_idx; debug_print("PerformanceCounter::ProcessTimingPing"); if (!timing_ctx->timing_initialized) return; clock_drift = abs(GetTickCount() - aries_payload[0]); timing_ctx->total_clock_drift += clock_drift; divisor = max(timing_ctx->bin_width, 1); bin_idx = min(elapsed_time / divisor, 20); timing_ctx->histogram[bin_idx]++; if (clock_drift > timing_ctx->histogram_width) print_timing_error(); } Type 27 packet format: * Timestamp: A 4-byte unsigned integer Type 28 packet format: * Histogram width: A 4-byte unsigned integer * Unknown: 4 bytes * Unknown: 4 bytes Type 29 (timing report) packet format: * Unknown: 88 bytes set to zero * Histogram: 84 bytes (A 4-byte unsigned integer for all 21 bins in the histogram) * Total elapsed time: A 4-byte unsigned integer The Type 27 and 28 Aries packets can be used to measure the variance in one-way latency. The server can send a Type 28 packet to begin a timing test with a desired histogram width in milliseconds. (There are 21 bins in this histogram.) When a timing test is running, the server sends one or more Type 27 packets, each containing the time that the server sent the packet. For each Type 27 packet, the client will compare the time passed in the packet with its own current time, find the absolute difference, and increment the corresponding bin in the histogram by 1. Finally, the server sends another Type 28 packet to end the timing test, and the client will respond with a Type 29 packet containing the test results, which include the histogram and the total clock drift over all tests. To determine the server->client variance, the server should perform the following steps: * The server should synchronize its clock such that each packet it sends to the client specifies a value that, once received by the client, matches the client's current time. To do this, the server should first find the current time (call it t0) and then send a Type 22 packet. The client will respond with a Type 21 packet containing its current time (call it t1) in the Aries header. Note that the server can convert its time (before the server->client trip) into the client's time (after the server->client trip) by adding an adjustment factor of t1-t0. * The server should then start a timing test by sending a Type 28 packet with a desired histogram width, unknown1, and unknown2. Then, the server should send one or more Type 27 packets, each time with the argument set to the current time plus the adjustment factor. To end the timing test, the server should finally send another Type 28 packet with 0 for all 3 arguments. The client will respond with a Type 29 packet with a histogram which approximates the distribution in server->client latency. The variance of the server->client latency can then be calculated from the histogram. Assuming the true mean of the latency is not known, we will use Bessel's correction: x_bar = sum(k=1 to 21 of histogram[k]*(k*bin_width)) sigma_squared_hat = 1/(num_tests - 1)*sum(k=1 to 21 of histogram[k]*(k*bin_width - x_bar)^2) It turns out that this timing test is not useful for finding latency; it is only useful for determining variance in the latency. To simply determine round-trip latency, the server should simply use the Type 22 packet as a "ping" packet: that is, find the current time (call it t0), send a Type 22 packet, wait for a response, and find the new current time (call it t1). The round-trip latency is given by t1-t0.