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
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
// Copyright 2021 SNIX LLC sina@snix.ir
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// version 2 as published by the Free Software Foundation.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
package ntcp
import (
"errors"
"goshkan/opts"
"goshkan/rgxp"
"regexp"
"sync"
"time"
)
type memoryTTL struct {
ticker *time.Ticker // age-out trigger
stopfc func() error // delete by user trigger
}
var inMemMap sync.Map // safe map
var cleanint time.Duration
func setupCache() {
switch opts.Settings.Clearc {
case 0: // zero map ttl, disable map cache
opts.SYSLOG(disabledMAP)
allowedOrNot = func(domain string) bool { return rgxp.RegexpCompiled().MatchString(domain) }
storeToMap = func(domain string) {}
RemoveFromMap = func(ptrn *string) error { return nil }
return
}
cleanint = time.Duration(opts.Settings.Clearc) * time.Second
}
var storeToMap = func(domain string) {
if ttl, ok := inMemMap.Load(domain); ok {
ttl.(memoryTTL).ticker.Reset(cleanint) // renew domain age.
return
}
tk := time.NewTicker(cleanint) // new ticker
ch := make(chan struct{})
fn := func() error {
var err error
select {
case ch <- struct{}{}:
return err
default:
return errors.New(errorChanNk)
}
}
inMemMap.Store(domain, memoryTTL{ticker: tk, stopfc: fn}) // add data to map
go cleanerMap(tk, domain, ch) // run cleaner
}
func cleanerMap(tk *time.Ticker, dm string, chtr <-chan struct{}) {
select {
case <-tk.C: // age out, remove form map
case <-chtr: // signal by user, remove from map
}
tk.Stop() // release ticker, its time to die.
inMemMap.Delete(dm)
}
var RemoveFromMap = func(ptrn *string) error {
re, err := regexp.Compile(*ptrn)
if err != nil {
return err // somthing is wrong!
}
rgtask := func(key interface{}, value interface{}) bool {
if re.MatchString(key.(string)) {
if err := value.(memoryTTL).stopfc(); err != nil {
opts.SYSLOG(err)
} // remove domain from map
}
return true
}
inMemMap.Range(rgtask)
return err
}
var allowedOrNot = func(domain string) bool {
// check memory cache first -> O(1)
if _, ok := inMemMap.Load(domain); ok {
return ok
}
// this take time, but we can do nothing about it :/
return rgxp.RegexpCompiled().MatchString(domain)
}
|