em-ruby-dbus 0.11.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 +7 -0
- data/COPYING +504 -0
- data/NEWS +253 -0
- data/README.md +93 -0
- data/Rakefile +58 -0
- data/VERSION +1 -0
- data/doc/Reference.md +207 -0
- data/doc/Tutorial.md +480 -0
- data/doc/ex-calling-methods.body.rb +8 -0
- data/doc/ex-calling-methods.rb +3 -0
- data/doc/ex-properties.body.rb +9 -0
- data/doc/ex-properties.rb +3 -0
- data/doc/ex-setup.rb +7 -0
- data/doc/ex-signal.body.rb +20 -0
- data/doc/ex-signal.rb +3 -0
- data/doc/example-helper.rb +6 -0
- data/em-ruby-dbus.gemspec +20 -0
- data/examples/gdbus/gdbus +255 -0
- data/examples/gdbus/gdbus.glade +184 -0
- data/examples/gdbus/launch.sh +4 -0
- data/examples/no-introspect/nm-test.rb +21 -0
- data/examples/no-introspect/tracker-test.rb +16 -0
- data/examples/rhythmbox/playpause.rb +25 -0
- data/examples/service/call_service.rb +25 -0
- data/examples/service/service_newapi.rb +51 -0
- data/examples/simple/call_introspect.rb +34 -0
- data/examples/simple/properties.rb +19 -0
- data/examples/utils/listnames.rb +11 -0
- data/examples/utils/notify.rb +19 -0
- data/lib/dbus.rb +82 -0
- data/lib/dbus/auth.rb +269 -0
- data/lib/dbus/bus.rb +739 -0
- data/lib/dbus/core_ext/array/extract_options.rb +31 -0
- data/lib/dbus/core_ext/class/attribute.rb +129 -0
- data/lib/dbus/core_ext/kernel/singleton_class.rb +8 -0
- data/lib/dbus/core_ext/module/remove_method.rb +14 -0
- data/lib/dbus/error.rb +46 -0
- data/lib/dbus/export.rb +128 -0
- data/lib/dbus/introspect.rb +219 -0
- data/lib/dbus/logger.rb +31 -0
- data/lib/dbus/loop-em.rb +19 -0
- data/lib/dbus/marshall.rb +434 -0
- data/lib/dbus/matchrule.rb +101 -0
- data/lib/dbus/message.rb +276 -0
- data/lib/dbus/message_queue.rb +166 -0
- data/lib/dbus/proxy_object.rb +149 -0
- data/lib/dbus/proxy_object_factory.rb +41 -0
- data/lib/dbus/proxy_object_interface.rb +128 -0
- data/lib/dbus/type.rb +193 -0
- data/lib/dbus/xml.rb +161 -0
- data/test/async_spec.rb +47 -0
- data/test/binding_spec.rb +74 -0
- data/test/bus_and_xml_backend_spec.rb +39 -0
- data/test/bus_driver_spec.rb +20 -0
- data/test/bus_spec.rb +20 -0
- data/test/byte_array_spec.rb +38 -0
- data/test/err_msg_spec.rb +42 -0
- data/test/introspect_xml_parser_spec.rb +26 -0
- data/test/introspection_spec.rb +32 -0
- data/test/main_loop_spec.rb +82 -0
- data/test/property_spec.rb +53 -0
- data/test/server_robustness_spec.rb +66 -0
- data/test/server_spec.rb +53 -0
- data/test/service_newapi.rb +217 -0
- data/test/session_bus_spec_manual.rb +15 -0
- data/test/signal_spec.rb +90 -0
- data/test/spec_helper.rb +33 -0
- data/test/thread_safety_spec.rb +31 -0
- data/test/tools/dbus-launch-simple +35 -0
- data/test/tools/dbus-limited-session.conf +28 -0
- data/test/tools/test_env +13 -0
- data/test/tools/test_server +39 -0
- data/test/type_spec.rb +19 -0
- data/test/value_spec.rb +81 -0
- data/test/variant_spec.rb +66 -0
- metadata +145 -0
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Trivial network interface lister using NetworkManager.
|
4
|
+
# NetworkManager does not support introspection, so the api is not that sexy.
|
5
|
+
|
6
|
+
require 'dbus'
|
7
|
+
|
8
|
+
bus = DBus::SystemBus.instance
|
9
|
+
|
10
|
+
nm_service = bus.service("org.freedesktop.NetworkManager")
|
11
|
+
nm_manager = nm_service.object("/org/freedesktop/NetworkManager")
|
12
|
+
poi = DBus::ProxyObjectInterface.new(nm_manager, "org.freedesktop.NetworkManager")
|
13
|
+
begin
|
14
|
+
poi.define_method("getDevices", "") # NM 0.6
|
15
|
+
p poi.getDevices
|
16
|
+
rescue Exception
|
17
|
+
poi.define_method("GetDevices", "") # NM 0.7
|
18
|
+
p poi.GetDevices
|
19
|
+
end
|
20
|
+
|
21
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
# Trivial network interface lister using NetworkManager.
|
4
|
+
# NetworkManager does not support introspection, so the api is not that sexy.
|
5
|
+
|
6
|
+
require 'dbus'
|
7
|
+
|
8
|
+
bus = DBus::SessionBus.instance
|
9
|
+
|
10
|
+
tracker_service = bus.service("org.freedesktop.Tracker")
|
11
|
+
tracker_manager = tracker_service.object("/org/freedesktop/tracker")
|
12
|
+
poi = DBus::ProxyObjectInterface.new(tracker_manager, "org.freedesktop.Tracker.Files")
|
13
|
+
poi.define_method("GetMetadataForFilesInFolder", "in live_query_id:i, in uri:s, in fields:as, out values:aas")
|
14
|
+
p poi.GetMetadataForFilesInFolder(-1, ENV['HOME'] + "/Desktop", ["File:Name", "File:Size"])
|
15
|
+
|
16
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'dbus'
|
4
|
+
bus = DBus::SessionBus.instance
|
5
|
+
# get a rb object
|
6
|
+
proxy = bus.introspect("org.gnome.Rhythmbox", "/org/gnome/Rhythmbox/Player")
|
7
|
+
proxyi = proxy["org.gnome.Rhythmbox.Player"]
|
8
|
+
|
9
|
+
# register for signals
|
10
|
+
|
11
|
+
mr = DBus::MatchRule.new
|
12
|
+
mr.type = "signal"
|
13
|
+
mr.interface = "org.gnome.Rhythmbox.Player"
|
14
|
+
mr.path = "/org/gnome/Rhythmbox/Player"
|
15
|
+
bus.add_match(mr) do |msg, first_param|
|
16
|
+
print msg.member + " "
|
17
|
+
puts first_param
|
18
|
+
end
|
19
|
+
|
20
|
+
proxyi.playPause(true)
|
21
|
+
|
22
|
+
main = DBus::Main.new
|
23
|
+
main << bus
|
24
|
+
main.run
|
25
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "dbus"
|
4
|
+
|
5
|
+
session_bus = DBus::SessionBus.instance
|
6
|
+
|
7
|
+
ruby_srv = session_bus.service("org.ruby.service")
|
8
|
+
|
9
|
+
# Get the object from this service
|
10
|
+
player = ruby_srv.object("/org/ruby/MyInstance")
|
11
|
+
|
12
|
+
# Introspect it
|
13
|
+
puts player.introspect
|
14
|
+
player.default_iface = "org.ruby.SampleInterface"
|
15
|
+
player.test_variant(["s", "coucou"])
|
16
|
+
player.on_signal("SomethingJustHappened") do |u, v|
|
17
|
+
puts "SomethingJustHappened: #{u} #{v}"
|
18
|
+
end
|
19
|
+
player.hello("8=======D", "(_._)")
|
20
|
+
p player["org.ruby.AnotherInterface"].Reverse("Hello world!")
|
21
|
+
|
22
|
+
main = DBus::Main.new
|
23
|
+
main << session_bus
|
24
|
+
main.run
|
25
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'dbus'
|
4
|
+
require 'thread'
|
5
|
+
Thread.abort_on_exception = true
|
6
|
+
|
7
|
+
class Test < DBus::Object
|
8
|
+
# Create an interface aggregating all upcoming dbus_method defines.
|
9
|
+
dbus_interface "org.ruby.SampleInterface" do
|
10
|
+
dbus_method :hello, "in name:s, in name2:s" do |name, name2|
|
11
|
+
puts "hello(#{name}, #{name2})"
|
12
|
+
end
|
13
|
+
|
14
|
+
dbus_method :test_variant, "in stuff:v" do |variant|
|
15
|
+
p variant
|
16
|
+
end
|
17
|
+
|
18
|
+
dbus_signal :SomethingJustHappened, "toto:s, tutu:u"
|
19
|
+
end
|
20
|
+
|
21
|
+
dbus_interface "org.ruby.AnotherInterface" do
|
22
|
+
dbus_method :ThatsALongMethodNameIThink do
|
23
|
+
puts "ThatsALongMethodNameIThink"
|
24
|
+
end
|
25
|
+
dbus_method :Reverse, "in instr:s, out outstr:s" do |instr|
|
26
|
+
outstr = instr.split(//).reverse.join
|
27
|
+
puts "got: #{instr}, replying: #{outstr}"
|
28
|
+
[outstr]
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
bus = DBus::SessionBus.instance
|
34
|
+
service = bus.request_service("org.ruby.service")
|
35
|
+
myobj = Test.new("/org/ruby/MyInstance")
|
36
|
+
service.export(myobj)
|
37
|
+
|
38
|
+
Thread.new do
|
39
|
+
i = 0
|
40
|
+
loop do
|
41
|
+
# Signal emission
|
42
|
+
myobj.SomethingJustHappened("hey", i += 1)
|
43
|
+
sleep(0.5)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
puts "listening"
|
48
|
+
main = DBus::Main.new
|
49
|
+
main << bus
|
50
|
+
main.run
|
51
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "dbus"
|
4
|
+
|
5
|
+
session_bus = DBus::SessionBus.instance
|
6
|
+
|
7
|
+
# Get the Rhythmbox service
|
8
|
+
rhythmbox = session_bus.service("org.gnome.Rhythmbox")
|
9
|
+
|
10
|
+
# Get the object from this service
|
11
|
+
player = rhythmbox.object("/org/gnome/Rhythmbox/Player")
|
12
|
+
|
13
|
+
# Introspect it
|
14
|
+
player.introspect
|
15
|
+
if player.has_iface? "org.gnome.Rhythmbox.Player"
|
16
|
+
puts "We have Rhythmbox Player interface"
|
17
|
+
end
|
18
|
+
|
19
|
+
player_with_iface = player["org.gnome.Rhythmbox.Player"]
|
20
|
+
p player_with_iface.getPlayingUri
|
21
|
+
|
22
|
+
# Maybe support default_iface=(iface_str) on an ProxyObject, so
|
23
|
+
# that this is possible?
|
24
|
+
player.default_iface = "org.gnome.Rhythmbox.Player"
|
25
|
+
puts "default_iface test:"
|
26
|
+
p player.getPlayingUri
|
27
|
+
player.on_signal("elapsedChanged") do |u|
|
28
|
+
puts "elapsedChanged: #{u}"
|
29
|
+
end
|
30
|
+
|
31
|
+
main = DBus::Main.new
|
32
|
+
main << session_bus
|
33
|
+
main.run
|
34
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
require 'dbus'
|
3
|
+
|
4
|
+
bus = DBus::SystemBus.instance
|
5
|
+
nm_service = bus["org.freedesktop.NetworkManager"]
|
6
|
+
network_manager_object = nm_service.object("/org/freedesktop/NetworkManager")
|
7
|
+
network_manager_object.introspect
|
8
|
+
nm_iface = network_manager_object["org.freedesktop.NetworkManager"]
|
9
|
+
|
10
|
+
# read a property
|
11
|
+
enabled = nm_iface["WirelessEnabled"]
|
12
|
+
if enabled
|
13
|
+
puts "Wireless is enabled"
|
14
|
+
else
|
15
|
+
puts "Wireless is disabled"
|
16
|
+
end
|
17
|
+
puts "Toggling wireless"
|
18
|
+
# write a property
|
19
|
+
nm_iface["WirelessEnabled"] = ! enabled
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'dbus'
|
4
|
+
|
5
|
+
if ARGV.size < 2
|
6
|
+
puts "Usage:"
|
7
|
+
puts "notify.rb \"title\" \"body\""
|
8
|
+
exit
|
9
|
+
end
|
10
|
+
|
11
|
+
d = DBus::SessionBus.instance
|
12
|
+
o = d.service("org.freedesktop.Notifications").object("/org/freedesktop/Notifications")
|
13
|
+
o.introspect
|
14
|
+
|
15
|
+
i = o["org.freedesktop.Notifications"]
|
16
|
+
|
17
|
+
i.Notify('notify.rb', 0, 'info', ARGV[0], ARGV[1], [], {}, 2000) do |ret, param|
|
18
|
+
end
|
19
|
+
|
data/lib/dbus.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
# dbus.rb - Module containing the low-level D-Bus implementation
|
2
|
+
#
|
3
|
+
# This file is part of the ruby-dbus project
|
4
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
5
|
+
#
|
6
|
+
# This library is free software; you can redistribute it and/or
|
7
|
+
# modify it under the terms of the GNU Lesser General Public
|
8
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
9
|
+
# See the file "COPYING" for the exact licensing terms.
|
10
|
+
|
11
|
+
require_relative "dbus/auth"
|
12
|
+
require_relative "dbus/bus"
|
13
|
+
require_relative "dbus/core_ext/class/attribute"
|
14
|
+
require_relative "dbus/error"
|
15
|
+
require_relative "dbus/export"
|
16
|
+
require_relative "dbus/introspect"
|
17
|
+
require_relative "dbus/logger"
|
18
|
+
require_relative "dbus/marshall"
|
19
|
+
require_relative "dbus/matchrule"
|
20
|
+
require_relative "dbus/message"
|
21
|
+
require_relative "dbus/message_queue"
|
22
|
+
require_relative "dbus/proxy_object"
|
23
|
+
require_relative "dbus/proxy_object_factory"
|
24
|
+
require_relative "dbus/proxy_object_interface"
|
25
|
+
require_relative "dbus/type"
|
26
|
+
require_relative "dbus/xml"
|
27
|
+
|
28
|
+
require "socket"
|
29
|
+
require "thread"
|
30
|
+
|
31
|
+
# = D-Bus main module
|
32
|
+
#
|
33
|
+
# Module containing all the D-Bus modules and classes.
|
34
|
+
module DBus
|
35
|
+
# Default socket name for the system bus.
|
36
|
+
SystemSocketName = "unix:path=/var/run/dbus/system_bus_socket"
|
37
|
+
|
38
|
+
# Byte signifying big endianness.
|
39
|
+
BIG_END = ?B
|
40
|
+
# Byte signifying little endianness.
|
41
|
+
LIL_END = ?l
|
42
|
+
|
43
|
+
# Byte signifying the host's endianness.
|
44
|
+
HOST_END = if [0x01020304].pack("L").unpack("V")[0] == 0x01020304
|
45
|
+
LIL_END
|
46
|
+
else
|
47
|
+
BIG_END
|
48
|
+
end
|
49
|
+
|
50
|
+
# General exceptions.
|
51
|
+
|
52
|
+
# Exception raised when an invalid packet is encountered.
|
53
|
+
class InvalidPacketException < Exception
|
54
|
+
end
|
55
|
+
|
56
|
+
# Exception raised when there is a problem with a type (may be unknown or
|
57
|
+
# mismatch).
|
58
|
+
class TypeException < Exception
|
59
|
+
end
|
60
|
+
|
61
|
+
# Exception raised when an unmarshalled buffer is truncated and
|
62
|
+
# incomplete.
|
63
|
+
class IncompleteBufferException < Exception
|
64
|
+
end
|
65
|
+
|
66
|
+
# Exception raised when a method has not been implemented (yet).
|
67
|
+
class MethodNotImplemented < Exception
|
68
|
+
end
|
69
|
+
|
70
|
+
# Exception raised when a method is invoked with invalid
|
71
|
+
# parameters (wrong number or type).
|
72
|
+
class InvalidParameters < Exception
|
73
|
+
end
|
74
|
+
|
75
|
+
# Exception raised when an invalid method name is used.
|
76
|
+
class InvalidMethodName < Exception
|
77
|
+
end
|
78
|
+
|
79
|
+
# Exception raised when invalid introspection data is parsed/used.
|
80
|
+
class InvalidIntrospectionData < Exception
|
81
|
+
end
|
82
|
+
end # module DBus
|
data/lib/dbus/auth.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
# This file is part of the ruby-dbus project
|
2
|
+
# Copyright (C) 2007 Arnaud Cornet and Paul van Tilburg
|
3
|
+
#
|
4
|
+
# This library is free software; you can redistribute it and/or
|
5
|
+
# modify it under the terms of the GNU Lesser General Public
|
6
|
+
# License, version 2.1 as published by the Free Software Foundation.
|
7
|
+
# See the file "COPYING" for the exact licensing terms.
|
8
|
+
|
9
|
+
require 'rbconfig'
|
10
|
+
|
11
|
+
module DBus
|
12
|
+
# Exception raised when authentication fails somehow.
|
13
|
+
class AuthenticationFailed < Exception
|
14
|
+
end
|
15
|
+
|
16
|
+
# = General class for authentication.
|
17
|
+
class Authenticator
|
18
|
+
# Returns the name of the authenticator.
|
19
|
+
def name
|
20
|
+
self.class.to_s.upcase.sub(/.*::/, "")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# = Anonymous authentication class
|
25
|
+
class Anonymous < Authenticator
|
26
|
+
def authenticate
|
27
|
+
'527562792044427573' # Hex encoded version of "Ruby DBus"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# = External authentication class
|
32
|
+
#
|
33
|
+
# Class for 'external' type authentication.
|
34
|
+
class External < Authenticator
|
35
|
+
# Performs the authentication.
|
36
|
+
def authenticate
|
37
|
+
# Take the user id (eg integer 1000) make a string out of it "1000", take
|
38
|
+
# each character and determin hex value "1" => 0x31, "0" => 0x30. You
|
39
|
+
# obtain for "1000" => 31303030 This is what the server is expecting.
|
40
|
+
# Why? I dunno. How did I come to that conclusion? by looking at rbus
|
41
|
+
# code. I have no idea how he found that out.
|
42
|
+
return Process.uid.to_s.split(//).collect { |a| "%x" % a[0].ord }.join
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# = Authentication class using SHA1 crypto algorithm
|
47
|
+
#
|
48
|
+
# Class for 'CookieSHA1' type authentication.
|
49
|
+
# Implements the AUTH DBUS_COOKIE_SHA1 mechanism.
|
50
|
+
class DBusCookieSHA1 < Authenticator
|
51
|
+
|
52
|
+
#the autenticate method (called in stage one of authentification)
|
53
|
+
def authenticate
|
54
|
+
require 'etc'
|
55
|
+
#number of retries we have for auth
|
56
|
+
@retries = 1
|
57
|
+
return "#{hex_encode(Etc.getlogin)}" #server expects it to be binary
|
58
|
+
end
|
59
|
+
|
60
|
+
#returns the modules name
|
61
|
+
def name
|
62
|
+
return 'DBUS_COOKIE_SHA1'
|
63
|
+
end
|
64
|
+
|
65
|
+
#handles the interesting crypto stuff, check the rbus-project for more info: http://rbus.rubyforge.org/
|
66
|
+
def data(hexdata)
|
67
|
+
require 'digest/sha1'
|
68
|
+
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 = Array.new(s_challenge.bytesize/2).map{|obj|obj=rand(255).to_s}.join
|
73
|
+
# Search cookie file for id
|
74
|
+
path = File.join(ENV['HOME'], '.dbus-keyrings', context)
|
75
|
+
DBus.logger.debug "path: #{path.inspect}"
|
76
|
+
File.foreach(path) do |line|
|
77
|
+
if line.index(id) == 0
|
78
|
+
# Right line of file, read cookie
|
79
|
+
cookie = line.split(' ')[2].chomp
|
80
|
+
DBus.logger.debug "cookie: #{cookie.inspect}"
|
81
|
+
# Concatenate and encrypt
|
82
|
+
to_encrypt = [s_challenge, c_challenge, cookie].join(':')
|
83
|
+
sha = Digest::SHA1.hexdigest(to_encrypt)
|
84
|
+
#the almighty tcp server wants everything hex encoded
|
85
|
+
hex_response = hex_encode("#{c_challenge} #{sha}")
|
86
|
+
# Return response
|
87
|
+
response = [:AuthOk, hex_response]
|
88
|
+
return response
|
89
|
+
end
|
90
|
+
end
|
91
|
+
#a little rescue magic
|
92
|
+
unless @retries <= 0
|
93
|
+
puts "ERROR: Could not auth, will now exit."
|
94
|
+
puts "ERROR: Unable to locate cookie, retry in 1 second."
|
95
|
+
@retries -= 1
|
96
|
+
sleep 1
|
97
|
+
data(hexdata)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# encode plain to hex
|
102
|
+
def hex_encode(plain)
|
103
|
+
return nil if plain.nil?
|
104
|
+
plain.to_s.unpack('H*')[0]
|
105
|
+
end
|
106
|
+
|
107
|
+
# decode hex to plain
|
108
|
+
def hex_decode(encoded)
|
109
|
+
encoded.scan(/[[:xdigit:]]{2}/).map{|h|h.hex.chr}.join
|
110
|
+
end
|
111
|
+
end #DBusCookieSHA1 class ends here
|
112
|
+
|
113
|
+
# Note: this following stuff is tested with External authenticator only!
|
114
|
+
|
115
|
+
# = Authentication client class.
|
116
|
+
#
|
117
|
+
# Class tha performs the actional authentication.
|
118
|
+
class Client
|
119
|
+
# Create a new authentication client.
|
120
|
+
def initialize(socket)
|
121
|
+
@socket = socket
|
122
|
+
@state = nil
|
123
|
+
@auth_list = [External,DBusCookieSHA1,Anonymous]
|
124
|
+
end
|
125
|
+
|
126
|
+
# Start the authentication process.
|
127
|
+
def authenticate
|
128
|
+
if (RbConfig::CONFIG["target_os"] =~ /freebsd/)
|
129
|
+
@socket.sendmsg(0.chr, 0, nil, [:SOCKET, :SCM_CREDS, ""])
|
130
|
+
else
|
131
|
+
@socket.write(0.chr)
|
132
|
+
end
|
133
|
+
next_authenticator
|
134
|
+
@state = :Starting
|
135
|
+
while @state != :Authenticated
|
136
|
+
r = next_state
|
137
|
+
return r if not r
|
138
|
+
end
|
139
|
+
true
|
140
|
+
end
|
141
|
+
|
142
|
+
##########
|
143
|
+
private
|
144
|
+
##########
|
145
|
+
|
146
|
+
# Send an authentication method _meth_ with arguments _args_ to the
|
147
|
+
# server.
|
148
|
+
def send(meth, *args)
|
149
|
+
o = ([meth] + args).join(" ")
|
150
|
+
@socket.write(o + "\r\n")
|
151
|
+
end
|
152
|
+
|
153
|
+
# Try authentication using the next authenticator.
|
154
|
+
def next_authenticator
|
155
|
+
begin
|
156
|
+
raise AuthenticationFailed if @auth_list.size == 0
|
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
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Read data (a buffer) from the bus until CR LF is encountered.
|
168
|
+
# Return the buffer without the CR LF characters.
|
169
|
+
def next_msg
|
170
|
+
data,crlf = "","\r\n"
|
171
|
+
left = 1024 #1024 byte, no idea if it's ever getting bigger
|
172
|
+
while left > 0
|
173
|
+
buf = @socket.read( left > 1 ? 1 : left )
|
174
|
+
break if buf.nil?
|
175
|
+
left -= buf.bytesize
|
176
|
+
data += buf
|
177
|
+
break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break
|
178
|
+
end
|
179
|
+
readline = data.chomp.split(" ")
|
180
|
+
DBus.logger.debug "readline: #{readline.inspect}"
|
181
|
+
return readline
|
182
|
+
end
|
183
|
+
|
184
|
+
=begin
|
185
|
+
# Read data (a buffer) from the bus until CR LF is encountered.
|
186
|
+
# Return the buffer without the CR LF characters.
|
187
|
+
def next_msg
|
188
|
+
@socket.readline.chomp.split(" ")
|
189
|
+
end
|
190
|
+
=end
|
191
|
+
|
192
|
+
# Try to reach the next state based on the current state.
|
193
|
+
def next_state
|
194
|
+
msg = next_msg
|
195
|
+
if @state == :Starting
|
196
|
+
DBus.logger.debug ":Starting msg: #{msg[0].inspect}"
|
197
|
+
case msg[0]
|
198
|
+
when "OK"
|
199
|
+
@state = :WaitingForOk
|
200
|
+
when "CONTINUE"
|
201
|
+
@state = :WaitingForData
|
202
|
+
when "REJECTED" #needed by tcp, unix-path/abstract doesn't get here
|
203
|
+
@state = :WaitingForData
|
204
|
+
end
|
205
|
+
end
|
206
|
+
DBus.logger.debug "state: #{@state}"
|
207
|
+
case @state
|
208
|
+
when :WaitingForData
|
209
|
+
DBus.logger.debug ":WaitingForData msg: #{msg[0].inspect}"
|
210
|
+
case msg[0]
|
211
|
+
when "DATA"
|
212
|
+
chall = msg[1]
|
213
|
+
resp, chall = @authenticator.data(chall)
|
214
|
+
DBus.logger.debug ":WaitingForData/DATA resp: #{resp.inspect}"
|
215
|
+
case resp
|
216
|
+
when :AuthContinue
|
217
|
+
send("DATA", chall)
|
218
|
+
@state = :WaitingForData
|
219
|
+
when :AuthOk
|
220
|
+
send("DATA", chall)
|
221
|
+
@state = :WaitingForOk
|
222
|
+
when :AuthError
|
223
|
+
send("ERROR")
|
224
|
+
@state = :WaitingForData
|
225
|
+
end
|
226
|
+
when "REJECTED"
|
227
|
+
next_authenticator
|
228
|
+
@state = :WaitingForData
|
229
|
+
when "ERROR"
|
230
|
+
send("CANCEL")
|
231
|
+
@state = :WaitingForReject
|
232
|
+
when "OK"
|
233
|
+
send("BEGIN")
|
234
|
+
@state = :Authenticated
|
235
|
+
else
|
236
|
+
send("ERROR")
|
237
|
+
@state = :WaitingForData
|
238
|
+
end
|
239
|
+
when :WaitingForOk
|
240
|
+
DBus.logger.debug ":WaitingForOk msg: #{msg[0].inspect}"
|
241
|
+
case msg[0]
|
242
|
+
when "OK"
|
243
|
+
send("BEGIN")
|
244
|
+
@state = :Authenticated
|
245
|
+
when "REJECT"
|
246
|
+
next_authenticator
|
247
|
+
@state = :WaitingForData
|
248
|
+
when "DATA", "ERROR"
|
249
|
+
send("CANCEL")
|
250
|
+
@state = :WaitingForReject
|
251
|
+
else
|
252
|
+
send("ERROR")
|
253
|
+
@state = :WaitingForOk
|
254
|
+
end
|
255
|
+
when :WaitingForReject
|
256
|
+
DBus.logger.debug ":WaitingForReject msg: #{msg[0].inspect}"
|
257
|
+
case msg[0]
|
258
|
+
when "REJECT"
|
259
|
+
next_authenticator
|
260
|
+
@state = :WaitingForOk
|
261
|
+
else
|
262
|
+
@socket.close
|
263
|
+
return false
|
264
|
+
end
|
265
|
+
end
|
266
|
+
return true
|
267
|
+
end # def next_state
|
268
|
+
end # class Client
|
269
|
+
end # module D-Bus
|