Skip to content

Commit 5fc14ba

Browse files
committed
Sender: Pluggable fec methods
1 parent 933f511 commit 5fc14ba

File tree

5 files changed

+122
-27
lines changed

5 files changed

+122
-27
lines changed

common/structs.h

+16
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,18 @@ typedef struct {
2121
} __attribute__ ((packed)) FecPacket;
2222

2323

24+
//A serial of 0 means something special: it defines the FEC parameters in use.
25+
typedef struct {
26+
uint16_t k;
27+
uint16_t n;
28+
uint8_t fecAlgoId;
29+
} __attribute__ ((packed)) FecDesc;
30+
31+
32+
#define FEC_ID_PARITY 0 //Simple parity addition
33+
#define FEC_ID_RS 1 //Reed-Solomon with tsd's code
34+
35+
2436
//Randomly chosen
2537
#define SERDES_MAGIC 0x1A014AF5
2638

@@ -113,3 +125,7 @@ typedef struct {
113125
} __attribute__ ((packed)) BDPacketChange;
114126

115127

128+
/*
129+
130+
*/
131+

server/Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
OBJS=main.o sender.o fec.o serdes.o ../common/crc16.o sha256.o uECC.o sign-ed25519.o packetloss.o hlmux.o
1+
OBJS=main.o sender.o fec.o serdes.o ../common/crc16.o sha256.o uECC.o sign-ed25519.o packetloss.o hlmux.o fec_parity.o
22
TARGET=bppsender
33
CFLAGS=-ggdb -std=gnu99 -I ../common -I ../micro-ecc -I ../sha256 -ggdb -I ../ed25519/src
44
LDFLAGS=../ed25519/src/libed25519.a

server/fec.c

+36-26
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@ parity packet.
1515
#include "sendif.h"
1616
#include "structs.h"
1717
#include <time.h>
18+
#include "fec.h"
1819

19-
//Emit a parity packet every FEC_M packets
20-
#define FEC_M 3
20+
extern FecGenerator fecGenParity;
21+
22+
static FecGenerator *gens[]={
23+
&fecGenParity,
24+
NULL
25+
};
26+
27+
static FecGenerator *currGen=NULL;
28+
29+
static int currK, currN;
2130

2231
static int sendMaxPktLen;
2332
static SendCb *sendCb;
2433
static int serial=0;
25-
static uint8_t *parPacket;
2634

2735
static time_t tsLastSaved;
2836

@@ -31,50 +39,52 @@ static time_t tsLastSaved;
3139
void fecInit(SendCb *cb, int maxlen) {
3240
sendCb=cb;
3341
sendMaxPktLen=maxlen;
34-
parPacket=malloc(maxlen);
35-
memset(parPacket, 0, maxlen);
3642
char buff[128];
3743
FILE *f=fopen(TSFILE, "r");
3844
if (f!=NULL) {
3945
fgets(buff, 127, f);
4046
serial=atoi(buff);
4147
fclose(f);
4248
}
49+
if (serial==0) serial=1; //because serial==0 is special
4350
tsLastSaved=time(NULL);
51+
currGen=gens[0];
52+
currK=3;
53+
currN=4;
54+
currGen->init(currK, currN, maxlen);
4455
}
4556

46-
47-
void fecSend(uint8_t *packet, size_t len) {
48-
int fecMaxPacketLen=(sendMaxPktLen-sizeof(FecPacket)); //max data in a fec packet
49-
FecPacket *p=malloc(sizeof(FecPacket)+fecMaxPacketLen);
57+
void fecSendFecced(uint8_t *packet, size_t len) {
58+
FecPacket *p=malloc(sizeof(FecPacket)+len);
5059
p->serial=htonl(serial);
5160
memcpy(p->data, packet, len);
52-
//Clear rest of packet to not leak stuff
53-
memset(p->data+len, 0, fecMaxPacketLen-len);
54-
//Add packet to parity
55-
for (int x=0; x<fecMaxPacketLen; x++) parPacket[x]^=p->data[x];
56-
sendCb((uint8_t*)p, sendMaxPktLen);
61+
sendCb((uint8_t*)p, sizeof(FecPacket)+len);
5762
serial++;
58-
//See if it's time to send the parity packet already.
59-
if ((serial % (FEC_M+1)) == FEC_M) {
60-
//Yes it is! Re-use p to send parity data.
61-
p->serial=htonl(serial);
62-
memcpy(p->data, parPacket, fecMaxPacketLen);
63-
sendCb((uint8_t*)p, sendMaxPktLen);
64-
serial++;
65-
//Zero out parity array for next set of packets.
66-
memset(parPacket, 0, fecMaxPacketLen);
67-
}
68-
//Save timestamp in case of crash/quit every 10 secs
63+
free(p);
64+
}
65+
66+
67+
void fecSend(uint8_t *packet, size_t len) {
68+
currGen->send(packet, len, serial, fecSendFecced);
69+
//Save timestamp every 10 secs in case of crash/quit
6970
if (time(NULL)-tsLastSaved > 10) {
7071
FILE *f;
7172
f=fopen(TSFILE".tmp", "w");
7273
fprintf(f, "%d", (int)serial);
7374
fclose(f);
7475
rename(TSFILE".tmp", TSFILE);
7576
tsLastSaved=time(NULL);
77+
78+
//Semi-hack: We use the same timer to send out the FEC parameters
79+
FecPacket *p=malloc(sizeof(FecPacket)+sizeof(FecDesc));
80+
p->serial=htonl(0);
81+
FecDesc *dsc=(FecDesc*)p->data;
82+
dsc->k=htons(currK);
83+
dsc->n=htons(currN);
84+
dsc->fecAlgoId=currGen->genId;
85+
sendCb(p, sizeof(FecPacket)+sizeof(FecDesc));
86+
free(p);
7687
}
77-
free(p);
7888
}
7989

8090

server/fec.h

+17
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,23 @@
33

44
#include "sendif.h"
55

6+
typedef void (*FecSendFeccedPacket)(uint8_t *packet, size_t len);
7+
8+
//WARNING: it is assumed that every packet sent through these functions will have length=maxsize
9+
//Emit n packets out for every k packets in
10+
typedef int (*FecGeneratorInit)(int k, int n, int maxsize);
11+
typedef int (*FecGeneratorSend)(uint8_t *packet, size_t len, int serial, FecSendFeccedPacket sendfn);
12+
typedef void (*FecGeneratorDeinit)();
13+
typedef struct {
14+
const char *name;
15+
const char *desc;
16+
const int genId;
17+
FecGeneratorInit init;
18+
FecGeneratorSend send;
19+
FecGeneratorDeinit deinit;
20+
} FecGenerator;
21+
22+
623
void fecInit(SendCb *cb, int maxlen);
724
int fecGetMaxPacketLength();
825
void fecSend(uint8_t *packet, size_t len);

server/fec_parity.c

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
#include <stdint.h>
2+
#include <stdlib.h>
3+
#include <stdio.h>
4+
#include <string.h>
5+
#include "sendif.h"
6+
#include "structs.h"
7+
#include "fec.h"
8+
9+
10+
static uint8_t *parPacket;
11+
int parM; //after how many packets to send a parity packet
12+
int biggestLen=0;
13+
14+
int parInit(int k, int n, int maxsize) {
15+
if (n!=k+1) return 0;
16+
parM=k;
17+
parPacket=malloc(maxsize);
18+
memset(parPacket, 0, maxsize);
19+
biggestLen=0;
20+
return 1;
21+
}
22+
23+
int parSend(uint8_t *packet, size_t len, int serial, FecSendFeccedPacket sendFn) {
24+
//Add to parity packet
25+
for (int i=0; i<len; i++) parPacket[i]^=packet[i];
26+
if (biggestLen<len) biggestLen=len;
27+
//Send packet
28+
sendFn(packet, len);
29+
//See if we need to send parity packet
30+
int p=serial%(parM+1);
31+
if (p==parM) {
32+
sendFn(parPacket, biggestLen);
33+
memset(parPacket, 0, biggestLen);
34+
biggestLen=0;
35+
}
36+
return 1;
37+
}
38+
39+
void parDeinit() {
40+
free(parPacket);
41+
return;
42+
}
43+
44+
FecGenerator fecGenParity={
45+
.name="parity",
46+
.desc="Single parity packet. N must be K+1; K can be arbitrary.",
47+
.genId=FEC_ID_PARITY,
48+
.init=parInit,
49+
.send=parSend,
50+
.deinit=parDeinit,
51+
};
52+

0 commit comments

Comments
 (0)