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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +19 -0
  4. data/.rspec +1 -0
  5. data/.travis.yml +5 -0
  6. data/Gemfile +6 -0
  7. data/History.rdoc +3 -0
  8. data/LICENSE.rdoc +22 -0
  9. data/README.rdoc +194 -0
  10. data/Rakefile +20 -0
  11. data/features/control_point.feature +13 -0
  12. data/features/device.feature +22 -0
  13. data/features/device_discovery.feature +9 -0
  14. data/features/step_definitions/control_point_steps.rb +19 -0
  15. data/features/step_definitions/device_discovery_steps.rb +40 -0
  16. data/features/step_definitions/device_steps.rb +28 -0
  17. data/features/support/common.rb +9 -0
  18. data/features/support/env.rb +17 -0
  19. data/features/support/fake_upnp_device_collection.rb +108 -0
  20. data/features/support/world_extensions.rb +15 -0
  21. data/lib/core_ext/hash_patch.rb +5 -0
  22. data/lib/core_ext/socket_patch.rb +16 -0
  23. data/lib/core_ext/to_upnp_s.rb +65 -0
  24. data/lib/playful.rb +5 -0
  25. data/lib/playful/control_point.rb +175 -0
  26. data/lib/playful/control_point/base.rb +74 -0
  27. data/lib/playful/control_point/device.rb +511 -0
  28. data/lib/playful/control_point/error.rb +13 -0
  29. data/lib/playful/control_point/service.rb +404 -0
  30. data/lib/playful/device.rb +28 -0
  31. data/lib/playful/logger.rb +8 -0
  32. data/lib/playful/ssdp.rb +195 -0
  33. data/lib/playful/ssdp/broadcast_searcher.rb +114 -0
  34. data/lib/playful/ssdp/error.rb +6 -0
  35. data/lib/playful/ssdp/listener.rb +38 -0
  36. data/lib/playful/ssdp/multicast_connection.rb +112 -0
  37. data/lib/playful/ssdp/network_constants.rb +17 -0
  38. data/lib/playful/ssdp/notifier.rb +41 -0
  39. data/lib/playful/ssdp/searcher.rb +87 -0
  40. data/lib/playful/version.rb +3 -0
  41. data/lib/rack/upnp_control_point.rb +70 -0
  42. data/playful.gemspec +38 -0
  43. data/spec/spec_helper.rb +16 -0
  44. data/spec/support/search_responses.rb +134 -0
  45. data/spec/unit/core_ext/to_upnp_s_spec.rb +105 -0
  46. data/spec/unit/playful/control_point/device_spec.rb +7 -0
  47. data/spec/unit/playful/control_point_spec.rb +45 -0
  48. data/spec/unit/playful/ssdp/listener_spec.rb +29 -0
  49. data/spec/unit/playful/ssdp/multicast_connection_spec.rb +157 -0
  50. data/spec/unit/playful/ssdp/notifier_spec.rb +76 -0
  51. data/spec/unit/playful/ssdp/searcher_spec.rb +110 -0
  52. data/spec/unit/playful/ssdp_spec.rb +214 -0
  53. data/tasks/control_point.html +30 -0
  54. data/tasks/control_point.thor +43 -0
  55. data/tasks/search.thor +128 -0
  56. data/tasks/test_js/FABridge.js +1425 -0
  57. data/tasks/test_js/WebSocketMain.swf +807 -0
  58. data/tasks/test_js/swfobject.js +825 -0
  59. data/tasks/test_js/web_socket.js +1133 -0
  60. data/test/test_ssdp.rb +298 -0
  61. data/test/test_ssdp_notification.rb +74 -0
  62. data/test/test_ssdp_response.rb +31 -0
  63. data/test/test_ssdp_search.rb +23 -0
  64. metadata +339 -0
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+ require 'playful/control_point/device'
3
+
4
+
5
+ describe Playful::ControlPoint::Device do
6
+ pending
7
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'playful/control_point'
3
+
4
+
5
+ describe Playful::ControlPoint do
6
+ subject do
7
+ Playful::ControlPoint.new(1)
8
+ end
9
+
10
+ describe '#ssdp_search_and_listen' do
11
+ let(:notification) do
12
+ double 'notification'
13
+ end
14
+
15
+ let(:searcher) do
16
+ s = double 'Playful::SSDP::Searcher'
17
+ s.stub_chain(:discovery_responses, :subscribe).and_yield notification
18
+
19
+ s
20
+ end
21
+
22
+ before do
23
+ expect(Playful::SSDP).to receive(:search).with('ssdp:all', {}).and_return searcher
24
+ EM.stub(:add_periodic_timer)
25
+ end
26
+
27
+ after do
28
+ EM.unstub(:add_periodic_timer)
29
+ end
30
+
31
+ it 'creates a ControlPoint::Device for every discovery response' do
32
+ EM.stub(:add_timer)
33
+ subject.should_receive(:create_device).with(notification)
34
+ subject.ssdp_search_and_listen('ssdp:all')
35
+ end
36
+
37
+ it 'shuts down the searcher and starts the listener after the given response wait time' do
38
+ EM.stub(:add_timer).and_yield
39
+ subject.stub(:create_device)
40
+ searcher.should_receive(:close_connection)
41
+ subject.should_receive(:listen)
42
+ subject.ssdp_search_and_listen('ssdp:all')
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/listener'
3
+
4
+
5
+ describe Playful::SSDP::Listener do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ before do
14
+ allow_any_instance_of(Playful::SSDP::Listener).to receive(:setup_multicast_socket)
15
+ end
16
+
17
+ subject { Playful::SSDP::Listener.new(1) }
18
+
19
+ describe '#receive_data' do
20
+ it 'logs the IP and port from which the request came from' do
21
+ expect(subject).to receive(:peer_info).and_return %w[ip port]
22
+ expect(subject).to receive(:log).
23
+ with("Response from ip:port:\nmessage\n")
24
+ allow(subject).to receive(:parse).and_return({})
25
+
26
+ subject.receive_data('message')
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,157 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/multicast_connection'
3
+
4
+
5
+ describe Playful::SSDP::MulticastConnection do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ subject { Playful::SSDP::MulticastConnection.new(1) }
14
+
15
+ before do
16
+ Playful.log = false
17
+ end
18
+
19
+ describe '#peer_info' do
20
+ before do
21
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
22
+ subject.stub_chain(:get_peername, :[], :unpack).
23
+ and_return(%w[1234 1 2 3 4])
24
+ end
25
+
26
+ it 'returns an Array with IP and port' do
27
+ expect(subject.peer_info).to eq ['1.2.3.4', 1234]
28
+ end
29
+
30
+ it 'returns IP as a String' do
31
+ expect(subject.peer_info.first).to be_a String
32
+ end
33
+
34
+ it 'returns port as a Fixnum' do
35
+ expect(subject.peer_info.last).to be_a Fixnum
36
+ end
37
+ end
38
+
39
+ describe '#parse' do
40
+ before do
41
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
42
+ end
43
+
44
+ it 'turns headers into Hash keys' do
45
+ result = subject.parse ROOT_DEVICE1
46
+ expect(result).to have_key :cache_control
47
+ expect(result).to have_key :date
48
+ expect(result).to have_key :location
49
+ expect(result).to have_key :server
50
+ expect(result).to have_key :st
51
+ expect(result).to have_key :ext
52
+ expect(result).to have_key :usn
53
+ expect(result).to have_key :content_length
54
+ end
55
+
56
+ it 'turns header values into Hash values' do
57
+ result = subject.parse ROOT_DEVICE1
58
+ expect(result[:cache_control]).to eq 'max-age=1200'
59
+ expect(result[:date]).to eq 'Mon, 26 Sep 2011 06:40:19 GMT'
60
+ expect(result[:location]).to eq 'http://1.2.3.4:5678/description/fetch'
61
+ expect(result[:server]).to eq 'Linux-i386-2.6.38-10-generic-pae, UPnP/1.0, PMS/1.25.1'
62
+ expect(result[:st]).to eq 'upnp:rootdevice'
63
+ expect(result[:ext]).to be_empty
64
+ expect(result[:usn]).to eq 'uuid:3c202906-992d-3f0f-b94c-90e1902a136d::upnp:rootdevice'
65
+ expect(result[:content_length]).to eq '0'
66
+ end
67
+
68
+ context 'single line String as response data' do
69
+ before { @data = ROOT_DEVICE1.gsub("\n", ' ') }
70
+
71
+ it 'returns an empty Hash' do
72
+ expect(subject.parse(@data)).to eq({ })
73
+ end
74
+
75
+ it "logs the 'bad' response" do
76
+ subject.should_receive(:log).twice
77
+ subject.parse @data
78
+ end
79
+ end
80
+ end
81
+
82
+ describe '#setup_multicast_socket' do
83
+ before do
84
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_membership)
85
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:switch_multicast_loop)
86
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_multicast_ttl)
87
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:set_ttl)
88
+ end
89
+
90
+ it 'adds 0.0.0.0 and 239.255.255.250 to the membership group' do
91
+ expect(subject).to receive(:set_membership).with(
92
+ IPAddr.new('239.255.255.250').hton + IPAddr.new('0.0.0.0').hton
93
+ )
94
+ subject.setup_multicast_socket
95
+ end
96
+
97
+ it 'sets multicast TTL to 4' do
98
+ expect(subject).to receive(:set_multicast_ttl).with(4)
99
+ subject.setup_multicast_socket
100
+ end
101
+
102
+ it 'sets TTL to 4' do
103
+ expect(subject).to receive(:set_ttl).with(4)
104
+ subject.setup_multicast_socket
105
+ end
106
+
107
+ context "ENV['RUBY_UPNP_ENV'] != testing" do
108
+ after { ENV['RUBY_UPNP_ENV'] = 'testing' }
109
+
110
+ it 'turns multicast loop off' do
111
+ ENV['RUBY_UPNP_ENV'] = 'development'
112
+ expect(subject).to receive(:switch_multicast_loop).with(:off)
113
+ subject.setup_multicast_socket
114
+ end
115
+ end
116
+ end
117
+
118
+ describe '#switch_multicast_loop' do
119
+ before do
120
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
121
+ end
122
+
123
+ it "passes '\\001' to the socket option call when param == :on" do
124
+ expect(subject).to receive(:set_sock_opt).with(
125
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\001"
126
+ )
127
+ subject.switch_multicast_loop :on
128
+ end
129
+
130
+ it "passes '\\001' to the socket option call when param == '\\001'" do
131
+ expect(subject).to receive(:set_sock_opt).with(
132
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\001"
133
+ )
134
+ subject.switch_multicast_loop "\001"
135
+ end
136
+
137
+ it "passes '\\000' to the socket option call when param == :off" do
138
+ expect(subject).to receive(:set_sock_opt).with(
139
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\000"
140
+ )
141
+ subject.switch_multicast_loop :off
142
+ end
143
+
144
+ it "passes '\\000' to the socket option call when param == '\\000'" do
145
+ expect(subject).to receive(:set_sock_opt).with(
146
+ Socket::IPPROTO_IP, Socket::IP_MULTICAST_LOOP, "\000"
147
+ )
148
+ subject.switch_multicast_loop "\000"
149
+ end
150
+
151
+ it "raises when not :on, :off, '\\000', or '\\001'" do
152
+ expect { subject.switch_multicast_loop 12312312 }.
153
+ to raise_error(Playful::SSDP::Error)
154
+ end
155
+ end
156
+ end
157
+
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/notifier'
3
+
4
+
5
+ describe Playful::SSDP::Notifier do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ let(:nt) { 'en tee' }
14
+ let(:usn) { 'you ess en' }
15
+ let(:ddf_url) { 'ddf url' }
16
+ let(:duration) { 567 }
17
+
18
+ subject do
19
+ Playful::SSDP::Notifier.new(1, nt, usn, ddf_url, duration)
20
+ end
21
+
22
+ describe '#initialize' do
23
+ it 'creates a notification' do
24
+ expect_any_instance_of(Playful::SSDP::Notifier).to receive(:notification).
25
+ with(nt, usn, ddf_url, duration)
26
+
27
+ subject
28
+ end
29
+ end
30
+
31
+ describe '#post_init' do
32
+ context 'send_datagram returns positive value' do
33
+ before do
34
+ expect(subject).to receive(:send_datagram).and_return 1
35
+ end
36
+
37
+ it 'logs what was sent' do
38
+ expect(subject).to receive(:log).with /Sent notification/
39
+
40
+ subject.post_init
41
+ end
42
+ end
43
+
44
+ context 'send_datagram returns 0' do
45
+ before do
46
+ expect(subject).to receive(:send_datagram).and_return 0
47
+ end
48
+
49
+ it 'does not log what was sent' do
50
+ expect(subject).to_not receive(:log)
51
+
52
+ subject.post_init
53
+ end
54
+ end
55
+ end
56
+
57
+ describe '#notification' do
58
+ before do
59
+ subject.instance_variable_set(:@os, 'my OS')
60
+ end
61
+
62
+ it 'builds the notification message' do
63
+ expect(subject.notification(nt, usn, ddf_url, duration)).to eq <<-NOTE
64
+ NOTIFY * HTTP/1.1\r
65
+ HOST: 239.255.255.250:1900\r
66
+ CACHE-CONTROL: max-age=567\r
67
+ LOCATION: ddf url\r
68
+ NT: en tee\r
69
+ NTS: ssdp:alive\r
70
+ SERVER: my OS UPnP/1.0 Playful/#{Playful::VERSION}\r
71
+ USN: you ess en\r
72
+ \r
73
+ NOTE
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,110 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp/searcher'
3
+
4
+
5
+ describe Playful::SSDP::Searcher do
6
+ around(:each) do |example|
7
+ EM.synchrony do
8
+ example.run
9
+ EM.stop
10
+ end
11
+ end
12
+
13
+ before do
14
+ Playful.log = false
15
+ allow_any_instance_of(Playful::SSDP::MulticastConnection).to receive(:setup_multicast_socket)
16
+ end
17
+
18
+ subject do
19
+ Playful::SSDP::Searcher.new(1, 'ssdp:all', {})
20
+ end
21
+
22
+ it 'lets you read its responses' do
23
+ responses = double 'responses'
24
+ subject.instance_variable_set(:@discovery_responses, responses)
25
+ expect(subject.discovery_responses).to eq responses
26
+ end
27
+
28
+ describe '#initialize' do
29
+ it 'does an #m_search' do
30
+ expect_any_instance_of(Playful::SSDP::Searcher).to receive(:m_search).and_return(<<-MSEARCH
31
+ M-SEARCH * HTTP/1.1\r
32
+ HOST: 239.255.255.250:1900\r
33
+ MAN: "ssdp:discover"\r
34
+ MX: 5\r
35
+ ST: ssdp:all\r
36
+ \r
37
+ MSEARCH
38
+ )
39
+ subject
40
+ end
41
+ end
42
+
43
+ describe '#receive_data' do
44
+ let(:parsed_response) do
45
+ parsed_response = double 'parsed response'
46
+ expect(parsed_response).to receive(:has_key?).with(:nts).and_return false
47
+ expect(parsed_response).to receive(:[]).and_return false
48
+
49
+ parsed_response
50
+ end
51
+
52
+ it 'takes a response and adds it to the list of responses' do
53
+ response = double 'response'
54
+ allow(subject).to receive(:peer_info).and_return(['0.0.0.0', 4567])
55
+
56
+ expect(subject).to receive(:parse).with(response).exactly(1).times.
57
+ and_return(parsed_response)
58
+ expect(subject.instance_variable_get(:@discovery_responses)).to receive(:<<).
59
+ with(parsed_response)
60
+
61
+ subject.receive_data(response)
62
+ end
63
+ end
64
+
65
+ describe '#post_init' do
66
+ before { allow_any_instance_of(Playful::SSDP::Searcher).to receive(:m_search).and_return('hi') }
67
+
68
+ it 'sends an M-SEARCH as a datagram over 239.255.255.250:1900' do
69
+ m_search_count_times = subject.instance_variable_get(:@m_search_count)
70
+ expect(subject).to receive(:send_datagram).
71
+ with('hi', '239.255.255.250', 1900).
72
+ exactly(m_search_count_times).times.
73
+ and_return 0
74
+ subject.post_init
75
+ end
76
+ end
77
+
78
+ describe '#m_search' do
79
+ it 'builds the MSEARCH string using the given parameters' do
80
+ expect(subject.m_search('ssdp:all', 10)).to eq <<-MSEARCH
81
+ M-SEARCH * HTTP/1.1\r
82
+ HOST: 239.255.255.250:1900\r
83
+ MAN: "ssdp:discover"\r
84
+ MX: 10\r
85
+ ST: ssdp:all\r
86
+ \r
87
+ MSEARCH
88
+ end
89
+
90
+ it 'uses 239.255.255.250 as the HOST IP' do
91
+ expect(subject.m_search('ssdp:all', 10)).to match(/HOST: 239.255.255.250/m)
92
+ end
93
+
94
+ it 'uses 1900 as the HOST port' do
95
+ expect(subject.m_search('ssdp:all', 10)).to match(/HOST:.*1900/m)
96
+ end
97
+
98
+ it 'lets you search for undefined search target types' do
99
+ expect(subject.m_search('spaceship', 10)).to eq <<-MSEARCH
100
+ M-SEARCH * HTTP/1.1\r
101
+ HOST: 239.255.255.250:1900\r
102
+ MAN: "ssdp:discover"\r
103
+ MX: 10\r
104
+ ST: spaceship\r
105
+ \r
106
+ MSEARCH
107
+ end
108
+ end
109
+ end
110
+
@@ -0,0 +1,214 @@
1
+ require 'spec_helper'
2
+ require 'playful/ssdp'
3
+
4
+
5
+ describe Playful::SSDP do
6
+ subject { Playful::SSDP }
7
+
8
+ describe '.listen' do
9
+ let(:listener) do
10
+ searcher = double 'Playful::SSDP::Listener'
11
+ searcher.stub_chain(:alive_notifications, :pop).and_yield(%w[one two])
12
+ searcher.stub_chain(:byebye_notifications, :pop).and_yield(%w[three four])
13
+
14
+ searcher
15
+ end
16
+
17
+ before do
18
+ allow(EM).to receive(:run).and_yield
19
+ allow(EM).to receive(:add_timer)
20
+ allow(EM).to receive(:open_datagram_socket).and_return listener
21
+ end
22
+
23
+ context 'reactor is already running' do
24
+ it 'returns a Playful::SSDP::Listener' do
25
+ allow(EM).to receive(:reactor_running?).and_return true
26
+ expect(subject.listen).to eq listener
27
+ end
28
+ end
29
+
30
+ context 'reactor is not already running' do
31
+ it 'returns a Hash of available and byebye responses' do
32
+ allow(EM).to receive(:add_shutdown_hook).and_yield
33
+ expect(subject.listen).to eq({
34
+ alive_notifications: %w[one two],
35
+ byebye_notifications: %w[three four]
36
+ })
37
+ end
38
+
39
+ it 'opens a UDP socket on 239.255.255.250, port 1900' do
40
+ allow(EM).to receive(:add_shutdown_hook)
41
+ expect(EM).to receive(:open_datagram_socket).with('239.255.255.250', 1900,
42
+ Playful::SSDP::Listener, 4)
43
+ subject.listen
44
+ end
45
+ end
46
+ end
47
+
48
+ describe '.search' do
49
+ let(:multicast_searcher) do
50
+ searcher = double 'Playful::SSDP::Searcher'
51
+ searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[one two])
52
+
53
+ searcher
54
+ end
55
+
56
+ let(:broadcast_searcher) do
57
+ searcher = double 'Playful::SSDP::BroadcastSearcher'
58
+ searcher.stub_chain(:discovery_responses, :subscribe).and_yield(%w[three four])
59
+
60
+ searcher
61
+ end
62
+
63
+ before do
64
+ allow(EM).to receive(:run).and_yield
65
+ allow(EM).to receive(:add_timer)
66
+ allow(EM).to receive(:open_datagram_socket).and_return multicast_searcher
67
+ end
68
+
69
+ context 'when search_target is not a String' do
70
+ it 'calls #to_upnp_s on search_target' do
71
+ search_target = double('search_target')
72
+ expect(search_target).to receive(:to_upnp_s)
73
+ subject.search(search_target)
74
+ end
75
+ end
76
+
77
+ context 'when search_target is a String' do
78
+ it 'calls #to_upnp_s on search_target but does not alter it' do
79
+ search_target = "I'm a string"
80
+ expect(search_target).to receive(:to_upnp_s).and_call_original
81
+
82
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0,
83
+ Playful::SSDP::Searcher, "I'm a string", {})
84
+ subject.search(search_target)
85
+ end
86
+ end
87
+
88
+ context 'reactor is already running' do
89
+ it 'returns a Playful::SSDP::Searcher' do
90
+ allow(EM).to receive(:reactor_running?).and_return true
91
+ expect(subject.search).to eq multicast_searcher
92
+ end
93
+ end
94
+
95
+ context 'reactor is not already running' do
96
+ context 'options hash includes do_broadcast_search' do
97
+ before do
98
+ allow(EM).to receive(:open_datagram_socket).
99
+ and_return(multicast_searcher, broadcast_searcher)
100
+ end
101
+
102
+ it 'returns an Array of responses' do
103
+ allow(EM).to receive(:add_shutdown_hook).and_yield
104
+ expect(subject.search(:all, do_broadcast_search: true)).to eq %w[one two three four]
105
+ end
106
+
107
+ it 'opens 2 UDP sockets on 0.0.0.0, port 0' do
108
+ allow(EM).to receive(:add_shutdown_hook)
109
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::Searcher,
110
+ 'ssdp:all', {})
111
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::BroadcastSearcher,
112
+ 'ssdp:all', 5, 4)
113
+ subject.search(:all, do_broadcast_search: true)
114
+ end
115
+ end
116
+
117
+ context 'options hash does not include do_broadcast_search' do
118
+ it 'returns an Array of responses' do
119
+ allow(EM).to receive(:add_shutdown_hook).and_yield
120
+ expect(subject.search).to eq %w[one two]
121
+ end
122
+
123
+ it 'opens a UDP socket on 0.0.0.0, port 0' do
124
+ allow(EM).to receive(:add_shutdown_hook)
125
+ expect(EM).to receive(:open_datagram_socket).with('0.0.0.0', 0, Playful::SSDP::Searcher,
126
+ 'ssdp:all', {})
127
+ subject.search
128
+ end
129
+ end
130
+ end
131
+ end
132
+
133
+ describe '.notify' do
134
+ pending 'Implementation of UPnP Devices'
135
+ end
136
+
137
+ describe '.send_notification' do
138
+ pending 'Implementation of UPnP Devices'
139
+ end
140
+
141
+ =begin
142
+ context 'by default' do
143
+ it "searches for 'ssdp:all'" do
144
+ pending
145
+ end
146
+
147
+ it 'waits for 5 seconds for responses' do
148
+ before = Time.now
149
+
150
+ SSDP.search
151
+
152
+ after = Time.now
153
+ (after - before).should < 5.1
154
+ (after - before).should > 5.0
155
+ end
156
+ end
157
+
158
+ context "finds 'upnp:rootdevice's" do
159
+ it "by using the spec's string 'upnp:rootdevice'" do
160
+ SSDP.search('upnp:rootdevice').should == [
161
+ {
162
+ :cache_control=>'max-age=1200',
163
+ :date=>'Mon, 26 Sep 2011 06:40:19 GMT',
164
+ :location=>'http://192.168.10.3:5001/description/fetch',
165
+ :server=>'Linux-i386-2.6.38-10-generic-pae, UPnP/1.0, PMS/1.25.1',
166
+ :st=>'upnp:rootdevice',
167
+ :ext=>'',
168
+ :usn=>'uuid:3c202906-992d-3f0f-b94c-90e1902a136d::upnp:rootdevice',
169
+ :content_length=>'0'
170
+ }
171
+ ]
172
+ end
173
+
174
+ it 'by using :root' do
175
+ pending
176
+ end
177
+ end
178
+
179
+ it 'can wait for user-defined seconds for responses' do
180
+ before = Time.now
181
+
182
+ SSDP.search(:all, 1)
183
+
184
+ after = Time.now
185
+ (after - before).should < 1.1
186
+ (after - before).should > 1.0
187
+ end
188
+
189
+ it 'finds a device by its URN' do
190
+ pending
191
+ end
192
+
193
+ it 'finds a device by its UUID' do
194
+ pending
195
+ end
196
+
197
+ it 'finds a device by its UPnP device type' do
198
+ pending
199
+ end
200
+
201
+ it 'finds a device by its UPnP device type using a non-standard domain name' do
202
+ pending
203
+ end
204
+
205
+ it 'finds a service by its UPnP service type' do
206
+ pending
207
+ end
208
+
209
+ it 'find a service by its UPnP service type using a non-standard domain name' do
210
+ pending
211
+ end
212
+ =end
213
+ end
214
+