gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }