pangdudu-ruby-dbus 0.2.3 → 0.2.4

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.
data/README.rdoc ADDED
@@ -0,0 +1,110 @@
1
+ = Ruby D-Bus -> ffwd
2
+
3
+ Ruby D-Bus provides an implementation of the D-Bus protocol such that the
4
+ D-Bus system can be used in the Ruby programming language.
5
+
6
+
7
+ This is my personal dev-fork of mvidners upstream.
8
+
9
+ Things will move on quick here if I need stuff. If you'd like to contrib/maintain
10
+ to this fork, let me know.
11
+
12
+ Most of my work here is actually for another project: http://github.com/pangdudu/robots/tree/master
13
+
14
+ I might also start writing a less ugly version of: http://github.com/pangdudu/ruby-dbus-daemon/tree/master
15
+
16
+ If you know of a nice custom-dbus-daemon let me know. Still thinking about writing
17
+ a dbus spec compliant server/daemon implementation in (pure) Ruby, so that I can
18
+ play around with the network and authentification more easily.
19
+
20
+ Oki, will clean up a little now. :)
21
+
22
+ Peace.
23
+
24
+ == Requirements
25
+
26
+ * Ruby 1.8 (>= 1.8.6?)
27
+
28
+ == Installation
29
+
30
+ sudo gem install pangdudu-ruby-dbus --source=http://gems.github.com
31
+
32
+ == Features
33
+
34
+ Ruby D-Bus currently supports the following features:
35
+
36
+ * Connecting to local buses.
37
+ * Accessing remote services, objects and interfaces.
38
+ * Invoking methods on remote objects synchronously and asynchronously.
39
+ * Catch signals on remote objects and handle them via callbacks.
40
+ * Remote object introspection.
41
+ * Walking object trees.
42
+ * Creating services and registering them on the bus.
43
+ * Exporting objects with interfaces on a bus for remote use.
44
+ * Rubyish D-Bus object and interface syntax support that automatically
45
+ allows for introspection.
46
+ * Emitting signals on exported objects.
47
+
48
+ * Connection to a local or remote bus over TCP/IP
49
+ * Authentification mechanisms working now: External,CookieSHA1
50
+
51
+ == Usage
52
+
53
+ === Basics:
54
+
55
+ View a tutorial online on http://trac.luon.net/data/ruby-dbus/tutorial/.
56
+
57
+
58
+ === TCP/Remote stuff:
59
+
60
+ Take a look at 'config/remote.session.dbus.conf' and start 'config/start_dbus_session.sh'.
61
+
62
+ You can now try and run one of the tests e.g. 'test/simple_socket_test.rb'.
63
+
64
+
65
+ === Problems you'll have with 'CookieSHA1' when using it remotely:
66
+
67
+ Unless we [including you :)] write a funkier SASL authentification mechanism that
68
+ makes sense when using it over-wire, we're stuck with the cookie auth.
69
+
70
+ Works like this:
71
+
72
+ There is a file in '~/.dbus-keyrings' named 'org_freedesktop_general'.
73
+ It is '-rw-------' so that only you can read it (if you change the permissions,
74
+ dbus-daemon will most likely ignore the file leaving you with 'External', which is
75
+ even worse remotely). It's kind of a secret key you use to auth against yourself
76
+ later on.
77
+
78
+ If you take a look at 'dbus/auth.rb line 40+' you'll see the problem:
79
+
80
+ # Search cookie file for id
81
+ path = File.join(ENV['HOME'], '.dbus-keyrings', context)
82
+
83
+ So if you're starting 'config/start_dbus_session.sh' on one host and 'config/start_dbus_session.sh'
84
+ on another one, you'll need to make sure that the content in '~/.dbus-keyrings/org_freedesktop_general'
85
+ is the same on both machines, in order for the 'CookieSHA1' auth to work.
86
+
87
+ Not cool. I can think of hacks with nfs,smb or fuse:sshfs making it less
88
+ painful to use.
89
+
90
+ The file content also get's updated every 5 minutes (when a client fails to auth etc.).
91
+ Making copy and paste from one shell to another very frolic.
92
+
93
+ To sum it up:
94
+
95
+ Today it's acceptable to use it like this, but until next week we'll need an easy
96
+ auth mechanism that works on the wire.
97
+
98
+
99
+ more infos:
100
+ http://dbus.freedesktop.org/doc/dbus-specification.html#auth-mechanisms
101
+ http://lists.freedesktop.org/archives/dbus/2007-June/008067.html
102
+
103
+ Booyaa.
104
+
105
+ == License
106
+
107
+ Ruby D-Bus is free software; you can redistribute it and/or modify it
108
+ under the terms of the GNU Lesser General Public License as published by the
109
+ Free Software Foundation; either version 2.1 of the License, or (at
110
+ your option) any later version.
@@ -0,0 +1,39 @@
1
+ <!-- This configuration file controls the per-user-login-session message bus.
2
+ Add a session-local.conf and edit that rather than changing this
3
+ file directly. -->
4
+
5
+ <!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-Bus Bus Configuration 1.0//EN"
6
+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
7
+ <busconfig>
8
+ <!-- Our well-known bus type, don't change this -->
9
+ <type>session</type>
10
+
11
+ <!-- If we fork, keep the user's original umask to avoid affecting
12
+ the behavior of child processes. -->
13
+ <keep_umask/>
14
+
15
+ <!-- <allow_anonymous/> -->
16
+
17
+ <!-- Listen to everything on tcp! -->
18
+ <listen>tcp:host=0.0.0.0,port=2687,family=ipv4</listen>
19
+ <!-- Listen on socket at this file location -->
20
+ <listen>unix:path=/tmp/socket_test_session_bus_socket</listen>
21
+
22
+ <standard_session_servicedirs />
23
+
24
+ <policy context="default">
25
+ <!-- Allow everything to be sent -->
26
+ <allow send_destination="*" eavesdrop="true"/>
27
+ <!-- Allow everything to be received -->
28
+ <allow eavesdrop="true"/>
29
+ <!-- Allow anyone to own anything -->
30
+ <allow own="*"/>
31
+ </policy>
32
+
33
+ <!-- raise the service start timeout to 40 seconds as it can timeout
34
+ on the live cd on slow machines -->
35
+ <limit name="service_start_timeout">60000</limit>
36
+
37
+ <include if_selinux_enabled="yes" selinux_root_relative="yes">contexts/dbus_contexts</include>
38
+
39
+ </busconfig>
@@ -0,0 +1,2 @@
1
+ #!/bin/bash
2
+ dbus-daemon --print-address --config-file=remote.session.dbus.conf
data/lib/dbus.rb CHANGED
@@ -7,11 +7,15 @@
7
7
  # modify it under the terms of the GNU Lesser General Public
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
+ require 'rubygems'
11
+ require 'rofl' #http://github.com/pangdudu/rofl/tree/master makes the debug/tracing easy
12
+ #comes from the Rofl logger/tracer module
13
+ @logger.level = Logger::DEBUG
10
14
 
11
15
  require 'dbus/type'
12
16
  require 'dbus/introspect'
13
17
  require 'dbus/export'
14
- require 'dbus/bus.rb'
18
+ require 'dbus/bus'
15
19
  require 'dbus/marshall'
16
20
  require 'dbus/message'
17
21
  require 'dbus/matchrule'
@@ -26,7 +30,7 @@ module DBus
26
30
  # Default socket name for the system bus.
27
31
  SystemSocketName = "unix:path=/var/run/dbus/system_bus_socket"
28
32
 
29
- # Socket name for the session bus.
33
+ # Socket name for the session bus, not pretty.
30
34
  SessionSocketName = ENV["DBUS_SESSION_BUS_ADDRESS"]
31
35
 
32
36
  # Byte signifying big endianness.
@@ -82,5 +86,3 @@ module DBus
82
86
  class InvalidIntrospectionData < Exception
83
87
  end
84
88
  end # module DBus
85
- #just for my info
86
- puts "pangdudus ruby-dbus fork."
data/lib/dbus/auth.rb CHANGED
@@ -29,7 +29,7 @@ module DBus
29
29
  # each character and determin hex value "1" => 0x31, "0" => 0x30. You
30
30
  # obtain for "1000" => 31303030 This is what the server is expecting.
31
31
  # Why? I dunno. How did I come to that conclusion? by looking at rbus
32
- # code. I have no idea how he found that out.
32
+ # code. I have no idea how he found that out.
33
33
  return Process.uid.to_s.split(//).collect { |a| "%x" % a[0] }.join
34
34
  end
35
35
  end
@@ -61,10 +61,12 @@ module DBus
61
61
  c_challenge = Array.new(s_challenge.length/2).map{|obj|obj=rand(255).to_s}.join
62
62
  # Search cookie file for id
63
63
  path = File.join(ENV['HOME'], '.dbus-keyrings', context)
64
+ dlog "path: #{path.inspect}"
64
65
  File.foreach(path) do |line|
65
66
  if line.index(id) == 0
66
67
  # Right line of file, read cookie
67
68
  cookie = line.split(' ')[2].chomp
69
+ dlog "cookie: #{cookie.inspect}"
68
70
  # Concatenate and encrypt
69
71
  to_encrypt = [s_challenge, c_challenge, cookie].join(':')
70
72
  sha = Digest::SHA1.hexdigest(to_encrypt)
@@ -75,7 +77,7 @@ module DBus
75
77
  return response
76
78
  end
77
79
  end
78
- raise AuthException, 'Unable to locate cookie'
80
+ elog "Unable to locate cookie"
79
81
  end
80
82
 
81
83
  # encode plain to hex
@@ -126,9 +128,16 @@ module DBus
126
128
 
127
129
  # Try authentication using the next authenticator.
128
130
  def next_authenticator
129
- raise AuthenticationFailed if @auth_list.size == 0
130
- @authenticator = @auth_list.shift.new
131
- send("AUTH", @authenticator.name, @authenticator.authenticate)
131
+ begin
132
+ raise AuthException if @auth_list.size == 0
133
+ @authenticator = @auth_list.shift.new
134
+ auth_msg = ["AUTH", @authenticator.name, @authenticator.authenticate]
135
+ dlog "auth_msg: #{auth_msg.inspect}"
136
+ send(auth_msg)
137
+ rescue AuthException
138
+ @socket.close
139
+ raise
140
+ end
132
141
  end
133
142
 
134
143
 
@@ -142,32 +151,36 @@ module DBus
142
151
  break if buf.nil?
143
152
  left -= buf.size
144
153
  data += buf
145
- break if data.include? crlf
154
+ break if data.include? crlf #crlf means line finished, the TCP socket keeps on listening, so we break
146
155
  end
147
156
  readline = data.chomp.split(" ")
157
+ dlog "readline: #{readline.inspect}"
148
158
  return readline
149
- #return @socket.readline.chomp.split(" ")
150
159
  end
151
160
 
152
161
  # Try to reach the next state based on the current state.
153
162
  def next_state
154
163
  msg = next_msg
155
164
  if @state == :Starting
165
+ dlog ":Starting msg: #{msg[0].inspect}"
156
166
  case msg[0]
157
167
  when "OK"
158
168
  @state = :WaitingForOk
159
169
  when "CONTINUE"
160
170
  @state = :WaitingForData
161
- when "REJECTED" #needed by tcp, unix-path/abstract don't get here
171
+ when "REJECTED" #needed by tcp, unix-path/abstract doesn't get here
162
172
  @state = :WaitingForData
163
173
  end
164
174
  end
175
+ dlog "state: #{@state}"
165
176
  case @state
166
177
  when :WaitingForData
178
+ dlog ":WaitingForData msg: #{msg[0].inspect}"
167
179
  case msg[0]
168
180
  when "DATA"
169
181
  chall = msg[1]
170
182
  resp, chall = @authenticator.data(chall)
183
+ dlog ":WaitingForData/DATA resp: #{resp.inspect}"
171
184
  case resp
172
185
  when :AuthContinue
173
186
  send("DATA", chall)
@@ -193,6 +206,7 @@ module DBus
193
206
  @state = :WaitingForData
194
207
  end
195
208
  when :WaitingForOk
209
+ dlog ":WaitingForOk msg: #{msg[0].inspect}"
196
210
  case msg[0]
197
211
  when "OK"
198
212
  send("BEGIN")
@@ -208,6 +222,7 @@ module DBus
208
222
  @state = :WaitingForOk
209
223
  end
210
224
  when :WaitingForReject
225
+ dlog ":WaitingForReject msg: #{msg[0].inspect}"
211
226
  case msg[0]
212
227
  when "REJECT"
213
228
  next_authenticator
data/lib/dbus/bus.rb CHANGED
@@ -7,7 +7,6 @@
7
7
  # modify it under the terms of the GNU Lesser General Public
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
-
11
10
  require 'socket'
12
11
  require 'thread'
13
12
  require 'singleton'
@@ -78,7 +77,7 @@ module DBus
78
77
  n = n[elem]
79
78
  end
80
79
  if n.nil?
81
- puts "Warning, unknown object #{path}" if $DEBUG
80
+ wlog "Unknown object #{path.inspect}"
82
81
  end
83
82
  n
84
83
  end
@@ -124,10 +123,9 @@ module DBus
124
123
 
125
124
  # Return an XML string representation of the node.
126
125
  def to_xml
127
- xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
128
- "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
129
- <node>
130
- '
126
+ xml = '<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
127
+ <node>'
128
+
131
129
  self.each_pair do |k, v|
132
130
  xml += "<node name=\"#{k}\" />"
133
131
  end
@@ -140,7 +138,7 @@ module DBus
140
138
  end
141
139
  end
142
140
  xml += '</node>'
143
- xml
141
+ return xml
144
142
  end
145
143
 
146
144
  # Return inspect information of the node.
@@ -176,11 +174,7 @@ module DBus
176
174
  # http://dbus.freedesktop.org/doc/dbus-specification.html#addresses
177
175
  # and is something like:
178
176
  # "transport1:key1=value1,key2=value2;transport2:key1=value1,key2=value2"
179
- # e.g. "unix:path=/tmp/dbus-test"
180
- #
181
- # Current implementation of ruby-dbus supports only a single server
182
- # address and only "unix:path=...,guid=..." and
183
- # "unix:abstract=...,guid=..." forms
177
+ # e.g. "unix:path=/tmp/dbus-test" or "tcp:host=localhost,port=2687"
184
178
  def initialize(path)
185
179
  @path = path
186
180
  @unique_name = nil
@@ -194,8 +188,8 @@ module DBus
194
188
 
195
189
  # Connect to the bus and initialize the connection.
196
190
  def connect
197
- connect_to_tcp if @path.include? "tcp:" #testing
198
- connect_to_unix_abstract if @path.include? "unix:" #supposed stable
191
+ connect_to_tcp if @path.include? "tcp:" #connect to tcp socket
192
+ connect_to_unix if @path.include? "unix:" #connect to unix socket
199
193
  end
200
194
 
201
195
  # Connect to a bus over tcp and initialize the connection.
@@ -209,18 +203,23 @@ module DBus
209
203
  port = para.sub("port=","").to_i if para.include? "port="
210
204
  family = para.sub("family=","") if para.include? "family="
211
205
  end
212
- #puts "host,port,family : #{host},#{port},#{family}"
213
- #initialize the tcp socket
214
- @socket = TCPSocket.new(host,port)
215
- init_connection
206
+ dlog "host,port,family : #{host},#{port},#{family}"
207
+ begin
208
+ #initialize the tcp socket
209
+ @socket = TCPSocket.new(host,port)
210
+ init_connection
211
+ rescue
212
+ elog "Could not establish connection to: #{@path}, will now exit."
213
+ exit(0) #a little harsh
214
+ end
216
215
  else
217
216
  #Danger, Will Robinson: the specified "path" is not usable
218
- puts "ERROR:dbus/bus.rb/Connection.connect_to_tcp: supplied path: #{@path}, unasable! sry" if $DEBUG
217
+ elog "supplied path: #{@path}, unusable! sorry."
219
218
  end
220
219
  end
221
220
 
222
221
  # Connect to an abstract unix bus and initialize the connection.
223
- def connect_to_unix_abstract
222
+ def connect_to_unix
224
223
  @socket = Socket.new(Socket::Constants::PF_UNIX,Socket::Constants::SOCK_STREAM, 0)
225
224
  parse_session_string
226
225
  if @transport == "unix" and @type == "abstract"
@@ -260,7 +259,7 @@ module DBus
260
259
 
261
260
  # Send the buffer _buf_ to the bus using Connection#writel.
262
261
  def send(buf)
263
- @socket.write(buf)
262
+ @socket.write(buf) unless @socket.nil?
264
263
  end
265
264
 
266
265
  # Tell a bus to register itself on the glib main loop
@@ -447,7 +446,7 @@ module DBus
447
446
  # Fill (append) the buffer from data that might be available on the
448
447
  # socket.
449
448
  def update_buffer
450
- @buffer += @socket.read_nonblock(MSG_BUF_SIZE)
449
+ @buffer += @socket.read_nonblock(MSG_BUF_SIZE) unless @socket.nil?
451
450
  end
452
451
 
453
452
  # Get one message from the bus and remove it from the buffer.
@@ -488,6 +487,10 @@ module DBus
488
487
 
489
488
  # Wait for a message to arrive. Return it once it is available.
490
489
  def wait_for_message
490
+ if @socket.nil?
491
+ elog "Can't wait for messages, @socket is nil."
492
+ return
493
+ end
491
494
  ret = pop_message
492
495
  while ret == nil
493
496
  r, d, d = IO.select([@socket])
@@ -502,11 +505,15 @@ module DBus
502
505
  # Send a message _m_ on to the bus. This is done synchronously, thus
503
506
  # the call will block until a reply message arrives.
504
507
  def send_sync(m, &retc) # :yields: reply/return message
508
+ return if m.nil? #check if somethings wrong
505
509
  send(m.marshall)
506
510
  @method_call_msgs[m.serial] = m
507
511
  @method_call_replies[m.serial] = retc
508
512
 
509
513
  retm = wait_for_message
514
+
515
+ return if retm.nil? #check if somethings wrong
516
+
510
517
  process(retm)
511
518
  until [DBus::Message::ERROR,
512
519
  DBus::Message::METHOD_RETURN].include?(retm.message_type) and
@@ -521,6 +528,7 @@ module DBus
521
528
  def on_return(m, &retc)
522
529
  # Have a better exception here
523
530
  if m.message_type != Message::METHOD_CALL
531
+ elog "Funky exception, occured."
524
532
  raise "on_return should only get method_calls"
525
533
  end
526
534
  @method_call_msgs[m.serial] = m
@@ -536,17 +544,14 @@ module DBus
536
544
  end
537
545
 
538
546
  # Process a message _m_ based on its type.
539
- # method call:: FIXME...
540
- # method call return value:: FIXME...
541
- # signal:: FIXME...
542
- # error:: FIXME...
543
547
  def process(m)
548
+ return if m.nil? #check if somethings wrong
544
549
  case m.message_type
545
550
  when Message::ERROR, Message::METHOD_RETURN
546
551
  raise InvalidPacketException if m.reply_serial == nil
547
552
  mcs = @method_call_replies[m.reply_serial]
548
553
  if not mcs
549
- puts "no return code for #{mcs.inspect} (#{m.inspect})" if $DEBUG
554
+ dlog "no return code for mcs: #{mcs.inspect} m: #{m.inspect}"
550
555
  else
551
556
  if m.message_type == Message::ERROR
552
557
  mcs.call(Error.new(m))
@@ -558,7 +563,7 @@ module DBus
558
563
  end
559
564
  when DBus::Message::METHOD_CALL
560
565
  if m.path == "/org/freedesktop/DBus"
561
- puts "Got method call on /org/freedesktop/DBus" if $DEBUG
566
+ dlog "Got method call on /org/freedesktop/DBus"
562
567
  end
563
568
  # handle introspectable as an exception:
564
569
  if m.interface == "org.freedesktop.DBus.Introspectable" and
@@ -586,7 +591,7 @@ module DBus
586
591
  end
587
592
  end
588
593
  else
589
- puts "Unknown message type: #{m.message_type}" if $DEBUG
594
+ dlog "Unknown message type: #{m.message_type}"
590
595
  end
591
596
  end
592
597
 
@@ -626,7 +631,7 @@ module DBus
626
631
  m.member = "Hello"
627
632
  send_sync(m) do |rmsg|
628
633
  @unique_name = rmsg.destination
629
- puts "Got hello reply. Our unique_name is #{@unique_name}" if $DEBUG
634
+ dlog "Got hello reply. Our unique_name is #{@unique_name}, i feel special."
630
635
  end
631
636
  end
632
637