demirten-ruby-dbus 0.2.4.6
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/COPYING +504 -0
- data/README.rdoc +127 -0
- data/config/remote.session.dbus.conf +39 -0
- data/config/start_dbus_session.sh +2 -0
- data/lib/dbus.rb +86 -0
- data/lib/dbus/auth.rb +251 -0
- data/lib/dbus/bus.rb +752 -0
- data/lib/dbus/export.rb +123 -0
- data/lib/dbus/introspect.rb +572 -0
- data/lib/dbus/marshall.rb +396 -0
- data/lib/dbus/matchrule.rb +98 -0
- data/lib/dbus/message.rb +281 -0
- data/lib/dbus/type.rb +207 -0
- data/test/simple_socket_test.rb +27 -0
- metadata +88 -0
data/lib/dbus/message.rb
ADDED
@@ -0,0 +1,281 @@
|
|
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
|
+
# = D-Bus main module
|
12
|
+
#
|
13
|
+
# Module containing all the D-Bus modules and classes.
|
14
|
+
module DBus
|
15
|
+
# = InvalidDestinationName class
|
16
|
+
# Thrown when you try do send a message to /org/freedesktop/DBus/Local, that
|
17
|
+
# is reserved.
|
18
|
+
class InvalidDestinationName < Exception
|
19
|
+
end
|
20
|
+
|
21
|
+
# = D-Bus message class
|
22
|
+
#
|
23
|
+
# Class that holds any type of message that travels over the bus.
|
24
|
+
class Message
|
25
|
+
# The serial number of the message.
|
26
|
+
@@serial = 1
|
27
|
+
# Mutex that protects updates on the serial number.
|
28
|
+
@@serial_mutex = Mutex.new
|
29
|
+
# Type of a message (by specification).
|
30
|
+
MESSAGE_SIGNATURE = "yyyyuua(yv)"
|
31
|
+
|
32
|
+
# FIXME: following message type constants should be under Message::Type IMO
|
33
|
+
# well, yeah sure
|
34
|
+
#
|
35
|
+
# Invalid message type.
|
36
|
+
INVALID = 0
|
37
|
+
# Method call message type.
|
38
|
+
METHOD_CALL = 1
|
39
|
+
# Method call return value message type.
|
40
|
+
METHOD_RETURN = 2
|
41
|
+
# Error message type.
|
42
|
+
ERROR = 3
|
43
|
+
# Signal message type.
|
44
|
+
SIGNAL = 4
|
45
|
+
|
46
|
+
# Message flag signyfing that no reply is expected.
|
47
|
+
NO_REPLY_EXPECTED = 0x1
|
48
|
+
# Message flag signifying that no automatic start is required/must be
|
49
|
+
# performed.
|
50
|
+
NO_AUTO_START = 0x2
|
51
|
+
|
52
|
+
# The type of the message.
|
53
|
+
attr_reader :message_type
|
54
|
+
# The path of the object instance the message must be sent to/is sent from.
|
55
|
+
attr_accessor :path
|
56
|
+
# The interface of the object that must be used/was used.
|
57
|
+
attr_accessor :interface
|
58
|
+
# The interface member (method/signal name) of the object that must be
|
59
|
+
# used/was used.
|
60
|
+
attr_accessor :member
|
61
|
+
# The name of the error (in case of an error message type).
|
62
|
+
attr_accessor :error_name
|
63
|
+
# The destination connection of the object that must be used/was used.
|
64
|
+
attr_accessor :destination
|
65
|
+
# The sender of the message.
|
66
|
+
attr_accessor :sender
|
67
|
+
# The signature of the message contents.
|
68
|
+
attr_accessor :signature
|
69
|
+
# The serial number of the message this message is a reply for.
|
70
|
+
attr_accessor :reply_serial
|
71
|
+
# The protocol.
|
72
|
+
attr_reader :protocol
|
73
|
+
# The serial of the message.
|
74
|
+
attr_reader :serial
|
75
|
+
# The parameters of the message.
|
76
|
+
attr_reader :params
|
77
|
+
|
78
|
+
# Create a message with message type _mtype_ with default values and a
|
79
|
+
# unique serial number.
|
80
|
+
def initialize(mtype = INVALID)
|
81
|
+
@message_type = mtype
|
82
|
+
|
83
|
+
@flags = 0
|
84
|
+
@protocol = 1
|
85
|
+
@body_length = 0
|
86
|
+
@signature = String.new
|
87
|
+
@@serial_mutex.synchronize do
|
88
|
+
@serial = @@serial
|
89
|
+
@@serial += 1
|
90
|
+
end
|
91
|
+
@params = Array.new
|
92
|
+
@destination = nil
|
93
|
+
@interface = nil
|
94
|
+
@error_name = nil
|
95
|
+
@member = nil
|
96
|
+
@path = nil
|
97
|
+
@reply_serial = nil
|
98
|
+
|
99
|
+
if mtype == METHOD_RETURN
|
100
|
+
@flags = NO_REPLY_EXPECTED
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Mark this message as a reply to a another message _m_, taking
|
105
|
+
# the serial number of _m_ as reply serial and the sender of _m_ as
|
106
|
+
# destination.
|
107
|
+
def reply_to(m)
|
108
|
+
@message_type = METHOD_RETURN
|
109
|
+
@reply_serial = m.serial
|
110
|
+
@destination = m.sender
|
111
|
+
self
|
112
|
+
end
|
113
|
+
|
114
|
+
# Add a parameter _val_ of type _type_ to the message.
|
115
|
+
def add_param(type, val)
|
116
|
+
type = type.chr if type.kind_of?(Fixnum)
|
117
|
+
@signature += type.to_s
|
118
|
+
@params << [type, val]
|
119
|
+
end
|
120
|
+
|
121
|
+
# FIXME: what are these? a message element constant enumeration?
|
122
|
+
# See method below, in a message, you have and array of optional parameters
|
123
|
+
# that come with an index, to determine their meaning. The values are in
|
124
|
+
# spec, more a definition than an enumeration.
|
125
|
+
|
126
|
+
PATH = 1
|
127
|
+
INTERFACE = 2
|
128
|
+
MEMBER = 3
|
129
|
+
ERROR_NAME = 4
|
130
|
+
REPLY_SERIAL = 5
|
131
|
+
DESTINATION = 6
|
132
|
+
SENDER = 7
|
133
|
+
SIGNATURE = 8
|
134
|
+
|
135
|
+
# Marshall the message with its current set parameters and return
|
136
|
+
# it in a packet form.
|
137
|
+
def marshall
|
138
|
+
if @path == "/org/freedesktop/DBus/Local"
|
139
|
+
raise InvalidDestinationName
|
140
|
+
end
|
141
|
+
|
142
|
+
params = PacketMarshaller.new
|
143
|
+
@params.each do |param|
|
144
|
+
params.append(param[0], param[1])
|
145
|
+
end
|
146
|
+
@body_length = params.packet.length
|
147
|
+
|
148
|
+
marshaller = PacketMarshaller.new
|
149
|
+
marshaller.append(Type::BYTE, HOST_END)
|
150
|
+
marshaller.append(Type::BYTE, @message_type)
|
151
|
+
marshaller.append(Type::BYTE, @flags)
|
152
|
+
marshaller.append(Type::BYTE, @protocol)
|
153
|
+
marshaller.append(Type::UINT32, @body_length)
|
154
|
+
marshaller.append(Type::UINT32, @serial)
|
155
|
+
marshaller.array(Type::Parser.new("y").parse[0]) do
|
156
|
+
if @path
|
157
|
+
marshaller.struct do
|
158
|
+
marshaller.append(Type::BYTE, PATH)
|
159
|
+
marshaller.append(Type::BYTE, 1)
|
160
|
+
marshaller.append_simple_string("o")
|
161
|
+
marshaller.append(Type::OBJECT_PATH, @path)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
if @interface
|
165
|
+
marshaller.struct do
|
166
|
+
marshaller.append(Type::BYTE, INTERFACE)
|
167
|
+
marshaller.append(Type::BYTE, 1)
|
168
|
+
marshaller.append_simple_string("s")
|
169
|
+
marshaller.append(Type::STRING, @interface)
|
170
|
+
end
|
171
|
+
end
|
172
|
+
if @member
|
173
|
+
marshaller.struct do
|
174
|
+
marshaller.append(Type::BYTE, MEMBER)
|
175
|
+
marshaller.append(Type::BYTE, 1)
|
176
|
+
marshaller.append_simple_string("s")
|
177
|
+
marshaller.append(Type::STRING, @member)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
if @error_name
|
181
|
+
marshaller.struct do
|
182
|
+
marshaller.append(Type::BYTE, ERROR_NAME)
|
183
|
+
marshaller.append(Type::BYTE, 1)
|
184
|
+
marshaller.append_simple_string("s")
|
185
|
+
marshaller.append(Type::STRING, @error_name)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
if @reply_serial
|
189
|
+
marshaller.struct do
|
190
|
+
marshaller.append(Type::BYTE, REPLY_SERIAL)
|
191
|
+
marshaller.append(Type::BYTE, 1)
|
192
|
+
marshaller.append_simple_string("u")
|
193
|
+
marshaller.append(Type::UINT32, @reply_serial)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
if @destination
|
197
|
+
marshaller.struct do
|
198
|
+
marshaller.append(Type::BYTE, DESTINATION)
|
199
|
+
marshaller.append(Type::BYTE, 1)
|
200
|
+
marshaller.append_simple_string("s")
|
201
|
+
marshaller.append(Type::STRING, @destination)
|
202
|
+
end
|
203
|
+
end
|
204
|
+
if @signature != ""
|
205
|
+
marshaller.struct do
|
206
|
+
marshaller.append(Type::BYTE, SIGNATURE)
|
207
|
+
marshaller.append(Type::BYTE, 1)
|
208
|
+
marshaller.append_simple_string("g")
|
209
|
+
marshaller.append(Type::SIGNATURE, @signature)
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
marshaller.align(8)
|
214
|
+
@params.each do |param|
|
215
|
+
marshaller.append(param[0], param[1])
|
216
|
+
end
|
217
|
+
marshaller.packet
|
218
|
+
end
|
219
|
+
|
220
|
+
# Unmarshall a packet contained in the buffer _buf_ and set the
|
221
|
+
# parameters of the message object according the data found in the
|
222
|
+
# buffer.
|
223
|
+
# Return the detected message and the index pointer of the buffer where
|
224
|
+
# the message data ended.
|
225
|
+
def unmarshall_buffer(buf)
|
226
|
+
buf = buf.dup
|
227
|
+
if buf[0] == ?l
|
228
|
+
endianness = LIL_END
|
229
|
+
else
|
230
|
+
endianness = BIG_END
|
231
|
+
end
|
232
|
+
pu = PacketUnmarshaller.new(buf, endianness)
|
233
|
+
mdata = pu.unmarshall(MESSAGE_SIGNATURE)
|
234
|
+
dummy, @message_type, @flags, @protocol, @body_length, @serial,
|
235
|
+
headers = mdata
|
236
|
+
|
237
|
+
headers.each do |struct|
|
238
|
+
case struct[0]
|
239
|
+
when PATH
|
240
|
+
@path = struct[1]
|
241
|
+
when INTERFACE
|
242
|
+
@interface = struct[1]
|
243
|
+
when MEMBER
|
244
|
+
@member = struct[1]
|
245
|
+
when ERROR_NAME
|
246
|
+
@error_name = struct[1]
|
247
|
+
when REPLY_SERIAL
|
248
|
+
@reply_serial = struct[1]
|
249
|
+
when DESTINATION
|
250
|
+
@destination = struct[1]
|
251
|
+
when SENDER
|
252
|
+
@sender = struct[1]
|
253
|
+
when SIGNATURE
|
254
|
+
@signature = struct[1]
|
255
|
+
end
|
256
|
+
end
|
257
|
+
pu.align(8)
|
258
|
+
if @body_length > 0 and @signature
|
259
|
+
@params = pu.unmarshall(@signature, @body_length)
|
260
|
+
end
|
261
|
+
[self, pu.idx]
|
262
|
+
end # def unmarshall_buf
|
263
|
+
|
264
|
+
# Unmarshall the data of a message found in the buffer _buf_ using
|
265
|
+
# Message#unmarshall_buf.
|
266
|
+
# Return the message.
|
267
|
+
def unmarshall(buf)
|
268
|
+
ret, size = unmarshall_buffer(buf)
|
269
|
+
ret
|
270
|
+
end
|
271
|
+
end # class Message
|
272
|
+
|
273
|
+
# A helper exception on errors
|
274
|
+
class Error < Exception
|
275
|
+
attr_reader :dbus_message
|
276
|
+
def initialize(msg)
|
277
|
+
super(msg.error_name + ": " + msg.params.join(", "))
|
278
|
+
@dbus_message = msg
|
279
|
+
end
|
280
|
+
end
|
281
|
+
end # module DBus
|
data/lib/dbus/type.rb
ADDED
@@ -0,0 +1,207 @@
|
|
1
|
+
# dbus/type.rb - module containing low-level D-Bus data type information
|
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
|
+
module DBus
|
12
|
+
|
13
|
+
# = D-Bus type module
|
14
|
+
#
|
15
|
+
# This module containts the constants of the types specified in the D-Bus
|
16
|
+
# protocol.
|
17
|
+
module Type
|
18
|
+
# The types.
|
19
|
+
INVALID = 0
|
20
|
+
BYTE = ?y
|
21
|
+
BOOLEAN = ?b
|
22
|
+
INT16 = ?n
|
23
|
+
UINT16 = ?q
|
24
|
+
INT32 = ?i
|
25
|
+
UINT32 = ?u
|
26
|
+
INT64 = ?x
|
27
|
+
UINT64 = ?t
|
28
|
+
DOUBLE = ?d
|
29
|
+
STRUCT = ?r
|
30
|
+
ARRAY = ?a
|
31
|
+
VARIANT = ?v
|
32
|
+
OBJECT_PATH = ?o
|
33
|
+
STRING = ?s
|
34
|
+
SIGNATURE = ?g
|
35
|
+
DICT_ENTRY = ?e
|
36
|
+
|
37
|
+
# Mapping from type number to name.
|
38
|
+
TypeName = {
|
39
|
+
INVALID => "INVALID",
|
40
|
+
BYTE => "BYTE",
|
41
|
+
BOOLEAN => "BOOLEAN",
|
42
|
+
INT16 => "INT16",
|
43
|
+
UINT16 => "UINT16",
|
44
|
+
INT32 => "INT32",
|
45
|
+
UINT32 => "UINT32",
|
46
|
+
INT64 => "INT64",
|
47
|
+
UINT64 => "UINT64",
|
48
|
+
DOUBLE => "DOUBLE",
|
49
|
+
STRUCT => "STRUCT",
|
50
|
+
ARRAY => "ARRAY",
|
51
|
+
VARIANT => "VARIANT",
|
52
|
+
OBJECT_PATH => "OBJECT_PATH",
|
53
|
+
STRING => "STRING",
|
54
|
+
SIGNATURE => "SIGNATURE",
|
55
|
+
DICT_ENTRY => "DICT_ENTRY"
|
56
|
+
}
|
57
|
+
|
58
|
+
# Exception raised when an unknown/incorrect type is encountered.
|
59
|
+
class SignatureException < Exception
|
60
|
+
end
|
61
|
+
|
62
|
+
# = D-Bus type conversion class
|
63
|
+
#
|
64
|
+
# Helper class for representing a D-Bus type.
|
65
|
+
class Type
|
66
|
+
# Returns the signature type number.
|
67
|
+
attr_reader :sigtype
|
68
|
+
# Return contained member types.
|
69
|
+
attr_reader :members
|
70
|
+
|
71
|
+
# Create a new type instance for type number _sigtype_.
|
72
|
+
def initialize(sigtype)
|
73
|
+
if not TypeName.keys.member?(sigtype)
|
74
|
+
raise SignatureException, "Unknown key in signature: #{sigtype.chr}"
|
75
|
+
end
|
76
|
+
@sigtype = sigtype
|
77
|
+
@members = Array.new
|
78
|
+
end
|
79
|
+
|
80
|
+
# Return the required alignment for the type.
|
81
|
+
def alignment
|
82
|
+
{
|
83
|
+
BYTE => 1,
|
84
|
+
BOOLEAN => 4,
|
85
|
+
INT16 => 2,
|
86
|
+
UINT16 => 2,
|
87
|
+
INT32 => 4,
|
88
|
+
UINT32 => 4,
|
89
|
+
INT64 => 8,
|
90
|
+
UINT64 => 8,
|
91
|
+
STRUCT => 8,
|
92
|
+
DICT_ENTRY => 8,
|
93
|
+
DOUBLE => 8,
|
94
|
+
ARRAY => 4,
|
95
|
+
VARIANT => 1,
|
96
|
+
OBJECT_PATH => 4,
|
97
|
+
STRING => 4,
|
98
|
+
SIGNATURE => 1,
|
99
|
+
}[@sigtype]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return a string representation of the type according to the
|
103
|
+
# D-Bus specification.
|
104
|
+
def to_s
|
105
|
+
case @sigtype
|
106
|
+
when STRUCT
|
107
|
+
"(" + @members.collect { |t| t.to_s }.join + ")"
|
108
|
+
when ARRAY
|
109
|
+
"a" + child.to_s
|
110
|
+
when DICT_ENTRY
|
111
|
+
"{" + @members.collect { |t| t.to_s }.join + "}"
|
112
|
+
else
|
113
|
+
if not TypeName.keys.member?(@sigtype)
|
114
|
+
raise NotImplementedError
|
115
|
+
end
|
116
|
+
@sigtype.chr
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Add a new member type _a_.
|
121
|
+
def <<(a)
|
122
|
+
if not [STRUCT, ARRAY, DICT_ENTRY].member?(@sigtype)
|
123
|
+
raise SignatureException
|
124
|
+
end
|
125
|
+
raise SignatureException if @sigtype == ARRAY and @members.size > 0
|
126
|
+
if @sigtype == DICT_ENTRY
|
127
|
+
if @members.size == 2
|
128
|
+
raise SignatureException, "Dict entries have exactly two members"
|
129
|
+
end
|
130
|
+
if @members.size == 0
|
131
|
+
if [STRUCT, ARRAY, DICT_ENTRY].member?(a.sigtype)
|
132
|
+
raise SignatureException, "Dict entry keys must be basic types"
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
@members << a
|
137
|
+
end
|
138
|
+
|
139
|
+
# Return the first contained member type.
|
140
|
+
def child
|
141
|
+
@members[0]
|
142
|
+
end
|
143
|
+
|
144
|
+
def inspect
|
145
|
+
s = TypeName[@sigtype]
|
146
|
+
if [STRUCT, ARRAY].member?(@sigtype)
|
147
|
+
s += ": " + @members.inspect
|
148
|
+
end
|
149
|
+
s
|
150
|
+
end
|
151
|
+
end # class Type
|
152
|
+
|
153
|
+
# = D-Bus type parser class
|
154
|
+
#
|
155
|
+
# Helper class to parse a type signature in the protocol.
|
156
|
+
class Parser
|
157
|
+
# Create a new parser for the given _signature_.
|
158
|
+
def initialize(signature)
|
159
|
+
@signature = signature
|
160
|
+
@idx = 0
|
161
|
+
end
|
162
|
+
|
163
|
+
# Returns the next character from the signature.
|
164
|
+
def nextchar
|
165
|
+
c = @signature[@idx]
|
166
|
+
@idx += 1
|
167
|
+
c
|
168
|
+
end
|
169
|
+
|
170
|
+
# Parse one character _c_ of the signature.
|
171
|
+
def parse_one(c)
|
172
|
+
res = nil
|
173
|
+
case c
|
174
|
+
when ?a
|
175
|
+
res = Type.new(ARRAY)
|
176
|
+
child = parse_one(nextchar)
|
177
|
+
res << child
|
178
|
+
when ?(
|
179
|
+
res = Type.new(STRUCT)
|
180
|
+
while (c = nextchar) != nil and c != ?)
|
181
|
+
res << parse_one(c)
|
182
|
+
end
|
183
|
+
raise SignatureException, "Parse error in #{@signature}" if c == nil
|
184
|
+
when ?{
|
185
|
+
res = Type.new(DICT_ENTRY)
|
186
|
+
while (c = nextchar) != nil and c != ?}
|
187
|
+
res << parse_one(c)
|
188
|
+
end
|
189
|
+
raise SignatureException, "Parse error in #{@signature}" if c == nil
|
190
|
+
else
|
191
|
+
res = Type.new(c)
|
192
|
+
end
|
193
|
+
res
|
194
|
+
end
|
195
|
+
|
196
|
+
# Parse the entire signature, return a DBus::Type object.
|
197
|
+
def parse
|
198
|
+
@idx = 0
|
199
|
+
ret = Array.new
|
200
|
+
while (c = nextchar)
|
201
|
+
ret << parse_one(c)
|
202
|
+
end
|
203
|
+
ret
|
204
|
+
end
|
205
|
+
end # class Parser
|
206
|
+
end # module Type
|
207
|
+
end # module DBus
|