1 package dbus
2
3 import (
4 "bytes"
5 "reflect"
6 "strings"
7 "sync"
8 )
9
10 func newIntrospectIntf(h *defaultHandler) *exportedIntf {
11 methods := make(map[string]Method)
12 methods["Introspect"] = exportedMethod{
13 reflect.ValueOf(func(msg Message) (string, *Error) {
14 path := msg.Headers[FieldPath].value.(ObjectPath)
15 return h.introspectPath(path), nil
16 }),
17 }
18 return newExportedIntf(methods, true)
19 }
20
21
22
23
24
25
26 func NewDefaultHandler() *defaultHandler {
27 h := &defaultHandler{
28 objects: make(map[ObjectPath]*exportedObj),
29 defaultIntf: make(map[string]*exportedIntf),
30 }
31 h.defaultIntf["org.freedesktop.DBus.Introspectable"] = newIntrospectIntf(h)
32 return h
33 }
34
35 type defaultHandler struct {
36 sync.RWMutex
37 objects map[ObjectPath]*exportedObj
38 defaultIntf map[string]*exportedIntf
39 }
40
41 func (h *defaultHandler) PathExists(path ObjectPath) bool {
42 _, ok := h.objects[path]
43 return ok
44 }
45
46 func (h *defaultHandler) introspectPath(path ObjectPath) string {
47 subpath := make(map[string]struct{})
48 var xml bytes.Buffer
49 xml.WriteString("<node>")
50 for obj := range h.objects {
51 p := string(path)
52 if p != "/" {
53 p += "/"
54 }
55 if strings.HasPrefix(string(obj), p) {
56 node_name := strings.Split(string(obj[len(p):]), "/")[0]
57 subpath[node_name] = struct{}{}
58 }
59 }
60 for s := range subpath {
61 xml.WriteString("\n\t<node name=\"" + s + "\"/>")
62 }
63 xml.WriteString("\n</node>")
64 return xml.String()
65 }
66
67 func (h *defaultHandler) LookupObject(path ObjectPath) (ServerObject, bool) {
68 h.RLock()
69 defer h.RUnlock()
70 object, ok := h.objects[path]
71 if ok {
72 return object, ok
73 }
74
75
76
77 subtreeObject := newExportedObject()
78 path = path[:strings.LastIndex(string(path), "/")]
79 for len(path) > 0 {
80 object, ok = h.objects[path]
81 if ok {
82 for name, iface := range object.interfaces {
83
84 if iface.isFallbackInterface() {
85 subtreeObject.interfaces[name] = iface
86 }
87 }
88 break
89 }
90
91 path = path[:strings.LastIndex(string(path), "/")]
92 }
93
94 for name, intf := range h.defaultIntf {
95 if _, exists := subtreeObject.interfaces[name]; exists {
96 continue
97 }
98 subtreeObject.interfaces[name] = intf
99 }
100
101 return subtreeObject, true
102 }
103
104 func (h *defaultHandler) AddObject(path ObjectPath, object *exportedObj) {
105 h.Lock()
106 h.objects[path] = object
107 h.Unlock()
108 }
109
110 func (h *defaultHandler) DeleteObject(path ObjectPath) {
111 h.Lock()
112 delete(h.objects, path)
113 h.Unlock()
114 }
115
116 type exportedMethod struct {
117 reflect.Value
118 }
119
120 func (m exportedMethod) Call(args ...interface{}) ([]interface{}, error) {
121 t := m.Type()
122
123 params := make([]reflect.Value, len(args))
124 for i := 0; i < len(args); i++ {
125 params[i] = reflect.ValueOf(args[i]).Elem()
126 }
127
128 ret := m.Value.Call(params)
129 var err error
130 nilErr := false
131 if t.NumOut() > 0 {
132 if e, ok := ret[t.NumOut()-1].Interface().(*Error); ok {
133 nilErr = ret[t.NumOut()-1].IsNil()
134 ret = ret[:t.NumOut()-1]
135 err = e
136 } else if ret[t.NumOut()-1].Type().Implements(errType) {
137 i := ret[t.NumOut()-1].Interface()
138 if i == nil {
139 nilErr = ret[t.NumOut()-1].IsNil()
140 } else {
141 err = i.(error)
142 }
143 ret = ret[:t.NumOut()-1]
144 }
145 }
146 out := make([]interface{}, len(ret))
147 for i, val := range ret {
148 out[i] = val.Interface()
149 }
150 if nilErr || err == nil {
151
152 return out, nil
153 }
154 return out, err
155 }
156
157 func (m exportedMethod) NumArguments() int {
158 return m.Value.Type().NumIn()
159 }
160
161 func (m exportedMethod) ArgumentValue(i int) interface{} {
162 return reflect.Zero(m.Type().In(i)).Interface()
163 }
164
165 func (m exportedMethod) NumReturns() int {
166 return m.Value.Type().NumOut()
167 }
168
169 func (m exportedMethod) ReturnValue(i int) interface{} {
170 return reflect.Zero(m.Type().Out(i)).Interface()
171 }
172
173 func newExportedObject() *exportedObj {
174 return &exportedObj{
175 interfaces: make(map[string]*exportedIntf),
176 }
177 }
178
179 type exportedObj struct {
180 mu sync.RWMutex
181 interfaces map[string]*exportedIntf
182 }
183
184 func (obj *exportedObj) LookupInterface(name string) (Interface, bool) {
185 if name == "" {
186 return obj, true
187 }
188 obj.mu.RLock()
189 defer obj.mu.RUnlock()
190 intf, exists := obj.interfaces[name]
191 return intf, exists
192 }
193
194 func (obj *exportedObj) AddInterface(name string, iface *exportedIntf) {
195 obj.mu.Lock()
196 defer obj.mu.Unlock()
197 obj.interfaces[name] = iface
198 }
199
200 func (obj *exportedObj) DeleteInterface(name string) {
201 obj.mu.Lock()
202 defer obj.mu.Unlock()
203 delete(obj.interfaces, name)
204 }
205
206 func (obj *exportedObj) LookupMethod(name string) (Method, bool) {
207 obj.mu.RLock()
208 defer obj.mu.RUnlock()
209 for _, intf := range obj.interfaces {
210 method, exists := intf.LookupMethod(name)
211 if exists {
212 return method, exists
213 }
214 }
215 return nil, false
216 }
217
218 func (obj *exportedObj) isFallbackInterface() bool {
219 return false
220 }
221
222 func newExportedIntf(methods map[string]Method, includeSubtree bool) *exportedIntf {
223 return &exportedIntf{
224 methods: methods,
225 includeSubtree: includeSubtree,
226 }
227 }
228
229 type exportedIntf struct {
230 methods map[string]Method
231
232
233 includeSubtree bool
234 }
235
236 func (obj *exportedIntf) LookupMethod(name string) (Method, bool) {
237 out, exists := obj.methods[name]
238 return out, exists
239 }
240
241 func (obj *exportedIntf) isFallbackInterface() bool {
242 return obj.includeSubtree
243 }
244
245
246
247
248
249
250 func NewDefaultSignalHandler() *defaultSignalHandler {
251 return &defaultSignalHandler{}
252 }
253
254 type defaultSignalHandler struct {
255 mu sync.RWMutex
256 closed bool
257 signals []*signalChannelData
258 }
259
260 func (sh *defaultSignalHandler) DeliverSignal(intf, name string, signal *Signal) {
261 sh.mu.RLock()
262 defer sh.mu.RUnlock()
263 if sh.closed {
264 return
265 }
266 for _, scd := range sh.signals {
267 scd.deliver(signal)
268 }
269 }
270
271 func (sh *defaultSignalHandler) Terminate() {
272 sh.mu.Lock()
273 defer sh.mu.Unlock()
274 if sh.closed {
275 return
276 }
277
278 for _, scd := range sh.signals {
279 scd.close()
280 close(scd.ch)
281 }
282 sh.closed = true
283 sh.signals = nil
284 }
285
286 func (sh *defaultSignalHandler) AddSignal(ch chan<- *Signal) {
287 sh.mu.Lock()
288 defer sh.mu.Unlock()
289 if sh.closed {
290 return
291 }
292 sh.signals = append(sh.signals, &signalChannelData{
293 ch: ch,
294 done: make(chan struct{}),
295 })
296 }
297
298 func (sh *defaultSignalHandler) RemoveSignal(ch chan<- *Signal) {
299 sh.mu.Lock()
300 defer sh.mu.Unlock()
301 if sh.closed {
302 return
303 }
304 for i := len(sh.signals) - 1; i >= 0; i-- {
305 if ch == sh.signals[i].ch {
306 sh.signals[i].close()
307 copy(sh.signals[i:], sh.signals[i+1:])
308 sh.signals[len(sh.signals)-1] = nil
309 sh.signals = sh.signals[:len(sh.signals)-1]
310 }
311 }
312 }
313
314 type signalChannelData struct {
315 wg sync.WaitGroup
316 ch chan<- *Signal
317 done chan struct{}
318 }
319
320 func (scd *signalChannelData) deliver(signal *Signal) {
321 select {
322 case scd.ch <- signal:
323 case <-scd.done:
324 return
325 default:
326 scd.wg.Add(1)
327 go scd.deferredDeliver(signal)
328 }
329 }
330
331 func (scd *signalChannelData) deferredDeliver(signal *Signal) {
332 select {
333 case scd.ch <- signal:
334 case <-scd.done:
335 }
336 scd.wg.Done()
337 }
338
339 func (scd *signalChannelData) close() {
340 close(scd.done)
341 scd.wg.Wait()
342 }
343
View as plain text