# Lower-Latency Screen Updates over QUIC with Forward Error Correction
## 4 Design and Implementation
### Adding FEC to ngtcp2 [8]  
In our previous paper on applying FEC for HTTP resources selectively over QUIC to reduce page-load time [8], we described our implementation of adding the support of an open-source FEC library called OpenFEC [9] over ngtcp2/nghttp3. In this paper, we can take advantage of our previous implementation for screen update workload as well, because we send each screen update over a QUIC stream. Therefore, each update can be seen as a resource that we can apply FEC on. Here, we briefly explain our implementation of adding FEC over QUIC. We implemented both the encoding and decoding procedures at the HTTP layer, within the nghttp3 library [13], to minimize the modification to QUIC as much as possible. We imported the OpenFEC library into nghttp3 to use its encoding/decoding functions. The OpenFEC library supports three erasure codes: (1) two-dimensional XOR matrix, (2) Reed-Solomon (RS), and (3) Low-Density Parity Check (LDPC). For each code, there are three main parameters: (1) \(k\) is the number of original symbols, (2) \(n\) is the summation of the number of original and redundant symbols, and (3) the symbol size. In other words, \((n-k)\times\textsc{symbol\_size}\) is the extra overhead of FEC or redundant data that need to be sent along with the original data to be used for loss recovery at the destination. In this paper, we used RS for all of our experiments. The OpenFEC library developers recommended RS when \(n\) is less than 255 and LDPC for larger values of \(n\). We tested \(k=100\) and \(n=\{103,105,110\}\) for different redundancy rates based on the packet-loss rates, but tuning for other values of \(n\) and \(k\) based on dynamic packet-loss monitoring and an extensive comparison of different FEC methods such as RS and LDPC remains as future work. Fortunately, ngtcp2 supports the Extensible Prioritization Scheme [29], so the client can set a parameter called \(u\) for the urgency of each resource. \(u=0\) means the highest urgency, and \(u=7\) means the lowest urgency. In our implementation, if a resource receives a value less than 3 for \(u\), we apply FEC to that as a high-priority resource, for 3 and largervalues, we do not apply FEC. In this way, we can enable and disable FEC for the partial delivery mode and study the impact of this through the evaluation discussed in Section 6. Figure 4 shows an example of running the HTTP/3 client of ngtcp2 to request two updates with enabled FEC (U1 and U2). $./client -q 192.168.1.1 4444 [[https://192.168.1.1:4444/U1?u=0](https://192.168.1.1:4444/U1?u=0)]([https://192.168.1.1:4444/U1?u=0](https://192.168.1.1:4444/U1?u=0)) [[https://192.168.1.1:4444/U2?u=0](https://192.168.1.1:4444/U2?u=0)]([https://192.168.1.1:4444/U2?u=0](https://192.168.1.1:4444/U2?u=0))  
For the scenario in Figure 4, the server would know that _U1_ and _U2_ need encoding based on their \(u\) values. The server calls the encoder and sends redundant frames after the original frames/messages. At the client side, we need to process the frames in arrival order to be able to apply decoding to recover any lost original frames. However, unmodified QUIC (as a reliable protocol) only sends the data in total order to the HTTP client within each stream. Therefore, the only part that we modified in QUIC layer implementation of ngtcp2 was adding a new user-level callback to be able to receive the QUIC frames in arrival order at the HTTP layer so we could try decoding to recover lost frames and not wait for the retransmissions at the end of the download. Whenever the decoder finishes recovering the whole update, the client can use ngtcp2_conn_shutdown_stream_read() to inform the server to stop sending. There can be some lost frames in the middle of the transfer, for which we have enough time to receive their retransmissions by the end of the download of the update, and there is no need for FEC recovery. However, the lost frames in the last cwnd could benefit from FEC recovery and reduce download completion time by an RTT.