1package dbus
2
3import (
4	"bytes"
5	"encoding/binary"
6	"errors"
7	"io"
8	"reflect"
9	"strconv"
10)
11
12const protoVersion byte = 1
13
14// Flags represents the possible flags of a D-Bus message.
15type Flags byte
16
17const (
18	// FlagNoReplyExpected signals that the message is not expected to generate
19	// a reply. If this flag is set on outgoing messages, any possible reply
20	// will be discarded.
21	FlagNoReplyExpected Flags = 1 << iota
22	// FlagNoAutoStart signals that the message bus should not automatically
23	// start an application when handling this message.
24	FlagNoAutoStart
25)
26
27// Type represents the possible types of a D-Bus message.
28type Type byte
29
30const (
31	TypeMethodCall Type = 1 + iota
32	TypeMethodReply
33	TypeError
34	TypeSignal
35	typeMax
36)
37
38func (t Type) String() string {
39	switch t {
40	case TypeMethodCall:
41		return "method call"
42	case TypeMethodReply:
43		return "reply"
44	case TypeError:
45		return "error"
46	case TypeSignal:
47		return "signal"
48	}
49	return "invalid"
50}
51
52// HeaderField represents the possible byte codes for the headers
53// of a D-Bus message.
54type HeaderField byte
55
56const (
57	FieldPath HeaderField = 1 + iota
58	FieldInterface
59	FieldMember
60	FieldErrorName
61	FieldReplySerial
62	FieldDestination
63	FieldSender
64	FieldSignature
65	FieldUnixFDs
66	fieldMax
67)
68
69// An InvalidMessageError describes the reason why a D-Bus message is regarded as
70// invalid.
71type InvalidMessageError string
72
73func (e InvalidMessageError) Error() string {
74	return "dbus: invalid message: " + string(e)
75}
76
77// fieldType are the types of the various header fields.
78var fieldTypes = [fieldMax]reflect.Type{
79	FieldPath:        objectPathType,
80	FieldInterface:   stringType,
81	FieldMember:      stringType,
82	FieldErrorName:   stringType,
83	FieldReplySerial: uint32Type,
84	FieldDestination: stringType,
85	FieldSender:      stringType,
86	FieldSignature:   signatureType,
87	FieldUnixFDs:     uint32Type,
88}
89
90// requiredFields lists the header fields that are required by the different
91// message types.
92var requiredFields = [typeMax][]HeaderField{
93	TypeMethodCall:  {FieldPath, FieldMember},
94	TypeMethodReply: {FieldReplySerial},
95	TypeError:       {FieldErrorName, FieldReplySerial},
96	TypeSignal:      {FieldPath, FieldInterface, FieldMember},
97}
98
99// Message represents a single D-Bus message.
100type Message struct {
101	Type
102	Flags
103	Headers map[HeaderField]Variant
104	Body    []interface{}
105
106	serial uint32
107}
108
109type header struct {
110	Field byte
111	Variant
112}
113
114// DecodeMessage tries to decode a single message in the D-Bus wire format
115// from the given reader. The byte order is figured out from the first byte.
116// The possibly returned error can be an error of the underlying reader, an
117// InvalidMessageError or a FormatError.
118func DecodeMessage(rd io.Reader) (msg *Message, err error) {
119	var order binary.ByteOrder
120	var hlength, length uint32
121	var typ, flags, proto byte
122	var headers []header
123
124	b := make([]byte, 1)
125	_, err = rd.Read(b)
126	if err != nil {
127		return
128	}
129	switch b[0] {
130	case 'l':
131		order = binary.LittleEndian
132	case 'B':
133		order = binary.BigEndian
134	default:
135		return nil, InvalidMessageError("invalid byte order")
136	}
137
138	dec := newDecoder(rd, order)
139	dec.pos = 1
140
141	msg = new(Message)
142	vs, err := dec.Decode(Signature{"yyyuu"})
143	if err != nil {
144		return nil, err
145	}
146	if err = Store(vs, &typ, &flags, &proto, &length, &msg.serial); err != nil {
147		return nil, err
148	}
149	msg.Type = Type(typ)
150	msg.Flags = Flags(flags)
151
152	// get the header length separately because we need it later
153	b = make([]byte, 4)
154	_, err = io.ReadFull(rd, b)
155	if err != nil {
156		return nil, err
157	}
158	binary.Read(bytes.NewBuffer(b), order, &hlength)
159	if hlength+length+16 > 1<<27 {
160		return nil, InvalidMessageError("message is too long")
161	}
162	dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order)
163	dec.pos = 12
164	vs, err = dec.Decode(Signature{"a(yv)"})
165	if err != nil {
166		return nil, err
167	}
168	if err = Store(vs, &headers); err != nil {
169		return nil, err
170	}
171
172	msg.Headers = make(map[HeaderField]Variant)
173	for _, v := range headers {
174		msg.Headers[HeaderField(v.Field)] = v.Variant
175	}
176
177	dec.align(8)
178	body := make([]byte, int(length))
179	if length != 0 {
180		_, err := io.ReadFull(rd, body)
181		if err != nil {
182			return nil, err
183		}
184	}
185
186	if err = msg.IsValid(); err != nil {
187		return nil, err
188	}
189	sig, _ := msg.Headers[FieldSignature].value.(Signature)
190	if sig.str != "" {
191		buf := bytes.NewBuffer(body)
192		dec = newDecoder(buf, order)
193		vs, err := dec.Decode(sig)
194		if err != nil {
195			return nil, err
196		}
197		msg.Body = vs
198	}
199
200	return
201}
202
203// EncodeTo encodes and sends a message to the given writer. The byte order must
204// be either binary.LittleEndian or binary.BigEndian. If the message is not
205// valid or an error occurs when writing, an error is returned.
206func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) error {
207	if err := msg.IsValid(); err != nil {
208		return err
209	}
210	var vs [7]interface{}
211	switch order {
212	case binary.LittleEndian:
213		vs[0] = byte('l')
214	case binary.BigEndian:
215		vs[0] = byte('B')
216	default:
217		return errors.New("dbus: invalid byte order")
218	}
219	body := new(bytes.Buffer)
220	enc := newEncoder(body, order)
221	if len(msg.Body) != 0 {
222		enc.Encode(msg.Body...)
223	}
224	vs[1] = msg.Type
225	vs[2] = msg.Flags
226	vs[3] = protoVersion
227	vs[4] = uint32(len(body.Bytes()))
228	vs[5] = msg.serial
229	headers := make([]header, 0, len(msg.Headers))
230	for k, v := range msg.Headers {
231		headers = append(headers, header{byte(k), v})
232	}
233	vs[6] = headers
234	var buf bytes.Buffer
235	enc = newEncoder(&buf, order)
236	enc.Encode(vs[:]...)
237	enc.align(8)
238	body.WriteTo(&buf)
239	if buf.Len() > 1<<27 {
240		return InvalidMessageError("message is too long")
241	}
242	if _, err := buf.WriteTo(out); err != nil {
243		return err
244	}
245	return nil
246}
247
248// IsValid checks whether msg is a valid message and returns an
249// InvalidMessageError if it is not.
250func (msg *Message) IsValid() error {
251	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected) != 0 {
252		return InvalidMessageError("invalid flags")
253	}
254	if msg.Type == 0 || msg.Type >= typeMax {
255		return InvalidMessageError("invalid message type")
256	}
257	for k, v := range msg.Headers {
258		if k == 0 || k >= fieldMax {
259			return InvalidMessageError("invalid header")
260		}
261		if reflect.TypeOf(v.value) != fieldTypes[k] {
262			return InvalidMessageError("invalid type of header field")
263		}
264	}
265	for _, v := range requiredFields[msg.Type] {
266		if _, ok := msg.Headers[v]; !ok {
267			return InvalidMessageError("missing required header")
268		}
269	}
270	if path, ok := msg.Headers[FieldPath]; ok {
271		if !path.value.(ObjectPath).IsValid() {
272			return InvalidMessageError("invalid path name")
273		}
274	}
275	if iface, ok := msg.Headers[FieldInterface]; ok {
276		if !isValidInterface(iface.value.(string)) {
277			return InvalidMessageError("invalid interface name")
278		}
279	}
280	if member, ok := msg.Headers[FieldMember]; ok {
281		if !isValidMember(member.value.(string)) {
282			return InvalidMessageError("invalid member name")
283		}
284	}
285	if errname, ok := msg.Headers[FieldErrorName]; ok {
286		if !isValidInterface(errname.value.(string)) {
287			return InvalidMessageError("invalid error name")
288		}
289	}
290	if len(msg.Body) != 0 {
291		if _, ok := msg.Headers[FieldSignature]; !ok {
292			return InvalidMessageError("missing signature")
293		}
294	}
295	return nil
296}
297
298// Serial returns the message's serial number. The returned value is only valid
299// for messages received by eavesdropping.
300func (msg *Message) Serial() uint32 {
301	return msg.serial
302}
303
304// String returns a string representation of a message similar to the format of
305// dbus-monitor.
306func (msg *Message) String() string {
307	if err := msg.IsValid(); err != nil {
308		return "<invalid>"
309	}
310	s := msg.Type.String()
311	if v, ok := msg.Headers[FieldSender]; ok {
312		s += " from " + v.value.(string)
313	}
314	if v, ok := msg.Headers[FieldDestination]; ok {
315		s += " to " + v.value.(string)
316	}
317	s += " serial " + strconv.FormatUint(uint64(msg.serial), 10)
318	if v, ok := msg.Headers[FieldReplySerial]; ok {
319		s += " reply_serial " + strconv.FormatUint(uint64(v.value.(uint32)), 10)
320	}
321	if v, ok := msg.Headers[FieldUnixFDs]; ok {
322		s += " unixfds " + strconv.FormatUint(uint64(v.value.(uint32)), 10)
323	}
324	if v, ok := msg.Headers[FieldPath]; ok {
325		s += " path " + string(v.value.(ObjectPath))
326	}
327	if v, ok := msg.Headers[FieldInterface]; ok {
328		s += " interface " + v.value.(string)
329	}
330	if v, ok := msg.Headers[FieldErrorName]; ok {
331		s += " error " + v.value.(string)
332	}
333	if v, ok := msg.Headers[FieldMember]; ok {
334		s += " member " + v.value.(string)
335	}
336	if len(msg.Body) != 0 {
337		s += "\n"
338	}
339	for i, v := range msg.Body {
340		s += "  " + MakeVariant(v).String()
341		if i != len(msg.Body)-1 {
342			s += "\n"
343		}
344	}
345	return s
346}
347