ruby-dbus 0.15.0 → 0.18.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/NEWS.md +41 -1
- data/README.md +3 -5
- data/Rakefile +18 -8
- data/VERSION +1 -1
- data/doc/Reference.md +93 -3
- data/examples/doc/_extract_examples +7 -0
- data/examples/gdbus/gdbus +31 -24
- 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/service_newapi.rb +1 -1
- data/examples/simple/call_introspect.rb +1 -0
- data/examples/simple/get_id.rb +2 -1
- data/examples/simple/properties.rb +2 -0
- data/examples/utils/listnames.rb +1 -0
- data/examples/utils/notify.rb +1 -0
- data/lib/dbus/api_options.rb +9 -0
- data/lib/dbus/auth.rb +20 -15
- data/lib/dbus/bus.rb +129 -74
- data/lib/dbus/bus_name.rb +31 -0
- data/lib/dbus/core_ext/class/attribute.rb +1 -1
- data/lib/dbus/error.rb +4 -2
- data/lib/dbus/introspect.rb +90 -34
- data/lib/dbus/logger.rb +3 -1
- data/lib/dbus/marshall.rb +119 -87
- data/lib/dbus/matchrule.rb +16 -16
- data/lib/dbus/message.rb +40 -27
- data/lib/dbus/message_queue.rb +26 -18
- data/lib/dbus/object.rb +401 -0
- data/lib/dbus/object_path.rb +28 -0
- data/lib/dbus/proxy_object.rb +23 -2
- data/lib/dbus/proxy_object_factory.rb +11 -7
- data/lib/dbus/proxy_object_interface.rb +26 -21
- data/lib/dbus/type.rb +59 -34
- data/lib/dbus/xml.rb +28 -17
- data/lib/dbus.rb +10 -8
- data/ruby-dbus.gemspec +8 -4
- data/spec/async_spec.rb +2 -0
- data/spec/binding_spec.rb +2 -0
- data/spec/bus_and_xml_backend_spec.rb +2 -0
- data/spec/bus_driver_spec.rb +2 -0
- data/spec/bus_name_spec.rb +27 -0
- data/spec/bus_spec.rb +2 -0
- data/spec/byte_array_spec.rb +2 -0
- data/spec/client_robustness_spec.rb +27 -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 +3 -1
- data/spec/node_spec.rb +23 -0
- data/spec/object_path_spec.rb +25 -0
- data/spec/property_spec.rb +64 -5
- data/spec/proxy_object_spec.rb +2 -0
- data/spec/server_robustness_spec.rb +2 -0
- data/spec/server_spec.rb +2 -0
- data/spec/service_newapi.rb +39 -70
- data/spec/session_bus_spec.rb +3 -1
- data/spec/session_bus_spec_manual.rb +2 -0
- data/spec/signal_spec.rb +5 -3
- data/spec/spec_helper.rb +23 -9
- data/spec/thread_safety_spec.rb +2 -0
- data/spec/tools/dbus-limited-session.conf +4 -0
- data/spec/type_spec.rb +2 -0
- data/spec/value_spec.rb +16 -1
- data/spec/variant_spec.rb +4 -2
- metadata +32 -12
- data/lib/dbus/export.rb +0 -131
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
|
@@ -27,7 +29,7 @@ module DBus
|
|
27
29
|
# Mutex that protects updates on the serial number.
|
28
30
|
@@serial_mutex = Mutex.new
|
29
31
|
# Type of a message (by specification).
|
30
|
-
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
32
|
+
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
31
33
|
|
32
34
|
# FIXME: following message type constants should be under Message::Type IMO
|
33
35
|
# well, yeah sure
|
@@ -43,6 +45,9 @@ module DBus
|
|
43
45
|
# Signal message type.
|
44
46
|
SIGNAL = 4
|
45
47
|
|
48
|
+
# Names used by signal match rules
|
49
|
+
TYPE_NAMES = ["invalid", "method_call", "method_return", "error", "signal"].freeze
|
50
|
+
|
46
51
|
# Message flag signyfing that no reply is expected.
|
47
52
|
NO_REPLY_EXPECTED = 0x1
|
48
53
|
# Message flag signifying that no automatic start is required/must be
|
@@ -66,11 +71,13 @@ module DBus
|
|
66
71
|
attr_accessor :sender
|
67
72
|
# The signature of the message contents.
|
68
73
|
attr_accessor :signature
|
69
|
-
#
|
74
|
+
# @return [Integer] (u32)
|
75
|
+
# The serial number of the message this message is a reply for.
|
70
76
|
attr_accessor :reply_serial
|
71
77
|
# The protocol.
|
72
78
|
attr_reader :protocol
|
73
|
-
#
|
79
|
+
# @return [Integer] (u32)
|
80
|
+
# The serial of the message.
|
74
81
|
attr_reader :serial
|
75
82
|
# The parameters of the message.
|
76
83
|
attr_reader :params
|
@@ -105,22 +112,28 @@ module DBus
|
|
105
112
|
"error_name=#{error_name}"
|
106
113
|
end
|
107
114
|
|
108
|
-
#
|
109
|
-
|
110
|
-
|
115
|
+
# @return [String] name of message type, as used in match rules:
|
116
|
+
# "method_call", "method_return", "signal", "error"
|
117
|
+
def message_type_s
|
118
|
+
TYPE_NAMES[message_type] || "unknown_type_#{message_type}"
|
111
119
|
end
|
112
120
|
|
113
|
-
# Create
|
114
|
-
def self.
|
115
|
-
|
121
|
+
# Create a regular reply to a message _msg_.
|
122
|
+
def self.method_return(msg)
|
123
|
+
MethodReturnMessage.new.reply_to(msg)
|
116
124
|
end
|
117
125
|
|
118
|
-
#
|
119
|
-
|
126
|
+
# Create an error reply to a message _msg_.
|
127
|
+
def self.error(msg, error_name, description = nil)
|
128
|
+
ErrorMessage.new(error_name, description).reply_to(msg)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Mark this message as a reply to a another message _msg_, taking
|
132
|
+
# the serial number of _msg_ as reply serial and the sender of _msg_ as
|
120
133
|
# destination.
|
121
|
-
def reply_to(
|
122
|
-
@reply_serial =
|
123
|
-
@destination =
|
134
|
+
def reply_to(msg)
|
135
|
+
@reply_serial = msg.serial
|
136
|
+
@destination = msg.sender
|
124
137
|
self
|
125
138
|
end
|
126
139
|
|
@@ -223,7 +236,7 @@ module DBus
|
|
223
236
|
end
|
224
237
|
end
|
225
238
|
pu.align(8)
|
226
|
-
if @body_length
|
239
|
+
if @body_length.positive? && @signature
|
227
240
|
@params = pu.unmarshall(@signature, @body_length)
|
228
241
|
end
|
229
242
|
[self, pu.idx]
|
@@ -231,12 +244,12 @@ module DBus
|
|
231
244
|
|
232
245
|
# Make a new exception from ex, mark it as being caused by this message
|
233
246
|
# @api private
|
234
|
-
def annotate_exception(
|
235
|
-
|
236
|
-
|
237
|
-
|
247
|
+
def annotate_exception(exc)
|
248
|
+
new_exc = exc.exception("#{exc}; caused by #{self}")
|
249
|
+
new_exc.set_backtrace(exc.backtrace)
|
250
|
+
new_exc
|
238
251
|
end
|
239
|
-
end
|
252
|
+
end
|
240
253
|
|
241
254
|
class MethodReturnMessage < Message
|
242
255
|
def initialize
|
@@ -251,17 +264,17 @@ module DBus
|
|
251
264
|
add_param(Type::STRING, description) unless description.nil?
|
252
265
|
end
|
253
266
|
|
254
|
-
def self.from_exception(
|
255
|
-
name = if
|
256
|
-
|
267
|
+
def self.from_exception(exc)
|
268
|
+
name = if exc.is_a? DBus::Error
|
269
|
+
exc.name
|
257
270
|
else
|
258
271
|
"org.freedesktop.DBus.Error.Failed"
|
259
|
-
#
|
272
|
+
# exc.class.to_s # RuntimeError is not a valid name, has no dot
|
260
273
|
end
|
261
|
-
description =
|
274
|
+
description = exc.message
|
262
275
|
msg = new(name, description)
|
263
|
-
msg.add_param(DBus.type("as"),
|
276
|
+
msg.add_param(DBus.type("as"), exc.backtrace)
|
264
277
|
msg
|
265
278
|
end
|
266
279
|
end
|
267
|
-
end
|
280
|
+
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
|
@@ -11,6 +13,7 @@ require "fcntl"
|
|
11
13
|
require "socket"
|
12
14
|
|
13
15
|
module DBus
|
16
|
+
# Encapsulates a socket so that we can {#push} and {#pop} {Message}s.
|
14
17
|
class MessageQueue
|
15
18
|
# The socket that is used to connect with the bus.
|
16
19
|
attr_reader :socket
|
@@ -22,14 +25,16 @@ module DBus
|
|
22
25
|
connect
|
23
26
|
end
|
24
27
|
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
|
28
|
+
# @param blocking [Boolean]
|
29
|
+
# true: wait to return a {Message};
|
30
|
+
# false: may return `nil`
|
31
|
+
# @return [Message,nil] one message or nil if unavailable
|
32
|
+
# @raise EOFError
|
33
|
+
# @todo failure modes
|
34
|
+
def pop(blocking: true)
|
30
35
|
buffer_from_socket_nonblock
|
31
36
|
message = message_from_buffer_nonblock
|
32
|
-
|
37
|
+
if blocking
|
33
38
|
# we can block
|
34
39
|
while message.nil?
|
35
40
|
r, _d, _d = IO.select([@socket])
|
@@ -53,7 +58,7 @@ module DBus
|
|
53
58
|
def connect
|
54
59
|
addresses = @address.split ";"
|
55
60
|
# connect to first one that succeeds
|
56
|
-
|
61
|
+
addresses.find do |a|
|
57
62
|
transport, keyvaluestring = a.split ":"
|
58
63
|
kv_list = keyvaluestring.split ","
|
59
64
|
kv_hash = {}
|
@@ -73,29 +78,29 @@ module DBus
|
|
73
78
|
# ignore, report?
|
74
79
|
end
|
75
80
|
end
|
76
|
-
worked
|
77
81
|
# returns the address that worked or nil.
|
78
82
|
# how to report failure?
|
79
83
|
end
|
80
84
|
|
81
85
|
# Connect to a bus over tcp and initialize the connection.
|
82
86
|
def connect_to_tcp(params)
|
83
|
-
|
84
|
-
|
87
|
+
host = params["host"]
|
88
|
+
port = params["port"]
|
89
|
+
if host && port
|
85
90
|
begin
|
86
91
|
# initialize the tcp socket
|
87
|
-
@socket = TCPSocket.new(
|
92
|
+
@socket = TCPSocket.new(host, port.to_i)
|
88
93
|
@socket.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
|
89
94
|
init_connection
|
90
95
|
@is_tcp = true
|
91
96
|
rescue Exception => e
|
92
97
|
puts "Oops:", e
|
93
|
-
puts "Error: Could not establish connection to: #{
|
98
|
+
puts "Error: Could not establish connection to: #{host}:#{port}, will now exit."
|
94
99
|
exit(1) # a little harsh
|
95
100
|
end
|
96
101
|
else
|
97
102
|
# Danger, Will Robinson: the specified "path" is not usable
|
98
|
-
puts "Error: supplied
|
103
|
+
puts "Error: supplied params: #{@params}, unusable! sorry."
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
@@ -124,22 +129,23 @@ module DBus
|
|
124
129
|
|
125
130
|
# Initialize the connection to the bus.
|
126
131
|
def init_connection
|
127
|
-
|
128
|
-
|
132
|
+
client = Client.new(@socket)
|
133
|
+
client.authenticate
|
129
134
|
end
|
130
135
|
|
131
136
|
public # FIXME: fix Main loop instead
|
132
137
|
|
133
138
|
# Get and remove one message from the buffer.
|
134
|
-
#
|
139
|
+
# @return [Message,nil] the message or nil if unavailable
|
135
140
|
def message_from_buffer_nonblock
|
136
141
|
return nil if @buffer.empty?
|
142
|
+
|
137
143
|
ret = nil
|
138
144
|
begin
|
139
145
|
ret, size = Message.new.unmarshall_buffer(@buffer)
|
140
146
|
@buffer.slice!(0, size)
|
141
147
|
rescue IncompleteBufferException
|
142
|
-
# fall through, let ret
|
148
|
+
# fall through, let ret remain nil
|
143
149
|
end
|
144
150
|
ret
|
145
151
|
end
|
@@ -149,7 +155,8 @@ module DBus
|
|
149
155
|
|
150
156
|
# Fill (append) the buffer from data that might be available on the
|
151
157
|
# socket.
|
152
|
-
#
|
158
|
+
# @return [void]
|
159
|
+
# @raise EOFError
|
153
160
|
def buffer_from_socket_nonblock
|
154
161
|
@buffer += @socket.read_nonblock(MSG_BUF_SIZE)
|
155
162
|
rescue EOFError
|
@@ -159,6 +166,7 @@ module DBus
|
|
159
166
|
rescue Exception => e
|
160
167
|
puts "Oops:", e
|
161
168
|
raise if @is_tcp # why?
|
169
|
+
|
162
170
|
puts "WARNING: read_nonblock failed, falling back to .recv"
|
163
171
|
@buffer += @socket.recv(MSG_BUF_SIZE)
|
164
172
|
end
|