1package zerobus
2
3import (
4 "encoding/binary"
5 "errors"
6 "math"
7 "strings"
8 "unicode/utf8"
9 "unsafe"
10)
11
12const (
13 maxMessage = 128 << 20 // the D-Bus limit for a whole message
14 maxArray = 64 << 20 // the D-Bus limit for one array
15 maxNest = 32 // array or struct levels in one signature
16 maxDepth = 64 // total levels in a value, variants included
17)
18
19var (
20 // ErrMalformed reports bytes that do not follow the D-Bus wire format.
21 ErrMalformed = errors.New("zerobus: malformed message")
22 // ErrTooLarge reports a message or array over the D-Bus size limits.
23 ErrTooLarge = errors.New("zerobus: message too large")
24 // ErrInvalid reports an outgoing value D-Bus does not allow, such as a
25 // string with a NUL byte or a body that does not match its signature.
26 ErrInvalid = errors.New("zerobus: invalid value")
27)
28
29// alignOf returns the alignment of the type that starts with signature byte c.
30func alignOf(c byte) int {
31 switch c {
32 case 'n', 'q':
33 return 2
34 case 'b', 'i', 'u', 'h', 's', 'o', 'a':
35 return 4
36 case 'x', 't', 'd', '(', '{':
37 return 8
38 }
39 return 1 // y, g, v
40}
41
42// pad rounds off up to a multiple of n, a power of two.
43func pad(off, n int) int { return (off + n - 1) &^ (n - 1) }
44
45// sigEnd returns the index just after the single complete type that starts
46// at sig[i], or -1 if there is none.
47func sigEnd(sig string, i int) int { return typeEnd(sig, i, 0, 0) }
48
49// typeEnd is sigEnd with the array and struct nesting so far. The spec
50// limits each to 32 levels; dict entries count as structs.
51func typeEnd(sig string, i, arrays, structs int) int {
52 if i >= len(sig) || arrays > maxNest || structs > maxNest {
53 return -1
54 }
55 switch sig[i] {
56 case 'y', 'b', 'n', 'q', 'i', 'u', 'x', 't', 'd', 'h', 's', 'o', 'g', 'v':
57 return i + 1
58 case 'a':
59 if i+1 < len(sig) && sig[i+1] == '{' {
60 return dictEnd(sig, i+1, arrays+1, structs+1)
61 }
62 return typeEnd(sig, i+1, arrays+1, structs)
63 case '(':
64 j := i + 1
65 if j < len(sig) && sig[j] == ')' {
66 return -1 // empty structs are not allowed
67 }
68 for j < len(sig) && sig[j] != ')' {
69 if j = typeEnd(sig, j, arrays, structs+1); j < 0 {
70 return -1
71 }
72 }
73 if j >= len(sig) {
74 return -1
75 }
76 return j + 1
77 }
78 return -1 // includes '{': a dict entry is only valid as an array element
79}
80
81// dictEnd returns the index just after the dict entry type at sig[i] ('{').
82// Its key must be a basic type and it holds exactly two types.
83func dictEnd(sig string, i, arrays, structs int) int {
84 j := i + 1
85 if j >= len(sig) || !basic(sig[j]) || structs > maxNest {
86 return -1
87 }
88 if j = typeEnd(sig, j+1, arrays, structs); j < 0 || j >= len(sig) || sig[j] != '}' {
89 return -1
90 }
91 return j + 1
92}
93
94func basic(c byte) bool {
95 switch c {
96 case 'y', 'b', 'n', 'q', 'i', 'u', 'x', 't', 'd', 'h', 's', 'o', 'g':
97 return true
98 }
99 return false
100}
101
102// validSignature reports whether sig is a list of complete types that fits
103// in a D-Bus signature.
104func validSignature(sig string) bool {
105 if len(sig) > 255 {
106 return false
107 }
108 for i := 0; i < len(sig); {
109 if i = sigEnd(sig, i); i < 0 {
110 return false
111 }
112 }
113 return true
114}
115
116// validPath reports whether p is a valid object path.
117func validPath(p string) bool {
118 if p == "/" {
119 return true
120 }
121 if len(p) < 2 || p[0] != '/' || p[len(p)-1] == '/' {
122 return false
123 }
124 for i := 1; i < len(p); i++ {
125 c := p[i]
126 switch {
127 case c == '/':
128 if p[i-1] == '/' {
129 return false
130 }
131 case c >= 'a' && c <= 'z', c >= 'A' && c <= 'Z', c >= '0' && c <= '9', c == '_':
132 default:
133 return false
134 }
135 }
136 return true
137}
138
139// validMember reports whether s is a valid member name: letters, digits and
140// '_', not starting with a digit.
141func validMember(s string) bool {
142 if s == "" || len(s) > 255 || s[0] >= '0' && s[0] <= '9' {
143 return false
144 }
145 for i := 0; i < len(s); i++ {
146 if !nameChar(s[i]) {
147 return false
148 }
149 }
150 return true
151}
152
153// nameChar reports whether c may appear in a member or interface name.
154func nameChar(c byte) bool {
155 return c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c >= '0' && c <= '9' || c == '_'
156}
157
158// validInterface reports whether s is a valid interface or error name: two
159// or more member-like elements separated by dots.
160func validInterface(s string) bool {
161 if len(s) > 255 {
162 return false
163 }
164 n := 0
165 for more := true; more; n++ {
166 var e string
167 e, s, more = strings.Cut(s, ".")
168 if !validMember(e) {
169 return false
170 }
171 }
172 return n >= 2
173}
174
175// validBusName reports whether s is a valid unique (":1.42") or well-known
176// ("org.example.App") bus name.
177func validBusName(s string) bool {
178 if s == "" || len(s) > 255 {
179 return false
180 }
181 unique := s[0] == ':'
182 if unique {
183 s = s[1:]
184 }
185 n := 0
186 for more := true; more; n++ {
187 var e string
188 e, s, more = strings.Cut(s, ".")
189 if e == "" || !unique && e[0] >= '0' && e[0] <= '9' {
190 return false
191 }
192 for i := 0; i < len(e); i++ {
193 if !nameChar(e[i]) && e[i] != '-' {
194 return false
195 }
196 }
197 }
198 return n >= 2
199}
200
201// Reader decodes D-Bus values in place.
202//
203// Strings and byte slices it returns point into the message buffer: they are
204// valid only until the next Conn.ReadMessage. Copy them (strings.Clone,
205// bytes.Clone) to keep them longer.
206//
207// Read values in the order of the message signature. Errors are sticky:
208// after the first one, every read returns a zero value and Err reports it.
209type Reader struct {
210 buf []byte
211 off int
212 big bool
213 err error
214}
215
216// Err returns the first error the reader met, or nil.
217func (r *Reader) Err() error { return r.err }
218
219// Done reports whether every byte was read without error.
220func (r *Reader) Done() bool { return r.err == nil && r.off == len(r.buf) }
221
222func (r *Reader) fail() {
223 if r.err == nil {
224 r.err = ErrMalformed
225 }
226}
227
228// take aligns to align and returns the next size bytes.
229func (r *Reader) take(align, size int) []byte {
230 if r.err != nil {
231 return nil
232 }
233 off := pad(r.off, align)
234 if off > len(r.buf)-size {
235 r.fail()
236 return nil
237 }
238 r.off = off + size
239 return r.buf[off:r.off]
240}
241
242// Byte reads a BYTE (y).
243func (r *Reader) Byte() byte {
244 if b := r.take(1, 1); b != nil {
245 return b[0]
246 }
247 return 0
248}
249
250// Bool reads a BOOLEAN (b).
251func (r *Reader) Bool() bool {
252 v := r.Uint32()
253 if v > 1 {
254 r.fail()
255 return false
256 }
257 return v == 1
258}
259
260// Int16 reads an INT16 (n).
261func (r *Reader) Int16() int16 { return int16(r.Uint16()) }
262
263// Uint16 reads a UINT16 (q).
264func (r *Reader) Uint16() uint16 {
265 b := r.take(2, 2)
266 if b == nil {
267 return 0
268 }
269 if r.big {
270 return binary.BigEndian.Uint16(b)
271 }
272 return binary.LittleEndian.Uint16(b)
273}
274
275// Int32 reads an INT32 (i).
276func (r *Reader) Int32() int32 { return int32(r.Uint32()) }
277
278// Uint32 reads a UINT32 (u).
279func (r *Reader) Uint32() uint32 {
280 b := r.take(4, 4)
281 if b == nil {
282 return 0
283 }
284 if r.big {
285 return binary.BigEndian.Uint32(b)
286 }
287 return binary.LittleEndian.Uint32(b)
288}
289
290// UnixFD reads a UNIX_FD (h): an index into the fds sent with the message.
291// zerobus does not receive file descriptors, so the index has nothing to
292// point to; it is only read so the following values can be.
293func (r *Reader) UnixFD() uint32 { return r.Uint32() }
294
295// Int64 reads an INT64 (x).
296func (r *Reader) Int64() int64 { return int64(r.Uint64()) }
297
298// Uint64 reads a UINT64 (t).
299func (r *Reader) Uint64() uint64 {
300 b := r.take(8, 8)
301 if b == nil {
302 return 0
303 }
304 if r.big {
305 return binary.BigEndian.Uint64(b)
306 }
307 return binary.LittleEndian.Uint64(b)
308}
309
310// Float64 reads a DOUBLE (d).
311func (r *Reader) Float64() float64 { return math.Float64frombits(r.Uint64()) }
312
313// Str reads a STRING (s). The result points into the message buffer.
314func (r *Reader) Str() string { return r.str(int(r.Uint32())) }
315
316// ObjectPath reads an OBJECT_PATH (o). The result points into the message
317// buffer.
318func (r *Reader) ObjectPath() string { return r.Str() }
319
320// Signature reads a SIGNATURE (g). The result points into the message buffer.
321func (r *Reader) Signature() string { return r.str(int(r.Byte())) }
322
323// str returns the next n bytes as a string and skips the NUL after them.
324func (r *Reader) str(n int) string {
325 if r.err != nil {
326 return ""
327 }
328 if n < 0 || n > len(r.buf)-r.off-1 || r.buf[r.off+n] != 0 {
329 r.fail()
330 return ""
331 }
332 s := unsafe.String(unsafe.SliceData(r.buf[r.off:]), n)
333 r.off += n + 1
334 return s
335}
336
337// Variant reads the signature of a VARIANT (v) and returns it. Read the
338// value that follows with the matching method, or skip it with Skip.
339func (r *Reader) Variant() string {
340 sig := r.Signature()
341 if r.err == nil && sigEnd(sig, 0) != len(sig) {
342 r.fail()
343 return ""
344 }
345 return sig
346}
347
348// Struct aligns the reader to the start of a STRUCT or DICT_ENTRY. Call it
349// before reading the first field.
350func (r *Reader) Struct() { r.take(8, 0) }
351
352// Array reads the header of an ARRAY whose element type starts with the
353// signature byte elem, and returns the offset where the array ends. Read the
354// elements while More returns true:
355//
356// end := r.Array('s')
357// for r.More(end) {
358// name := r.Str()
359// }
360func (r *Reader) Array(elem byte) int {
361 n := r.Uint32()
362 if r.err != nil {
363 return r.off
364 }
365 if n > maxArray {
366 r.fail()
367 return r.off
368 }
369 off := pad(r.off, alignOf(elem))
370 if off > len(r.buf)-int(n) {
371 r.fail()
372 return r.off
373 }
374 r.off = off
375 return off + int(n)
376}
377
378// More reports whether the array that ends at end has another element.
379func (r *Reader) More(end int) bool {
380 if r.err != nil {
381 return false
382 }
383 if r.off < end {
384 return true
385 }
386 if r.off > end {
387 r.fail()
388 }
389 return false
390}
391
392// SkipTo moves to end, the value returned by Array. Use it to leave an array
393// before its last element.
394func (r *Reader) SkipTo(end int) {
395 if r.err != nil {
396 return
397 }
398 if end < r.off || end > len(r.buf) {
399 r.fail()
400 return
401 }
402 r.off = end
403}
404
405// ByteArray reads an ARRAY of BYTE (ay). The result points into the message
406// buffer.
407func (r *Reader) ByteArray() []byte {
408 end := r.Array('y')
409 if r.err != nil {
410 return nil
411 }
412 b := r.buf[r.off:end:end]
413 r.off = end
414 return b
415}
416
417// Skip reads past values of the given signature. Arrays are skipped by their
418// length, without reading their elements.
419func (r *Reader) Skip(sig string) { r.skip(sig, 0, false) }
420
421// check reads every value of sig, array elements included, and fails on any
422// value the bus would reject. It proves an outgoing body matches its
423// signature.
424func (r *Reader) check(sig string) { r.skip(sig, 0, true) }
425
426func (r *Reader) skip(sig string, depth int, strict bool) {
427 for i := 0; i < len(sig) && r.err == nil; {
428 i = r.skipOne(sig, i, depth, strict)
429 }
430}
431
432// skipOne skips the value of the type at sig[i] and returns the index of the
433// next type. In strict mode it also reads array elements and checks values.
434func (r *Reader) skipOne(sig string, i, depth int, strict bool) int {
435 if depth > maxDepth {
436 r.fail()
437 return len(sig)
438 }
439 switch c := sig[i]; c {
440 case 'y':
441 r.take(1, 1)
442 case 'n', 'q':
443 r.take(2, 2)
444 case 'b':
445 r.Bool()
446 case 'i', 'u', 'h':
447 r.take(4, 4)
448 case 'x', 't', 'd':
449 r.take(8, 8)
450 case 's', 'o':
451 s := r.Str()
452 if strict && (!utf8.ValidString(s) || c == 'o' && !validPath(s)) {
453 r.fail()
454 }
455 case 'g':
456 if s := r.Signature(); strict && !validSignature(s) {
457 r.fail()
458 }
459 case 'v':
460 r.skip(r.Variant(), depth+1, strict)
461 case 'a':
462 next := sigEnd(sig, i)
463 if next < 0 {
464 r.fail()
465 return len(sig)
466 }
467 end := r.Array(sig[i+1])
468 if !strict {
469 r.SkipTo(end)
470 return next
471 }
472 for r.More(end) {
473 r.skipOne(sig, i+1, depth+1, true)
474 }
475 return next
476 case '(', '{':
477 closer := byte(')')
478 if c == '{' {
479 closer = '}'
480 }
481 r.Struct()
482 j := i + 1
483 for j < len(sig) && sig[j] != closer && r.err == nil {
484 j = r.skipOne(sig, j, depth+1, strict)
485 }
486 if j >= len(sig) {
487 r.fail()
488 return len(sig)
489 }
490 return j + 1
491 default:
492 r.fail()
493 return len(sig)
494 }
495 return i + 1
496}
497
498// Encoder appends D-Bus values to an outgoing message. Get one from
499// Conn.NewCall, Conn.Signal, Conn.Reply or Conn.Error, write the body values
500// in the order of the message signature, then call Conn.Send.
501//
502// Errors are sticky and reported by Conn.Send.
503type Encoder struct {
504 buf []byte
505 body int // offset of the body; 0 when no message is being built
506 sig string // body signature, checked by finish
507 err error
508}
509
510func (e *Encoder) invalid() {
511 if e.err == nil {
512 e.err = ErrInvalid
513 }
514}
515
516func (e *Encoder) pad(n int) {
517 for len(e.buf)&(n-1) != 0 {
518 e.buf = append(e.buf, 0)
519 }
520}
521
522// Byte writes a BYTE (y).
523func (e *Encoder) Byte(v byte) { e.buf = append(e.buf, v) }
524
525// Bool writes a BOOLEAN (b).
526func (e *Encoder) Bool(v bool) {
527 var u uint32
528 if v {
529 u = 1
530 }
531 e.Uint32(u)
532}
533
534// Int16 writes an INT16 (n).
535func (e *Encoder) Int16(v int16) { e.Uint16(uint16(v)) }
536
537// Uint16 writes a UINT16 (q).
538func (e *Encoder) Uint16(v uint16) {
539 e.pad(2)
540 e.buf = binary.LittleEndian.AppendUint16(e.buf, v)
541}
542
543// Int32 writes an INT32 (i).
544func (e *Encoder) Int32(v int32) { e.Uint32(uint32(v)) }
545
546// Uint32 writes a UINT32 (u).
547func (e *Encoder) Uint32(v uint32) {
548 e.pad(4)
549 e.buf = binary.LittleEndian.AppendUint32(e.buf, v)
550}
551
552// Int64 writes an INT64 (x).
553func (e *Encoder) Int64(v int64) { e.Uint64(uint64(v)) }
554
555// Uint64 writes a UINT64 (t).
556func (e *Encoder) Uint64(v uint64) {
557 e.pad(8)
558 e.buf = binary.LittleEndian.AppendUint64(e.buf, v)
559}
560
561// Float64 writes a DOUBLE (d).
562func (e *Encoder) Float64(v float64) { e.Uint64(math.Float64bits(v)) }
563
564// Str writes a STRING (s).
565func (e *Encoder) Str(s string) {
566 e.Uint32(uint32(len(s)))
567 e.text(s)
568}
569
570// ObjectPath writes an OBJECT_PATH (o).
571func (e *Encoder) ObjectPath(p string) {
572 if !validPath(p) {
573 e.invalid()
574 }
575 e.Str(p)
576}
577
578// Signature writes a SIGNATURE (g).
579func (e *Encoder) Signature(sig string) {
580 if !validSignature(sig) {
581 e.invalid()
582 }
583 e.Byte(byte(len(sig)))
584 e.text(sig)
585}
586
587// text appends s and its NUL terminator.
588func (e *Encoder) text(s string) {
589 // The bus disconnects a client that sends a NUL or invalid UTF-8.
590 if strings.IndexByte(s, 0) >= 0 || !utf8.ValidString(s) {
591 e.invalid()
592 }
593 e.buf = append(e.buf, s...)
594 e.buf = append(e.buf, 0)
595}
596
597// Variant writes the signature of a VARIANT (v). Write its value next.
598func (e *Encoder) Variant(sig string) {
599 if sigEnd(sig, 0) != len(sig) {
600 e.invalid()
601 }
602 e.Signature(sig)
603}
604
605// Struct aligns the encoder to the start of a STRUCT or DICT_ENTRY. Call it
606// before writing the first field.
607func (e *Encoder) Struct() { e.pad(8) }
608
609// ArrayMark is an array being written; pass it to EndArray.
610type ArrayMark struct{ at, start int }
611
612// BeginArray starts an ARRAY whose element type starts with the signature
613// byte elem. Write the elements, then call EndArray:
614//
615// a := e.BeginArray('s')
616// e.Str("one")
617// e.Str("two")
618// e.EndArray(a)
619func (e *Encoder) BeginArray(elem byte) ArrayMark {
620 e.pad(4)
621 at := len(e.buf)
622 e.buf = append(e.buf, 0, 0, 0, 0)
623 e.pad(alignOf(elem))
624 return ArrayMark{at: at, start: len(e.buf)}
625}
626
627// EndArray finishes the array started by BeginArray.
628func (e *Encoder) EndArray(a ArrayMark) {
629 n := len(e.buf) - a.start
630 if n > maxArray {
631 e.invalid()
632 return
633 }
634 binary.LittleEndian.PutUint32(e.buf[a.at:], uint32(n))
635}
636
637// ByteArray writes an ARRAY of BYTE (ay).
638func (e *Encoder) ByteArray(b []byte) {
639 e.Uint32(uint32(len(b)))
640 e.buf = append(e.buf, b...)
641}
642
643// SetFlags sets the flags of the message being built.
644func (e *Encoder) SetFlags(f Flags) {
645 if e.body != 0 {
646 e.buf[2] = byte(f)
647 }
648}