-
Notifications
You must be signed in to change notification settings - Fork 23
/
mux.go
229 lines (185 loc) · 5.89 KB
/
mux.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
package openflow
import (
"fmt"
"sync"
)
// A Matcher interface is used by multiplexer to find the handler for
// the received request.
type Matcher interface {
Match(*Request) bool
}
// MatcherFunc type is an adapter to allow the use of ordinary functions
// as OpenFlow request matchers.
type MatcherFunc struct {
Func func(*Request) bool
}
// Match implements Matcher interface and calls fn(r).
func (m *MatcherFunc) Match(r *Request) bool {
return m.Func(r)
}
// TypeMatcher used to match requests by their types.
type TypeMatcher Type
// Match implements Matcher interface and matches the request by the type.
func (t TypeMatcher) Match(r *Request) bool {
return r.Header.Type == Type(t)
}
// MultiMatcher creates a new Matcher instance that matches the request
// by all specified criteria.
func MultiMatcher(m ...Matcher) Matcher {
fn := func(r *Request) bool {
for _, matcher := range m {
if !matcher.Match(r) {
return false
}
}
return true
}
return &MatcherFunc{fn}
}
type muxEntry struct {
matcher Matcher
handler Handler
// once means handler will be executed only once, it will
// be removed from the list of registered handlers.
once bool
}
// ServeMux is an OpenFlow request multiplexer.
type ServeMux struct {
mu sync.RWMutex
handlers map[Matcher]*muxEntry
}
// NewServeMux allocates and returns a new ServeMux.
func NewServeMux() *ServeMux {
return &ServeMux{handlers: make(map[Matcher]*muxEntry)}
}
// DefaultHandler is the Handler used for Requests that don't have a Matcher.
var DefaultHandler = DiscardHandler
// handle appends to the list of registered handlers a new one. If the
// matcher or handler of the entry is not defined, a panic function will
// be called.
func (mux *ServeMux) handle(e *muxEntry) {
mux.mu.Lock()
defer mux.mu.Unlock()
if e.matcher == nil {
panic("openflow: nil matcher")
}
if e.handler == nil {
panic("openflow: nil handler")
}
if _, dup := mux.handlers[e.matcher]; dup {
text := "openflow: multiple registrations for %v"
panic(fmt.Errorf(text, e.matcher))
}
mux.handlers[e.matcher] = e
}
// Handle registers the handler for the given pattern.
func (mux *ServeMux) Handle(m Matcher, h Handler) {
mux.handle(&muxEntry{m, h, false})
}
// HandleOnce registers disposable handler for the given pattern.
//
// It is not guaranteed that handler will process the first message
// exemplar of the matching message.
func (mux *ServeMux) HandleOnce(m Matcher, h Handler) {
mux.handle(&muxEntry{m, h, true})
}
// HandleFunc registers handler function for the given pattern.
func (mux *ServeMux) HandleFunc(m Matcher, h HandlerFunc) {
mux.Handle(m, h)
}
// Handler returns a handler of the specified request.
func (mux *ServeMux) Handler(r *Request) Handler {
var matcher Matcher
var entry *muxEntry
// Acquire a read lock to ensure that list would not
// be modified during the search of registered handler.
mux.mu.RLock()
var matched bool
// Try to match the processing request to any of the registered
// filters.
for matcher, entry = range mux.handlers {
if matched = matcher.Match(r); matched {
break
}
}
mux.mu.RUnlock()
// Use the DefaultHandler when there are no matching entries in the list.
if !matched {
return DefaultHandler
}
// If the retrieved entry is not disposable one, we will
// return it as is without any processing.
if !entry.once {
return entry.handler
}
// But when the entry is disposable, we need to remove it
// from the list.
// We need to acquire the write lock in order to remove the
// entry from the root. This procedure does not guarantee,
// that handler will process the first message.
mux.mu.Lock()
defer mux.mu.Unlock()
// If the concurrent message have already started the message
// processing, it will be no longer presented in the list.
if _, ok := mux.handlers[matcher]; !ok {
return DiscardHandler
}
// Remove the entry from the list if it is marked as disposable.
delete(mux.handlers, matcher)
return entry.handler
}
// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *ServeMux) Serve(rw ResponseWriter, r *Request) {
h := mux.Handler(r)
h.Serve(rw, r)
}
// TypeMux is an OpenFlow request multiplexer. It matches the type
// of the OpenFlow message against a list of registered handlers and calls
// the marching handler.
type TypeMux struct {
mux *ServeMux
}
// NewTypeMux creates and returns a new TypeMux.
func NewTypeMux() *TypeMux {
return &TypeMux{NewServeMux()}
}
// Handle registers the handler for the given message type.
func (mux *TypeMux) Handle(t Type, h Handler) {
mux.mux.Handle(TypeMatcher(t), h)
}
// HandleOnce registers a disposable handler for the given message type.
func (mux *TypeMux) HandleOnce(t Type, h Handler) {
mux.mux.HandleOnce(TypeMatcher(t), h)
}
// HandleFunc registers handler function for the given message type.
func (mux *TypeMux) HandleFunc(t Type, f HandlerFunc) {
mux.Handle(t, f)
}
// Handler returns a Handler instance for the given OpenFlow request.
func (mux *TypeMux) Handler(r *Request) Handler {
return mux.mux.Handler(r)
}
// Serve implements Handler internface. It processing the request and
// writes back the response.
func (mux *TypeMux) Serve(rw ResponseWriter, r *Request) {
mux.mux.Serve(rw, r)
}
// DefaultMux is an instance of the TypeMux used as
// a default handler in the DefaultServer instance.
var DefaultMux = NewTypeMux()
// Handle registers the handler for the given message type message in the
// DefaultMux. The documentation for TypeMux
func Handle(t Type, handler Handler) {
DefaultMux.Handle(t, handler)
}
// HandleOnce registers a disposable handler for the given message type
// in the DefaultMux.
func HandleOnce(t Type, handler Handler) {
DefaultMux.HandleOnce(t, handler)
}
// HandleFunc registers the handler function on the given message type
// in the DefaultMux.
func HandleFunc(t Type, f func(ResponseWriter, *Request)) {
DefaultMux.HandleFunc(t, f)
}