rtp 0.0.1 → 0.1.0

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 (60) hide show
  1. data/Gemfile +0 -3
  2. data/History.rdoc +42 -0
  3. data/README.rdoc +60 -15
  4. data/Rakefile +9 -4
  5. data/lib/rtp.rb +0 -3
  6. data/lib/rtp/logger.rb +11 -0
  7. data/lib/rtp/packet.rb +39 -3
  8. data/lib/rtp/receiver.rb +255 -152
  9. data/lib/rtp/version.rb +1 -1
  10. data/rtp.gemspec +2 -1
  11. data/spec/rtp/coverage/assets/0.7.1/application.css +1110 -0
  12. data/spec/rtp/coverage/assets/0.7.1/application.js +626 -0
  13. data/spec/rtp/coverage/assets/0.7.1/fancybox/blank.gif +0 -0
  14. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_close.png +0 -0
  15. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_loading.png +0 -0
  16. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_nav_left.png +0 -0
  17. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_nav_right.png +0 -0
  18. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_e.png +0 -0
  19. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_n.png +0 -0
  20. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_ne.png +0 -0
  21. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_nw.png +0 -0
  22. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_s.png +0 -0
  23. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_se.png +0 -0
  24. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_sw.png +0 -0
  25. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_shadow_w.png +0 -0
  26. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_title_left.png +0 -0
  27. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_title_main.png +0 -0
  28. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_title_over.png +0 -0
  29. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancy_title_right.png +0 -0
  30. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancybox-x.png +0 -0
  31. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancybox-y.png +0 -0
  32. data/spec/rtp/coverage/assets/0.7.1/fancybox/fancybox.png +0 -0
  33. data/spec/rtp/coverage/assets/0.7.1/favicon_green.png +0 -0
  34. data/spec/rtp/coverage/assets/0.7.1/favicon_red.png +0 -0
  35. data/spec/rtp/coverage/assets/0.7.1/favicon_yellow.png +0 -0
  36. data/spec/rtp/coverage/assets/0.7.1/loading.gif +0 -0
  37. data/spec/rtp/coverage/assets/0.7.1/magnify.png +0 -0
  38. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png +0 -0
  39. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_flat_75_ffffff_40x100.png +0 -0
  40. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png +0 -0
  41. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  42. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_dadada_1x400.png +0 -0
  43. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png +0 -0
  44. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png +0 -0
  45. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png +0 -0
  46. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-icons_222222_256x240.png +0 -0
  47. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-icons_2e83ff_256x240.png +0 -0
  48. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-icons_454545_256x240.png +0 -0
  49. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-icons_888888_256x240.png +0 -0
  50. data/spec/rtp/coverage/assets/0.7.1/smoothness/images/ui-icons_cd0a0a_256x240.png +0 -0
  51. data/spec/rtp/coverage/index.html +146 -0
  52. data/spec/rtp/receiver_spec.rb +241 -258
  53. data/spec/rtp_spec.rb +1 -1
  54. data/spec/spec_helper.rb +4 -13
  55. metadata +152 -23
  56. data/tasks/roodi.rake +0 -10
  57. data/tasks/roodi_config.yaml +0 -14
  58. data/tasks/rspec.rake +0 -10
  59. data/tasks/stats.rake +0 -12
  60. data/tasks/yard.rake +0 -8
@@ -0,0 +1,146 @@
1
+ <!DOCTYPE html>
2
+ <html xmlns='http://www.w3.org/1999/xhtml'>
3
+ <head>
4
+ <title>Code coverage for Rtp</title>
5
+ <meta http-equiv="content-type" content="text/html; charset=utf-8" />
6
+ <script src='./assets/0.7.1/application.js' type='text/javascript'></script>
7
+ <link href='./assets/0.7.1/application.css' media='screen, projection, print' rel='stylesheet' type='text/css'>
8
+ <link rel="shortcut icon" type="image/png" href="./assets/0.7.1/favicon_green.png" />
9
+ <link rel="icon" type="image/png" href="./assets/0.7.1/favicon.png" />
10
+ </head>
11
+
12
+ <body>
13
+ <div id="loading">
14
+ <img src="./assets/0.7.1/loading.gif" alt="loading"/>
15
+ </div>
16
+ <div id="wrapper" style="display:none;">
17
+ <div class="timestamp">Generated <abbr class="timeago" title="2012-11-20T10:56:32-08:00">2012-11-20T10:56:32-08:00</abbr></div>
18
+ <ul class="group_tabs"></ul>
19
+
20
+ <div id="content">
21
+ <div class="file_list_container" id="AllFiles">
22
+ <h2>
23
+ <span class="group_name">All Files</span>
24
+ (<span class="covered_percent"><span class="green">100.0%</span></span>
25
+ covered at
26
+ <span class="covered_strength">
27
+ <span class="red">
28
+ 0.0
29
+ </span>
30
+ </span> hits/line)
31
+ </h2>
32
+ <a name="AllFiles"></a>
33
+ <div>
34
+ <b>0</b> files in total.
35
+ <b>0.0</b> relevant lines.
36
+ <span class="green"><b>0.0</b> lines covered</span> and
37
+ <span class="red"><b>0.0</b> lines missed </span>
38
+ </div>
39
+ <table class="file_list">
40
+ <thead>
41
+ <tr>
42
+ <th>File</th>
43
+ <th>% covered</th>
44
+ <th>Lines</th>
45
+ <th>Relevant Lines</th>
46
+ <th>Lines covered</th>
47
+ <th>Lines missed</th>
48
+ <th>Avg. Hits / Line</th>
49
+ </tr>
50
+ </thead>
51
+ <tbody>
52
+
53
+ </tbody>
54
+ </table>
55
+ </div>
56
+
57
+
58
+
59
+ <div class="file_list_container" id="Lib">
60
+ <h2>
61
+ <span class="group_name">Lib</span>
62
+ (<span class="covered_percent"><span class="green">100.0%</span></span>
63
+ covered at
64
+ <span class="covered_strength">
65
+ <span class="red">
66
+ 0.0
67
+ </span>
68
+ </span> hits/line)
69
+ </h2>
70
+ <a name="Lib"></a>
71
+ <div>
72
+ <b>0</b> files in total.
73
+ <b>0.0</b> relevant lines.
74
+ <span class="green"><b>0.0</b> lines covered</span> and
75
+ <span class="red"><b>0.0</b> lines missed </span>
76
+ </div>
77
+ <table class="file_list">
78
+ <thead>
79
+ <tr>
80
+ <th>File</th>
81
+ <th>% covered</th>
82
+ <th>Lines</th>
83
+ <th>Relevant Lines</th>
84
+ <th>Lines covered</th>
85
+ <th>Lines missed</th>
86
+ <th>Avg. Hits / Line</th>
87
+ </tr>
88
+ </thead>
89
+ <tbody>
90
+
91
+ </tbody>
92
+ </table>
93
+ </div>
94
+
95
+
96
+ <div class="file_list_container" id="Specs">
97
+ <h2>
98
+ <span class="group_name">Specs</span>
99
+ (<span class="covered_percent"><span class="green">100.0%</span></span>
100
+ covered at
101
+ <span class="covered_strength">
102
+ <span class="red">
103
+ 0.0
104
+ </span>
105
+ </span> hits/line)
106
+ </h2>
107
+ <a name="Specs"></a>
108
+ <div>
109
+ <b>0</b> files in total.
110
+ <b>0.0</b> relevant lines.
111
+ <span class="green"><b>0.0</b> lines covered</span> and
112
+ <span class="red"><b>0.0</b> lines missed </span>
113
+ </div>
114
+ <table class="file_list">
115
+ <thead>
116
+ <tr>
117
+ <th>File</th>
118
+ <th>% covered</th>
119
+ <th>Lines</th>
120
+ <th>Relevant Lines</th>
121
+ <th>Lines covered</th>
122
+ <th>Lines missed</th>
123
+ <th>Avg. Hits / Line</th>
124
+ </tr>
125
+ </thead>
126
+ <tbody>
127
+
128
+ </tbody>
129
+ </table>
130
+ </div>
131
+
132
+
133
+ </div>
134
+
135
+ <div id="footer">
136
+ Generated by <a href="http://github.com/colszowka/simplecov">simplecov</a> v0.7.1
137
+ and simplecov-html v0.7.1<br/>
138
+ using RSpec
139
+ </div>
140
+
141
+ <div class="source_files">
142
+
143
+ </div>
144
+ </div>
145
+ </body>
146
+ </html>
@@ -1,368 +1,351 @@
1
- require_relative '../spec_helper'
1
+ require 'spec_helper'
2
2
  require 'rtp/receiver'
3
3
 
4
4
  Thread.abort_on_exception = true
5
- RTP.log = false
5
+ RTP::Logger.log = false
6
6
 
7
7
  describe RTP::Receiver do
8
8
  describe "#initialize" do
9
- context "with default parameters" do
10
- it "uses UDP" do
11
- subject.instance_variable_get(:@transport_protocol).should == :UDP
12
- end
13
-
14
- it "uses port 9000" do
15
- subject.instance_variable_get(:@rtp_port).should == 9000
16
- end
17
-
18
- it "creates a new Tempfile" do
19
- subject.instance_variable_get(:@rtp_file).should be_a Tempfile
20
- end
9
+ it "sets default values for accessors" do
10
+ subject.transport_protocol.should == :UDP
11
+ subject.instance_variable_get(:@ip_address).should == '0.0.0.0'
12
+ subject.rtp_port.should == 6970
13
+ subject.rtcp_port.should == 6971
14
+ subject.capture_file.should be_a Tempfile
15
+ end
21
16
 
22
- it "initializes @packet_timestamps" do
23
- subject.instance_variable_get(:@packet_timestamps).should == []
24
- end
17
+ it "isn't running" do
18
+ subject.should_not be_running
19
+ end
20
+ end
25
21
 
26
- it "initializes an Array for holding the data buffer" do
27
- subject.instance_variable_get(:@payload_data).should be_a Array
28
- end
22
+ describe "#start" do
23
+ context "running" do
24
+ before { subject.stub(:running?).and_return true }
29
25
 
30
- it "initializes an Array for holding the sequence_list" do
31
- subject.instance_variable_get(:@sequence_list).should be_a Array
26
+ it "doesn't try starting anything else" do
27
+ subject.should_not_receive(:start_packet_writer)
28
+ subject.should_not_receive(:init_socket)
29
+ subject.should_not_receive(:start_listener)
30
+ subject.start
32
31
  end
33
32
  end
34
33
 
35
- context "non-default parameters" do
36
- it "can use TCP" do
37
- RTP::Receiver.new(:TCP).instance_variable_get(:@transport_protocol).should == :TCP
38
- end
34
+ context "not running" do
35
+ before { subject.stub(:running?).and_return false }
36
+ let(:packet_writer) { double "@packet_writer", :abort_on_exception= => nil }
37
+ let(:listener) { double "@listener", :abort_on_exception= => nil }
39
38
 
40
- it "can take another port" do
41
- RTP::Receiver.new(:UDP, 12345).instance_variable_get(:@rtp_port).should == 12345
42
- end
39
+ it "initializes the listener socket, listener thread, and packet writer" do
40
+ subject.should_receive(:start_packet_writer).and_return packet_writer
41
+ subject.should_receive(:init_socket).with(:UDP, 6970, '0.0.0.0')
42
+ subject.should_receive(:start_listener).and_return packet_writer
43
43
 
44
- it "can take an IO object" do
45
- fd = IO.sysopen("/dev/null", "w")
46
- io = IO.new(fd, 'w')
47
- capturer = RTP::Receiver.new(:UDP, 12345, io)
48
- capturer.instance_variable_get(:@rtp_file).should be_a IO
44
+ subject.start
49
45
  end
50
46
  end
51
-
52
- it "isn't running" do
53
- subject.should_not be_running
54
- end
55
47
  end
56
48
 
57
- describe "#init_server" do
58
- context "UDP" do
59
- it "calls #init_udp_server with port 9000" do
60
- subject.should_receive(:init_udp_server).with(9000)
61
- subject.init_server(:UDP)
49
+ describe "#stop" do
50
+ context "running" do
51
+ before { subject.stub(:running?).and_return true }
52
+
53
+ it "calls #stop_listener" do
54
+ subject.should_receive(:stop_listener)
55
+ subject.stop
62
56
  end
63
57
 
64
- it "returns a UDPSocket" do
65
- subject.init_server(:UDP).should be_a UDPSocket
58
+ it "calls #stop_packet_writer" do
59
+ subject.should_receive(:stop_packet_writer)
60
+ subject.stop
66
61
  end
67
62
  end
68
63
 
69
- context "TCP" do
70
- it "calls #init_tcp_server with port 9000" do
71
- subject.should_receive(:init_tcp_server).with(9000)
72
- subject.init_server(:TCP)
73
- end
64
+ context "not running" do
65
+ before { subject.stub(:running?).and_return false }
66
+ specify { subject.stop.should be_false }
67
+ end
68
+ end
74
69
 
75
- it "returns a TCPServer" do
76
- subject.init_server(:TCP).should be_a(TCPServer)
77
- end
70
+ describe "#listening?" do
71
+ context "@listner is nil" do
72
+ before { subject.instance_variable_set(:@listener, nil) }
73
+ specify { subject.should_not be_listening }
78
74
  end
79
75
 
80
- it "raises an RTP::Error when some other protocol is given" do
81
- expect { subject.init_server(:BOBO) }.to raise_error RTP::Error
76
+ context "@listener is not nil" do
77
+ let(:listener) { double "@listener", :alive? => true }
78
+ before { subject.instance_variable_set(:@listener, listener) }
79
+ specify { subject.should be_listening }
82
80
  end
83
81
  end
84
82
 
85
- describe "#init_udp_server" do
86
- let(:udp_server) do
87
- double "UDPSocket", setsockopt: nil
83
+ describe "#writing_packets?" do
84
+ context "@packet_writer is nil" do
85
+ before { subject.instance_variable_set(:@packet_writer, nil) }
86
+ specify { subject.should_not be_writing_packets }
88
87
  end
89
88
 
90
- it "returns a UDPSocket" do
91
- subject.init_udp_server(subject.rtp_port).should be_a UDPSocket
89
+ context "@packet_writer is not nil" do
90
+ let(:writer) { double "@packet_writer", :alive? => true }
91
+ before { subject.instance_variable_set(:@packet_writer, writer) }
92
+ specify { subject.should be_writing_packets }
92
93
  end
94
+ end
93
95
 
94
- context "when port 9000 - 9048 are taken" do
95
- it "retries MAX_PORT_NUMBER_RETRIES times then returns the UDPSocket" do
96
- udp_server.should_receive(:bind).exactly(50).times.and_raise(Errno::EADDRINUSE)
97
- udp_server.should_receive(:bind).with('0.0.0.0', 9050)
98
- UDPSocket.stub(:open).and_return(udp_server)
96
+ describe "#running?" do
97
+ context "listening and writing packets" do
98
+ before do
99
+ subject.stub(:listening?).and_return(true)
100
+ subject.stub(:writing_packets?).and_return(true)
101
+ end
99
102
 
100
- subject.init_udp_server(9000).should == udp_server
103
+ specify { subject.should be_running }
104
+ end
101
105
 
102
- UDPSocket.unstub(:open)
106
+ context "listening, not writing packets" do
107
+ before do
108
+ subject.stub(:listening?).and_return(true)
109
+ subject.stub(:writing_packets?).and_return(false)
103
110
  end
111
+
112
+ specify { subject.should_not be_running }
104
113
  end
105
114
 
106
- context "when no available ports" do
115
+ context "not listening, writing packets" do
107
116
  before do
108
- UDPSocket.should_receive(:open).exactly(51).times.and_raise(Errno::EADDRINUSE)
117
+ subject.stub(:listening?).and_return(false)
118
+ subject.stub(:writing_packets?).and_return(true)
109
119
  end
110
120
 
111
- it "retries 50 times to get a port then allows the Errno::EADDRINUSE to raise" do
112
- expect { subject.init_udp_server(9000) }.to raise_error Errno::EADDRINUSE
113
- end
121
+ specify { subject.should_not be_running }
122
+ end
114
123
 
115
- it "sets @rtp_port back to 9000 after trying all" do
116
- expect { subject.init_udp_server(9000) }.to raise_error Errno::EADDRINUSE
117
- subject.rtp_port.should == 9000
124
+ context "not listening, not writing packets" do
125
+ before do
126
+ subject.stub(:listening?).and_return(false)
127
+ subject.stub(:writing_packets?).and_return(false)
118
128
  end
129
+
130
+ specify { subject.should_not be_running }
119
131
  end
120
132
  end
121
133
 
122
- describe "#init_tcp_server" do
123
- it "returns a TCPSocket" do
124
- subject.init_tcp_server(3456).should be_a TCPSocket
125
- end
134
+ describe "#rtp_port=" do
135
+ specify {
136
+ subject.rtp_port.should == 6970
137
+ subject.rtcp_port.should == 6971
126
138
 
127
- it "uses port a port between 9000 and 9000 + MAX_PORT_NUMBER_RETRIES" do
128
- subject.init_tcp_server(9000)
129
- subject.rtp_port.should >= 9000
130
- subject.rtp_port.should <= 9000 + RTP::Receiver::MAX_PORT_NUMBER_RETRIES
131
- end
132
- end
139
+ subject.rtp_port = 10000
133
140
 
134
- describe "#run" do
135
- it "calls #start_listener" do
136
- subject.should_receive(:start_listener)
137
- subject.run
138
- end
141
+ subject.rtp_port.should == 10000
142
+ subject.rtcp_port.should == 10001
143
+ }
139
144
  end
140
145
 
141
- describe "#running?" do
142
- context "#listening? returns true" do
143
- before { subject.stub(:listening?).and_return(true) }
144
- it { should be_true }
145
- end
146
+ #----------------------------------------------------------------------------
147
+ # PRIVATES
148
+ #----------------------------------------------------------------------------
149
+
150
+ describe "#start_packet_writer" do
151
+ context "packet writer running" do
152
+ let(:packet) { double "RTP::Packet" }
146
153
 
147
- context "#listening? returns true, #file_building? returns true" do
148
154
  before do
149
- subject.stub(:listening? => true, :file_building? => true)
150
- it { should be_true }
155
+ Thread.stub(:start).and_yield
156
+ subject.stub(:loop).and_yield
157
+ subject.instance_variable_set(:@packets, [packet])
158
+ RTP::Packet.should_receive(:read).and_return packet
151
159
  end
152
- end
153
160
 
154
- context "#listening? returns true, #file_building? returns false" do
155
- before do
156
- subject.stub(:listening? => true, :file_building? => false)
157
- it { should be_false }
161
+ after do
162
+ Thread.unstub(:start)
163
+ end
164
+
165
+ context "@strip_headers is false" do
166
+ before { subject.instance_variable_set(:@strip_headers, false) }
167
+
168
+ it "adds the incoming data to @packets Queue" do
169
+ packet.should_not_receive(:rtp_payload)
170
+ subject.instance_variable_get(:@capture_file).should_receive(:write).
171
+ with packet
172
+ subject.send(:start_packet_writer)
173
+ end
174
+ end
175
+
176
+ context "@strip_headers is true" do
177
+ before { subject.instance_variable_set(:@strip_headers, true) }
178
+
179
+ it "adds the stripped data to @payload_data buffer" do
180
+ packet.should_receive(:rtp_payload).and_return("payload_data")
181
+ subject.instance_variable_get(:@capture_file).should_receive(:write).
182
+ with "payload_data"
183
+ subject.send(:start_packet_writer)
184
+ end
158
185
  end
159
186
  end
160
187
 
161
- context "#listening? returns false, #file_building? returns false" do
188
+ context "packet writer not running" do
189
+ let(:packet_writer) { double "@packet_writer" }
190
+
162
191
  before do
163
- subject.stub(:listening? => false, :file_building? => false)
164
- it { should be_false }
192
+ subject.instance_variable_set(:@packet_writer, packet_writer)
165
193
  end
194
+
195
+ specify { subject.send(:start_packet_writer).should == packet_writer }
166
196
  end
167
197
  end
168
198
 
169
- describe "#stop" do
170
- it "calls #stop_listener" do
171
- subject.should_receive(:stop_listener)
172
- subject.stop
199
+ describe "#init_socket" do
200
+ let(:udp_server) do
201
+ double "UDPSocket", setsockopt: nil
173
202
  end
174
203
 
175
- it "calls #write_buffer_to_file" do
176
- subject.should_receive(:write_buffer_to_file)
177
- subject.stop
204
+ let(:tcp_server) do
205
+ double "TCPServer", setsockopt: nil
178
206
  end
179
- end
180
-
181
- describe "#start_listener" do
182
- let(:listener) do
183
- l = double "@listener"
184
- l.stub(:abort_on_exception=)
185
207
 
186
- l
187
- end
208
+ context "UDP" do
209
+ before do
210
+ UDPSocket.should_receive(:open).and_return udp_server
211
+ end
188
212
 
189
- context "#listening? is true" do
190
- before { subject.stub(:listening?).and_return true }
213
+ it "returns a UDPSocket" do
214
+ udp_server.should_receive(:bind).with('0.0.0.0', 1234)
215
+ subject.send(:init_socket, :UDP, 1234, '0.0.0.0').should == udp_server
216
+ end
191
217
 
192
- it "returns @listener" do
193
- subject.instance_variable_set(:@listener, listener)
194
- subject.start_listener.should equal listener
218
+ it "sets socket options to get the timestamp" do
219
+ udp_server.stub(:bind)
220
+ subject.should_receive(:set_socket_time_options).with(udp_server)
221
+ subject.send(:init_socket, :UDP, 1234, '0.0.0.0')
195
222
  end
196
223
  end
197
224
 
198
- context "#listening? is false" do
199
- before { subject.stub(:listening?).and_return false }
200
-
201
- it "starts a new Thread and assigns that to @listener" do
202
- Thread.should_receive(:start).and_return listener
203
- subject.start_listener
204
- subject.instance_variable_get(:@listener).should equal listener
225
+ context "TCP" do
226
+ before do
227
+ TCPServer.should_receive(:new).with('0.0.0.0', 1234).and_return tcp_server
205
228
  end
206
229
 
207
- it "initializes the server socket" do
208
- subject.instance_variable_set(:@listener, listener)
209
- Thread.stub(:start).and_yield.and_return listener
210
- subject.should_receive(:init_server)
211
- subject.stub(:loop)
212
-
213
- subject.start_listener
230
+ it "returns a TCPServer" do
231
+ subject.send(:init_socket, :TCP, 1234, '0.0.0.0').should == tcp_server
232
+ end
233
+ end
214
234
 
215
- Thread.unstub(:start)
235
+ context "not UDP or TCP" do
236
+ it "raises an RTP::Error" do
237
+ expect {
238
+ subject.send(:init_socket, :BOBO, 1234, '1.2.3.4')
239
+ }.to raise_error RTP::Error
216
240
  end
241
+ end
217
242
 
218
- let!(:data) do
219
- d = double "data"
220
- d.stub(:size)
243
+ context "multicast" do
244
+ context "multicast_address given" do
245
+ pending
246
+ end
221
247
 
222
- d
248
+ context "multicast_address not given" do
249
+ pending
223
250
  end
251
+ end
252
+ end
224
253
 
225
- let!(:timestamp) { double "timestamp" }
254
+ describe "#multicast?" do
255
+ context "is not multicast" do
256
+ specify { subject.should_not be_multicast }
257
+ end
226
258
 
227
- let(:message) do
228
- m = double "msg"
229
- m.stub(:first).and_return data
230
- m.stub_chain(:last, :timestamp).and_return timestamp
259
+ context "is multicast 224.0.0.0" do
260
+ subject { RTP::Receiver.new(ip_address: '224.0.0.0') }
261
+ specify { subject.should be_multicast }
262
+ end
231
263
 
232
- m
233
- end
264
+ context "is multicast 239.255.255.255" do
265
+ subject { RTP::Receiver.new(ip_address: '239.255.255.255') }
266
+ specify { subject.should be_multicast }
267
+ end
268
+ end
234
269
 
235
- let(:server) do
236
- double "Server"
237
- end
270
+ describe "#start_listener" do
271
+ let(:listener) do
272
+ l = double "Thread"
273
+ l.stub(:abort_on_exception=)
238
274
 
239
- it "receives data from the client and hands it to RTP::Packet to read" do
240
- subject.instance_variable_set(:@listener, listener)
241
- Thread.stub(:start).and_yield.and_return listener
242
- server.should_receive(:recvmsg_nonblock).with(1500).and_return message
243
- subject.should_receive(:init_server).and_return server
244
- packet = double "RTP::Packet"
245
- packet.stub_chain(:[], :size)
246
- packet.stub_chain(:[], :to_i).and_return(10)
247
- RTP::Packet.should_receive(:read).with(data).and_return packet
248
- subject.stub(:write_buffer_to_file)
249
- subject.stub(:loop).and_yield
275
+ l
276
+ end
250
277
 
251
- subject.start_listener
278
+ let(:data) do
279
+ d = double "data"
280
+ d.stub(:size)
252
281
 
253
- Thread.unstub(:start)
254
- end
282
+ d
283
+ end
255
284
 
256
- it "extracts the timestamp of the received data and adds it to @packet_timestamps" do
257
- pending
258
- end
285
+ let(:timestamp) { double "timestamp" }
259
286
 
260
- context "@strip_headers is false" do
261
- it "adds the incoming data to @payload_data buffer" do
262
- subject.instance_variable_set(:@listener, listener)
263
- Thread.stub(:start).and_yield.and_return listener
264
- server.should_receive(:recvmsg_nonblock).with(1500).and_return message
265
- subject.should_receive(:init_server).and_return server
266
- packet = double "RTP::Packet"
267
- packet.stub_chain(:[], :size)
268
- packet.stub_chain(:[], :to_i).and_return(0)
269
- RTP::Packet.stub(:read).and_return packet
270
- subject.stub(:write_buffer_to_file)
271
- subject.stub(:loop).and_yield
272
-
273
- subject.start_listener
274
- subject.instance_variable_get(:@payload_data).should == [data]
275
- Thread.unstub(:start)
276
- end
277
- end
287
+ let(:message) do
288
+ m = double "msg"
289
+ m.stub(:first).and_return data
290
+ m.stub_chain(:last, :timestamp).and_return timestamp
278
291
 
279
- context "@strip_headers is true" do
280
- it "adds the stripped data to @payload_data buffer" do
281
- subject.instance_variable_set(:@listener, listener)
282
- subject.instance_variable_set(:@strip_headers, true)
283
- Thread.stub(:start).and_yield.and_return listener
284
- server.should_receive(:recvmsg_nonblock).with(1500).and_return message
285
- subject.should_receive(:init_server).and_return server
286
- packet = double "RTP::Packet"
287
- packet.should_receive(:[]).with("rtp_payload").twice.and_return("payload_data")
288
- packet.should_receive(:[]).with("sequence_number").exactly(3).times.and_return("0")
289
- RTP::Packet.stub(:read).and_return packet
290
- subject.stub(:write_buffer_to_file)
291
- subject.stub(:loop).and_yield
292
-
293
- subject.start_listener
294
- subject.instance_variable_get(:@payload_data).should == ["payload_data"]
295
- Thread.unstub(:start)
296
- end
297
- end
292
+ m
298
293
  end
299
- end
300
294
 
301
- describe "#write_buffer_to_file" do
302
- before do
303
- sequence_list = [54322, 54323, 54320, 54324, 54325, 54321]
304
- data = []
295
+ let(:socket) do
296
+ double "Socket", recvmsg: message
297
+ end
305
298
 
306
- sequence_list.each do |sequence|
307
- data[sequence] = "data#{sequence}"
308
- end
299
+ it "starts a new Thread and returns that" do
300
+ Thread.should_receive(:start).with(socket).and_return listener
301
+ subject.send(:start_listener, socket).should == listener
302
+ end
309
303
 
310
- subject.instance_variable_set(:@sequence_list, sequence_list)
311
- subject.instance_variable_set(:@payload_data, data)
312
- end
304
+ it "receives data from the client" do
305
+ Thread.stub(:start).and_yield
306
+ subject.stub(:loop).and_yield
313
307
 
314
- it "sorts the buffer and writes to file" do
315
- output = StringIO.new
316
- expected_output = "data54320data54321data54322data54323data54324data54325"
317
- subject.instance_variable_set(:@rtp_file, output)
318
- subject.write_buffer_to_file
319
- output.string.should == expected_output
320
- end
308
+ socket.should_receive(:recvmsg).with(1500).and_return message
321
309
 
322
- it "clears the sequence list after writing to file" do
323
- output = StringIO.new
324
- subject.instance_variable_set(:@rtp_file, output)
325
- subject.write_buffer_to_file
326
- subject.instance_variable_get(:@sequence_list).should == []
327
- end
310
+ subject.send(:start_listener, socket)
328
311
 
329
- it "clears the data buffer after writing to file" do
330
- output = StringIO.new
331
- subject.instance_variable_set(:@rtp_file, output)
332
- subject.write_buffer_to_file
333
- subject.instance_variable_get(:@payload_data).should == []
334
- end
312
+ Thread.unstub(:start)
335
313
  end
336
314
 
315
+ it "extracts the timestamp of the received data and adds it to @packet_timestamps" do
316
+ pending
317
+ end
318
+ end
319
+
337
320
  describe "#stop_listener" do
338
321
  let(:listener) { double "@listener" }
339
322
 
340
- it "sets @listener to nil" do
341
- local_listener = "test"
342
- subject.stub(:listening?).and_return false
343
- subject.instance_variable_set(:@listener, local_listener)
344
- subject.stop_listener
345
- subject.instance_variable_get(:@listener)
323
+ before do
324
+ subject.instance_variable_set(:@listener, listener)
346
325
  end
347
326
 
348
- context "#listeining? is false" do
349
- before { subject.stub(:listening?).and_return false }
327
+ context "listening" do
328
+ before { subject.stub(:listening?).and_return true }
350
329
 
351
- it "doesn't get #kill called on it" do
352
- listener.should_not_receive(:kill)
353
- subject.instance_variable_set(:@listener, listener)
354
- subject.stop_listener
330
+ it "kills the listener and resets it" do
331
+ listener.should_receive(:kill)
332
+ subject.send(:stop_listener)
333
+ subject.instance_variable_get(:@listener).should be_nil
355
334
  end
356
335
  end
357
336
 
358
- context "#listening? is true" do
359
- before { subject.stub(:listening?).and_return true }
337
+ context "not listening" do
338
+ before { subject.stub(:listening?).and_return false }
360
339
 
361
- it "gets killed" do
362
- listener.should_receive(:kill)
363
- subject.instance_variable_set(:@listener, listener)
364
- subject.stop_listener
340
+ it "listener doesn't get killed but is reset" do
341
+ listener.should_not_receive(:kill)
342
+ subject.send(:stop_listener)
343
+ subject.instance_variable_get(:@listener).should be_nil
365
344
  end
366
345
  end
367
346
  end
368
- end
347
+
348
+ describe "#stop_packet_writer" do
349
+ pending
350
+ end
351
+ end