pangdudu-ruby-dbus 0.2.3 → 0.2.4

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