From: Andre Noll Date: Sun, 23 May 2010 17:21:02 +0000 (+0200) Subject: fecdec_filter: Detect and ingore duplicate slices. X-Git-Tag: v0.4.3~20^2 X-Git-Url: http://git.tue.mpg.de/?a=commitdiff_plain;h=04d57a4d05ce0a0f8d16c32d14d056e312527808;p=paraslash.git fecdec_filter: Detect and ingore duplicate slices. This introduces a bit array to keep track of the slices of a FEC group that have been received so far. This allows to quickly look up whether the current slice is already present in the FEC group, in which case we simply ignore it. This avoids errors of the kind unregister_task: unregistering fecdec (slot 0) (invalid index vector) which have been observed with the UDP transport. The patch also cleans up add_slice() a bit: It replaces the calls to para_malloc() and memset() by a simple call to para_calloc() and initializes slice_num earlier so that it can be used throughout the function. --- diff --git a/fecdec_filter.c b/fecdec_filter.c index 195dbaae..939f7e3d 100644 --- a/fecdec_filter.c +++ b/fecdec_filter.c @@ -61,6 +61,8 @@ struct fecdec_group { struct fec_header h; /** How many slices received so far. */ int num_received_slices; + /** Bitmap of received slices. */ + uint8_t received_slices[32]; /** The size of the \a idx and the \a data arrays below. */ int num_slices; /** Array of indices of the received slices. */ @@ -206,29 +208,40 @@ success: return ret; } +static bool test_and_set_slice_bit(struct fecdec_group *fg, uint8_t slice_num) +{ + uint8_t *p = fg->received_slices + slice_num / 8, old = *p; + + *p |= 1 << (slice_num % 8); + return old == *p; +} + /* * returns 1 if slice was added, zero otherwise (because the group was already - * complete). In any case the number of received slices is being increased by - * one. + * complete or a slice has been received twice). */ static int add_slice(char *buf, struct fecdec_group *fg) { - int r, slice_num; + int r; + uint8_t slice_num = fg->h.slice_num; if (group_complete(fg)) { PARA_DEBUG_LOG("group %d complete, ignoring slice %d\n", - fg->h.group_num, fg->h.slice_num); - fg->num_received_slices++; + fg->h.group_num, slice_num); return 0; } - slice_num = fg->h.slice_num; if (fg->num_slices == 0) { fg->num_slices = fg->h.slices_per_group; fg->idx = para_malloc(fg->num_slices * sizeof(int)); - fg->data = para_malloc(fg->num_slices * sizeof(unsigned char *)); - memset(fg->data, 0, fg->num_slices * sizeof(unsigned char *)); + fg->data = para_calloc(fg->num_slices * sizeof(unsigned char *)); } r = fg->num_received_slices; + /* Check if we already have this slice. */ + if (test_and_set_slice_bit(fg, slice_num)) { + PARA_INFO_LOG("ignoring duplicate slice %d:%d\n", fg->h.group_num, + slice_num); + return 0; + } fg->idx[r] = slice_num; fg->data[r] = para_malloc(fg->h.slice_bytes); memcpy(fg->data[r], buf, fg->h.slice_bytes);