-
Notifications
You must be signed in to change notification settings - Fork 5
/
router.go
89 lines (78 loc) · 1.61 KB
/
router.go
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
package transport
import (
"container/list"
"sync"
"github.com/zenhotels/astranet/protocol"
)
type Router struct {
cbLock sync.RWMutex
cbMap map[Filter]*list.List
initCtl sync.Once
}
func (self *Router) init() {
self.initCtl.Do(func() {
self.cbMap = make(map[Filter]*list.List)
})
}
func (self *Router) Handle(cb Callback, filters ...Filter) Handler {
self.init()
var eList = make(map[Filter]*list.Element, len(filters))
for _, f := range filters {
if eList[f] != nil {
continue
}
self.cbLock.Lock()
var l = self.cbMap[f]
if l == nil {
l = list.New()
self.cbMap[f] = l
}
eList[f] = l.PushBack(cb)
self.cbLock.Unlock()
}
return &handler{cb, eList, self, false}
}
func (self *Router) CloseHandle(filter Filter, el *list.Element) {
self.init()
self.cbLock.Lock()
var eMap = self.cbMap[filter]
if eMap != nil {
eMap.Remove(el)
if eMap.Len() == 0 {
delete(self.cbMap, filter)
}
}
self.cbLock.Unlock()
}
func (self *Router) checkCb(f Filter) (cb Callback) {
self.cbLock.RLock()
if cbL, found := self.cbMap[f]; found && cbL.Len() > 0 {
cb = cbL.Back().Value.(Callback)
}
self.cbLock.RUnlock()
return cb
}
func (self *Router) Check(fL ...Filter) (cb Callback) {
self.init()
for _, f := range fL {
if cb = self.checkCb(f); cb != nil {
return cb
}
}
return
}
func (self *Router) CheckFrame(job protocol.Op) (cb Callback) {
return self.Check(Filter{
Cmd: job.Cmd,
Remote: job.Remote,
RPort: job.RPort,
Local: job.Local,
LPort: job.LPort,
}, Filter{
Cmd: job.Cmd,
Remote: job.Remote,
RPort: job.RPort,
}, Filter{
Cmd: job.Cmd,
}, Filter{})
}