#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"
#include <algorithm>
using namespace std;
+
+RSEncoder::RSEncoder(Sender *sender)
+ : sender(sender),
+ rs(RS_PAYLOAD_SIZE, RS_GROUP_SIZE)
+{
+}
void RSEncoder::send_packet(uint16_t proto, const std::string &data, int incoming_seq)
{
// 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=%d 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();
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);
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_8(reinterpret_cast<unsigned char *>(&data[0]),
- reinterpret_cast<unsigned char *>(&parity[0]),
- RS_PAD);
- 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);
+ int start_seq = packet_history[0].seq - 1;
+ sender->send_packet(0xffff, string(sdata, size), start_seq - (packet_num - RS_PAYLOAD_SIZE));
+ });
packet_history.clear();
}