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.
@@ -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