encoder.go 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. package dbus
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "io"
  6. "reflect"
  7. "strings"
  8. "unicode/utf8"
  9. )
  10. // An encoder encodes values to the D-Bus wire format.
  11. type encoder struct {
  12. out io.Writer
  13. fds []int
  14. order binary.ByteOrder
  15. pos int
  16. }
  17. // NewEncoder returns a new encoder that writes to out in the given byte order.
  18. func newEncoder(out io.Writer, order binary.ByteOrder, fds []int) *encoder {
  19. enc := newEncoderAtOffset(out, 0, order, fds)
  20. return enc
  21. }
  22. // newEncoderAtOffset returns a new encoder that writes to out in the given
  23. // byte order. Specify the offset to initialize pos for proper alignment
  24. // computation.
  25. func newEncoderAtOffset(out io.Writer, offset int, order binary.ByteOrder, fds []int) *encoder {
  26. enc := new(encoder)
  27. enc.out = out
  28. enc.order = order
  29. enc.pos = offset
  30. enc.fds = fds
  31. return enc
  32. }
  33. // Aligns the next output to be on a multiple of n. Panics on write errors.
  34. func (enc *encoder) align(n int) {
  35. pad := enc.padding(0, n)
  36. if pad > 0 {
  37. empty := make([]byte, pad)
  38. if _, err := enc.out.Write(empty); err != nil {
  39. panic(err)
  40. }
  41. enc.pos += pad
  42. }
  43. }
  44. // pad returns the number of bytes of padding, based on current position and additional offset.
  45. // and alignment.
  46. func (enc *encoder) padding(offset, algn int) int {
  47. abs := enc.pos + offset
  48. if abs%algn != 0 {
  49. newabs := (abs + algn - 1) & ^(algn - 1)
  50. return newabs - abs
  51. }
  52. return 0
  53. }
  54. // Calls binary.Write(enc.out, enc.order, v) and panics on write errors.
  55. func (enc *encoder) binwrite(v interface{}) {
  56. if err := binary.Write(enc.out, enc.order, v); err != nil {
  57. panic(err)
  58. }
  59. }
  60. // Encode encodes the given values to the underlying reader. All written values
  61. // are aligned properly as required by the D-Bus spec.
  62. func (enc *encoder) Encode(vs ...interface{}) (err error) {
  63. defer func() {
  64. err, _ = recover().(error)
  65. }()
  66. for _, v := range vs {
  67. enc.encode(reflect.ValueOf(v), 0)
  68. }
  69. return nil
  70. }
  71. // encode encodes the given value to the writer and panics on error. depth holds
  72. // the depth of the container nesting.
  73. func (enc *encoder) encode(v reflect.Value, depth int) {
  74. if depth > 64 {
  75. panic(FormatError("input exceeds depth limitation"))
  76. }
  77. enc.align(alignment(v.Type()))
  78. switch v.Kind() {
  79. case reflect.Uint8:
  80. var b [1]byte
  81. b[0] = byte(v.Uint())
  82. if _, err := enc.out.Write(b[:]); err != nil {
  83. panic(err)
  84. }
  85. enc.pos++
  86. case reflect.Bool:
  87. if v.Bool() {
  88. enc.encode(reflect.ValueOf(uint32(1)), depth)
  89. } else {
  90. enc.encode(reflect.ValueOf(uint32(0)), depth)
  91. }
  92. case reflect.Int16:
  93. enc.binwrite(int16(v.Int()))
  94. enc.pos += 2
  95. case reflect.Uint16:
  96. enc.binwrite(uint16(v.Uint()))
  97. enc.pos += 2
  98. case reflect.Int, reflect.Int32:
  99. if v.Type() == unixFDType {
  100. fd := v.Int()
  101. idx := len(enc.fds)
  102. enc.fds = append(enc.fds, int(fd))
  103. enc.binwrite(uint32(idx))
  104. } else {
  105. enc.binwrite(int32(v.Int()))
  106. }
  107. enc.pos += 4
  108. case reflect.Uint, reflect.Uint32:
  109. enc.binwrite(uint32(v.Uint()))
  110. enc.pos += 4
  111. case reflect.Int64:
  112. enc.binwrite(v.Int())
  113. enc.pos += 8
  114. case reflect.Uint64:
  115. enc.binwrite(v.Uint())
  116. enc.pos += 8
  117. case reflect.Float64:
  118. enc.binwrite(v.Float())
  119. enc.pos += 8
  120. case reflect.String:
  121. str := v.String()
  122. if !utf8.ValidString(str) {
  123. panic(FormatError("input has a not-utf8 char in string"))
  124. }
  125. if strings.IndexByte(str, byte(0)) != -1 {
  126. panic(FormatError("input has a null char('\\000') in string"))
  127. }
  128. if v.Type() == objectPathType {
  129. if !ObjectPath(str).IsValid() {
  130. panic(FormatError("invalid object path"))
  131. }
  132. }
  133. enc.encode(reflect.ValueOf(uint32(len(str))), depth)
  134. b := make([]byte, v.Len()+1)
  135. copy(b, str)
  136. b[len(b)-1] = 0
  137. n, err := enc.out.Write(b)
  138. if err != nil {
  139. panic(err)
  140. }
  141. enc.pos += n
  142. case reflect.Ptr:
  143. enc.encode(v.Elem(), depth)
  144. case reflect.Slice, reflect.Array:
  145. // Lookahead offset: 4 bytes for uint32 length (with alignment),
  146. // plus alignment for elements.
  147. n := enc.padding(0, 4) + 4
  148. offset := enc.pos + n + enc.padding(n, alignment(v.Type().Elem()))
  149. var buf bytes.Buffer
  150. bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
  151. for i := 0; i < v.Len(); i++ {
  152. bufenc.encode(v.Index(i), depth+1)
  153. }
  154. if buf.Len() > 1<<26 {
  155. panic(FormatError("input exceeds array size limitation"))
  156. }
  157. enc.fds = bufenc.fds
  158. enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
  159. length := buf.Len()
  160. enc.align(alignment(v.Type().Elem()))
  161. if _, err := buf.WriteTo(enc.out); err != nil {
  162. panic(err)
  163. }
  164. enc.pos += length
  165. case reflect.Struct:
  166. switch t := v.Type(); t {
  167. case signatureType:
  168. str := v.Field(0)
  169. enc.encode(reflect.ValueOf(byte(str.Len())), depth)
  170. b := make([]byte, str.Len()+1)
  171. copy(b, str.String())
  172. b[len(b)-1] = 0
  173. n, err := enc.out.Write(b)
  174. if err != nil {
  175. panic(err)
  176. }
  177. enc.pos += n
  178. case variantType:
  179. variant := v.Interface().(Variant)
  180. enc.encode(reflect.ValueOf(variant.sig), depth+1)
  181. enc.encode(reflect.ValueOf(variant.value), depth+1)
  182. default:
  183. for i := 0; i < v.Type().NumField(); i++ {
  184. field := t.Field(i)
  185. if field.PkgPath == "" && field.Tag.Get("dbus") != "-" {
  186. enc.encode(v.Field(i), depth+1)
  187. }
  188. }
  189. }
  190. case reflect.Map:
  191. // Maps are arrays of structures, so they actually increase the depth by
  192. // 2.
  193. if !isKeyType(v.Type().Key()) {
  194. panic(InvalidTypeError{v.Type()})
  195. }
  196. keys := v.MapKeys()
  197. // Lookahead offset: 4 bytes for uint32 length (with alignment),
  198. // plus 8-byte alignment
  199. n := enc.padding(0, 4) + 4
  200. offset := enc.pos + n + enc.padding(n, 8)
  201. var buf bytes.Buffer
  202. bufenc := newEncoderAtOffset(&buf, offset, enc.order, enc.fds)
  203. for _, k := range keys {
  204. bufenc.align(8)
  205. bufenc.encode(k, depth+2)
  206. bufenc.encode(v.MapIndex(k), depth+2)
  207. }
  208. enc.fds = bufenc.fds
  209. enc.encode(reflect.ValueOf(uint32(buf.Len())), depth)
  210. length := buf.Len()
  211. enc.align(8)
  212. if _, err := buf.WriteTo(enc.out); err != nil {
  213. panic(err)
  214. }
  215. enc.pos += length
  216. case reflect.Interface:
  217. enc.encode(reflect.ValueOf(MakeVariant(v.Interface())), depth)
  218. default:
  219. panic(InvalidTypeError{v.Type()})
  220. }
  221. }