ruby-dbus 0.16.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/NEWS.md +288 -3
- data/README.md +3 -5
- data/Rakefile +27 -12
- data/VERSION +1 -1
- data/doc/Reference.md +109 -10
- data/examples/doc/_extract_examples +7 -0
- data/examples/no-bus/pulseaudio.rb +50 -0
- data/examples/no-introspect/nm-test.rb +2 -0
- data/examples/no-introspect/tracker-test.rb +3 -1
- data/examples/rhythmbox/playpause.rb +2 -1
- data/examples/service/call_service.rb +2 -1
- data/examples/service/complex-property.rb +21 -0
- data/examples/service/service_newapi.rb +3 -3
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +6 -3
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +10 -1
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +307 -217
- data/lib/dbus/bus.rb +155 -588
- data/lib/dbus/bus_name.rb +12 -8
- data/lib/dbus/connection.rb +363 -0
- data/lib/dbus/core_ext/class/attribute.rb +1 -1
- data/lib/dbus/data.rb +821 -0
- data/lib/dbus/emits_changed_signal.rb +83 -0
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +133 -31
- data/lib/dbus/logger.rb +6 -3
- data/lib/dbus/main.rb +66 -0
- data/lib/dbus/marshall.rb +247 -296
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +66 -57
- data/lib/dbus/message_queue.rb +40 -25
- data/lib/dbus/node_tree.rb +105 -0
- data/lib/dbus/object.rb +442 -33
- data/lib/dbus/object_manager.rb +61 -0
- data/lib/dbus/object_path.rb +11 -6
- data/lib/dbus/object_server.rb +149 -0
- data/lib/dbus/org.freedesktop.DBus.xml +97 -0
- data/lib/dbus/platform.rb +26 -0
- data/lib/dbus/proxy_object.rb +30 -11
- data/lib/dbus/proxy_object_factory.rb +13 -7
- data/lib/dbus/proxy_object_interface.rb +63 -30
- data/lib/dbus/proxy_service.rb +107 -0
- data/lib/dbus/raw_message.rb +91 -0
- data/lib/dbus/type.rb +319 -86
- data/lib/dbus/xml.rb +40 -19
- data/lib/dbus.rb +28 -17
- data/ruby-dbus.gemspec +13 -6
- data/spec/async_spec.rb +2 -0
- data/spec/auth_spec.rb +225 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +5 -1
- data/spec/bus_connection_spec.rb +93 -0
- data/spec/bus_name_spec.rb +3 -1
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +4 -2
- data/spec/connection_spec.rb +37 -0
- data/spec/coverage_helper.rb +39 -0
- data/spec/data/marshall.yaml +1667 -0
- data/spec/data_spec.rb +673 -0
- data/spec/dbus_spec.rb +22 -0
- data/spec/emits_changed_signal_spec.rb +58 -0
- data/spec/err_msg_spec.rb +2 -0
- data/spec/introspect_xml_parser_spec.rb +2 -0
- data/spec/introspection_spec.rb +2 -0
- data/spec/main_loop_spec.rb +17 -1
- data/spec/message_spec.rb +21 -0
- data/spec/mock-service/cockpit-dbustests.rb +29 -0
- data/spec/mock-service/com.redhat.Cockpit.DBusTests.xml +180 -0
- data/spec/mock-service/org.ruby.service.service +4 -0
- data/spec/mock-service/org.rubygems.ruby_dbus.DBusTests.service +4 -0
- data/spec/{service_newapi.rb → mock-service/spaghetti-monster.rb} +122 -75
- data/spec/node_spec.rb +65 -0
- data/spec/object_manager_spec.rb +33 -0
- data/spec/object_path_spec.rb +3 -0
- data/spec/object_server_spec.rb +138 -0
- data/spec/object_spec.rb +194 -0
- data/spec/packet_marshaller_spec.rb +41 -0
- data/spec/packet_unmarshaller_spec.rb +248 -0
- data/spec/platform_spec.rb +14 -0
- data/spec/property_spec.rb +214 -12
- data/spec/proxy_object_interface_spec.rb +35 -0
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/{bus_driver_spec.rb → proxy_service_spec.rb} +15 -8
- data/spec/raw_message_spec.rb +32 -0
- data/spec/server_robustness_spec.rb +20 -6
- data/spec/session_bus_spec.rb +36 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +16 -3
- data/spec/spec_helper.rb +25 -33
- data/spec/thread_safety_spec.rb +55 -12
- data/spec/tools/dbus-launch-simple +9 -6
- data/spec/tools/dbus-limited-session.conf +32 -0
- data/spec/tools/test_env +26 -6
- data/spec/type_spec.rb +214 -6
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- data/spec/zzz_quit_spec.rb +16 -0
- metadata +92 -20
- data/examples/gdbus/gdbus +0 -257
- data/examples/gdbus/gdbus.glade +0 -98
- data/examples/gdbus/launch.sh +0 -4
- data/spec/server_spec.rb +0 -53
- data/spec/tools/test_server +0 -39
data/lib/dbus/matchrule.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# This file is part of the ruby-dbus project
|
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
|
3
5
|
#
|
|
@@ -27,7 +29,7 @@ module DBus
|
|
|
27
29
|
attr_accessor :path
|
|
28
30
|
# The destination filter.
|
|
29
31
|
attr_accessor :destination
|
|
30
|
-
# The type type that is matched.
|
|
32
|
+
# @return [String] The type type that is matched.
|
|
31
33
|
attr_reader :type
|
|
32
34
|
|
|
33
35
|
# Create a new match rule
|
|
@@ -35,13 +37,14 @@ module DBus
|
|
|
35
37
|
@sender = @interface = @member = @path = @destination = @type = nil
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
# Set the message types to filter to type
|
|
40
|
+
# Set the message types to filter to type _typ_.
|
|
39
41
|
# Possible message types are: signal, method_call, method_return, and error.
|
|
40
|
-
def type=(
|
|
41
|
-
if !["signal", "method_call", "method_return", "error"].member?(
|
|
42
|
-
raise MatchRuleException,
|
|
42
|
+
def type=(typ)
|
|
43
|
+
if !["signal", "method_call", "method_return", "error"].member?(typ)
|
|
44
|
+
raise MatchRuleException, typ
|
|
43
45
|
end
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
@type = typ
|
|
45
48
|
end
|
|
46
49
|
|
|
47
50
|
# Returns a match rule string version of the object. E.g.:
|
|
@@ -58,11 +61,13 @@ module DBus
|
|
|
58
61
|
def from_s(str)
|
|
59
62
|
str.split(",").each do |eq|
|
|
60
63
|
next unless eq =~ /^(.*)='([^']*)'$/
|
|
64
|
+
|
|
61
65
|
# "
|
|
62
66
|
name = Regexp.last_match(1)
|
|
63
67
|
val = Regexp.last_match(2)
|
|
64
68
|
raise MatchRuleException, name unless FILTERS.member?(name.to_sym)
|
|
65
|
-
|
|
69
|
+
|
|
70
|
+
method("#{name}=").call(val)
|
|
66
71
|
end
|
|
67
72
|
self
|
|
68
73
|
end
|
|
@@ -80,18 +85,13 @@ module DBus
|
|
|
80
85
|
|
|
81
86
|
# Determines whether a message _msg_ matches the match rule.
|
|
82
87
|
def match(msg)
|
|
83
|
-
if @type
|
|
84
|
-
if { Message::SIGNAL => "signal", Message::METHOD_CALL => "method_call",
|
|
85
|
-
Message::METHOD_RETURN => "method_return",
|
|
86
|
-
Message::ERROR => "error" }[msg.message_type] != @type
|
|
87
|
-
return false
|
|
88
|
-
end
|
|
89
|
-
end
|
|
88
|
+
return false if @type && @type != msg.message_type_s
|
|
90
89
|
return false if @interface && @interface != msg.interface
|
|
91
90
|
return false if @member && @member != msg.member
|
|
92
91
|
return false if @path && @path != msg.path
|
|
92
|
+
|
|
93
93
|
# FIXME: sender and destination are ignored
|
|
94
94
|
true
|
|
95
95
|
end
|
|
96
|
-
end
|
|
97
|
-
end
|
|
96
|
+
end
|
|
97
|
+
end
|
data/lib/dbus/message.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# dbus.rb - Module containing the low-level D-Bus implementation
|
|
2
4
|
#
|
|
3
5
|
# This file is part of the ruby-dbus project
|
|
@@ -8,16 +10,12 @@
|
|
|
8
10
|
# License, version 2.1 as published by the Free Software Foundation.
|
|
9
11
|
# See the file "COPYING" for the exact licensing terms.
|
|
10
12
|
|
|
13
|
+
require_relative "raw_message"
|
|
14
|
+
|
|
11
15
|
# = D-Bus main module
|
|
12
16
|
#
|
|
13
17
|
# Module containing all the D-Bus modules and classes.
|
|
14
18
|
module DBus
|
|
15
|
-
# = InvalidDestinationName class
|
|
16
|
-
# Thrown when you try to send a message to /org/freedesktop/DBus/Local, that
|
|
17
|
-
# is reserved.
|
|
18
|
-
class InvalidDestinationName < Exception
|
|
19
|
-
end
|
|
20
|
-
|
|
21
19
|
# = D-Bus message class
|
|
22
20
|
#
|
|
23
21
|
# Class that holds any type of message that travels over the bus.
|
|
@@ -27,7 +25,7 @@ module DBus
|
|
|
27
25
|
# Mutex that protects updates on the serial number.
|
|
28
26
|
@@serial_mutex = Mutex.new
|
|
29
27
|
# Type of a message (by specification).
|
|
30
|
-
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
|
28
|
+
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
|
31
29
|
|
|
32
30
|
# FIXME: following message type constants should be under Message::Type IMO
|
|
33
31
|
# well, yeah sure
|
|
@@ -43,6 +41,9 @@ module DBus
|
|
|
43
41
|
# Signal message type.
|
|
44
42
|
SIGNAL = 4
|
|
45
43
|
|
|
44
|
+
# Names used by signal match rules
|
|
45
|
+
TYPE_NAMES = ["invalid", "method_call", "method_return", "error", "signal"].freeze
|
|
46
|
+
|
|
46
47
|
# Message flag signyfing that no reply is expected.
|
|
47
48
|
NO_REPLY_EXPECTED = 0x1
|
|
48
49
|
# Message flag signifying that no automatic start is required/must be
|
|
@@ -66,11 +67,13 @@ module DBus
|
|
|
66
67
|
attr_accessor :sender
|
|
67
68
|
# The signature of the message contents.
|
|
68
69
|
attr_accessor :signature
|
|
69
|
-
#
|
|
70
|
+
# @return [Integer] (u32)
|
|
71
|
+
# The serial number of the message this message is a reply for.
|
|
70
72
|
attr_accessor :reply_serial
|
|
71
73
|
# The protocol.
|
|
72
74
|
attr_reader :protocol
|
|
73
|
-
#
|
|
75
|
+
# @return [Integer] (u32)
|
|
76
|
+
# The serial of the message.
|
|
74
77
|
attr_reader :serial
|
|
75
78
|
# The parameters of the message.
|
|
76
79
|
attr_reader :params
|
|
@@ -100,27 +103,33 @@ module DBus
|
|
|
100
103
|
|
|
101
104
|
def to_s
|
|
102
105
|
"#{message_type} sender=#{sender} -> dest=#{destination} " \
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
"serial=#{serial} reply_serial=#{reply_serial} " \
|
|
107
|
+
"path=#{path}; interface=#{interface}; member=#{member} " \
|
|
108
|
+
"error_name=#{error_name}"
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# @return [String] name of message type, as used in match rules:
|
|
112
|
+
# "method_call", "method_return", "signal", "error"
|
|
113
|
+
def message_type_s
|
|
114
|
+
TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
|
|
106
115
|
end
|
|
107
116
|
|
|
108
|
-
# Create a regular reply to a message
|
|
109
|
-
def self.method_return(
|
|
110
|
-
MethodReturnMessage.new.reply_to(
|
|
117
|
+
# Create a regular reply to a message _msg_.
|
|
118
|
+
def self.method_return(msg)
|
|
119
|
+
MethodReturnMessage.new.reply_to(msg)
|
|
111
120
|
end
|
|
112
121
|
|
|
113
|
-
# Create an error reply to a message
|
|
114
|
-
def self.error(
|
|
115
|
-
ErrorMessage.new(error_name, description).reply_to(
|
|
122
|
+
# Create an error reply to a message _msg_.
|
|
123
|
+
def self.error(msg, error_name, description = nil)
|
|
124
|
+
ErrorMessage.new(error_name, description).reply_to(msg)
|
|
116
125
|
end
|
|
117
126
|
|
|
118
|
-
# Mark this message as a reply to a another message
|
|
119
|
-
# the serial number of
|
|
127
|
+
# Mark this message as a reply to a another message _msg_, taking
|
|
128
|
+
# the serial number of _msg_ as reply serial and the sender of _msg_ as
|
|
120
129
|
# destination.
|
|
121
|
-
def reply_to(
|
|
122
|
-
@reply_serial =
|
|
123
|
-
@destination =
|
|
130
|
+
def reply_to(msg)
|
|
131
|
+
@reply_serial = msg.serial
|
|
132
|
+
@destination = msg.sender
|
|
124
133
|
self
|
|
125
134
|
end
|
|
126
135
|
|
|
@@ -131,6 +140,10 @@ module DBus
|
|
|
131
140
|
@params << [type, val]
|
|
132
141
|
end
|
|
133
142
|
|
|
143
|
+
# "l" or "B"
|
|
144
|
+
ENDIANNESS_CHAR = ENV.fetch("RUBY_DBUS_ENDIANNESS", HOST_END)
|
|
145
|
+
ENDIANNESS = RawMessage.endianness(ENDIANNESS_CHAR)
|
|
146
|
+
|
|
134
147
|
# FIXME: what are these? a message element constant enumeration?
|
|
135
148
|
# See method below, in a message, you have and array of optional parameters
|
|
136
149
|
# that come with an index, to determine their meaning. The values are in
|
|
@@ -145,21 +158,25 @@ module DBus
|
|
|
145
158
|
SENDER = 7
|
|
146
159
|
SIGNATURE = 8
|
|
147
160
|
|
|
161
|
+
RESERVED_PATH = "/org/freedesktop/DBus/Local"
|
|
162
|
+
|
|
148
163
|
# Marshall the message with its current set parameters and return
|
|
149
164
|
# it in a packet form.
|
|
165
|
+
# @return [String]
|
|
150
166
|
def marshall
|
|
151
|
-
if @path ==
|
|
152
|
-
|
|
167
|
+
if @path == RESERVED_PATH
|
|
168
|
+
# the bus would disconnect us, better explain why
|
|
169
|
+
raise "Cannot send a message with the reserved path #{RESERVED_PATH}: #{inspect}"
|
|
153
170
|
end
|
|
154
171
|
|
|
155
|
-
|
|
156
|
-
@params.each do |
|
|
157
|
-
|
|
172
|
+
params_marshaller = PacketMarshaller.new(endianness: ENDIANNESS)
|
|
173
|
+
@params.each do |type, value|
|
|
174
|
+
params_marshaller.append(type, value)
|
|
158
175
|
end
|
|
159
|
-
@body_length =
|
|
176
|
+
@body_length = params_marshaller.packet.bytesize
|
|
160
177
|
|
|
161
|
-
marshaller = PacketMarshaller.new
|
|
162
|
-
marshaller.append(Type::BYTE,
|
|
178
|
+
marshaller = PacketMarshaller.new(endianness: ENDIANNESS)
|
|
179
|
+
marshaller.append(Type::BYTE, ENDIANNESS_CHAR.ord)
|
|
163
180
|
marshaller.append(Type::BYTE, @message_type)
|
|
164
181
|
marshaller.append(Type::BYTE, @flags)
|
|
165
182
|
marshaller.append(Type::BYTE, @protocol)
|
|
@@ -178,10 +195,8 @@ module DBus
|
|
|
178
195
|
marshaller.append("a(yv)", headers)
|
|
179
196
|
|
|
180
197
|
marshaller.align(8)
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
end
|
|
184
|
-
marshaller.packet
|
|
198
|
+
|
|
199
|
+
marshaller.packet + params_marshaller.packet
|
|
185
200
|
end
|
|
186
201
|
|
|
187
202
|
# Unmarshall a packet contained in the buffer _buf_ and set the
|
|
@@ -191,13 +206,7 @@ module DBus
|
|
|
191
206
|
# the detected message (self) and
|
|
192
207
|
# the index pointer of the buffer where the message data ended.
|
|
193
208
|
def unmarshall_buffer(buf)
|
|
194
|
-
|
|
195
|
-
endianness = if buf[0] == "l"
|
|
196
|
-
LIL_END
|
|
197
|
-
else
|
|
198
|
-
BIG_END
|
|
199
|
-
end
|
|
200
|
-
pu = PacketUnmarshaller.new(buf, endianness)
|
|
209
|
+
pu = PacketUnmarshaller.new(buf, RawMessage.endianness(buf[0]))
|
|
201
210
|
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
|
202
211
|
_, @message_type, @flags, @protocol, @body_length, @serial,
|
|
203
212
|
headers = mdata
|
|
@@ -222,21 +231,21 @@ module DBus
|
|
|
222
231
|
@signature = struct[1]
|
|
223
232
|
end
|
|
224
233
|
end
|
|
225
|
-
pu.
|
|
226
|
-
if @body_length
|
|
234
|
+
pu.align_body
|
|
235
|
+
if @body_length.positive? && @signature
|
|
227
236
|
@params = pu.unmarshall(@signature, @body_length)
|
|
228
237
|
end
|
|
229
|
-
[self, pu.
|
|
238
|
+
[self, pu.consumed_size]
|
|
230
239
|
end
|
|
231
240
|
|
|
232
241
|
# Make a new exception from ex, mark it as being caused by this message
|
|
233
242
|
# @api private
|
|
234
|
-
def annotate_exception(
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
243
|
+
def annotate_exception(exc)
|
|
244
|
+
new_exc = exc.exception("#{exc}; caused by #{self}")
|
|
245
|
+
new_exc.set_backtrace(exc.backtrace)
|
|
246
|
+
new_exc
|
|
238
247
|
end
|
|
239
|
-
end
|
|
248
|
+
end
|
|
240
249
|
|
|
241
250
|
class MethodReturnMessage < Message
|
|
242
251
|
def initialize
|
|
@@ -251,17 +260,17 @@ module DBus
|
|
|
251
260
|
add_param(Type::STRING, description) unless description.nil?
|
|
252
261
|
end
|
|
253
262
|
|
|
254
|
-
def self.from_exception(
|
|
255
|
-
name = if
|
|
256
|
-
|
|
263
|
+
def self.from_exception(exc)
|
|
264
|
+
name = if exc.is_a? DBus::Error
|
|
265
|
+
exc.name
|
|
257
266
|
else
|
|
258
267
|
"org.freedesktop.DBus.Error.Failed"
|
|
259
|
-
#
|
|
268
|
+
# exc.class.to_s # RuntimeError is not a valid name, has no dot
|
|
260
269
|
end
|
|
261
|
-
description =
|
|
270
|
+
description = exc.message
|
|
262
271
|
msg = new(name, description)
|
|
263
|
-
msg.add_param(DBus.type("as"),
|
|
272
|
+
msg.add_param(DBus.type("as"), exc.backtrace)
|
|
264
273
|
msg
|
|
265
274
|
end
|
|
266
275
|
end
|
|
267
|
-
end
|
|
276
|
+
end
|
data/lib/dbus/message_queue.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# This file is part of the ruby-dbus project
|
|
2
4
|
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
|
3
5
|
# Copyright (C) 2009-2014 Martin Vidner
|
|
@@ -16,35 +18,49 @@ module DBus
|
|
|
16
18
|
# The socket that is used to connect with the bus.
|
|
17
19
|
attr_reader :socket
|
|
18
20
|
|
|
21
|
+
# The buffer size for messages.
|
|
22
|
+
MSG_BUF_SIZE = 4096
|
|
23
|
+
|
|
19
24
|
def initialize(address)
|
|
25
|
+
DBus.logger.debug "MessageQueue: #{address}"
|
|
20
26
|
@address = address
|
|
21
27
|
@buffer = ""
|
|
28
|
+
# Reduce allocations by using a single buffer for our socket
|
|
29
|
+
@read_buffer = String.new(capacity: MSG_BUF_SIZE)
|
|
22
30
|
@is_tcp = false
|
|
31
|
+
@mutex = Mutex.new
|
|
23
32
|
connect
|
|
24
33
|
end
|
|
25
34
|
|
|
26
|
-
# @param
|
|
35
|
+
# @param blocking [Boolean]
|
|
36
|
+
# true: wait to return a {Message};
|
|
37
|
+
# false: may return `nil`
|
|
27
38
|
# @return [Message,nil] one message or nil if unavailable
|
|
28
39
|
# @raise EOFError
|
|
29
40
|
# @todo failure modes
|
|
30
|
-
def pop(
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
def pop(blocking: true)
|
|
42
|
+
# FIXME: this is not enough, the R/W test deadlocks on shared connections
|
|
43
|
+
@mutex.synchronize do
|
|
44
|
+
buffer_from_socket_nonblock
|
|
45
|
+
message = message_from_buffer_nonblock
|
|
46
|
+
if blocking
|
|
47
|
+
# we can block
|
|
48
|
+
while message.nil?
|
|
49
|
+
r, _d, _d = IO.select([@socket])
|
|
50
|
+
if r && r[0] == @socket
|
|
51
|
+
buffer_from_socket_nonblock
|
|
52
|
+
message = message_from_buffer_nonblock
|
|
53
|
+
end
|
|
40
54
|
end
|
|
41
55
|
end
|
|
56
|
+
message
|
|
42
57
|
end
|
|
43
|
-
message
|
|
44
58
|
end
|
|
45
59
|
|
|
46
60
|
def push(message)
|
|
47
|
-
@
|
|
61
|
+
@mutex.synchronize do
|
|
62
|
+
@socket.write(message.marshall)
|
|
63
|
+
end
|
|
48
64
|
end
|
|
49
65
|
alias << push
|
|
50
66
|
|
|
@@ -54,7 +70,7 @@ module DBus
|
|
|
54
70
|
def connect
|
|
55
71
|
addresses = @address.split ";"
|
|
56
72
|
# connect to first one that succeeds
|
|
57
|
-
|
|
73
|
+
addresses.find do |a|
|
|
58
74
|
transport, keyvaluestring = a.split ":"
|
|
59
75
|
kv_list = keyvaluestring.split ","
|
|
60
76
|
kv_hash = {}
|
|
@@ -74,29 +90,29 @@ module DBus
|
|
|
74
90
|
# ignore, report?
|
|
75
91
|
end
|
|
76
92
|
end
|
|
77
|
-
worked
|
|
78
93
|
# returns the address that worked or nil.
|
|
79
94
|
# how to report failure?
|
|
80
95
|
end
|
|
81
96
|
|
|
82
97
|
# Connect to a bus over tcp and initialize the connection.
|
|
83
98
|
def connect_to_tcp(params)
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
host = params["host"]
|
|
100
|
+
port = params["port"]
|
|
101
|
+
if host && port
|
|
86
102
|
begin
|
|
87
103
|
# initialize the tcp socket
|
|
88
|
-
@socket = TCPSocket.new(
|
|
104
|
+
@socket = TCPSocket.new(host, port.to_i)
|
|
89
105
|
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
|
90
106
|
init_connection
|
|
91
107
|
@is_tcp = true
|
|
92
108
|
rescue Exception => e
|
|
93
109
|
puts "Oops:", e
|
|
94
|
-
puts "Error: Could not establish connection to: #{
|
|
110
|
+
puts "Error: Could not establish connection to: #{host}:#{port}, will now exit."
|
|
95
111
|
exit(1) # a little harsh
|
|
96
112
|
end
|
|
97
113
|
else
|
|
98
114
|
# Danger, Will Robinson: the specified "path" is not usable
|
|
99
|
-
puts "Error: supplied
|
|
115
|
+
puts "Error: supplied params: #{@params}, unusable! sorry."
|
|
100
116
|
end
|
|
101
117
|
end
|
|
102
118
|
|
|
@@ -125,7 +141,7 @@ module DBus
|
|
|
125
141
|
|
|
126
142
|
# Initialize the connection to the bus.
|
|
127
143
|
def init_connection
|
|
128
|
-
client = Client.new(@socket)
|
|
144
|
+
client = Authentication::Client.new(@socket)
|
|
129
145
|
client.authenticate
|
|
130
146
|
end
|
|
131
147
|
|
|
@@ -135,6 +151,7 @@ module DBus
|
|
|
135
151
|
# @return [Message,nil] the message or nil if unavailable
|
|
136
152
|
def message_from_buffer_nonblock
|
|
137
153
|
return nil if @buffer.empty?
|
|
154
|
+
|
|
138
155
|
ret = nil
|
|
139
156
|
begin
|
|
140
157
|
ret, size = Message.new.unmarshall_buffer(@buffer)
|
|
@@ -145,15 +162,12 @@ module DBus
|
|
|
145
162
|
ret
|
|
146
163
|
end
|
|
147
164
|
|
|
148
|
-
# The buffer size for messages.
|
|
149
|
-
MSG_BUF_SIZE = 4096
|
|
150
|
-
|
|
151
165
|
# Fill (append) the buffer from data that might be available on the
|
|
152
166
|
# socket.
|
|
153
167
|
# @return [void]
|
|
154
168
|
# @raise EOFError
|
|
155
169
|
def buffer_from_socket_nonblock
|
|
156
|
-
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
|
170
|
+
@buffer += @socket.read_nonblock(MSG_BUF_SIZE, @read_buffer)
|
|
157
171
|
rescue EOFError
|
|
158
172
|
raise # the caller expects it
|
|
159
173
|
rescue Errno::EAGAIN
|
|
@@ -161,6 +175,7 @@ module DBus
|
|
|
161
175
|
rescue Exception => e
|
|
162
176
|
puts "Oops:", e
|
|
163
177
|
raise if @is_tcp # why?
|
|
178
|
+
|
|
164
179
|
puts "WARNING: read_nonblock failed, falling back to .recv"
|
|
165
180
|
@buffer += @socket.recv(MSG_BUF_SIZE)
|
|
166
181
|
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# This file is part of the ruby-dbus project
|
|
4
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
|
5
|
+
# Copyright (C) 2023 Martin Vidner
|
|
6
|
+
#
|
|
7
|
+
# This library is free software; you can redistribute it and/or
|
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
|
9
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
|
10
|
+
# See the file "COPYING" for the exact licensing terms.
|
|
11
|
+
|
|
12
|
+
module DBus
|
|
13
|
+
# Has a tree of {Node}s, refering to {Object}s or to {ProxyObject}s.
|
|
14
|
+
class NodeTree
|
|
15
|
+
# @return [Node]
|
|
16
|
+
attr_reader :root
|
|
17
|
+
|
|
18
|
+
def initialize
|
|
19
|
+
@root = Node.new("/")
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Get the object node corresponding to the given *path*.
|
|
23
|
+
# @param path [ObjectPath]
|
|
24
|
+
# @param create [Boolean] if true, the the {Node}s in the path are created
|
|
25
|
+
# if they do not already exist.
|
|
26
|
+
# @return [Node,nil]
|
|
27
|
+
def get_node(path, create: false)
|
|
28
|
+
n = @root
|
|
29
|
+
path.sub(%r{^/}, "").split("/").each do |elem|
|
|
30
|
+
if !(n[elem])
|
|
31
|
+
return nil if !create
|
|
32
|
+
|
|
33
|
+
n[elem] = Node.new(elem)
|
|
34
|
+
end
|
|
35
|
+
n = n[elem]
|
|
36
|
+
end
|
|
37
|
+
n
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# = Object path node class
|
|
42
|
+
#
|
|
43
|
+
# Class representing a node on an object path.
|
|
44
|
+
class Node < Hash
|
|
45
|
+
# @return [DBus::Object,DBus::ProxyObject,nil]
|
|
46
|
+
# The D-Bus object contained by the node.
|
|
47
|
+
attr_accessor :object
|
|
48
|
+
|
|
49
|
+
# The name of the node.
|
|
50
|
+
# @return [String] the last component of its object path, or "/"
|
|
51
|
+
attr_reader :name
|
|
52
|
+
|
|
53
|
+
# Create a new node with a given _name_.
|
|
54
|
+
def initialize(name)
|
|
55
|
+
super()
|
|
56
|
+
@name = name
|
|
57
|
+
@object = nil
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Return an XML string representation of the node.
|
|
61
|
+
# It is shallow, not recursing into subnodes
|
|
62
|
+
# @param node_opath [String]
|
|
63
|
+
def to_xml(node_opath)
|
|
64
|
+
xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
|
|
65
|
+
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
|
66
|
+
'
|
|
67
|
+
xml += "<node name=\"#{node_opath}\">\n"
|
|
68
|
+
each_key do |k|
|
|
69
|
+
xml += " <node name=\"#{k}\" />\n"
|
|
70
|
+
end
|
|
71
|
+
@object&.intfs&.each_value do |v|
|
|
72
|
+
xml += v.to_xml
|
|
73
|
+
end
|
|
74
|
+
xml += "</node>"
|
|
75
|
+
xml
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Return inspect information of the node.
|
|
79
|
+
def inspect
|
|
80
|
+
# Need something here
|
|
81
|
+
"<DBus::Node #{sub_inspect}>"
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Return instance inspect information, used by Node#inspect.
|
|
85
|
+
def sub_inspect
|
|
86
|
+
s = ""
|
|
87
|
+
if !@object.nil?
|
|
88
|
+
s += format("%x ", @object.object_id)
|
|
89
|
+
end
|
|
90
|
+
contents_sub_inspect = keys
|
|
91
|
+
.map { |k| "#{k} => #{self[k].sub_inspect}" }
|
|
92
|
+
.join(",")
|
|
93
|
+
"#{s}{#{contents_sub_inspect}}"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# All objects (not paths) under this path (except itself).
|
|
97
|
+
# @return [Array<DBus::Object>]
|
|
98
|
+
def descendant_objects
|
|
99
|
+
children_objects = values.map(&:object).compact
|
|
100
|
+
descendants = values.map(&:descendant_objects)
|
|
101
|
+
flat_descendants = descendants.reduce([], &:+)
|
|
102
|
+
children_objects + flat_descendants
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|