ruby-dbus 0.12.0 → 0.13.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 +344 -0
- data/Rakefile +21 -15
- data/VERSION +1 -1
- data/doc/Reference.md +26 -37
- data/examples/doc/_extract_examples +4 -4
- data/examples/gdbus/gdbus +40 -39
- data/examples/no-introspect/nm-test.rb +1 -3
- data/examples/no-introspect/tracker-test.rb +2 -4
- data/examples/rhythmbox/playpause.rb +1 -2
- data/examples/service/call_service.rb +0 -3
- data/examples/service/service_newapi.rb +3 -4
- data/examples/simple/call_introspect.rb +0 -3
- data/examples/simple/get_id.rb +1 -3
- data/examples/simple/properties.rb +3 -4
- data/examples/utils/listnames.rb +6 -7
- data/examples/utils/notify.rb +3 -5
- data/lib/dbus.rb +8 -20
- data/lib/dbus/auth.rb +59 -61
- data/lib/dbus/bus.rb +86 -97
- data/lib/dbus/error.rb +1 -1
- data/lib/dbus/export.rb +20 -18
- data/lib/dbus/introspect.rb +26 -28
- data/lib/dbus/logger.rb +1 -1
- data/lib/dbus/marshall.rb +72 -74
- data/lib/dbus/matchrule.rb +22 -26
- data/lib/dbus/message.rb +24 -33
- data/lib/dbus/message_queue.rb +30 -30
- data/lib/dbus/proxy_object.rb +34 -30
- data/lib/dbus/proxy_object_factory.rb +5 -2
- data/lib/dbus/proxy_object_interface.rb +10 -8
- data/lib/dbus/type.rb +154 -156
- data/lib/dbus/xml.rb +22 -16
- data/ruby-dbus.gemspec +15 -3
- data/spec/async_spec.rb +2 -4
- data/spec/binding_spec.rb +1 -5
- data/spec/bus_and_xml_backend_spec.rb +6 -9
- data/spec/bus_spec.rb +1 -1
- data/spec/byte_array_spec.rb +0 -2
- data/spec/err_msg_spec.rb +13 -10
- data/spec/introspect_xml_parser_spec.rb +2 -2
- data/spec/introspection_spec.rb +1 -1
- data/spec/main_loop_spec.rb +4 -5
- data/spec/property_spec.rb +0 -3
- data/spec/proxy_object_spec.rb +42 -0
- data/spec/server_robustness_spec.rb +0 -2
- data/spec/service_newapi.rb +51 -41
- data/spec/session_bus_spec.rb +6 -7
- data/spec/signal_spec.rb +2 -3
- data/spec/spec_helper.rb +28 -24
- data/spec/thread_safety_spec.rb +1 -2
- data/spec/type_spec.rb +2 -2
- data/spec/value_spec.rb +7 -10
- data/spec/variant_spec.rb +15 -16
- metadata +60 -3
- data/NEWS +0 -279
data/lib/dbus/auth.rb
CHANGED
@@ -6,7 +6,7 @@
|
|
6
6
|
# License, version 2.1 as published by the Free Software Foundation.
|
7
7
|
# See the file "COPYING" for the exact licensing terms.
|
8
8
|
|
9
|
-
require
|
9
|
+
require "rbconfig"
|
10
10
|
|
11
11
|
module DBus
|
12
12
|
# Exception raised when authentication fails somehow.
|
@@ -24,11 +24,11 @@ module DBus
|
|
24
24
|
# = Anonymous authentication class
|
25
25
|
class Anonymous < Authenticator
|
26
26
|
def authenticate
|
27
|
-
|
27
|
+
"527562792044427573" # Hex encoded version of "Ruby DBus"
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
# = External authentication class
|
31
|
+
# = External authentication class
|
32
32
|
#
|
33
33
|
# Class for 'external' type authentication.
|
34
34
|
class External < Authenticator
|
@@ -39,76 +39,75 @@ module DBus
|
|
39
39
|
# obtain for "1000" => 31303030 This is what the server is expecting.
|
40
40
|
# Why? I dunno. How did I come to that conclusion? by looking at rbus
|
41
41
|
# code. I have no idea how he found that out.
|
42
|
-
|
42
|
+
Process.uid.to_s.split(//).map { |d| d.ord.to_s(16) }.join
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
46
|
-
# = Authentication class using SHA1 crypto algorithm
|
45
|
+
|
46
|
+
# = Authentication class using SHA1 crypto algorithm
|
47
47
|
#
|
48
48
|
# Class for 'CookieSHA1' type authentication.
|
49
49
|
# Implements the AUTH DBUS_COOKIE_SHA1 mechanism.
|
50
50
|
class DBusCookieSHA1 < Authenticator
|
51
|
-
|
52
|
-
#the autenticate method (called in stage one of authentification)
|
51
|
+
# the autenticate method (called in stage one of authentification)
|
53
52
|
def authenticate
|
54
|
-
require
|
55
|
-
#number of retries we have for auth
|
53
|
+
require "etc"
|
54
|
+
# number of retries we have for auth
|
56
55
|
@retries = 1
|
57
|
-
|
56
|
+
hex_encode(Etc.getlogin).to_s # server expects it to be binary
|
58
57
|
end
|
59
58
|
|
60
|
-
#returns the modules name
|
59
|
+
# returns the modules name
|
61
60
|
def name
|
62
|
-
|
61
|
+
"DBUS_COOKIE_SHA1"
|
63
62
|
end
|
64
|
-
|
65
|
-
#handles the interesting crypto stuff, check the rbus-project for more info: http://rbus.rubyforge.org/
|
63
|
+
|
64
|
+
# handles the interesting crypto stuff, check the rbus-project for more info: http://rbus.rubyforge.org/
|
66
65
|
def data(hexdata)
|
67
|
-
require
|
66
|
+
require "digest/sha1"
|
68
67
|
data = hex_decode(hexdata)
|
69
|
-
# name of cookie file, id of cookie in file, servers random challenge
|
70
|
-
context, id, s_challenge = data.split(
|
71
|
-
# Random client challenge
|
72
|
-
c_challenge =
|
68
|
+
# name of cookie file, id of cookie in file, servers random challenge
|
69
|
+
context, id, s_challenge = data.split(" ")
|
70
|
+
# Random client challenge
|
71
|
+
c_challenge = 1.upto(s_challenge.bytesize / 2).map { rand(255).to_s }.join
|
73
72
|
# Search cookie file for id
|
74
|
-
path = File.join(ENV[
|
73
|
+
path = File.join(ENV["HOME"], ".dbus-keyrings", context)
|
75
74
|
DBus.logger.debug "path: #{path.inspect}"
|
76
75
|
File.foreach(path) do |line|
|
77
76
|
if line.index(id) == 0
|
78
77
|
# Right line of file, read cookie
|
79
|
-
cookie = line.split(
|
78
|
+
cookie = line.split(" ")[2].chomp
|
80
79
|
DBus.logger.debug "cookie: #{cookie.inspect}"
|
81
80
|
# Concatenate and encrypt
|
82
|
-
to_encrypt = [s_challenge, c_challenge, cookie].join(
|
81
|
+
to_encrypt = [s_challenge, c_challenge, cookie].join(":")
|
83
82
|
sha = Digest::SHA1.hexdigest(to_encrypt)
|
84
|
-
#the almighty tcp server wants everything hex encoded
|
83
|
+
# the almighty tcp server wants everything hex encoded
|
85
84
|
hex_response = hex_encode("#{c_challenge} #{sha}")
|
86
85
|
# Return response
|
87
86
|
response = [:AuthOk, hex_response]
|
88
87
|
return response
|
89
88
|
end
|
90
89
|
end
|
91
|
-
#a little rescue magic
|
90
|
+
# a little rescue magic
|
92
91
|
unless @retries <= 0
|
93
|
-
puts "ERROR: Could not auth, will now exit."
|
92
|
+
puts "ERROR: Could not auth, will now exit."
|
94
93
|
puts "ERROR: Unable to locate cookie, retry in 1 second."
|
95
94
|
@retries -= 1
|
96
95
|
sleep 1
|
97
96
|
data(hexdata)
|
98
97
|
end
|
99
|
-
end
|
100
|
-
|
98
|
+
end
|
99
|
+
|
101
100
|
# encode plain to hex
|
102
101
|
def hex_encode(plain)
|
103
102
|
return nil if plain.nil?
|
104
|
-
plain.to_s.unpack(
|
103
|
+
plain.to_s.unpack("H*")[0]
|
105
104
|
end
|
106
|
-
|
105
|
+
|
107
106
|
# decode hex to plain
|
108
107
|
def hex_decode(encoded)
|
109
|
-
encoded.scan(/[[:xdigit:]]{2}/).map{|h|h.hex.chr}.join
|
110
|
-
end
|
111
|
-
end #DBusCookieSHA1 class ends here
|
108
|
+
encoded.scan(/[[:xdigit:]]{2}/).map { |h| h.hex.chr }.join
|
109
|
+
end
|
110
|
+
end # DBusCookieSHA1 class ends here
|
112
111
|
|
113
112
|
# Note: this following stuff is tested with External authenticator only!
|
114
113
|
|
@@ -120,12 +119,12 @@ module DBus
|
|
120
119
|
def initialize(socket)
|
121
120
|
@socket = socket
|
122
121
|
@state = nil
|
123
|
-
@auth_list = [External,DBusCookieSHA1,Anonymous]
|
122
|
+
@auth_list = [External, DBusCookieSHA1, Anonymous]
|
124
123
|
end
|
125
124
|
|
126
125
|
# Start the authentication process.
|
127
126
|
def authenticate
|
128
|
-
if
|
127
|
+
if RbConfig::CONFIG["target_os"] =~ /freebsd/
|
129
128
|
@socket.sendmsg(0.chr, 0, nil, [:SOCKET, :SCM_CREDS, ""])
|
130
129
|
else
|
131
130
|
@socket.write(0.chr)
|
@@ -134,13 +133,15 @@ module DBus
|
|
134
133
|
@state = :Starting
|
135
134
|
while @state != :Authenticated
|
136
135
|
r = next_state
|
137
|
-
return r if
|
136
|
+
return r if !r
|
138
137
|
end
|
139
138
|
true
|
140
139
|
end
|
141
140
|
|
142
141
|
##########
|
142
|
+
|
143
143
|
private
|
144
|
+
|
144
145
|
##########
|
145
146
|
|
146
147
|
# Send an authentication method _meth_ with arguments _args_ to the
|
@@ -152,42 +153,39 @@ module DBus
|
|
152
153
|
|
153
154
|
# Try authentication using the next authenticator.
|
154
155
|
def next_authenticator
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
raise
|
164
|
-
end
|
156
|
+
raise AuthenticationFailed if @auth_list.empty?
|
157
|
+
@authenticator = @auth_list.shift.new
|
158
|
+
auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
|
159
|
+
DBus.logger.debug "auth_msg: #{auth_msg.inspect}"
|
160
|
+
send(auth_msg)
|
161
|
+
rescue AuthenticationFailed
|
162
|
+
@socket.close
|
163
|
+
raise
|
165
164
|
end
|
166
165
|
|
167
166
|
# Read data (a buffer) from the bus until CR LF is encountered.
|
168
167
|
# Return the buffer without the CR LF characters.
|
169
168
|
def next_msg
|
170
|
-
data
|
171
|
-
|
169
|
+
data = ""
|
170
|
+
crlf = "\r\n"
|
171
|
+
left = 1024 # 1024 byte, no idea if it's ever getting bigger
|
172
172
|
while left > 0
|
173
|
-
buf = @socket.read(
|
173
|
+
buf = @socket.read(left > 1 ? 1 : left)
|
174
174
|
break if buf.nil?
|
175
175
|
left -= buf.bytesize
|
176
176
|
data += buf
|
177
|
-
break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break
|
177
|
+
break if data.include? crlf # crlf means line finished, the TCP socket keeps on listening, so we break
|
178
178
|
end
|
179
179
|
readline = data.chomp.split(" ")
|
180
180
|
DBus.logger.debug "readline: #{readline.inspect}"
|
181
|
-
|
181
|
+
readline
|
182
182
|
end
|
183
183
|
|
184
|
-
|
185
|
-
#
|
186
|
-
#
|
187
|
-
|
188
|
-
|
189
|
-
end
|
190
|
-
=end
|
184
|
+
# # Read data (a buffer) from the bus until CR LF is encountered.
|
185
|
+
# # Return the buffer without the CR LF characters.
|
186
|
+
# def next_msg
|
187
|
+
# @socket.readline.chomp.split(" ")
|
188
|
+
# end
|
191
189
|
|
192
190
|
# Try to reach the next state based on the current state.
|
193
191
|
def next_state
|
@@ -196,10 +194,10 @@ module DBus
|
|
196
194
|
DBus.logger.debug ":Starting msg: #{msg[0].inspect}"
|
197
195
|
case msg[0]
|
198
196
|
when "OK"
|
199
|
-
@state = :WaitingForOk
|
197
|
+
@state = :WaitingForOk
|
200
198
|
when "CONTINUE"
|
201
199
|
@state = :WaitingForData
|
202
|
-
when "REJECTED" #needed by tcp, unix-path/abstract doesn't get here
|
200
|
+
when "REJECTED" # needed by tcp, unix-path/abstract doesn't get here
|
203
201
|
@state = :WaitingForData
|
204
202
|
end
|
205
203
|
end
|
@@ -263,7 +261,7 @@ module DBus
|
|
263
261
|
return false
|
264
262
|
end
|
265
263
|
end
|
266
|
-
|
264
|
+
true
|
267
265
|
end # def next_state
|
268
266
|
end # class Client
|
269
267
|
end # module D-Bus
|
data/lib/dbus/bus.rb
CHANGED
@@ -8,9 +8,9 @@
|
|
8
8
|
# License, version 2.1 as published by the Free Software Foundation.
|
9
9
|
# See the file "COPYING" for the exact licensing terms.
|
10
10
|
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
11
|
+
require "socket"
|
12
|
+
require "thread"
|
13
|
+
require "singleton"
|
14
14
|
|
15
15
|
# = D-Bus main module
|
16
16
|
#
|
@@ -28,7 +28,8 @@ module DBus
|
|
28
28
|
|
29
29
|
# Create a new service with a given _name_ on a given _bus_.
|
30
30
|
def initialize(name, bus)
|
31
|
-
@name
|
31
|
+
@name = name
|
32
|
+
@bus = bus
|
32
33
|
@root = Node.new("/")
|
33
34
|
end
|
34
35
|
|
@@ -40,11 +41,9 @@ module DBus
|
|
40
41
|
# Perform an introspection on all the objects on the service
|
41
42
|
# (starting recursively from the root).
|
42
43
|
def introspect
|
43
|
-
if block_given?
|
44
|
-
|
45
|
-
|
46
|
-
rec_introspect(@root, "/")
|
47
|
-
end
|
44
|
+
raise NotImplementedError if block_given?
|
45
|
+
|
46
|
+
rec_introspect(@root, "/")
|
48
47
|
self
|
49
48
|
end
|
50
49
|
|
@@ -63,7 +62,7 @@ module DBus
|
|
63
62
|
node.object = ProxyObject.new(
|
64
63
|
@bus, @name, path,
|
65
64
|
api: api
|
66
|
-
|
65
|
+
)
|
67
66
|
end
|
68
67
|
node.object
|
69
68
|
end
|
@@ -78,11 +77,11 @@ module DBus
|
|
78
77
|
# Raises ArgumentError if it is not a DBus::Object.
|
79
78
|
# Returns the object, or false if _obj_ was not exported.
|
80
79
|
def unexport(obj)
|
81
|
-
raise ArgumentError
|
80
|
+
raise ArgumentError, "DBus::Service#unexport() expects a DBus::Object argument" unless obj.is_a?(DBus::Object)
|
82
81
|
return false unless obj.path
|
83
|
-
|
84
|
-
parent_path = obj.path[1..
|
85
|
-
node_name = obj.path[
|
82
|
+
last_path_separator_idx = obj.path.rindex("/")
|
83
|
+
parent_path = obj.path[1..last_path_separator_idx - 1]
|
84
|
+
node_name = obj.path[last_path_separator_idx + 1..-1]
|
86
85
|
|
87
86
|
parent_node = get_node(parent_path, false)
|
88
87
|
return false unless parent_node
|
@@ -94,13 +93,10 @@ module DBus
|
|
94
93
|
# true, the the nodes in the path are created if they do not already exist.
|
95
94
|
def get_node(path, create = false)
|
96
95
|
n = @root
|
97
|
-
path.sub(
|
98
|
-
if
|
99
|
-
if
|
100
|
-
|
101
|
-
else
|
102
|
-
n[elem] = Node.new(elem)
|
103
|
-
end
|
96
|
+
path.sub(%r{^/}, "").split("/").each do |elem|
|
97
|
+
if !(n[elem])
|
98
|
+
return nil if !create
|
99
|
+
n[elem] = Node.new(elem)
|
104
100
|
end
|
105
101
|
n = n[elem]
|
106
102
|
end
|
@@ -111,7 +107,9 @@ module DBus
|
|
111
107
|
end
|
112
108
|
|
113
109
|
#########
|
110
|
+
|
114
111
|
private
|
112
|
+
|
115
113
|
#########
|
116
114
|
|
117
115
|
# Perform a recursive retrospection on the given current _node_
|
@@ -121,16 +119,15 @@ module DBus
|
|
121
119
|
intfs, subnodes = IntrospectXMLParser.new(xml).parse
|
122
120
|
subnodes.each do |nodename|
|
123
121
|
subnode = node[nodename] = Node.new(nodename)
|
124
|
-
if path == "/"
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
122
|
+
subpath = if path == "/"
|
123
|
+
"/" + nodename
|
124
|
+
else
|
125
|
+
path + "/" + nodename
|
126
|
+
end
|
129
127
|
rec_introspect(subnode, subpath)
|
130
128
|
end
|
131
|
-
if intfs.
|
132
|
-
|
133
|
-
end
|
129
|
+
return if intfs.empty?
|
130
|
+
node.object = ProxyObjectFactory.new(xml, @bus, @name, path).build
|
134
131
|
end
|
135
132
|
end
|
136
133
|
|
@@ -156,18 +153,18 @@ module DBus
|
|
156
153
|
"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
|
157
154
|
<node>
|
158
155
|
'
|
159
|
-
|
156
|
+
each_pair do |k, _v|
|
160
157
|
xml += "<node name=\"#{k}\" />"
|
161
158
|
end
|
162
159
|
if @object
|
163
|
-
@object.intfs.each_pair do |
|
164
|
-
xml += %
|
160
|
+
@object.intfs.each_pair do |_k, v|
|
161
|
+
xml += %(<interface name="#{v.name}">\n)
|
165
162
|
v.methods.each_value { |m| xml += m.to_xml }
|
166
163
|
v.signals.each_value { |m| xml += m.to_xml }
|
167
|
-
xml +="</interface>\n"
|
164
|
+
xml += "</interface>\n"
|
168
165
|
end
|
169
166
|
end
|
170
|
-
xml +=
|
167
|
+
xml += "</node>"
|
171
168
|
xml
|
172
169
|
end
|
173
170
|
|
@@ -180,8 +177,8 @@ module DBus
|
|
180
177
|
# Return instance inspect information, used by Node#inspect.
|
181
178
|
def sub_inspect
|
182
179
|
s = ""
|
183
|
-
if
|
184
|
-
s += "%x "
|
180
|
+
if !@object.nil?
|
181
|
+
s += format("%x ", @object.object_id)
|
185
182
|
end
|
186
183
|
s + "{" + keys.collect { |k| "#{k} => #{self[k].sub_inspect}" }.join(",") + "}"
|
187
184
|
end
|
@@ -208,9 +205,9 @@ module DBus
|
|
208
205
|
def initialize(path)
|
209
206
|
@message_queue = MessageQueue.new(path)
|
210
207
|
@unique_name = nil
|
211
|
-
@method_call_replies =
|
212
|
-
@method_call_msgs =
|
213
|
-
@signal_matchrules =
|
208
|
+
@method_call_replies = {}
|
209
|
+
@method_call_msgs = {}
|
210
|
+
@signal_matchrules = {}
|
214
211
|
@proxy = nil
|
215
212
|
@object_root = Node.new("/")
|
216
213
|
end
|
@@ -219,20 +216,20 @@ module DBus
|
|
219
216
|
# but do not block on the queue.
|
220
217
|
# Called by a main loop when something is available in the queue
|
221
218
|
def dispatch_message_queue
|
222
|
-
while (msg = @message_queue.pop(:non_block)) # FIXME EOFError
|
219
|
+
while (msg = @message_queue.pop(:non_block)) # FIXME: EOFError
|
223
220
|
process(msg)
|
224
221
|
end
|
225
222
|
end
|
226
223
|
|
227
224
|
# Tell a bus to register itself on the glib main loop
|
228
225
|
def glibize
|
229
|
-
require
|
226
|
+
require "glib2"
|
230
227
|
# Circumvent a ruby-glib bug
|
231
|
-
@channels ||=
|
228
|
+
@channels ||= []
|
232
229
|
|
233
230
|
gio = GLib::IOChannel.new(@message_queue.socket.fileno)
|
234
231
|
@channels << gio
|
235
|
-
gio.add_watch(GLib::IOChannel::IN) do |
|
232
|
+
gio.add_watch(GLib::IOChannel::IN) do |_c, _ch|
|
236
233
|
dispatch_message_queue
|
237
234
|
true
|
238
235
|
end
|
@@ -326,8 +323,8 @@ module DBus
|
|
326
323
|
</signal>
|
327
324
|
</interface>
|
328
325
|
</node>
|
329
|
-
'
|
330
|
-
# This apostroph is for syntax highlighting editors confused by above xml: "
|
326
|
+
'.freeze
|
327
|
+
# This apostroph is for syntax highlighting editors confused by above xml: "
|
331
328
|
|
332
329
|
# @api private
|
333
330
|
# Send a _message_.
|
@@ -340,11 +337,8 @@ module DBus
|
|
340
337
|
ret = nil
|
341
338
|
if reply_handler.nil?
|
342
339
|
send_sync(message) do |rmsg|
|
343
|
-
if rmsg.is_a?(Error)
|
344
|
-
|
345
|
-
else
|
346
|
-
ret = rmsg.params
|
347
|
-
end
|
340
|
+
raise rmsg if rmsg.is_a?(Error)
|
341
|
+
ret = rmsg.params
|
348
342
|
end
|
349
343
|
else
|
350
344
|
on_return(message) do |rmsg|
|
@@ -371,8 +365,8 @@ module DBus
|
|
371
365
|
send_sync_or_async(m).first
|
372
366
|
else
|
373
367
|
send_sync_or_async(m) do |*args|
|
374
|
-
# TODO test async introspection, is it used at all?
|
375
|
-
args.shift
|
368
|
+
# TODO: test async introspection, is it used at all?
|
369
|
+
args.shift # forget the message, pass only the text
|
376
370
|
reply_handler.call(*args)
|
377
371
|
nil
|
378
372
|
end
|
@@ -389,7 +383,7 @@ module DBus
|
|
389
383
|
# The returned object is a ProxyObject that has methods you can call to
|
390
384
|
# issue somme METHOD_CALL messages, and to setup to receive METHOD_RETURN
|
391
385
|
def introspect(dest, path)
|
392
|
-
if
|
386
|
+
if !block_given?
|
393
387
|
# introspect in synchronous !
|
394
388
|
data = introspect_data(dest, path)
|
395
389
|
pof = DBus::ProxyObjectFactory.new(data, self, dest, path)
|
@@ -416,11 +410,9 @@ module DBus
|
|
416
410
|
# method calls to be serviced arrive before the reply for RequestName
|
417
411
|
# (Ticket#29).
|
418
412
|
proxy.RequestName(name, NAME_FLAG_REPLACE_EXISTING) do |rmsg, r|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
raise NameRequestError
|
423
|
-
end
|
413
|
+
# check and report errors first
|
414
|
+
raise rmsg if rmsg.is_a?(Error)
|
415
|
+
raise NameRequestError unless r == REQUEST_NAME_REPLY_PRIMARY_OWNER
|
424
416
|
end
|
425
417
|
@service = Service.new(name, self)
|
426
418
|
@service
|
@@ -431,13 +423,13 @@ module DBus
|
|
431
423
|
# ({DBus::ApiOptions#proxy_method_returns_array})
|
432
424
|
# Returns the object.
|
433
425
|
def proxy
|
434
|
-
if @proxy
|
426
|
+
if @proxy.nil?
|
435
427
|
path = "/org/freedesktop/DBus"
|
436
428
|
dest = "org.freedesktop.DBus"
|
437
429
|
pof = DBus::ProxyObjectFactory.new(
|
438
430
|
DBUSXMLINTRO, self, dest, path,
|
439
431
|
api: ApiOptions::A0
|
440
|
-
|
432
|
+
)
|
441
433
|
@proxy = pof.build["org.freedesktop.DBus"]
|
442
434
|
end
|
443
435
|
@proxy
|
@@ -446,23 +438,23 @@ module DBus
|
|
446
438
|
# @api private
|
447
439
|
# Wait for a message to arrive. Return it once it is available.
|
448
440
|
def wait_for_message
|
449
|
-
@message_queue.pop
|
441
|
+
@message_queue.pop # FIXME: EOFError
|
450
442
|
end
|
451
443
|
|
452
444
|
# @api private
|
453
445
|
# Send a message _m_ on to the bus. This is done synchronously, thus
|
454
446
|
# the call will block until a reply message arrives.
|
455
447
|
def send_sync(m, &retc) # :yields: reply/return message
|
456
|
-
return if m.nil? #check if somethings wrong
|
448
|
+
return if m.nil? # check if somethings wrong
|
457
449
|
@message_queue.push(m)
|
458
450
|
@method_call_msgs[m.serial] = m
|
459
451
|
@method_call_replies[m.serial] = retc
|
460
452
|
|
461
453
|
retm = wait_for_message
|
462
|
-
return if retm.nil? #check if somethings wrong
|
463
|
-
|
454
|
+
return if retm.nil? # check if somethings wrong
|
455
|
+
|
464
456
|
process(retm)
|
465
|
-
while @method_call_replies.
|
457
|
+
while @method_call_replies.key? m.serial
|
466
458
|
retm = wait_for_message
|
467
459
|
process(retm)
|
468
460
|
end
|
@@ -496,23 +488,23 @@ module DBus
|
|
496
488
|
|
497
489
|
def remove_match(mr)
|
498
490
|
mrs = mr.to_s
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
491
|
+
rule_existed = @signal_matchrules.delete(mrs).nil?
|
492
|
+
# don't remove nonexisting matches.
|
493
|
+
return if rule_existed
|
494
|
+
# FIXME: if we do try, the Error.MatchRuleNotFound is *not* raised
|
495
|
+
# and instead is reported as "no return code for nil"
|
496
|
+
proxy.RemoveMatch(mrs)
|
505
497
|
end
|
506
498
|
|
507
499
|
# @api private
|
508
500
|
# Process a message _m_ based on its type.
|
509
501
|
def process(m)
|
510
|
-
return if m.nil? #check if somethings wrong
|
502
|
+
return if m.nil? # check if somethings wrong
|
511
503
|
case m.message_type
|
512
504
|
when Message::ERROR, Message::METHOD_RETURN
|
513
|
-
raise InvalidPacketException if m.reply_serial
|
505
|
+
raise InvalidPacketException if m.reply_serial.nil?
|
514
506
|
mcs = @method_call_replies[m.reply_serial]
|
515
|
-
if
|
507
|
+
if !mcs
|
516
508
|
DBus.logger.debug "no return code for mcs: #{mcs.inspect} m: #{m.inspect}"
|
517
509
|
else
|
518
510
|
if m.message_type == Message::ERROR
|
@@ -528,20 +520,20 @@ module DBus
|
|
528
520
|
DBus.logger.debug "Got method call on /org/freedesktop/DBus"
|
529
521
|
end
|
530
522
|
node = @service.get_node(m.path)
|
531
|
-
if
|
523
|
+
if !node
|
532
524
|
reply = Message.error(m, "org.freedesktop.DBus.Error.UnknownObject",
|
533
525
|
"Object #{m.path} doesn't exist")
|
534
526
|
@message_queue.push(reply)
|
535
527
|
# handle introspectable as an exception:
|
536
|
-
elsif m.interface == "org.freedesktop.DBus.Introspectable"
|
537
|
-
|
528
|
+
elsif m.interface == "org.freedesktop.DBus.Introspectable" &&
|
529
|
+
m.member == "Introspect"
|
538
530
|
reply = Message.new(Message::METHOD_RETURN).reply_to(m)
|
539
531
|
reply.sender = @unique_name
|
540
532
|
reply.add_param(Type::STRING, node.to_xml)
|
541
533
|
@message_queue.push(reply)
|
542
534
|
else
|
543
535
|
obj = node.object
|
544
|
-
return if obj.nil?
|
536
|
+
return if obj.nil? # FIXME, pushes no reply
|
545
537
|
obj.dispatch(m) if obj
|
546
538
|
end
|
547
539
|
when DBus::Message::SIGNAL
|
@@ -565,7 +557,7 @@ module DBus
|
|
565
557
|
# anything
|
566
558
|
Service.new(name, self)
|
567
559
|
end
|
568
|
-
alias
|
560
|
+
alias [] service
|
569
561
|
|
570
562
|
# @api private
|
571
563
|
# Emit a signal event for the given _service_, object _obj_, interface
|
@@ -602,7 +594,6 @@ module DBus
|
|
602
594
|
end
|
603
595
|
end # class Connection
|
604
596
|
|
605
|
-
|
606
597
|
# = D-Bus session bus class
|
607
598
|
#
|
608
599
|
# The session bus is a session specific bus (mostly for desktop use).
|
@@ -625,18 +616,18 @@ module DBus
|
|
625
616
|
def self.address_from_file
|
626
617
|
# systemd uses /etc/machine-id
|
627
618
|
# traditional dbus uses /var/lib/dbus/machine-id
|
628
|
-
machine_id_path = Dir[
|
619
|
+
machine_id_path = Dir["{/etc,/var/lib/dbus,/var/db/dbus}/machine-id"].first
|
629
620
|
return nil unless machine_id_path
|
630
621
|
machine_id = File.read(machine_id_path).chomp
|
631
622
|
|
632
623
|
display = ENV["DISPLAY"][/:(\d+)\.?/, 1]
|
633
624
|
|
634
625
|
bus_file_path = File.join(ENV["HOME"], "/.dbus/session-bus/#{machine_id}-#{display}")
|
635
|
-
return nil unless File.
|
626
|
+
return nil unless File.exist?(bus_file_path)
|
636
627
|
|
637
628
|
File.open(bus_file_path).each_line do |line|
|
638
629
|
if line =~ /^DBUS_SESSION_BUS_ADDRESS=(.*)/
|
639
|
-
address =
|
630
|
+
address = Regexp.last_match(1)
|
640
631
|
return address[/\A'(.*)'\z/, 1] || address[/\A"(.*)"\z/, 1] || address
|
641
632
|
end
|
642
633
|
end
|
@@ -648,7 +639,6 @@ module DBus
|
|
648
639
|
include Singleton
|
649
640
|
end
|
650
641
|
|
651
|
-
|
652
642
|
# = D-Bus system bus class
|
653
643
|
#
|
654
644
|
# The system bus is a system-wide bus mostly used for global or
|
@@ -663,22 +653,21 @@ module DBus
|
|
663
653
|
send_hello
|
664
654
|
end
|
665
655
|
end
|
666
|
-
|
656
|
+
|
667
657
|
# = D-Bus remote (TCP) bus class
|
668
658
|
#
|
669
|
-
# This class may be used when connecting to remote (listening on a TCP socket)
|
659
|
+
# This class may be used when connecting to remote (listening on a TCP socket)
|
670
660
|
# busses. You can also use it to connect to other non-standard path busses.
|
671
|
-
#
|
661
|
+
#
|
672
662
|
# The specified socket_name should look like this:
|
673
663
|
# (for TCP) tcp:host=127.0.0.1,port=2687
|
674
664
|
# (for Unix-socket) unix:path=/tmp/my_funky_bus_socket
|
675
|
-
#
|
676
|
-
# you'll need to take care about authentification then, more info here:
|
665
|
+
#
|
666
|
+
# you'll need to take care about authentification then, more info here:
|
677
667
|
# http://github.com/pangdudu/ruby-dbus/blob/master/README.rdoc
|
678
668
|
class RemoteBus < Connection
|
679
|
-
|
680
669
|
# Get the remote bus.
|
681
|
-
def initialize
|
670
|
+
def initialize(socket_name)
|
682
671
|
super(socket_name)
|
683
672
|
send_hello
|
684
673
|
end
|
@@ -691,13 +680,13 @@ module DBus
|
|
691
680
|
|
692
681
|
# Shortcut for the {SystemBus} instance
|
693
682
|
# @return [Connection]
|
694
|
-
def
|
683
|
+
def self.system_bus
|
695
684
|
SystemBus.instance
|
696
685
|
end
|
697
686
|
|
698
687
|
# Shortcut for the {SessionBus} instance
|
699
688
|
# @return [Connection]
|
700
|
-
def
|
689
|
+
def self.session_bus
|
701
690
|
SessionBus.instance
|
702
691
|
end
|
703
692
|
|
@@ -709,7 +698,7 @@ module DBus
|
|
709
698
|
class Main
|
710
699
|
# Create a new main event loop.
|
711
700
|
def initialize
|
712
|
-
@buses =
|
701
|
+
@buses = {}
|
713
702
|
@quitting = false
|
714
703
|
end
|
715
704
|
|
@@ -728,11 +717,11 @@ module DBus
|
|
728
717
|
# before blocking, empty the buffers
|
729
718
|
# https://bugzilla.novell.com/show_bug.cgi?id=537401
|
730
719
|
@buses.each_value do |b|
|
731
|
-
while m = b.message_queue.message_from_buffer_nonblock
|
720
|
+
while (m = b.message_queue.message_from_buffer_nonblock)
|
732
721
|
b.process(m)
|
733
722
|
end
|
734
723
|
end
|
735
|
-
while
|
724
|
+
while !@quitting && !@buses.empty?
|
736
725
|
ready = IO.select(@buses.keys, [], [], 5) # timeout 5 seconds
|
737
726
|
next unless ready # timeout exceeds so continue unless quitting
|
738
727
|
ready.first.each do |socket|
|
@@ -743,7 +732,7 @@ module DBus
|
|
743
732
|
@buses.delete socket # this bus died
|
744
733
|
next
|
745
734
|
end
|
746
|
-
while m = b.message_queue.message_from_buffer_nonblock
|
735
|
+
while (m = b.message_queue.message_from_buffer_nonblock)
|
747
736
|
b.process(m)
|
748
737
|
end
|
749
738
|
end
|