Class: DBus::Message

Inherits:
Object
  • Object
show all
Defined in:
lib/dbus/message.rb

Overview

D-Bus message class

Class that holds any type of message that travels over the bus.

Direct Known Subclasses

ErrorMessage, MethodReturnMessage

Constant Summary collapse

MESSAGE_SIGNATURE =

Type of a message (by specification).

"yyyyuua(yv)"
INVALID =

FIXME: following message type constants should be under Message::Type IMO well, yeah sure

Invalid message type.

0
METHOD_CALL =

Method call message type.

1
METHOD_RETURN =

Method call return value message type.

2
ERROR =

Error message type.

3
SIGNAL =

Signal message type.

4
TYPE_NAMES =

Names used by signal match rules

["invalid", "method_call", "method_return", "error", "signal"].freeze
NO_REPLY_EXPECTED =

Message flag signyfing that no reply is expected.

0x1
NO_AUTO_START =

Message flag signifying that no automatic start is required/must be performed.

0x2
ENDIANNESS_CHAR =

“l” or “B”

ENV.fetch("RUBY_DBUS_ENDIANNESS", HOST_END)
ENDIANNESS =
RawMessage.endianness(ENDIANNESS_CHAR)
PATH =

FIXME: what are these? a message element constant enumeration? See method below, in a message, you have and array of optional parameters that come with an index, to determine their meaning. The values are in spec, more a definition than an enumeration.

1
INTERFACE =
2
MEMBER =
3
ERROR_NAME =
4
REPLY_SERIAL =
5
DESTINATION =
6
SENDER =
7
SIGNATURE =
8
RESERVED_PATH =
"/org/freedesktop/DBus/Local"
@@serial =

The serial number of the message.

1
@@serial_mutex =

Mutex that protects updates on the serial number.

Mutex.new

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(mtype = INVALID) ⇒ Message

Create a message with message type mtype with default values and a unique serial number.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/dbus/message.rb', line 83

def initialize(mtype = INVALID)
  @message_type = mtype

  @flags = 0
  @protocol = 1
  @body_length = 0
  @signature = ""
  @@serial_mutex.synchronize do
    @serial = @@serial
    @@serial += 1
  end
  @params = []
  @destination = nil
  @interface = nil
  @error_name = nil
  @member = nil
  @path = nil
  @reply_serial = nil
  @flags = NO_REPLY_EXPECTED if mtype == METHOD_RETURN
end

Instance Attribute Details

#destinationObject

The destination connection of the object that must be used/was used.



65
66
67
# File 'lib/dbus/message.rb', line 65

def destination
  @destination
end

#error_nameObject

The name of the error (in case of an error message type).



63
64
65
# File 'lib/dbus/message.rb', line 63

def error_name
  @error_name
end

#interfaceObject

The interface of the object that must be used/was used.



58
59
60
# File 'lib/dbus/message.rb', line 58

def interface
  @interface
end

#memberObject

The interface member (method/signal name) of the object that must be used/was used.



61
62
63
# File 'lib/dbus/message.rb', line 61

def member
  @member
end

#message_typeObject (readonly)

The type of the message.



54
55
56
# File 'lib/dbus/message.rb', line 54

def message_type
  @message_type
end

#paramsObject (readonly)

The parameters of the message.



79
80
81
# File 'lib/dbus/message.rb', line 79

def params
  @params
end

#pathObject

The path of the object instance the message must be sent to/is sent from.



56
57
58
# File 'lib/dbus/message.rb', line 56

def path
  @path
end

#protocolObject (readonly)

The protocol.



74
75
76
# File 'lib/dbus/message.rb', line 74

def protocol
  @protocol
end

#reply_serialInteger

Returns (u32) The serial number of the message this message is a reply for.

Returns:

  • (Integer)

    (u32) The serial number of the message this message is a reply for.



72
73
74
# File 'lib/dbus/message.rb', line 72

def reply_serial
  @reply_serial
end

#senderObject

The sender of the message.



67
68
69
# File 'lib/dbus/message.rb', line 67

def sender
  @sender
end

#serialInteger (readonly)

Returns (u32) The serial of the message.

Returns:

  • (Integer)

    (u32) The serial of the message.



77
78
79
# File 'lib/dbus/message.rb', line 77

def serial
  @serial
end

#signatureObject

The signature of the message contents.



69
70
71
# File 'lib/dbus/message.rb', line 69

def signature
  @signature
end

Class Method Details

.error(msg, error_name, description = nil) ⇒ Object

Create an error reply to a message msg.



123
124
125
# File 'lib/dbus/message.rb', line 123

def self.error(msg, error_name, description = nil)
  ErrorMessage.new(error_name, description).reply_to(msg)
end

.method_return(msg) ⇒ Object

Create a regular reply to a message msg.



118
119
120
# File 'lib/dbus/message.rb', line 118

def self.method_return(msg)
  MethodReturnMessage.new.reply_to(msg)
end

Instance Method Details

#add_param(type, val) ⇒ Object

Add a parameter val of type type to the message.



137
138
139
140
141
# File 'lib/dbus/message.rb', line 137

def add_param(type, val)
  type = type.chr if type.is_a?(Integer)
  @signature += type.to_s
  @params << [type, val]
end

#annotate_exception(exc) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Make a new exception from ex, mark it as being caused by this message



243
244
245
246
247
# File 'lib/dbus/message.rb', line 243

def annotate_exception(exc)
  new_exc = exc.exception("#{exc}; caused by #{self}")
  new_exc.set_backtrace(exc.backtrace)
  new_exc
end

#marshallString

Marshall the message with its current set parameters and return it in a packet form.

Returns:

  • (String)


166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
# File 'lib/dbus/message.rb', line 166

def marshall
  if @path == RESERVED_PATH
    # the bus would disconnect us, better explain why
    raise "Cannot send a message with the reserved path #{RESERVED_PATH}: #{inspect}"
  end

  params_marshaller = PacketMarshaller.new(endianness: ENDIANNESS)
  @params.each do |type, value|
    params_marshaller.append(type, value)
  end
  @body_length = params_marshaller.packet.bytesize

  marshaller = PacketMarshaller.new(endianness: ENDIANNESS)
  marshaller.append(Type::BYTE, ENDIANNESS_CHAR.ord)
  marshaller.append(Type::BYTE, @message_type)
  marshaller.append(Type::BYTE, @flags)
  marshaller.append(Type::BYTE, @protocol)
  marshaller.append(Type::UINT32, @body_length)
  marshaller.append(Type::UINT32, @serial)

  headers = []
  headers << [PATH,         ["o", @path]]         if @path
  headers << [INTERFACE,    ["s", @interface]]    if @interface
  headers << [MEMBER,       ["s", @member]]       if @member
  headers << [ERROR_NAME,   ["s", @error_name]]   if @error_name
  headers << [REPLY_SERIAL, ["u", @reply_serial]] if @reply_serial
  headers << [DESTINATION,  ["s", @destination]]  if @destination
  #           SENDER is not sent, the message bus fills it in instead
  headers << [SIGNATURE,    ["g", @signature]]    if @signature != ""
  marshaller.append("a(yv)", headers)

  marshaller.align(8)

  marshaller.packet + params_marshaller.packet
end

#message_type_sString

Returns name of message type, as used in match rules: “method_call”, “method_return”, “signal”, “error”.

Returns:

  • (String)

    name of message type, as used in match rules: “method_call”, “method_return”, “signal”, “error”



113
114
115
# File 'lib/dbus/message.rb', line 113

def message_type_s
  TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
end

#reply_to(msg) ⇒ Object

Mark this message as a reply to a another message msg, taking the serial number of msg as reply serial and the sender of msg as destination.



130
131
132
133
134
# File 'lib/dbus/message.rb', line 130

def reply_to(msg)
  @reply_serial = msg.serial
  @destination = msg.sender
  self
end

#to_sObject



104
105
106
107
108
109
# File 'lib/dbus/message.rb', line 104

def to_s
  "#{message_type} sender=#{sender} -> dest=#{destination} " \
  "serial=#{serial} reply_serial=#{reply_serial} " \
  "path=#{path}; interface=#{interface}; member=#{member} " \
  "error_name=#{error_name}"
end

#unmarshall_buffer(buf) ⇒ Array(Message,Integer)

Unmarshall a packet contained in the buffer buf and set the parameters of the message object according the data found in the buffer.

Returns:

  • (Array(Message,Integer))

    the detected message (self) and the index pointer of the buffer where the message data ended.



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
# File 'lib/dbus/message.rb', line 208

def unmarshall_buffer(buf)
  pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
  mdata = pu.unmarshall(MESSAGE_SIGNATURE)
  _, @message_type, @flags, @protocol, @body_length, @serial,
    headers = mdata

  headers.each do |struct|
    case struct[0]
    when PATH
      @path = struct[1]
    when INTERFACE
      @interface = struct[1]
    when MEMBER
      @member = struct[1]
    when ERROR_NAME
      @error_name = struct[1]
    when REPLY_SERIAL
      @reply_serial = struct[1]
    when DESTINATION
      @destination = struct[1]
    when SENDER
      @sender = struct[1]
    when SIGNATURE
      @signature = struct[1]
    end
  end
  pu.align_body
  if @body_length.positive? && @signature
    @params = pu.unmarshall(@signature, @body_length)
  end
  [self, pu.consumed_size]
end