3 #include <netinet/in.h>
6 #include <sys/select.h>
7 #include <sys/socket.h>
10 #include "reorderer.h"
11 #include "rsencoder.h"
18 RSEncoder::RSEncoder(Sender *sender)
20 rs(RS_PAYLOAD_SIZE, RS_GROUP_SIZE)
24 void RSEncoder::send_packet(uint16_t proto, const std::string &data, uint32_t incoming_seq)
26 if (!packet_history.empty() &&
27 incoming_seq <= packet_history.back().seq) {
28 // Reorderer should have done this for us.
31 if (!packet_history.empty() &&
32 incoming_seq / RS_PAYLOAD_SIZE !=
33 packet_history.back().seq / RS_PAYLOAD_SIZE) {
34 // Received an unfinished group.
35 packet_history.clear();
37 bool debug_drop_packet = false; // For testing only.
38 if (incoming_seq % RS_PAYLOAD_SIZE == 3) {
39 //debug_drop_packet = true;
41 if (debug_drop_packet) {
42 const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data.data());
43 printf("DEBUG: Dropping packet seq=%u proto=0x%04x len=%d data=%02x %02x %02x %02x %02x %02x %02x %02x ...\n",
44 incoming_seq, proto, data.size(), ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
46 sender->send_packet(proto, data, incoming_seq);
48 packet_history.emplace_back(GREPacket{incoming_seq, proto, data});
49 if (packet_history.size() == RS_PAYLOAD_SIZE) {
54 void RSEncoder::finish_group()
56 // Our RS packets need to have the same max length as the longest one.
58 for (int i = 0; i < packet_history.size(); ++i) {
59 max_length = max<int>(max_length, packet_history[i].data.size());
62 string padded_packets;
63 padded_packets.reserve((max_length + 4) * packet_history.size());
65 for (int i = 0; i < packet_history.size(); ++i) {
67 p.resize(max_length + 4);
68 memset(&p[0], 0, max_length + 4);
69 uint16_t proto_be = htons(packet_history[i].proto);
70 memcpy(&p[0], &proto_be, sizeof(uint16_t));
71 uint16_t len_be = htons(packet_history[i].data.size());
72 memcpy(&p[2], &len_be, sizeof(uint16_t));
73 memcpy(&p[4], packet_history[i].data.data(), packet_history[i].data.size());
77 // Now construct and send RS packets.
78 rs.encode(reinterpret_cast<const fecpp::byte*>(padded_packets.data()),
79 padded_packets.size(),
80 [&](size_t packet_num, size_t num_packets, const fecpp::byte data[], size_t size) {
81 // The first N packets are just the original ones; ignore them.
82 if (packet_num < RS_PAYLOAD_SIZE) {
86 const char *sdata = reinterpret_cast<const char *>(data);
87 uint32_t start_seq = packet_history[0].seq - 1;
88 sender->send_packet(0xffff, string(sdata, size), start_seq - (packet_num - RS_PAYLOAD_SIZE));
91 packet_history.clear();