UPnP 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/.autotest +9 -0
- data/History.txt +8 -0
- data/Manifest.txt +8 -0
- data/README.txt +18 -7
- data/Rakefile +3 -0
- data/lib/UPnP.rb +1 -1
- data/lib/UPnP/SSDP.rb +288 -25
- data/lib/UPnP/UUID.rb +187 -0
- data/lib/UPnP/control/service.rb +4 -1
- data/lib/UPnP/device.rb +692 -0
- data/lib/UPnP/root_server.rb +143 -0
- data/lib/UPnP/service.rb +376 -0
- data/test/test_UPnP_SSDP.rb +80 -17
- data/test/test_UPnP_SSDP_response.rb +2 -0
- data/test/test_UPnP_SSDP_search.rb +25 -0
- data/test/test_UPnP_control_device.rb +2 -0
- data/test/test_UPnP_control_service.rb +2 -0
- data/test/test_UPnP_device.rb +295 -0
- data/test/test_UPnP_root_server.rb +99 -0
- data/test/test_UPnP_service.rb +171 -0
- data/test/utilities.rb +61 -14
- metadata +36 -4
- metadata.gz.sig +0 -0
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'test/utilities'
|
4
|
+
require 'UPnP/root_server'
|
5
|
+
|
6
|
+
class TestUPnPRootServer < UPnP::TestCase
|
7
|
+
|
8
|
+
def setup
|
9
|
+
super
|
10
|
+
|
11
|
+
@device = UPnP::Device.new 'TestDevice', 'test device'
|
12
|
+
@device.manufacturer = 'UPnP Manufacturer'
|
13
|
+
@device.model_name = 'UPnP Model'
|
14
|
+
|
15
|
+
@service = @device.add_service 'TestService'
|
16
|
+
|
17
|
+
@root_server = UPnP::RootServer.new @device
|
18
|
+
|
19
|
+
@req = WEBrick::HTTPRequest.new :Logger => nil
|
20
|
+
@res = WEBrick::HTTPResponse.new :HTTPVersion => '1.0'
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_initialize
|
24
|
+
assert_equal @device, @root_server.root_device
|
25
|
+
assert @root_server.scpds.empty?
|
26
|
+
assert_equal WEBrick::BasicLog::FATAL, @root_server.logger.level,
|
27
|
+
'default log level'
|
28
|
+
|
29
|
+
assert util_mount_tab['/description']
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_description
|
33
|
+
data = StringIO.new "GET /description HTTP/1.0\r\n\r\n"
|
34
|
+
@req.parse data
|
35
|
+
|
36
|
+
@root_server.description @req, @res
|
37
|
+
|
38
|
+
assert_equal 200, @res.status, @res.body
|
39
|
+
assert_equal 'text/xml', @res['content-type']
|
40
|
+
assert_equal @device.description, @res.body
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_description_other
|
44
|
+
data = StringIO.new "GET /description/other HTTP/1.0\r\n\r\n"
|
45
|
+
@req.parse data
|
46
|
+
|
47
|
+
assert_raise WEBrick::HTTPStatus::NotFound do
|
48
|
+
@root_server.description @req, @res
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_mount_server
|
53
|
+
assert_nil util_mount_tab['/TestDevice/TestService/control']
|
54
|
+
|
55
|
+
@root_server.mount_server @service.control_url, @service.server
|
56
|
+
|
57
|
+
assert_equal @root_server.logger, @service.server.config[:Logger]
|
58
|
+
assert util_mount_tab['/TestDevice/TestService/control']
|
59
|
+
end
|
60
|
+
|
61
|
+
def test_mount_service
|
62
|
+
@root_server.mount_service @service
|
63
|
+
|
64
|
+
assert_equal [@service.scpd_url], @root_server.scpds.keys
|
65
|
+
|
66
|
+
assert util_mount_tab['/TestDevice/TestService']
|
67
|
+
assert util_mount_tab['/TestDevice/TestService/control']
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_scpd
|
71
|
+
@root_server.mount_service @service
|
72
|
+
|
73
|
+
data = StringIO.new "GET #{@service.scpd_url} HTTP/1.0\r\n\r\n"
|
74
|
+
@req.parse data
|
75
|
+
|
76
|
+
@root_server.scpd @req, @res
|
77
|
+
|
78
|
+
assert_equal 200, @res.status, @res.body
|
79
|
+
assert_equal 'text/xml', @res['content-type']
|
80
|
+
assert_equal @service.scpd, @res.body
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_scpd_other
|
84
|
+
@root_server.mount_service @service
|
85
|
+
|
86
|
+
data = StringIO.new "GET /TestDevice/TestOtherService HTTP/1.0\r\n\r\n"
|
87
|
+
@req.parse data
|
88
|
+
|
89
|
+
assert_raise WEBrick::HTTPStatus::NotFound do
|
90
|
+
@root_server.description @req, @res
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def util_mount_tab
|
95
|
+
@root_server.instance_variable_get :@mount_tab
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
@@ -0,0 +1,171 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'test/utilities'
|
3
|
+
require 'UPnP/service'
|
4
|
+
|
5
|
+
class TestUPnPService < UPnP::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
super
|
9
|
+
|
10
|
+
@device = UPnP::Device.new 'TestDevice', 'test device'
|
11
|
+
@service = @device.add_service 'TestService'
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_initialize
|
15
|
+
assert_equal @device, @service.device
|
16
|
+
assert_equal 'TestService', @service.type
|
17
|
+
|
18
|
+
assert_equal 'TestService', @service.appname
|
19
|
+
assert_equal "#{UPnP::SERVICE_SCHEMA_PREFIX}:TestService:1",
|
20
|
+
@service.default_namespace
|
21
|
+
|
22
|
+
router = @service.instance_variable_get :@router
|
23
|
+
operations = router.instance_variable_get :@operation_by_qname
|
24
|
+
|
25
|
+
qname = XSD::QName.new @service.type_urn, 'TestAction'
|
26
|
+
|
27
|
+
assert operations.key?(qname)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_actions
|
31
|
+
expected = {
|
32
|
+
'TestAction' => [
|
33
|
+
%w[in TestInput TestInVar],
|
34
|
+
%w[out TestOutput TestOutVar],
|
35
|
+
],
|
36
|
+
}
|
37
|
+
|
38
|
+
assert_equal expected, @service.actions
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_add_actions
|
42
|
+
router = @service.instance_variable_get :@router
|
43
|
+
operations = router.instance_variable_get :@operation_by_qname
|
44
|
+
|
45
|
+
qname = XSD::QName.new @service.type_urn, 'TestAction'
|
46
|
+
|
47
|
+
assert_equal [qname], operations.keys
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_control_url
|
51
|
+
assert_equal '/TestDevice/TestService/control', @service.control_url
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_create_config
|
55
|
+
assert_equal true, @service.create_config[:DoNotListen]
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_description
|
59
|
+
desc = ''
|
60
|
+
xml = Builder::XmlMarkup.new :indent => 2, :target => desc
|
61
|
+
|
62
|
+
@service.description xml
|
63
|
+
|
64
|
+
expected = <<-XML
|
65
|
+
<service>
|
66
|
+
<serviceType>urn:schemas-upnp-org:service:TestService:1</serviceType>
|
67
|
+
<serviceId>urn:upnp-org:serviceId:TestService</serviceId>
|
68
|
+
<SCPDURL>/TestDevice/TestService</SCPDURL>
|
69
|
+
<controlURL>/TestDevice/TestService/control</controlURL>
|
70
|
+
<eventSubURL>/TestDevice/TestService/event_sub</eventSubURL>
|
71
|
+
</service>
|
72
|
+
XML
|
73
|
+
|
74
|
+
assert_equal expected, desc
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_device_path
|
78
|
+
assert_equal '/TestDevice', @service.device_path
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_event_sub_url
|
82
|
+
assert_equal '/TestDevice/TestService/event_sub', @service.event_sub_url
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_marshal_dump
|
86
|
+
assert_equal [@device, 'TestService'], @service.marshal_dump
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_marshal_load
|
90
|
+
data = [@device, 'TestService']
|
91
|
+
|
92
|
+
service = UPnP::Service.allocate
|
93
|
+
|
94
|
+
service.marshal_load data
|
95
|
+
|
96
|
+
assert_equal 'TestService', @service.type
|
97
|
+
assert_equal 'TestService', @service.appname
|
98
|
+
|
99
|
+
assert data.empty?, 'unconsumed data'
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_root_device
|
103
|
+
assert_equal @device, @service.root_device
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_scpd
|
107
|
+
scpd = @service.scpd
|
108
|
+
|
109
|
+
expected = <<-XML
|
110
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
111
|
+
<scpd xmlns="urn:schemas-upnp-org:service-1-0">
|
112
|
+
<specVersion>
|
113
|
+
<major>1</major>
|
114
|
+
<minor>0</minor>
|
115
|
+
</specVersion>
|
116
|
+
<actionList>
|
117
|
+
<action>
|
118
|
+
<name>TestAction</name>
|
119
|
+
<argumentList>
|
120
|
+
<argument>
|
121
|
+
<direction>in</direction>
|
122
|
+
<name>TestInput</name>
|
123
|
+
<relatedStateVariable>TestInVar</relatedStateVariable>
|
124
|
+
</argument>
|
125
|
+
<argument>
|
126
|
+
<direction>out</direction>
|
127
|
+
<name>TestOutput</name>
|
128
|
+
<relatedStateVariable>TestOutVar</relatedStateVariable>
|
129
|
+
</argument>
|
130
|
+
</argumentList>
|
131
|
+
</action>
|
132
|
+
</actionList>
|
133
|
+
<serviceStateTable>
|
134
|
+
<stateVariable sendEvents="no">
|
135
|
+
<name>TestOutVar</name>
|
136
|
+
<dataType>string</dataType>
|
137
|
+
</stateVariable>
|
138
|
+
<stateVariable sendEvents="no">
|
139
|
+
<name>TestInVar</name>
|
140
|
+
<dataType>string</dataType>
|
141
|
+
</stateVariable>
|
142
|
+
</serviceStateTable>
|
143
|
+
</scpd>
|
144
|
+
XML
|
145
|
+
|
146
|
+
assert_equal expected, scpd
|
147
|
+
end
|
148
|
+
|
149
|
+
def test_scpd_url
|
150
|
+
assert_equal '/TestDevice/TestService', @service.scpd_url
|
151
|
+
end
|
152
|
+
|
153
|
+
def test_service_path
|
154
|
+
assert_equal '/TestDevice/TestService', @service.service_path
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_type_urn
|
158
|
+
assert_equal 'urn:schemas-upnp-org:service:TestService:1', @service.type_urn
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_variables
|
162
|
+
expected = {
|
163
|
+
'TestOutVar' => ['string', nil, nil, false],
|
164
|
+
'TestInVar' => ['string', nil, nil, false],
|
165
|
+
}
|
166
|
+
|
167
|
+
assert_equal expected, @service.variables
|
168
|
+
end
|
169
|
+
|
170
|
+
end
|
171
|
+
|
data/test/utilities.rb
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'tmpdir'
|
1
3
|
require 'test/unit'
|
4
|
+
require 'UPnP'
|
5
|
+
require 'UPnP/device'
|
2
6
|
|
3
7
|
module UPnP
|
4
8
|
|
@@ -67,23 +71,30 @@ module UPnP
|
|
67
71
|
|
68
72
|
class TestCase < Test::Unit::TestCase
|
69
73
|
|
74
|
+
undef_method :default_test
|
75
|
+
|
76
|
+
def setup
|
77
|
+
@tempdir = File.join Dir.tmpdir, "test_UPnP_#{$$}"
|
78
|
+
FileUtils.mkdir_p @tempdir
|
79
|
+
|
80
|
+
@home = File.join @tempdir, 'home'
|
81
|
+
FileUtils.mkdir_p @home
|
82
|
+
|
83
|
+
@orig_ENV_HOME = ENV['HOME']
|
84
|
+
ENV['HOME'] = @home
|
85
|
+
end
|
86
|
+
|
70
87
|
def teardown
|
88
|
+
if @orig_ENV_HOME then
|
89
|
+
ENV['HOME'] = @orig_ENV_HOME
|
90
|
+
else
|
91
|
+
ENV.delete 'HOME'
|
92
|
+
end
|
93
|
+
|
94
|
+
FileUtils.rm_rf @tempdir
|
71
95
|
UPnP::OpenStub::FILES.clear
|
72
96
|
end
|
73
97
|
|
74
|
-
def util_search_response
|
75
|
-
<<-SEARCH_RESPONSE
|
76
|
-
HTTP/1.1 200 OK\r
|
77
|
-
CACHE-CONTROL: max-age = 10\r
|
78
|
-
EXT:\r
|
79
|
-
LOCATION: http://example.com/root_device.xml\r
|
80
|
-
SERVER: OS/5 UPnP/1.0 product/7\r
|
81
|
-
ST: upnp:rootdevice\r
|
82
|
-
USN: uuid:BOGUS::upnp:rootdevice\r
|
83
|
-
\r
|
84
|
-
SEARCH_RESPONSE
|
85
|
-
end
|
86
|
-
|
87
98
|
def util_notify
|
88
99
|
<<-NOTIFY
|
89
100
|
NOTIFY * HTTP/1.1\r
|
@@ -109,7 +120,28 @@ USN: uuid:BOGUS::upnp:rootdevice\r
|
|
109
120
|
NOTIFY_BYEBYE
|
110
121
|
end
|
111
122
|
|
112
|
-
|
123
|
+
def util_search
|
124
|
+
<<-SEARCH
|
125
|
+
M-SEARCH * HTTP/1.1
|
126
|
+
HOST: 239.255.255.250:1900
|
127
|
+
MAN: "ssdp:discover"
|
128
|
+
MX: 2
|
129
|
+
ST: upnp:rootdevice
|
130
|
+
SEARCH
|
131
|
+
end
|
132
|
+
|
133
|
+
def util_search_response
|
134
|
+
<<-SEARCH_RESPONSE
|
135
|
+
HTTP/1.1 200 OK\r
|
136
|
+
CACHE-CONTROL: max-age = 10\r
|
137
|
+
EXT:\r
|
138
|
+
LOCATION: http://example.com/root_device.xml\r
|
139
|
+
SERVER: OS/5 UPnP/1.0 product/7\r
|
140
|
+
ST: upnp:rootdevice\r
|
141
|
+
USN: uuid:BOGUS::upnp:rootdevice\r
|
142
|
+
\r
|
143
|
+
SEARCH_RESPONSE
|
144
|
+
end
|
113
145
|
|
114
146
|
IGD_XML = <<-XML
|
115
147
|
<?xml version="1.0"?>
|
@@ -1024,5 +1056,20 @@ USN: uuid:BOGUS::upnp:rootdevice\r
|
|
1024
1056
|
|
1025
1057
|
end
|
1026
1058
|
|
1059
|
+
class Service::TestService < Service
|
1060
|
+
add_action 'TestAction',
|
1061
|
+
[IN, 'TestInput', 'TestInVar'],
|
1062
|
+
[OUT, 'TestOutput', 'TestOutVar']
|
1063
|
+
|
1064
|
+
add_variable 'TestInVar', 'string'
|
1065
|
+
add_variable 'TestOutVar', 'string'
|
1066
|
+
end
|
1067
|
+
|
1068
|
+
class Device::TestDevice < Device
|
1069
|
+
|
1070
|
+
add_service_id UPnP::Service::TestService, 'TestService'
|
1071
|
+
|
1072
|
+
end
|
1073
|
+
|
1027
1074
|
end
|
1028
1075
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: UPnP
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Hodel
|
@@ -30,18 +30,38 @@ cert_chain:
|
|
30
30
|
x52qPcexcYZR7w==
|
31
31
|
-----END CERTIFICATE-----
|
32
32
|
|
33
|
-
date: 2008-
|
33
|
+
date: 2008-07-23 00:00:00 -07:00
|
34
34
|
default_executable:
|
35
35
|
dependencies:
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
37
|
+
name: soap4r
|
38
|
+
type: :runtime
|
39
|
+
version_requirement:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: builder
|
38
48
|
type: :runtime
|
39
49
|
version_requirement:
|
40
50
|
version_requirements: !ruby/object:Gem::Requirement
|
41
51
|
requirements:
|
42
52
|
- - ">="
|
43
53
|
- !ruby/object:Gem::Version
|
44
|
-
version:
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: hoe
|
58
|
+
type: :development
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 1.7.0
|
45
65
|
version:
|
46
66
|
description: An implementation of the UPnP protocol
|
47
67
|
email:
|
@@ -65,14 +85,22 @@ files:
|
|
65
85
|
- bin/upnp_listen
|
66
86
|
- lib/UPnP.rb
|
67
87
|
- lib/UPnP/SSDP.rb
|
88
|
+
- lib/UPnP/UUID.rb
|
68
89
|
- lib/UPnP/control.rb
|
69
90
|
- lib/UPnP/control/device.rb
|
70
91
|
- lib/UPnP/control/service.rb
|
92
|
+
- lib/UPnP/device.rb
|
93
|
+
- lib/UPnP/root_server.rb
|
94
|
+
- lib/UPnP/service.rb
|
71
95
|
- test/test_UPnP_SSDP.rb
|
72
96
|
- test/test_UPnP_SSDP_notification.rb
|
73
97
|
- test/test_UPnP_SSDP_response.rb
|
98
|
+
- test/test_UPnP_SSDP_search.rb
|
74
99
|
- test/test_UPnP_control_device.rb
|
75
100
|
- test/test_UPnP_control_service.rb
|
101
|
+
- test/test_UPnP_device.rb
|
102
|
+
- test/test_UPnP_root_server.rb
|
103
|
+
- test/test_UPnP_service.rb
|
76
104
|
- test/utilities.rb
|
77
105
|
has_rdoc: true
|
78
106
|
homepage: http://seattlerb.org/UPnP
|
@@ -104,6 +132,10 @@ summary: An implementation of the UPnP protocol
|
|
104
132
|
test_files:
|
105
133
|
- test/test_UPnP_control_device.rb
|
106
134
|
- test/test_UPnP_control_service.rb
|
135
|
+
- test/test_UPnP_device.rb
|
136
|
+
- test/test_UPnP_root_server.rb
|
137
|
+
- test/test_UPnP_service.rb
|
107
138
|
- test/test_UPnP_SSDP.rb
|
108
139
|
- test/test_UPnP_SSDP_notification.rb
|
109
140
|
- test/test_UPnP_SSDP_response.rb
|
141
|
+
- test/test_UPnP_SSDP_search.rb
|