playful 0.1.0.alpha.1
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/.gemtest +0 -0
- data/.gitignore +19 -0
- data/.rspec +1 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/History.rdoc +3 -0
- data/LICENSE.rdoc +22 -0
- data/README.rdoc +194 -0
- data/Rakefile +20 -0
- data/features/control_point.feature +13 -0
- data/features/device.feature +22 -0
- data/features/device_discovery.feature +9 -0
- data/features/step_definitions/control_point_steps.rb +19 -0
- data/features/step_definitions/device_discovery_steps.rb +40 -0
- data/features/step_definitions/device_steps.rb +28 -0
- data/features/support/common.rb +9 -0
- data/features/support/env.rb +17 -0
- data/features/support/fake_upnp_device_collection.rb +108 -0
- data/features/support/world_extensions.rb +15 -0
- data/lib/core_ext/hash_patch.rb +5 -0
- data/lib/core_ext/socket_patch.rb +16 -0
- data/lib/core_ext/to_upnp_s.rb +65 -0
- data/lib/playful.rb +5 -0
- data/lib/playful/control_point.rb +175 -0
- data/lib/playful/control_point/base.rb +74 -0
- data/lib/playful/control_point/device.rb +511 -0
- data/lib/playful/control_point/error.rb +13 -0
- data/lib/playful/control_point/service.rb +404 -0
- data/lib/playful/device.rb +28 -0
- data/lib/playful/logger.rb +8 -0
- data/lib/playful/ssdp.rb +195 -0
- data/lib/playful/ssdp/broadcast_searcher.rb +114 -0
- data/lib/playful/ssdp/error.rb +6 -0
- data/lib/playful/ssdp/listener.rb +38 -0
- data/lib/playful/ssdp/multicast_connection.rb +112 -0
- data/lib/playful/ssdp/network_constants.rb +17 -0
- data/lib/playful/ssdp/notifier.rb +41 -0
- data/lib/playful/ssdp/searcher.rb +87 -0
- data/lib/playful/version.rb +3 -0
- data/lib/rack/upnp_control_point.rb +70 -0
- data/playful.gemspec +38 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/support/search_responses.rb +134 -0
- data/spec/unit/core_ext/to_upnp_s_spec.rb +105 -0
- data/spec/unit/playful/control_point/device_spec.rb +7 -0
- data/spec/unit/playful/control_point_spec.rb +45 -0
- data/spec/unit/playful/ssdp/listener_spec.rb +29 -0
- data/spec/unit/playful/ssdp/multicast_connection_spec.rb +157 -0
- data/spec/unit/playful/ssdp/notifier_spec.rb +76 -0
- data/spec/unit/playful/ssdp/searcher_spec.rb +110 -0
- data/spec/unit/playful/ssdp_spec.rb +214 -0
- data/tasks/control_point.html +30 -0
- data/tasks/control_point.thor +43 -0
- data/tasks/search.thor +128 -0
- data/tasks/test_js/FABridge.js +1425 -0
- data/tasks/test_js/WebSocketMain.swf +807 -0
- data/tasks/test_js/swfobject.js +825 -0
- data/tasks/test_js/web_socket.js +1133 -0
- data/test/test_ssdp.rb +298 -0
- data/test/test_ssdp_notification.rb +74 -0
- data/test/test_ssdp_response.rb +31 -0
- data/test/test_ssdp_search.rb +23 -0
- metadata +339 -0
@@ -0,0 +1,511 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require_relative 'service'
|
3
|
+
require_relative 'error'
|
4
|
+
require 'uri'
|
5
|
+
require 'eventmachine'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
|
9
|
+
module Playful
|
10
|
+
class ControlPoint
|
11
|
+
class Device < Base
|
12
|
+
include EM::Deferrable
|
13
|
+
include LogSwitch::Mixin
|
14
|
+
|
15
|
+
attr_reader :ssdp_notification
|
16
|
+
|
17
|
+
#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
18
|
+
# Passed in as part of +device_info+; given by the SSDP search response.
|
19
|
+
#
|
20
|
+
attr_reader :cache_control
|
21
|
+
attr_reader :date
|
22
|
+
attr_reader :ext
|
23
|
+
attr_reader :location
|
24
|
+
attr_reader :server
|
25
|
+
attr_reader :st
|
26
|
+
attr_reader :usn
|
27
|
+
#
|
28
|
+
# DONE +device_info+
|
29
|
+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
30
|
+
|
31
|
+
# @return [Hash] The whole parsed description... just in case.
|
32
|
+
attr_reader :description
|
33
|
+
|
34
|
+
attr_reader :expiration
|
35
|
+
|
36
|
+
#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
|
37
|
+
# Determined by device description file.
|
38
|
+
#
|
39
|
+
|
40
|
+
#------- <root> elements -------
|
41
|
+
|
42
|
+
# @return [String] The xmlns attribute of the device from the description file.
|
43
|
+
attr_reader :xmlns
|
44
|
+
|
45
|
+
# @return [Hash] :major and :minor revisions of the UPnP spec this device adheres to.
|
46
|
+
attr_reader :spec_version
|
47
|
+
|
48
|
+
# @return [String] URLBase from the device's description file.
|
49
|
+
attr_reader :url_base
|
50
|
+
|
51
|
+
#------- <root><device> elements -------
|
52
|
+
|
53
|
+
# @return [String] The type of UPnP device (URN) from the description file.
|
54
|
+
attr_reader :device_type
|
55
|
+
|
56
|
+
# @return [String] Short device description for the end user.
|
57
|
+
attr_reader :friendly_name
|
58
|
+
|
59
|
+
# @return [String] Manufacturer's name.
|
60
|
+
attr_reader :manufacturer
|
61
|
+
|
62
|
+
# @return [String] Manufacturer's web site.
|
63
|
+
attr_reader :manufacturer_url
|
64
|
+
|
65
|
+
# @return [String] Long model description for the end user, from the description file.
|
66
|
+
attr_reader :model_description
|
67
|
+
|
68
|
+
# @return [String] Model name of this device from the description file.
|
69
|
+
attr_reader :model_name
|
70
|
+
|
71
|
+
# @return [String] Model number of this device from the description file.
|
72
|
+
attr_reader :model_number
|
73
|
+
|
74
|
+
# @return [String] Web site for model of this device.
|
75
|
+
attr_reader :model_url
|
76
|
+
|
77
|
+
# @return [String] The serial number from the description file.
|
78
|
+
attr_reader :serial_number
|
79
|
+
|
80
|
+
# @return [String] The UDN for the device, from the description file.
|
81
|
+
attr_reader :udn
|
82
|
+
|
83
|
+
# @return [String] The UPC of the device from the description file.
|
84
|
+
attr_reader :upc
|
85
|
+
|
86
|
+
# @return [Array<Hash>] An Array where each element is a Hash that describes an icon.
|
87
|
+
attr_reader :icon_list
|
88
|
+
|
89
|
+
# Services provided directly by this device.
|
90
|
+
attr_reader :service_list
|
91
|
+
|
92
|
+
# Devices embedded directly into this device.
|
93
|
+
attr_reader :device_list
|
94
|
+
|
95
|
+
# @return [String] URL for device control via a browser.
|
96
|
+
attr_reader :presentation_url
|
97
|
+
|
98
|
+
#
|
99
|
+
# DONE description file
|
100
|
+
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
101
|
+
|
102
|
+
# @param [Hash] device_info
|
103
|
+
# @option device_info [Hash] ssdp_notification
|
104
|
+
# @option device_info [Hash] device_description
|
105
|
+
# @option device_info [Hash] parent_base_url
|
106
|
+
def initialize(device_info)
|
107
|
+
super()
|
108
|
+
|
109
|
+
@device_info = device_info
|
110
|
+
log "Got device info: #{@device_info}"
|
111
|
+
@device_list = []
|
112
|
+
@service_list = []
|
113
|
+
@icon_list = []
|
114
|
+
@xmlns = ''
|
115
|
+
@done_creating_devices = false
|
116
|
+
@done_creating_services = false
|
117
|
+
end
|
118
|
+
|
119
|
+
def fetch
|
120
|
+
description_getter = EventMachine::DefaultDeferrable.new
|
121
|
+
|
122
|
+
description_getter.errback do
|
123
|
+
msg = 'Failed getting description.'
|
124
|
+
log msg, :error
|
125
|
+
@done_creating_devices = true
|
126
|
+
@done_creating_services = true
|
127
|
+
set_deferred_status(:failed, msg)
|
128
|
+
|
129
|
+
if ControlPoint.raise_on_remote_error
|
130
|
+
raise ControlPoint::Error, msg
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
if @device_info.has_key? :ssdp_notification
|
135
|
+
extract_from_ssdp_notification(description_getter)
|
136
|
+
elsif @device_info.has_key? :device_description
|
137
|
+
log 'Creating device from device description file info.'
|
138
|
+
description_getter.set_deferred_success @device_info[:device_description]
|
139
|
+
else
|
140
|
+
log "Not sure what to extract from this device's info."
|
141
|
+
description_getter.set_deferred_failure
|
142
|
+
end
|
143
|
+
|
144
|
+
description_getter.callback do |description|
|
145
|
+
log "Description received from #{description_getter.object_id}"
|
146
|
+
@description = description
|
147
|
+
|
148
|
+
if @description.nil?
|
149
|
+
log 'Description is empty.', :error
|
150
|
+
set_deferred_status(:failed, 'Got back an empty description...')
|
151
|
+
return
|
152
|
+
end
|
153
|
+
|
154
|
+
extract_spec_version
|
155
|
+
|
156
|
+
@url_base = extract_url_base
|
157
|
+
log "Set url_base to #{@url_base}"
|
158
|
+
|
159
|
+
if @device_info[:ssdp_notification]
|
160
|
+
@xmlns = @description[:root][:@xmlns]
|
161
|
+
log "Extracting description for root device #{description_getter.object_id}"
|
162
|
+
extract_description(@description[:root][:device])
|
163
|
+
elsif @device_info.has_key? :device_description
|
164
|
+
log "Extracting description for non-root device #{description_getter.object_id}"
|
165
|
+
extract_description(@description)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
tickloop = EM.tick_loop do
|
170
|
+
if @done_creating_devices && @done_creating_services
|
171
|
+
log 'All done creating stuff'
|
172
|
+
:stop
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
tickloop.on_stop { set_deferred_status :succeeded, self }
|
177
|
+
end
|
178
|
+
|
179
|
+
def extract_from_ssdp_notification(callback)
|
180
|
+
log 'Creating device from SSDP Notification info.'
|
181
|
+
@ssdp_notification = @device_info[:ssdp_notification]
|
182
|
+
|
183
|
+
@cache_control = @ssdp_notification[:cache_control]
|
184
|
+
@location = ssdp_notification[:location]
|
185
|
+
@server = ssdp_notification[:server]
|
186
|
+
@st = ssdp_notification[:st] || ssdp_notification[:nt]
|
187
|
+
@ext = ssdp_notification.has_key?(:ext) ? true : false
|
188
|
+
@usn = ssdp_notification[:usn]
|
189
|
+
@date = ssdp_notification[:date] || ''
|
190
|
+
@expiration = if @date.empty?
|
191
|
+
Time.now + @cache_control.match(/\d+/)[0].to_i
|
192
|
+
else
|
193
|
+
Time.at(Time.parse(@date).to_i + @cache_control.match(/\d+/)[0].to_i)
|
194
|
+
end
|
195
|
+
|
196
|
+
if @location
|
197
|
+
get_description(@location, callback)
|
198
|
+
else
|
199
|
+
message = 'M-SEARCH response is either missing the Location header or has an empty value.'
|
200
|
+
message << "Response: #{@ssdp_notification}"
|
201
|
+
|
202
|
+
if ControlPoint.raise_on_remote_error
|
203
|
+
raise ControlPoint::Error, message
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
def extract_url_base
|
209
|
+
if @description[:root] && @description[:root][:URLBase]
|
210
|
+
@description[:root][:URLBase]
|
211
|
+
elsif @device_info[:parent_base_url]
|
212
|
+
@device_info[:parent_base_url]
|
213
|
+
else
|
214
|
+
tmp_uri = URI(@location)
|
215
|
+
"#{tmp_uri.scheme}://#{tmp_uri.host}:#{tmp_uri.port}/"
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# True if the device hasn't received an alive notification since it last
|
220
|
+
# told its max age.
|
221
|
+
def expired?
|
222
|
+
Time.now > @expiration if @expiration
|
223
|
+
end
|
224
|
+
|
225
|
+
def has_devices?
|
226
|
+
!@device_list.empty?
|
227
|
+
end
|
228
|
+
|
229
|
+
def has_services?
|
230
|
+
!@service_list.empty?
|
231
|
+
end
|
232
|
+
|
233
|
+
def extract_description(ddf)
|
234
|
+
log 'Extracting basic attributes from description...'
|
235
|
+
|
236
|
+
@device_type = ddf[:deviceType] || ''
|
237
|
+
@friendly_name = ddf[:friendlyName] || ''
|
238
|
+
@manufacturer = ddf[:manufacturer] || ''
|
239
|
+
@manufacturer_url = ddf[:manufacturerURL] || ''
|
240
|
+
@model_description = ddf[:modelDescription] || ''
|
241
|
+
@model_name = ddf[:modelName] || ''
|
242
|
+
@model_number = ddf[:modelNumber] || ''
|
243
|
+
@model_url = ddf[:modelURL] || ''
|
244
|
+
@serial_number = ddf[:serialNumber] || ''
|
245
|
+
@udn = ddf[:UDN] || ''
|
246
|
+
@upc = ddf[:UPC] || ''
|
247
|
+
@icon_list = extract_icons(ddf[:iconList])
|
248
|
+
@presentation_url = ddf[:presentationURL] || ''
|
249
|
+
|
250
|
+
log 'Basic attributes extracted.'
|
251
|
+
|
252
|
+
start_device_extraction
|
253
|
+
start_service_extraction
|
254
|
+
end
|
255
|
+
|
256
|
+
def extract_spec_version
|
257
|
+
if @description[:root]
|
258
|
+
"#{@description[:root][:specVersion][:major]}.#{@description[:root][:specVersion][:minor]}"
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
def start_service_extraction
|
263
|
+
services_extractor = EventMachine::DefaultDeferrable.new
|
264
|
+
|
265
|
+
if @description[:serviceList]
|
266
|
+
log 'Extracting services from non-root device.'
|
267
|
+
extract_services(@description[:serviceList], services_extractor)
|
268
|
+
elsif @description[:root][:device][:serviceList]
|
269
|
+
log 'Extracting services from root device.'
|
270
|
+
extract_services(@description[:root][:device][:serviceList], services_extractor)
|
271
|
+
end
|
272
|
+
|
273
|
+
services_extractor.errback do
|
274
|
+
msg = 'Failed extracting services.'
|
275
|
+
log msg, :error
|
276
|
+
@done_creating_services = true
|
277
|
+
|
278
|
+
if ControlPoint.raise_on_remote_error
|
279
|
+
raise ControlPoint::Error, msg
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
services_extractor.callback do |services|
|
284
|
+
log 'Done extracting services.'
|
285
|
+
@service_list = services
|
286
|
+
|
287
|
+
log "New service count: #{@service_list.size}."
|
288
|
+
@done_creating_services = true
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def start_device_extraction
|
293
|
+
device_extractor = EventMachine::DefaultDeferrable.new
|
294
|
+
extract_devices(device_extractor)
|
295
|
+
|
296
|
+
device_extractor.errback do
|
297
|
+
msg = 'Failed extracting device.'
|
298
|
+
log msg, :error
|
299
|
+
@done_creating_devices = true
|
300
|
+
|
301
|
+
if ControlPoint.raise_on_remote_error
|
302
|
+
raise ControlPoint::Error, msg
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
device_extractor.callback do |device|
|
307
|
+
if device
|
308
|
+
log "Device extracted from #{device_extractor.object_id}."
|
309
|
+
@device_list << device
|
310
|
+
else
|
311
|
+
log "Device extraction done from #{device_extractor.object_id} but none were extracted."
|
312
|
+
end
|
313
|
+
|
314
|
+
log "Child device size is now: #{@device_list.size}"
|
315
|
+
@done_creating_devices = true
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
# @return [Array<Hash>]
|
320
|
+
def extract_icons(ddf_icon_list)
|
321
|
+
return [] unless ddf_icon_list
|
322
|
+
log "Icon list: #{ddf_icon_list}"
|
323
|
+
|
324
|
+
if ddf_icon_list[:icon].is_a? Array
|
325
|
+
ddf_icon_list[:icon].map do |values|
|
326
|
+
values[:url] = build_url(@url_base, values[:url])
|
327
|
+
values
|
328
|
+
end
|
329
|
+
else
|
330
|
+
[{
|
331
|
+
mimetype: ddf_icon_list[:icon][:mimetype],
|
332
|
+
width: ddf_icon_list[:icon][:width],
|
333
|
+
height: ddf_icon_list[:icon][:height],
|
334
|
+
depth: ddf_icon_list[:icon][:depth],
|
335
|
+
url: build_url(@url_base, ddf_icon_list[:icon][:url])
|
336
|
+
}]
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def extract_devices(group_device_extractor)
|
341
|
+
log "Extracting child devices for #{self.object_id} using #{group_device_extractor.object_id}"
|
342
|
+
|
343
|
+
device_list_hash = if @description.has_key? :root
|
344
|
+
log 'Description has a :root key...'
|
345
|
+
|
346
|
+
if @description[:root][:device][:deviceList]
|
347
|
+
@description[:root][:device][:deviceList][:device]
|
348
|
+
else
|
349
|
+
log 'No child devices to extract.'
|
350
|
+
group_device_extractor.set_deferred_status(:succeeded)
|
351
|
+
end
|
352
|
+
elsif @description[:deviceList]
|
353
|
+
log 'Description does not have a :root key...'
|
354
|
+
@description[:deviceList][:device]
|
355
|
+
else
|
356
|
+
log 'No child devices to extract.'
|
357
|
+
group_device_extractor.set_deferred_status(:succeeded)
|
358
|
+
end
|
359
|
+
|
360
|
+
if device_list_hash.nil? || device_list_hash.empty?
|
361
|
+
group_device_extractor.set_deferred_status(:succeeded)
|
362
|
+
return
|
363
|
+
end
|
364
|
+
|
365
|
+
log "device list: #{device_list_hash}"
|
366
|
+
|
367
|
+
if device_list_hash.is_a? Array
|
368
|
+
EM::Iterator.new(device_list_hash, device_list_hash.count).map(
|
369
|
+
proc do |device, iter|
|
370
|
+
single_device_extractor = EventMachine::DefaultDeferrable.new
|
371
|
+
|
372
|
+
single_device_extractor.errback do
|
373
|
+
msg = 'Failed extracting device.'
|
374
|
+
log msg, :error
|
375
|
+
|
376
|
+
if ControlPoint.raise_on_remote_error
|
377
|
+
raise ControlPoint::Error, msg
|
378
|
+
end
|
379
|
+
end
|
380
|
+
|
381
|
+
single_device_extractor.callback do |d|
|
382
|
+
iter.return(d)
|
383
|
+
end
|
384
|
+
|
385
|
+
extract_device(device, single_device_extractor)
|
386
|
+
end,
|
387
|
+
proc do |found_devices|
|
388
|
+
group_device_extractor.set_deferred_status(:succeeded, found_devices)
|
389
|
+
end
|
390
|
+
)
|
391
|
+
else
|
392
|
+
single_device_extractor = EventMachine::DefaultDeferrable.new
|
393
|
+
|
394
|
+
single_device_extractor.errback do
|
395
|
+
msg = 'Failed extracting device.'
|
396
|
+
log msg, :error
|
397
|
+
group_device_extractor.set_deferred_status(:failed, msg)
|
398
|
+
|
399
|
+
if ControlPoint.raise_on_remote_error
|
400
|
+
raise ControlPoint::Error, msg
|
401
|
+
end
|
402
|
+
end
|
403
|
+
|
404
|
+
single_device_extractor.callback do |device|
|
405
|
+
group_device_extractor.set_deferred_status(:succeeded, [device])
|
406
|
+
end
|
407
|
+
|
408
|
+
log 'Extracting single device...'
|
409
|
+
extract_device(device_list_hash, group_device_extractor)
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
def extract_device(device, device_extractor)
|
414
|
+
deferred_device = Device.new(device_description: device, parent_base_url: @url_base)
|
415
|
+
|
416
|
+
deferred_device.errback do
|
417
|
+
msg = "Couldn't build device!"
|
418
|
+
log msg, :error
|
419
|
+
device_extractor.set_deferred_status(:failed, msg)
|
420
|
+
|
421
|
+
if ControlPoint.raise_on_remote_error
|
422
|
+
raise ControlPoint::Error, msg
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
deferred_device.callback do |built_device|
|
427
|
+
log "Device created: #{built_device.device_type}"
|
428
|
+
device_extractor.set_deferred_status(:succeeded, built_device)
|
429
|
+
end
|
430
|
+
|
431
|
+
deferred_device.fetch
|
432
|
+
end
|
433
|
+
|
434
|
+
def extract_services(service_list, group_service_extractor)
|
435
|
+
log 'Extracting services...'
|
436
|
+
|
437
|
+
log "service list: #{service_list}"
|
438
|
+
return if service_list.nil?
|
439
|
+
|
440
|
+
service_list.each_value do |service|
|
441
|
+
if service.is_a? Array
|
442
|
+
EM::Iterator.new(service, service.count).map(
|
443
|
+
proc do |s, iter|
|
444
|
+
single_service_extractor = EventMachine::DefaultDeferrable.new
|
445
|
+
|
446
|
+
single_service_extractor.errback do
|
447
|
+
msg = 'Failed to create service.'
|
448
|
+
log msg, :error
|
449
|
+
|
450
|
+
if ControlPoint.raise_on_remote_error
|
451
|
+
raise ControlPoint::Error, msg
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
single_service_extractor.callback do |s|
|
456
|
+
iter.return(s)
|
457
|
+
end
|
458
|
+
|
459
|
+
extract_service(s, single_service_extractor)
|
460
|
+
end,
|
461
|
+
proc do |found_services|
|
462
|
+
group_service_extractor.set_deferred_status(:succeeded, found_services)
|
463
|
+
end
|
464
|
+
)
|
465
|
+
else
|
466
|
+
single_service_extractor = EventMachine::DefaultDeferrable.new
|
467
|
+
|
468
|
+
single_service_extractor.errback do
|
469
|
+
msg = 'Failed to create service.'
|
470
|
+
log msg, :error
|
471
|
+
group_service_extractor.set_deferred_status :failed, msg
|
472
|
+
|
473
|
+
if ControlPoint.raise_on_remote_error
|
474
|
+
raise ControlPoint::Error, msg
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
single_service_extractor.callback do |s|
|
479
|
+
group_service_extractor.set_deferred_status :succeeded, [s]
|
480
|
+
end
|
481
|
+
|
482
|
+
log 'Extracting single service...'
|
483
|
+
extract_service(service, single_service_extractor)
|
484
|
+
end
|
485
|
+
end
|
486
|
+
end
|
487
|
+
|
488
|
+
def extract_service(service, single_service_extractor)
|
489
|
+
service_getter = Service.new(@url_base, service)
|
490
|
+
log "Extracting service with #{service_getter.object_id}"
|
491
|
+
|
492
|
+
service_getter.errback do |message|
|
493
|
+
msg = "Couldn't build service with info: #{service}"
|
494
|
+
log msg, :error
|
495
|
+
single_service_extractor.set_deferred_status(:failed, msg)
|
496
|
+
|
497
|
+
if ControlPoint.raise_on_remote_error
|
498
|
+
raise ControlPoint::Error, message
|
499
|
+
end
|
500
|
+
end
|
501
|
+
|
502
|
+
service_getter.callback do |built_service|
|
503
|
+
log "Service created: #{built_service.service_type}"
|
504
|
+
single_service_extractor.set_deferred_status(:succeeded, built_service)
|
505
|
+
end
|
506
|
+
|
507
|
+
service_getter.fetch
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|
511
|
+
end
|