...

Source file src/github.com/godbus/dbus/v5/message.go

Documentation: github.com/godbus/dbus/v5

     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  func DecodeMessageWithFDs(rd io.Reader, fds []int) (msg *Message, err error) {
   122  	var order binary.ByteOrder
   123  	var hlength, length uint32
   124  	var typ, flags, proto byte
   125  	var headers []header
   126  
   127  	b := make([]byte, 1)
   128  	_, err = rd.Read(b)
   129  	if err != nil {
   130  		return
   131  	}
   132  	switch b[0] {
   133  	case 'l':
   134  		order = binary.LittleEndian
   135  	case 'B':
   136  		order = binary.BigEndian
   137  	default:
   138  		return nil, InvalidMessageError("invalid byte order")
   139  	}
   140  
   141  	dec := newDecoder(rd, order, fds)
   142  	dec.pos = 1
   143  
   144  	msg = new(Message)
   145  	vs, err := dec.Decode(Signature{"yyyuu"})
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  	if err = Store(vs, &typ, &flags, &proto, &length, &msg.serial); err != nil {
   150  		return nil, err
   151  	}
   152  	msg.Type = Type(typ)
   153  	msg.Flags = Flags(flags)
   154  
   155  	// get the header length separately because we need it later
   156  	b = make([]byte, 4)
   157  	_, err = io.ReadFull(rd, b)
   158  	if err != nil {
   159  		return nil, err
   160  	}
   161  	binary.Read(bytes.NewBuffer(b), order, &hlength)
   162  	if hlength+length+16 > 1<<27 {
   163  		return nil, InvalidMessageError("message is too long")
   164  	}
   165  	dec = newDecoder(io.MultiReader(bytes.NewBuffer(b), rd), order, fds)
   166  	dec.pos = 12
   167  	vs, err = dec.Decode(Signature{"a(yv)"})
   168  	if err != nil {
   169  		return nil, err
   170  	}
   171  	if err = Store(vs, &headers); err != nil {
   172  		return nil, err
   173  	}
   174  
   175  	msg.Headers = make(map[HeaderField]Variant)
   176  	for _, v := range headers {
   177  		msg.Headers[HeaderField(v.Field)] = v.Variant
   178  	}
   179  
   180  	dec.align(8)
   181  	body := make([]byte, int(length))
   182  	if length != 0 {
   183  		_, err := io.ReadFull(rd, body)
   184  		if err != nil {
   185  			return nil, err
   186  		}
   187  	}
   188  
   189  	if err = msg.IsValid(); err != nil {
   190  		return nil, err
   191  	}
   192  	sig, _ := msg.Headers[FieldSignature].value.(Signature)
   193  	if sig.str != "" {
   194  		buf := bytes.NewBuffer(body)
   195  		dec = newDecoder(buf, order, fds)
   196  		vs, err := dec.Decode(sig)
   197  		if err != nil {
   198  			return nil, err
   199  		}
   200  		msg.Body = vs
   201  	}
   202  
   203  	return
   204  }
   205  
   206  // DecodeMessage tries to decode a single message in the D-Bus wire format
   207  // from the given reader. The byte order is figured out from the first byte.
   208  // The possibly returned error can be an error of the underlying reader, an
   209  // InvalidMessageError or a FormatError.
   210  func DecodeMessage(rd io.Reader) (msg *Message, err error) {
   211  	return DecodeMessageWithFDs(rd, make([]int, 0))
   212  }
   213  
   214  type nullwriter struct{}
   215  
   216  func (nullwriter) Write(p []byte) (cnt int, err error) {
   217  	return len(p), nil
   218  }
   219  
   220  func (msg *Message) CountFds() (int, error) {
   221  	if len(msg.Body) == 0 {
   222  		return 0, nil
   223  	}
   224  	enc := newEncoder(nullwriter{}, nativeEndian, make([]int, 0))
   225  	err := enc.Encode(msg.Body...)
   226  	return len(enc.fds), err
   227  }
   228  
   229  func (msg *Message) EncodeToWithFDs(out io.Writer, order binary.ByteOrder) (fds []int, err error) {
   230  	if err := msg.validateHeader(); err != nil {
   231  		return nil, err
   232  	}
   233  	var vs [7]interface{}
   234  	switch order {
   235  	case binary.LittleEndian:
   236  		vs[0] = byte('l')
   237  	case binary.BigEndian:
   238  		vs[0] = byte('B')
   239  	default:
   240  		return nil, errors.New("dbus: invalid byte order")
   241  	}
   242  	body := new(bytes.Buffer)
   243  	fds = make([]int, 0)
   244  	enc := newEncoder(body, order, fds)
   245  	if len(msg.Body) != 0 {
   246  		err = enc.Encode(msg.Body...)
   247  		if err != nil {
   248  			return
   249  		}
   250  	}
   251  	vs[1] = msg.Type
   252  	vs[2] = msg.Flags
   253  	vs[3] = protoVersion
   254  	vs[4] = uint32(len(body.Bytes()))
   255  	vs[5] = msg.serial
   256  	headers := make([]header, 0, len(msg.Headers))
   257  	for k, v := range msg.Headers {
   258  		headers = append(headers, header{byte(k), v})
   259  	}
   260  	vs[6] = headers
   261  	var buf bytes.Buffer
   262  	enc = newEncoder(&buf, order, enc.fds)
   263  	err = enc.Encode(vs[:]...)
   264  	if err != nil {
   265  		return
   266  	}
   267  	enc.align(8)
   268  	body.WriteTo(&buf)
   269  	if buf.Len() > 1<<27 {
   270  		return make([]int, 0), InvalidMessageError("message is too long")
   271  	}
   272  	if _, err := buf.WriteTo(out); err != nil {
   273  		return make([]int, 0), err
   274  	}
   275  	return enc.fds, nil
   276  }
   277  
   278  // EncodeTo encodes and sends a message to the given writer. The byte order must
   279  // be either binary.LittleEndian or binary.BigEndian. If the message is not
   280  // valid or an error occurs when writing, an error is returned.
   281  func (msg *Message) EncodeTo(out io.Writer, order binary.ByteOrder) (err error) {
   282  	_, err = msg.EncodeToWithFDs(out, order)
   283  	return err
   284  }
   285  
   286  // IsValid checks whether msg is a valid message and returns an
   287  // InvalidMessageError or FormatError if it is not.
   288  func (msg *Message) IsValid() error {
   289  	var b bytes.Buffer
   290  	return msg.EncodeTo(&b, nativeEndian)
   291  }
   292  
   293  func (msg *Message) validateHeader() error {
   294  	if msg.Flags & ^(FlagNoAutoStart|FlagNoReplyExpected|FlagAllowInteractiveAuthorization) != 0 {
   295  		return InvalidMessageError("invalid flags")
   296  	}
   297  	if msg.Type == 0 || msg.Type >= typeMax {
   298  		return InvalidMessageError("invalid message type")
   299  	}
   300  	for k, v := range msg.Headers {
   301  		if k == 0 || k >= fieldMax {
   302  			return InvalidMessageError("invalid header")
   303  		}
   304  		if reflect.TypeOf(v.value) != fieldTypes[k] {
   305  			return InvalidMessageError("invalid type of header field")
   306  		}
   307  	}
   308  	for _, v := range requiredFields[msg.Type] {
   309  		if _, ok := msg.Headers[v]; !ok {
   310  			return InvalidMessageError("missing required header")
   311  		}
   312  	}
   313  	if path, ok := msg.Headers[FieldPath]; ok {
   314  		if !path.value.(ObjectPath).IsValid() {
   315  			return InvalidMessageError("invalid path name")
   316  		}
   317  	}
   318  	if iface, ok := msg.Headers[FieldInterface]; ok {
   319  		if !isValidInterface(iface.value.(string)) {
   320  			return InvalidMessageError("invalid interface name")
   321  		}
   322  	}
   323  	if member, ok := msg.Headers[FieldMember]; ok {
   324  		if !isValidMember(member.value.(string)) {
   325  			return InvalidMessageError("invalid member name")
   326  		}
   327  	}
   328  	if errname, ok := msg.Headers[FieldErrorName]; ok {
   329  		if !isValidInterface(errname.value.(string)) {
   330  			return InvalidMessageError("invalid error name")
   331  		}
   332  	}
   333  	if len(msg.Body) != 0 {
   334  		if _, ok := msg.Headers[FieldSignature]; !ok {
   335  			return InvalidMessageError("missing signature")
   336  		}
   337  	}
   338  
   339  	return nil
   340  }
   341  
   342  // Serial returns the message's serial number. The returned value is only valid
   343  // for messages received by eavesdropping.
   344  func (msg *Message) Serial() uint32 {
   345  	return msg.serial
   346  }
   347  
   348  // String returns a string representation of a message similar to the format of
   349  // dbus-monitor.
   350  func (msg *Message) String() string {
   351  	if err := msg.IsValid(); err != nil {
   352  		return "<invalid>"
   353  	}
   354  	s := msg.Type.String()
   355  	if v, ok := msg.Headers[FieldSender]; ok {
   356  		s += " from " + v.value.(string)
   357  	}
   358  	if v, ok := msg.Headers[FieldDestination]; ok {
   359  		s += " to " + v.value.(string)
   360  	}
   361  	s += " serial " + strconv.FormatUint(uint64(msg.serial), 10)
   362  	if v, ok := msg.Headers[FieldReplySerial]; ok {
   363  		s += " reply_serial " + strconv.FormatUint(uint64(v.value.(uint32)), 10)
   364  	}
   365  	if v, ok := msg.Headers[FieldUnixFDs]; ok {
   366  		s += " unixfds " + strconv.FormatUint(uint64(v.value.(uint32)), 10)
   367  	}
   368  	if v, ok := msg.Headers[FieldPath]; ok {
   369  		s += " path " + string(v.value.(ObjectPath))
   370  	}
   371  	if v, ok := msg.Headers[FieldInterface]; ok {
   372  		s += " interface " + v.value.(string)
   373  	}
   374  	if v, ok := msg.Headers[FieldErrorName]; ok {
   375  		s += " error " + v.value.(string)
   376  	}
   377  	if v, ok := msg.Headers[FieldMember]; ok {
   378  		s += " member " + v.value.(string)
   379  	}
   380  	if len(msg.Body) != 0 {
   381  		s += "\n"
   382  	}
   383  	for i, v := range msg.Body {
   384  		s += "  " + MakeVariant(v).String()
   385  		if i != len(msg.Body)-1 {
   386  			s += "\n"
   387  		}
   388  	}
   389  	return s
   390  }
   391  

View as plain text