Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error correction for network packets (proof of concept) #266

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions code/qcommon/msg.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "q_shared.h"
#include "qcommon.h"
#include "../rscode/ecc.h"

static huffman_t msgHuff;

Expand Down Expand Up @@ -262,6 +263,31 @@ void MSG_WriteData( msg_t *buf, const void *data, int length ) {
}
}

void MSG_WriteDataWithECC( msg_t *buf, const void *data, int length ) {
int i;
char buf_copy[28];
char data_and_ecc[32];
for(i=0;i<length;i++) {
MSG_WriteByte(buf, ((byte *)data)[i]);
// copy the current byte in a buffer
buf_copy[i % 28] = ((byte *)data)[i];
// reached the size to generate an ecc, or we are at the end of the message
if i == 28 || i == (length - 1) {
// if end of message but the buffer is not full, we pad with 0s
if i == (length - 1) && (i % length) < 27 {
for(j=(i+1) % length;j<28;j++) {
buf_copy[j] = 0;
}
}
// generate ecc symbols (will be appended to the message)
encode_data(buf_copy, sizeof(buf_ecc), data_and_ecc);
for(j=28;j<sizeof(data_and_ecc);j++) {
MSG_WriteByte(buf, ((byte *)data_and_ecc)[i]);
}
}
}
}

void MSG_WriteShort( msg_t *sb, int c ) {
#ifdef PARANOID
if (c < ((short)0x8000) || c > (short)0x7fff)
Expand Down Expand Up @@ -510,6 +536,25 @@ void MSG_ReadData( msg_t *msg, void *data, int len ) {
}
}

void MSG_ReadDataWithECC( msg_t *msg, void *data, int length ) {
int i;
char data_and_ecc[32];
// Decode each codeword blocks
for(i=0;i<(int)(length/32);i++) {
// Read codeword (data + ecc symbols)
MSG_ReadData(msg, data_and_ecc, 32);
// Decode the syndromes
decode_data(data_and_ecc, sizeof(data_and_ecc);
// Check the syndrome, if not null, then there are errors
if (check_syndrome () != 0) {
// Correct errors
correct_errors_erasures (data_and_ecc, sizeof(data_and_ecc), 0, 0); // disable erasures detection because we have no idea where the erasures might be, so just do error correction
// Copy the corrected message to data (ie, the first 28 bytes)
for(j=0;j<28;j++)
((byte *)data)[i*28+j] = data_and_ecc[j];
}
}

// a string hasher which gives the same hash value even if the
// string is later modified via the legacy MSG read/write code
int MSG_HashKey(const char *string, int maxlen) {
Expand Down
23 changes: 22 additions & 1 deletion code/qcommon/net_chan.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ void Netchan_Init( int port ) {
showpackets = Cvar_Get ("showpackets", "0", CVAR_TEMP );
showdrop = Cvar_Get ("showdrop", "0", CVAR_TEMP );
qport = Cvar_Get ("net_qport", va("%i", port), CVAR_INIT );
initialize_ecc(); // initialize error correction lib
}

/*
Expand Down Expand Up @@ -211,7 +212,9 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {

chan->outgoingSequence++;

MSG_WriteData( &send, data, length );
// Write data
//MSG_WriteData( &send, data, length );
MSG_WriteDataWithECC( &send, data, length );

// send the datagram
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remoteAddress );
Expand Down Expand Up @@ -245,6 +248,10 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
int sequence;
int fragmentStart, fragmentLength;
qboolean fragmented;
// for error correction
msg_t corrected_msg;
int bak_readcount = 0;
int bak_bit = 0;

// XOR unscramble all data in the packet after the header
// Netchan_UnScramblePacket( msg );
Expand Down Expand Up @@ -277,6 +284,20 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
return qfalse;
}

// Apply error correction on message data if not fragmented (FIXME: implement also for fragmented packets)
if ( !fragmented ) {
// Store current cursor position
bak_readcount = msg->readcount;
bak_bit = msg->bit;
// Read and ecc decode message content
MSG_ReadDataWithECC( msg, corrected_msg, sizeof(msg));
// Replace current message with the corrected one, and restore cursor position
Q_strncpyz(msg, corrected_msg, MAX_PACKETLEN);
MSG_BeginReadingOOB( msg );
msg->readcount = bak_readcount;
msg->bit = bak_bit;
}

// read the fragment information
if ( fragmented ) {
fragmentStart = MSG_ReadShort( msg );
Expand Down
10 changes: 10 additions & 0 deletions code/rscode/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
* (C) Henry Minsky (hqm@alum.mit.edu) 1991-2009
*
* This software library is licensed under terms of the GNU GENERAL
* PUBLIC LICENSE. [See file gpl.txt]
*
* Commercial licensing is available under a separate license, please
* contact author for details.
*
* Latest source code and other info at http://rscode.sourceforge.net

50 changes: 50 additions & 0 deletions code/rscode/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Makefile for Cross Interleaved Reed Solomon encoder/decoder
#
# (c) Henry Minsky, Universal Access 1991-1996
#

RANLIB = ranlib
AR = ar


VERSION = 1.0
DIRNAME= rscode-$(VERSION)


CC = gcc
# OPTIMIZE_FLAGS = -O69
DEBUG_FLAGS = -g
CFLAGS = -Wall -Wstrict-prototypes $(OPTIMIZE_FLAGS) $(DEBUG_FLAGS) -I..
LDFLAGS = $(OPTIMIZE_FLAGS) $(DEBUG_FLAGS)

LIB_CSRC = rs.c galois.c berlekamp.c crcgen.c
LIB_HSRC = ecc.h
LIB_OBJS = rs.o galois.o berlekamp.o crcgen.o

TARGET_LIB = libecc.a
TEST_PROGS = example

TARGETS = $(TARGET_LIB) $(TEST_PROGS)

all: $(TARGETS)

$(TARGET_LIB): $(LIB_OBJS)
$(RM) $@
$(AR) cq $@ $(LIB_OBJS)
if [ "$(RANLIB)" ]; then $(RANLIB) $@; fi

example: example.o galois.o berlekamp.o crcgen.o rs.o
gcc -o example example.o -L. -lecc

clean:
rm -f *.o example libecc.a
rm -f *~

dist:
(cd ..; tar -cvf rscode-$(VERSION).tar $(DIRNAME))

depend:
makedepend $(SRCS)

# DO NOT DELETE THIS LINE -- make depend depends on it.

27 changes: 27 additions & 0 deletions code/rscode/README
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
RSCODE version 1.3

See the files

config.doc documentation of some compile time parameters
rs.doc overview of the Reed-Solomon coding program
rs.man a man page, slightly outdated at this point
example.c a simple example of encoding,decoding, and error correction

Makefile should work on a Sun system, may require GNU make.


Henry Minsky
hqm@alum.mit.edu


* (c) Henry Minsky (hqm@alum.mit.edu) 1991-2009
*
* This software library is licensed under terms of the GNU GENERAL
* PUBLIC LICENSE. (See gpl.txt)
*
* Commercial licensing is available under a separate license, please
* contact author for details.
*
* Source code is available at http://rscode.sourceforge.net


Loading