aboutsummaryrefslogtreecommitdiff
path: root/dedupe.go
blob: 2b103b8f0a4de545c272ca625b8f2a44bcf9036f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package meshtastic

import (
	"encoding/hex"
	"fmt"
	"hash"
	"sync"
	"time"
)

type PacketDeduplicator struct {
	hasher       hash.Hash
	expiresAfter time.Duration
	sync.RWMutex
	seen map[string]time.Time
}

func NewDeduplicator(hasher hash.Hash, expiresAfter time.Duration) *PacketDeduplicator {
	pd := PacketDeduplicator{
		seen:         make(map[string]time.Time),
		hasher:       hasher,
		expiresAfter: expiresAfter,
	}
	go func() {
		for {
			time.Sleep(expiresAfter)
			pd.Lock()
			for packet, timestamp := range pd.seen {
				if time.Since(timestamp) > pd.expiresAfter {
					delete(pd.seen, packet)
				}
			}
			pd.Unlock()
		}
	}()

	return &pd
}
func (p *PacketDeduplicator) Seen(sender, packetID uint32) bool {
	asString := fmt.Sprintf("%d-%d", sender, packetID)
	p.RLock()
	if _, exists := p.seen[asString]; !exists {
		p.RUnlock()
		p.Lock()
		defer p.Unlock()
		p.seen[asString] = time.Now()
		return false
	}
	p.RUnlock()
	return true
}
func (p *PacketDeduplicator) SeenData(data []byte) bool {
	hashed := p.hasher.Sum(data)
	asHex := hex.EncodeToString(hashed)
	p.RLock()
	if _, exists := p.seen[asHex]; !exists {
		p.RUnlock()
		p.Lock()
		defer p.Unlock()
		p.seen[asHex] = time.Now()
		return false
	}
	p.RUnlock()

	return true
}