]> git.sesse.net Git - greproxy/blobdiff - rsdecoder.cpp
Merge branch 'master' of /srv/git.sesse.net/www/greproxy
[greproxy] / rsdecoder.cpp
index 20297bf53230e77e84bfd9bd2f8aab98c114b9b6..0a11541c377a595a1ce7cfcffff9421656817a6e 100644 (file)
@@ -1,23 +1,23 @@
 #include <stdio.h>
 #include <string.h>
 #include <arpa/inet.h>
+#include <fecpp.h>
 
 #include <map>
 #include "rsdecoder.h"
 #include "rs_parm.h"
 
-extern "C" {
-#include <fec.h>
-}
-
 #define RS_GROUP_HISTORY 3
 
 using namespace std;
 
 RSDecoder::RSDecoder(Sender *sender)
-       : sender(sender) {}
+       : sender(sender),
+         rs(RS_PAYLOAD_SIZE, RS_GROUP_SIZE)
+{
+}
 
-void RSDecoder::send_packet(uint16_t proto, const std::string &data, int incoming_seq)
+void RSDecoder::send_packet(uint16_t proto, const std::string &data, uint32_t incoming_seq)
 {
        int rs_group;
        if (proto == 0xffff) {
@@ -83,60 +83,49 @@ void RSDecoder::send_packet(uint16_t proto, const std::string &data, int incomin
                if (num_regular < RS_PAYLOAD_SIZE) {
                        // Piece the data back into the different RS groups.
                        vector<string> padded_packets;
-                       vector<int> missing_packets;
-                       for (int i = 0; i < RS_GROUP_SIZE; ++i) {
-                               int packet_num = (i < RS_PAYLOAD_SIZE) ? rs_group * RS_PAYLOAD_SIZE + i :
-                                       rs_group * RS_PAYLOAD_SIZE - 1 - (i - RS_PAYLOAD_SIZE);
+                       std::map<size_t, const fecpp::byte *> shares;
+                       for (const auto &packet_pair : group.packets) {
+                               uint32_t packet_seq = packet_pair.first;
+                               int share_num;
                                string p;
                                p.resize(max_length);
-                               const auto it = group.packets.find(packet_num);
-                               if (it == group.packets.end()) {
-                                       missing_packets.push_back(i);
-                               } else {
-                                       const GREPacket &packet = it->second;
+                               const GREPacket &packet = packet_pair.second;
+                               if (packet_seq >= rs_group * RS_PAYLOAD_SIZE) {
+                                       // Regular packet.
+                                       share_num = packet_seq - rs_group * RS_PAYLOAD_SIZE;
                                        uint16_t proto_be = htons(packet.proto);
                                        memcpy(&p[0], &proto_be, sizeof(uint16_t));
                                        uint16_t len_be = htons(packet.data.size());
                                        memcpy(&p[2], &len_be, sizeof(uint16_t));
                                        memcpy(&p[4], packet.data.data(), packet.data.size());
+                               } else {
+                                       // RS packet.
+                                       share_num = RS_PAYLOAD_SIZE + (rs_group * RS_PAYLOAD_SIZE - packet_seq - 1);
+                                       memcpy(&p[0], packet.data.data(), packet.data.size());
                                }
                                padded_packets.push_back(p);
-                       }
-
-                       // Now reconstruct the missing pieces.
-                       unsigned char ch[RS_GROUP_SIZE];
-                       for (int i = 0; i < max_length; ++i) {
-                               for (int j = 0; j < RS_GROUP_SIZE; ++j) {
-                                       ch[j] = padded_packets[j][i];
-                               }
-                               int ret = decode_rs_8(ch, &missing_packets[0], missing_packets.size(),
-                                       RS_PAD);
-                               if (ret == -1) {
-                                       printf("Failed reconstruction!\n");
-                                       // We might get more data later, so don't remove it.
-                                       return;
-                               }
-                               for (int j = 0; j < RS_GROUP_SIZE; ++j) {
-                                       padded_packets[j][i] = ch[j];
-                               }
+                               shares[share_num] = reinterpret_cast<const fecpp::byte *>(padded_packets.back().data());
                        }
 
                        // Output all packets we didn't have before. They will come
                        // out-of-order, which will be the job of the Reorderer to fix.
-                       for (int i = 0; i < RS_PAYLOAD_SIZE; ++i) {
-                               int packet_num = rs_group * RS_PAYLOAD_SIZE + i;
-                               if (group.packets.count(packet_num) != 0) {
+                       rs.decode(shares, max_length, [&](size_t share_num, size_t num_shares, const fecpp::byte data[], size_t len){
+                               if (shares.count(share_num)) {
                                        // Already had this packet.
-                                       continue;
+                                       return;
                                }
-                               const string &p = padded_packets[i];
+                               int packet_num = rs_group * RS_PAYLOAD_SIZE + share_num;
                                uint16_t proto_be, len_be;
-                               memcpy(&proto_be, &p[0], sizeof(uint16_t));
-                               memcpy(&len_be, &p[2], sizeof(uint16_t));
-                               string s(&p[4], &p[4 + ntohs(len_be)]);  // TODO: security
+                               memcpy(&proto_be, &data[0], sizeof(uint16_t));
+                               memcpy(&len_be, &data[2], sizeof(uint16_t));
+                               string s(&data[4], &data[4 + ntohs(len_be)]);  // TODO: security
                                sender->send_packet(ntohs(proto_be), s, packet_num);
-                               printf("Reconstructed packet %d\n", packet_num);
-                       }
+                               const unsigned char *ptr = &data[4];
+                               printf("Reconstructed packet %d (proto=0x%04x len=%d, data=%02x %02x %02x %02x %02x %02x %02x %02x)\n", packet_num,
+                                        ntohs(proto_be), ntohs(len_be),
+                                       ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6], ptr[7]);
+                               ++num_recovered_packets;
+                       });
                }
                
                group.done = true;