]> git.sesse.net Git - greproxy/blobdiff - rsencoder.cpp
Merge branch 'master' of /srv/git.sesse.net/www/greproxy
[greproxy] / rsencoder.cpp
index d98a13caf16cb9612965915a501f833a820cc96a..e4e9481f8b35c61715a3d2ba1966eaa8c414fa83 100644 (file)
@@ -5,9 +5,7 @@
 #include <stdlib.h>
 #include <sys/select.h>
 #include <sys/socket.h>
-extern "C" {
-#include <fec.h>
-}
+#include <fecpp.h>
 
 #include "reorderer.h"
 #include "rsencoder.h"
@@ -18,12 +16,12 @@ extern "C" {
 using namespace std;
        
 RSEncoder::RSEncoder(Sender *sender) 
-       : sender(sender)
+       : sender(sender),
+         rs(RS_PAYLOAD_SIZE, RS_GROUP_SIZE)
 {
-       rs = init_rs_char(RS_SYM_SIZE, RS_GF_POLY, 1, 1, RS_PARITY_SIZE, RS_PAD);
 }
 
-void RSEncoder::send_packet(uint16_t proto, const std::string &data, int incoming_seq)
+void RSEncoder::send_packet(uint16_t proto, const std::string &data, uint32_t incoming_seq)
 {
        if (!packet_history.empty() &&
            incoming_seq <= packet_history.back().seq) {
@@ -36,7 +34,17 @@ void RSEncoder::send_packet(uint16_t proto, const std::string &data, int incomin
                // Received an unfinished group.
                packet_history.clear();
        }
-       sender->send_packet(proto, data, incoming_seq);
+       bool debug_drop_packet = false;  // For testing only.
+       if (incoming_seq % RS_PAYLOAD_SIZE == 3) {
+               //debug_drop_packet = true;
+       }
+       if (debug_drop_packet) {
+               const unsigned char *ptr = reinterpret_cast<const unsigned char *>(data.data());
+               printf("DEBUG: Dropping packet seq=%u proto=0x%04x len=%d data=%02x %02x %02x %02x %02x %02x %02x %02x ...\n",
+                       incoming_seq, proto, data.size(), ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
+       } else {
+               sender->send_packet(proto, data, incoming_seq);
+       }
        packet_history.emplace_back(GREPacket{incoming_seq, proto, data});
        if (packet_history.size() == RS_PAYLOAD_SIZE) {
                finish_group();
@@ -51,7 +59,9 @@ void RSEncoder::finish_group()
                max_length = max<int>(max_length, packet_history[i].data.size());
        }
 
-       vector<string> padded_packets;
+       string padded_packets;
+       padded_packets.reserve((max_length + 4) * packet_history.size());
+       // TODO: RS_PAD
        for (int i = 0; i < packet_history.size(); ++i) {
                string p;
                p.resize(max_length + 4);
@@ -61,37 +71,22 @@ void RSEncoder::finish_group()
                uint16_t len_be = htons(packet_history[i].data.size());
                memcpy(&p[2], &len_be, sizeof(uint16_t));
                memcpy(&p[4], packet_history[i].data.data(), packet_history[i].data.size());
-               padded_packets.push_back(p);
+               padded_packets += p;
        }
 
-       // Now construct RS packets.
-       vector<string> rs_packets;
-       for (int i = 0; i < RS_PARITY_SIZE; ++i) {
-               string p;
-               p.resize(max_length + 4);
-               memset(&p[0], 0, max_length + 4);
-               rs_packets.push_back(p);
-       }
-       string data, parity;
-       data.resize(RS_PAYLOAD_SIZE);
-       parity.resize(RS_PARITY_SIZE);
-       for (int i = 0; i < max_length + 4; ++i) {
-               for (int j = 0; j < packet_history.size(); ++j) {
-                       data[j] = packet_history[j].data[i];
-               }
-               encode_rs_char(rs,
-                              reinterpret_cast<unsigned char *>(&data[0]),
-                              reinterpret_cast<unsigned char *>(&parity[0]));
-               for (int j = 0; j < RS_PARITY_SIZE; ++j) {
-                       rs_packets[j][i] = parity[j];
-               }
-       }
+       // Now construct and send RS packets.
+       rs.encode(reinterpret_cast<const fecpp::byte*>(padded_packets.data()),
+                 padded_packets.size(),
+                 [&](size_t packet_num, size_t num_packets, const fecpp::byte data[], size_t size) {
+                       // The first N packets are just the original ones; ignore them.
+                       if (packet_num < RS_PAYLOAD_SIZE) {
+                               return;
+                       }
 
-       // Actually send the RS packets.
-       int start_seq = packet_history[0].seq - 1;
-       for (int i = 0; i < RS_PARITY_SIZE; ++i) {
-               sender->send_packet(0xffff, rs_packets[i], start_seq - i);
-       }
+                       const char *sdata = reinterpret_cast<const char *>(data);
+                       uint32_t start_seq = packet_history[0].seq - 1;
+                       sender->send_packet(0xffff, string(sdata, size), start_seq - (packet_num - RS_PAYLOAD_SIZE));
+               });
        
        packet_history.clear();
 }