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