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