Initial commit
This commit is contained in:
79
replay.go
Normal file
79
replay.go
Normal file
@@ -0,0 +1,79 @@
|
||||
package lafsession
|
||||
|
||||
type replayWindow struct {
|
||||
maxSeq uint64
|
||||
size uint64
|
||||
bits []uint64
|
||||
}
|
||||
|
||||
func newReplayWindow(size uint64) *replayWindow {
|
||||
if size < 64 {
|
||||
size = 64
|
||||
}
|
||||
words := (size + 63) / 64
|
||||
return &replayWindow{
|
||||
size: size,
|
||||
bits: make([]uint64, words),
|
||||
}
|
||||
}
|
||||
|
||||
func (w *replayWindow) accept(seq uint64) bool {
|
||||
if seq+w.size <= w.maxSeq {
|
||||
return false
|
||||
}
|
||||
if seq > w.maxSeq {
|
||||
shift := seq - w.maxSeq
|
||||
if shift >= w.size {
|
||||
for i := range w.bits {
|
||||
w.bits[i] = 0
|
||||
}
|
||||
} else {
|
||||
w.shift(shift)
|
||||
}
|
||||
w.maxSeq = seq
|
||||
}
|
||||
idx := w.maxSeq - seq
|
||||
word := idx / 64
|
||||
bit := idx % 64
|
||||
if word >= uint64(len(w.bits)) {
|
||||
return false
|
||||
}
|
||||
mask := uint64(1) << bit
|
||||
if w.bits[word]&mask != 0 {
|
||||
return false
|
||||
}
|
||||
w.bits[word] |= mask
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *replayWindow) shift(n uint64) {
|
||||
words := n / 64
|
||||
bits := n % 64
|
||||
if words > 0 {
|
||||
copy(w.bits[words:], w.bits)
|
||||
for i := uint64(0); i < words && i < uint64(len(w.bits)); i++ {
|
||||
w.bits[i] = 0
|
||||
}
|
||||
for i := uint64(len(w.bits)); i > words; i-- {
|
||||
}
|
||||
if words < uint64(len(w.bits)) {
|
||||
for i := 0; i < int(words); i++ {
|
||||
w.bits[i] = 0
|
||||
}
|
||||
} else {
|
||||
for i := range w.bits {
|
||||
w.bits[i] = 0
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
if bits == 0 {
|
||||
return
|
||||
}
|
||||
var carry uint64
|
||||
for i := len(w.bits) - 1; i >= 0; i-- {
|
||||
newCarry := w.bits[i] >> (64 - bits)
|
||||
w.bits[i] = (w.bits[i] << bits) | carry
|
||||
carry = newCarry
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user