-
Notifications
You must be signed in to change notification settings - Fork 160
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements RFC 6347 Section 4.1.2.6. Set config.ReplayProtectionWindow to change the size of the protection window. Default is 64.
- Loading branch information
Showing
8 changed files
with
360 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Package replaydetector provides packet replay detection algorithm. | ||
package replaydetector | ||
|
||
// ReplayDetector is the interface of sequence replay detector. | ||
type ReplayDetector interface { | ||
// Check returns true if given sequence number is not replayed. | ||
// Call accept() to mark the packet is received properly. | ||
Check(seq uint64) (accept func(), ok bool) | ||
} | ||
|
||
type slidingWindowDetector struct { | ||
latestSeq uint64 | ||
maxSeq uint64 | ||
windowSize uint64 | ||
mask []uint64 | ||
} | ||
|
||
// New creates ReplayDetector. | ||
func New(windowSize uint, maxSeq uint64) ReplayDetector { | ||
chunkSize := (windowSize + 63) / 64 | ||
if chunkSize == 0 { | ||
chunkSize = 1 | ||
} | ||
return &slidingWindowDetector{ | ||
windowSize: uint64(windowSize), | ||
maxSeq: maxSeq, | ||
mask: make([]uint64, chunkSize), | ||
} | ||
} | ||
|
||
func (d *slidingWindowDetector) Check(seq uint64) (accept func(), ok bool) { | ||
if seq+d.windowSize < d.latestSeq || seq > d.maxSeq { | ||
// Older than window size or exceeding upper limit. | ||
return func() {}, false | ||
} | ||
if seq > d.latestSeq { | ||
// Update the head of the window. | ||
shift := seq - d.latestSeq | ||
for i := len(d.mask) - 1; i > 0; i-- { | ||
d.mask[i] <<= shift | ||
d.mask[i] |= d.mask[i-1] >> (64 - shift) | ||
} | ||
d.mask[0] <<= shift | ||
d.latestSeq = seq | ||
} | ||
|
||
chunk := (d.latestSeq - seq) / 64 | ||
pos := (d.latestSeq - seq) % 64 | ||
bit := uint64(1) << pos | ||
|
||
if d.mask[chunk]&bit != 0 { | ||
// The sequence number is duplicated. | ||
return func() {}, false | ||
} | ||
|
||
return func() { | ||
d.mask[chunk] |= bit | ||
}, true | ||
} |
Oops, something went wrong.