aboutsummaryrefslogtreecommitdiff
path: root/ntcp/map.go
blob: 6127149ac7b1e6bbff1b0e1865de3203eccd8c65 (plain) (blame)
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)
}

Snix LLC Git Repository Holder Copyright(C) 2022 All Rights Reserved Email To Snix.IR