78 lines
1.9 KiB
Objective-C
78 lines
1.9 KiB
Objective-C
//
|
|
// ReplayProtector.m
|
|
// TunnelKit
|
|
//
|
|
// Created by Davide De Rosa on 2/17/17.
|
|
// Copyright © 2018 London Trust Media. All rights reserved.
|
|
//
|
|
|
|
#import "ReplayProtector.h"
|
|
#import "Allocation.h"
|
|
|
|
#define HIDDEN_WINSIZE 128
|
|
#define BITMAP_LEN (HIDDEN_WINSIZE / 32)
|
|
#define BITMAP_INDEX_MASK (BITMAP_LEN - 1)
|
|
#define REDUNDANT_BIT_SHIFTS 5
|
|
#define REDUNDANT_BITS (1 << REDUNDANT_BIT_SHIFTS)
|
|
#define BITMAP_LOC_MASK (REDUNDANT_BITS - 1)
|
|
#define REPLAY_WINSIZE (HIDDEN_WINSIZE - REDUNDANT_BITS)
|
|
|
|
@interface ReplayProtector ()
|
|
|
|
@property (nonatomic, assign) uint32_t highestPacketId;
|
|
@property (nonatomic, unsafe_unretained) uint32_t *bitmap;
|
|
|
|
@end
|
|
|
|
@implementation ReplayProtector
|
|
|
|
- (instancetype)init
|
|
{
|
|
if ((self = [super init])) {
|
|
self.highestPacketId = 0;
|
|
self.bitmap = allocate_safely(BITMAP_LEN * sizeof(uint32_t));
|
|
bzero(self.bitmap, BITMAP_LEN * sizeof(uint32_t));
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
free(self.bitmap);
|
|
}
|
|
|
|
- (BOOL)isReplayedPacketId:(uint32_t)packetId
|
|
{
|
|
if (packetId == 0) {
|
|
return YES;
|
|
}
|
|
if ((REPLAY_WINSIZE + packetId) < self.highestPacketId) {
|
|
return YES;
|
|
}
|
|
|
|
uint32_t index = (packetId >> REDUNDANT_BIT_SHIFTS);
|
|
|
|
if (packetId > self.highestPacketId) {
|
|
const uint32_t currentIndex = self.highestPacketId >> REDUNDANT_BIT_SHIFTS;
|
|
const uint32_t diff = MIN(index - currentIndex, BITMAP_LEN);
|
|
|
|
for (uint32_t bid = 0; bid < diff; ++bid) {
|
|
self.bitmap[(bid + currentIndex + 1) & BITMAP_INDEX_MASK] = 0;
|
|
}
|
|
|
|
self.highestPacketId = packetId;
|
|
}
|
|
|
|
index &= BITMAP_INDEX_MASK;
|
|
const uint32_t bitLocation = packetId & BITMAP_LOC_MASK;
|
|
const uint32_t bitmask = (1 << bitLocation);
|
|
|
|
if (self.bitmap[index] & bitmask) {
|
|
return YES;
|
|
}
|
|
self.bitmap[index] |= bitmask;
|
|
return NO;
|
|
}
|
|
|
|
@end
|