ruby-dbus 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|