sdp 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +3 -0
- data/.infinity_test +4 -0
- data/.rspec +3 -0
- data/.yardopts +1 -0
- data/ChangeLog.rdoc +7 -0
- data/Gemfile +16 -0
- data/Gemfile.lock +111 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +141 -0
- data/Rakefile +39 -0
- data/features/sdp_create.feature +15 -0
- data/features/sdp_get.feature +35 -0
- data/features/step_definitions/sdp_create_steps.rb +46 -0
- data/features/step_definitions/sdp_get_steps.rb +23 -0
- data/features/support/env.rb +3 -0
- data/features/support/sdp_file.txt +12 -0
- data/gemspec.yml +15 -0
- data/lib/sdp/description.rb +172 -0
- data/lib/sdp/parser.rb +116 -0
- data/lib/sdp/session_template.erb +41 -0
- data/lib/sdp/version.rb +4 -0
- data/lib/sdp.rb +23 -0
- data/sdp.gemspec +114 -0
- data/spec/sdp/description_spec.rb +370 -0
- data/spec/sdp/parser_spec.rb +167 -0
- data/spec/sdp_spec.rb +181 -0
- data/spec/spec_helper.rb +3 -0
- data/tasks/metrics.rake +25 -0
- data/tasks/roodi_config.yml +14 -0
- data/tasks/stats.rake +13 -0
- metadata +143 -0
data/lib/sdp/parser.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
require 'sdp'
|
2
|
+
require 'parslet'
|
3
|
+
|
4
|
+
# Class for parsing SDP description text, ideally when receiving as some sort
|
5
|
+
# of client that uses SDP for describing the session for that protocol.
|
6
|
+
#
|
7
|
+
# This parser _could_ raise an error when not finding a required SDP field, but
|
8
|
+
# was instead designed to not do so. For example, if the parser parses the
|
9
|
+
# text from an SDP description, and that text is missing the Timing field (t=),
|
10
|
+
# the RFC 4566 implies that this description isn't valid (because that field is
|
11
|
+
# required). Instead ofraising an exception, the parser lets the
|
12
|
+
# SDP::Description class deal with this.
|
13
|
+
class SDP::Parser < Parslet::Parser
|
14
|
+
# All of the fields
|
15
|
+
rule(:version) { str('v=') >> field_value.as(:protocol_version) >> eol }
|
16
|
+
|
17
|
+
rule(:origin) do
|
18
|
+
str('o=') >> field_value.as(:username) >> space >>
|
19
|
+
field_value.as(:id) >> space >>
|
20
|
+
field_value.as(:version) >> space >>
|
21
|
+
field_value.as(:network_type) >> space >>
|
22
|
+
field_value.as(:address_type) >> space >>
|
23
|
+
field_value.as(:unicast_address) >> eol
|
24
|
+
end
|
25
|
+
|
26
|
+
rule(:session_name) { str('s=') >> field_value_string.as(:name) >> eol }
|
27
|
+
|
28
|
+
rule(:session_information) do
|
29
|
+
str('i=') >> field_value_string.as(:information) >> eol
|
30
|
+
end
|
31
|
+
|
32
|
+
rule(:uri) { str('u=') >> field_value.as(:uri) >> eol }
|
33
|
+
|
34
|
+
rule(:email_address) do
|
35
|
+
str('e=') >> field_value_string.as(:email_address) >> eol
|
36
|
+
end
|
37
|
+
|
38
|
+
rule(:phone_number) do
|
39
|
+
str('p=') >> field_value_string.as(:phone_number) >> eol
|
40
|
+
end
|
41
|
+
|
42
|
+
rule(:connection_data) do
|
43
|
+
str('c=') >> field_value >> space >> field_value >> space >>
|
44
|
+
field_value.as(:connection_address) >> eol
|
45
|
+
end
|
46
|
+
|
47
|
+
rule(:bandwidth) do
|
48
|
+
str('b=') >> match('[\w]').repeat(2).as(:bandwidth_type) >> str(':') >>
|
49
|
+
field_value.as(:bandwidth) >> eol
|
50
|
+
end
|
51
|
+
|
52
|
+
rule(:timing) do
|
53
|
+
str('t=') >> field_value.as(:start_time) >> space >>
|
54
|
+
field_value.as(:stop_time) >> eol
|
55
|
+
end
|
56
|
+
|
57
|
+
rule(:repeat_times) do
|
58
|
+
str('r=') >> field_value.as(:repeat_interval) >> space >>
|
59
|
+
field_value.as(:active_duration) >>
|
60
|
+
space >> field_value_string.as(:offsets_from_start_time) >> eol
|
61
|
+
end
|
62
|
+
|
63
|
+
rule(:time_zone_group) do
|
64
|
+
field_value.as(:adjustment_time) >> space >> field_value.as(:offset)
|
65
|
+
end
|
66
|
+
|
67
|
+
rule(:time_zones) do
|
68
|
+
str('z=') >> (time_zone_group >>
|
69
|
+
(space >> time_zone_group).repeat).as(:time_zones) >> eol
|
70
|
+
end
|
71
|
+
|
72
|
+
rule(:encryption_keys) do
|
73
|
+
str('k=') >> match('[\w]').repeat.as(:encryption_method) >>
|
74
|
+
(str(':') >> field_value.as(:encryption_key)).maybe >> eol
|
75
|
+
end
|
76
|
+
|
77
|
+
rule(:attribute) do
|
78
|
+
str('a=') >> match('[\w]').repeat(1).as(:attribute) >>
|
79
|
+
(str(':') >> field_value_string.as(:value)).maybe >> eol
|
80
|
+
end
|
81
|
+
|
82
|
+
rule(:attributes) { attribute.repeat(1).as(:attributes) }
|
83
|
+
|
84
|
+
rule(:media_description) do
|
85
|
+
str('m=') >> field_value.as(:media) >> space >>
|
86
|
+
field_value.as(:port) >> space >>
|
87
|
+
field_value.as(:protocol) >> space >>
|
88
|
+
field_value.as(:format) >> eol
|
89
|
+
end
|
90
|
+
|
91
|
+
# Generics
|
92
|
+
rule(:space) { match('[ ]').repeat(1) }
|
93
|
+
rule(:eol) { match('[\r]').maybe >> match('[\n]') }
|
94
|
+
rule(:field_value) { match('\S').repeat }
|
95
|
+
rule(:field_value_string) { match('[^\r\n]').repeat }
|
96
|
+
|
97
|
+
# The SDP description
|
98
|
+
rule(:session_section) do
|
99
|
+
version.maybe >> origin.maybe >> session_name.maybe >>
|
100
|
+
session_information.maybe >> uri.maybe >> email_address.maybe >>
|
101
|
+
phone_number.maybe >> connection_data.maybe >> bandwidth.maybe >>
|
102
|
+
timing.maybe >> repeat_times.maybe >> time_zones.maybe >>
|
103
|
+
encryption_keys.maybe >> attributes.maybe
|
104
|
+
end
|
105
|
+
|
106
|
+
rule(:media_section) do
|
107
|
+
media_description >> attributes.maybe
|
108
|
+
end
|
109
|
+
|
110
|
+
rule(:description) do
|
111
|
+
session_section.as(:session_section) >>
|
112
|
+
media_section.repeat.as(:media_sections)
|
113
|
+
end
|
114
|
+
|
115
|
+
root :description
|
116
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
<%# -*- coding: UTF-8 -*- %>
|
2
|
+
v=<%= protocol_version %>
|
3
|
+
o=<%= username %> <%= id %> <%= version %> <%= network_type %> <%= address_type %> <%= unicast_address %>
|
4
|
+
s=<%= name %>
|
5
|
+
<% if information %>
|
6
|
+
i=<%= information %>
|
7
|
+
<% end %>
|
8
|
+
<% if uri %>
|
9
|
+
u=<%= uri %>
|
10
|
+
<% end %>
|
11
|
+
<% if email_address %>
|
12
|
+
e=<%= email_address %>
|
13
|
+
<% end %>
|
14
|
+
<% if phone_number %>
|
15
|
+
p=<%= phone_number %>
|
16
|
+
<% end %>
|
17
|
+
c=<%= network_type %> <%= address_type %> <%= connection_address %>
|
18
|
+
<% if bandwidth %>
|
19
|
+
b=<%= bandwidth_type %>:<%= bandwidth %>
|
20
|
+
<% end %>
|
21
|
+
t=<%= start_time %> <%= stop_time %>
|
22
|
+
<% if repeat_interval %>
|
23
|
+
r=<%= repeat_interval %> <%= active_duration %> <%= offsets_from_start_time %>
|
24
|
+
<% end %>
|
25
|
+
<% unless time_zones.empty? %>
|
26
|
+
<% if time_zones.class == Array %>
|
27
|
+
z=<% time_zones.each do |time_zone| %><%= time_zone[:adjustment_time] %> <%= time_zone[:offset] %><% end %>
|
28
|
+
<% else %>
|
29
|
+
z=<%= time_zones[:adjustment_time] %> <%= time_zones[:offset] %><% end %>
|
30
|
+
<% end %>
|
31
|
+
<% if encryption_method %>
|
32
|
+
k=<%= encryption_method %><% if encryption_key %>:<%= encryption_key %><% end %>
|
33
|
+
<% end %>
|
34
|
+
<% unless attributes.empty? %>
|
35
|
+
a=<% attributes.each do |a| %><%= a[:attribute] %><% if a[:value] %>:<%= a[:value] %><% end %><% end %>
|
36
|
+
<% end %>
|
37
|
+
<% media_sections.each do |media_section| %>
|
38
|
+
m=<%= media_section[:media] %> <%= media_section[:port]%> <%= media_section[:protocol]%> <%= media_section[:format]%>
|
39
|
+
<% if media_section[:attributes] %>
|
40
|
+
<% media_section[:attributes].each do |attribute| %>
|
41
|
+
a=<%= attribute[:attribute] %><% if attribute[:value] %>:<%= attribute[:value] %><% end %><% end %><% end %><% end %>
|
data/lib/sdp/version.rb
ADDED
data/lib/sdp.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'sdp/version'
|
2
|
+
require 'sdp/description'
|
3
|
+
require 'sdp/parser'
|
4
|
+
|
5
|
+
# The only use for this class is the #parse method, which is in this
|
6
|
+
# base class solely for convenience. Other than this method, this
|
7
|
+
# base class doesn't really do anything.
|
8
|
+
class SDP
|
9
|
+
|
10
|
+
# Creates a parser and parses the given text in to an SDP::Description
|
11
|
+
# object.
|
12
|
+
#
|
13
|
+
# @param [String] sdp_text The text from an SDP description.
|
14
|
+
# @return [SDP::Description] The object that represents the description
|
15
|
+
# that was parsed.
|
16
|
+
def self.parse sdp_text
|
17
|
+
sdp_hash = SDP::Parser.new.parse sdp_text
|
18
|
+
SDP::Description.new(sdp_hash)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Reclass so we can raise our own Exceptions.
|
23
|
+
class SDP::RuntimeError < StandardError; end;
|
data/sdp.gemspec
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{sdp}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.3.6") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["sloveless"]
|
12
|
+
s.date = %q{2011-01-22}
|
13
|
+
s.description = %q{This gem allows for parsing SDP (Session Description Protocol) information in to a Ruby object, making it easy to read and work with that data. It also allows for easily creating SDP objects that can be converted to text using #to_s.}
|
14
|
+
s.email = %q{steve.loveless@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"ChangeLog.rdoc",
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.rdoc"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".document",
|
22
|
+
".infinity_test",
|
23
|
+
".rspec",
|
24
|
+
".yardopts",
|
25
|
+
"ChangeLog.rdoc",
|
26
|
+
"Gemfile",
|
27
|
+
"Gemfile.lock",
|
28
|
+
"LICENSE.txt",
|
29
|
+
"README.rdoc",
|
30
|
+
"Rakefile",
|
31
|
+
"features/sdp_create.feature",
|
32
|
+
"features/sdp_get.feature",
|
33
|
+
"features/step_definitions/sdp_create_steps.rb",
|
34
|
+
"features/step_definitions/sdp_get_steps.rb",
|
35
|
+
"features/support/env.rb",
|
36
|
+
"features/support/sdp_file.txt",
|
37
|
+
"gemspec.yml",
|
38
|
+
"lib/sdp.rb",
|
39
|
+
"lib/sdp/description.rb",
|
40
|
+
"lib/sdp/parser.rb",
|
41
|
+
"lib/sdp/session_template.erb",
|
42
|
+
"lib/sdp/version.rb",
|
43
|
+
"sdp.gemspec",
|
44
|
+
"spec/sdp/description_spec.rb",
|
45
|
+
"spec/sdp/parser_spec.rb",
|
46
|
+
"spec/sdp_spec.rb",
|
47
|
+
"spec/spec_helper.rb",
|
48
|
+
"tasks/metrics.rake",
|
49
|
+
"tasks/roodi_config.yml",
|
50
|
+
"tasks/stats.rake"
|
51
|
+
]
|
52
|
+
s.has_rdoc = %q{yard}
|
53
|
+
s.homepage = %q{http://rubygems.org/gems/sdp}
|
54
|
+
s.licenses = ["MIT"]
|
55
|
+
s.require_paths = ["lib"]
|
56
|
+
s.rubyforge_project = %q{sdp}
|
57
|
+
s.rubygems_version = %q{1.3.7}
|
58
|
+
s.summary = %q{Parse and create SDP (Session Description Protocol) text based on RFC4566.}
|
59
|
+
s.test_files = [
|
60
|
+
"spec/sdp/description_spec.rb",
|
61
|
+
"spec/sdp/parser_spec.rb",
|
62
|
+
"spec/sdp_spec.rb"
|
63
|
+
]
|
64
|
+
|
65
|
+
if s.respond_to? :specification_version then
|
66
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_runtime_dependency(%q<parslet>, ["~> 1.0.0"])
|
71
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
72
|
+
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
73
|
+
s.add_runtime_dependency(%q<parslet>, ["~> 1.0.0"])
|
74
|
+
s.add_development_dependency(%q<rake>, ["~> 0.8.7"])
|
75
|
+
s.add_development_dependency(%q<ore-core>, ["~> 0.1.0"])
|
76
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.5.0"])
|
77
|
+
s.add_development_dependency(%q<ore-tasks>, ["~> 0.3.0"])
|
78
|
+
s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
|
79
|
+
s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
|
80
|
+
s.add_development_dependency(%q<infinity_test>, [">= 0"])
|
81
|
+
s.add_development_dependency(%q<metric_fu>, [">= 0"])
|
82
|
+
s.add_development_dependency(%q<code_statistics>, ["~> 0.2.13"])
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<parslet>, ["~> 1.0.0"])
|
85
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
86
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
87
|
+
s.add_dependency(%q<parslet>, ["~> 1.0.0"])
|
88
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
89
|
+
s.add_dependency(%q<ore-core>, ["~> 0.1.0"])
|
90
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
|
91
|
+
s.add_dependency(%q<ore-tasks>, ["~> 0.3.0"])
|
92
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
93
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
94
|
+
s.add_dependency(%q<infinity_test>, [">= 0"])
|
95
|
+
s.add_dependency(%q<metric_fu>, [">= 0"])
|
96
|
+
s.add_dependency(%q<code_statistics>, ["~> 0.2.13"])
|
97
|
+
end
|
98
|
+
else
|
99
|
+
s.add_dependency(%q<parslet>, ["~> 1.0.0"])
|
100
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
101
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
102
|
+
s.add_dependency(%q<parslet>, ["~> 1.0.0"])
|
103
|
+
s.add_dependency(%q<rake>, ["~> 0.8.7"])
|
104
|
+
s.add_dependency(%q<ore-core>, ["~> 0.1.0"])
|
105
|
+
s.add_dependency(%q<jeweler>, ["~> 1.5.0"])
|
106
|
+
s.add_dependency(%q<ore-tasks>, ["~> 0.3.0"])
|
107
|
+
s.add_dependency(%q<rspec>, ["~> 2.3.0"])
|
108
|
+
s.add_dependency(%q<yard>, ["~> 0.6.0"])
|
109
|
+
s.add_dependency(%q<infinity_test>, [">= 0"])
|
110
|
+
s.add_dependency(%q<metric_fu>, [">= 0"])
|
111
|
+
s.add_dependency(%q<code_statistics>, ["~> 0.2.13"])
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
@@ -0,0 +1,370 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'sdp/description'
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
describe SDP::Description do
|
6
|
+
before :each do
|
7
|
+
@sdp = SDP::Description.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "initializes with the protocol_version value set" do
|
11
|
+
@sdp.protocol_version.should == SDP::PROTOCOL_VERSION
|
12
|
+
end
|
13
|
+
|
14
|
+
context "can add and retrieve fields" do
|
15
|
+
it "protocol_version" do
|
16
|
+
@sdp.protocol_version = 1
|
17
|
+
@sdp.protocol_version.should == 1
|
18
|
+
end
|
19
|
+
|
20
|
+
it "username" do
|
21
|
+
@sdp.username = "jdoe"
|
22
|
+
@sdp.username.should == "jdoe"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "id" do
|
26
|
+
@sdp.id = 2890844526
|
27
|
+
@sdp.id.should == 2890844526
|
28
|
+
end
|
29
|
+
|
30
|
+
it "version" do
|
31
|
+
@sdp.version = 2890842807
|
32
|
+
@sdp.version.should == 2890842807
|
33
|
+
end
|
34
|
+
|
35
|
+
it "network_type" do
|
36
|
+
@sdp.network_type = :IN
|
37
|
+
@sdp.network_type.should == :IN
|
38
|
+
end
|
39
|
+
|
40
|
+
it "address_type" do
|
41
|
+
@sdp.address_type = :IP4
|
42
|
+
@sdp.address_type.should == :IP4
|
43
|
+
end
|
44
|
+
|
45
|
+
it "unicast_address" do
|
46
|
+
@sdp.unicast_address = "10.47.16.5"
|
47
|
+
@sdp.unicast_address.should == "10.47.16.5"
|
48
|
+
end
|
49
|
+
|
50
|
+
it "name" do
|
51
|
+
@sdp.name = "This is a session"
|
52
|
+
@sdp.name.should == "This is a session"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "name can be a ' '" do
|
56
|
+
@sdp.name = " "
|
57
|
+
@sdp.name.should == " "
|
58
|
+
end
|
59
|
+
|
60
|
+
it "information" do
|
61
|
+
@sdp.information = "This is a session"
|
62
|
+
@sdp.information.should == "This is a session"
|
63
|
+
end
|
64
|
+
|
65
|
+
it "uri" do
|
66
|
+
@sdp.uri = "http://localhost"
|
67
|
+
@sdp.uri.should == "http://localhost"
|
68
|
+
end
|
69
|
+
|
70
|
+
it "email_address" do
|
71
|
+
@sdp.email_address = 'me@me.com'
|
72
|
+
@sdp.email_address.should == 'me@me.com'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "email_address in alternate form" do
|
76
|
+
@sdp.email_address = "Jane Doe <j.doe@example.com>"
|
77
|
+
@sdp.email_address.should == "Jane Doe <j.doe@example.com>"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "phone_number" do
|
81
|
+
@sdp.phone_number = "+1 555 123 4567"
|
82
|
+
@sdp.phone_number.should == "+1 555 123 4567"
|
83
|
+
end
|
84
|
+
|
85
|
+
it "connection_address" do
|
86
|
+
@sdp.connection_address = 'localhost'
|
87
|
+
@sdp.connection_address.should == 'localhost'
|
88
|
+
end
|
89
|
+
|
90
|
+
it "connection_address using TTL" do
|
91
|
+
@sdp.connection_address = "224.2.36.42/127"
|
92
|
+
@sdp.connection_address.should == "224.2.36.42/127"
|
93
|
+
end
|
94
|
+
|
95
|
+
it "connection_address using IPv6 address and count" do
|
96
|
+
@sdp.connection_address = "FF15::101/3"
|
97
|
+
@sdp.connection_address.should == "FF15::101/3"
|
98
|
+
end
|
99
|
+
|
100
|
+
it "bandwidth_type" do
|
101
|
+
@sdp.bandwidth = :CT
|
102
|
+
@sdp.bandwidth.should == :CT
|
103
|
+
end
|
104
|
+
|
105
|
+
it "bandwidth" do
|
106
|
+
@sdp.bandwidth = 100
|
107
|
+
@sdp.bandwidth.should == 100
|
108
|
+
end
|
109
|
+
|
110
|
+
it "start_time" do
|
111
|
+
@sdp.start_time = 99112299
|
112
|
+
@sdp.start_time.should == 99112299
|
113
|
+
end
|
114
|
+
|
115
|
+
it "stop_time" do
|
116
|
+
@sdp.stop_time = 99999999
|
117
|
+
@sdp.stop_time.should == 99999999
|
118
|
+
end
|
119
|
+
|
120
|
+
it "repeat_interval" do
|
121
|
+
@sdp.repeat_interval = 12345
|
122
|
+
@sdp.repeat_interval.should == 12345
|
123
|
+
end
|
124
|
+
|
125
|
+
it "active_duration" do
|
126
|
+
@sdp.active_duration = 12345
|
127
|
+
@sdp.active_duration.should == 12345
|
128
|
+
end
|
129
|
+
|
130
|
+
it "offsets_from_start_time" do
|
131
|
+
@sdp.offsets_from_start_time = 99
|
132
|
+
@sdp.offsets_from_start_time.should == 99
|
133
|
+
end
|
134
|
+
|
135
|
+
context "time_zones" do
|
136
|
+
it "one time zone" do
|
137
|
+
new_values = { :adjustment_time => 111111,
|
138
|
+
:offset => 99 }
|
139
|
+
@sdp.time_zones << new_values
|
140
|
+
@sdp.time_zones.should == [new_values]
|
141
|
+
end
|
142
|
+
|
143
|
+
it "two time_zones" do
|
144
|
+
new_values1 = { :adjustment_time => 111111,
|
145
|
+
:offset => 99 }
|
146
|
+
new_values2 = { :adjustment_time => 222222,
|
147
|
+
:offset => 88 }
|
148
|
+
@sdp.time_zones << new_values1
|
149
|
+
@sdp.time_zones << new_values2
|
150
|
+
@sdp.time_zones.should == [new_values1, new_values2]
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "encryption keys" do
|
155
|
+
it "clear" do
|
156
|
+
@sdp.encryption_method = 'clear'
|
157
|
+
@sdp.encryption_method.should == 'clear'
|
158
|
+
@sdp.encryption_key = 'password'
|
159
|
+
@sdp.encryption_key.should == 'password'
|
160
|
+
end
|
161
|
+
|
162
|
+
it "base64" do
|
163
|
+
@sdp.encryption_method = 'base64'
|
164
|
+
@sdp.encryption_method.should == 'base64'
|
165
|
+
enc = Base64.encode64('password')
|
166
|
+
@sdp.encryption_key = enc
|
167
|
+
@sdp.encryption_key.should == enc
|
168
|
+
end
|
169
|
+
|
170
|
+
it "uri" do
|
171
|
+
@sdp.encryption_method = 'uri'
|
172
|
+
@sdp.encryption_method.should == 'uri'
|
173
|
+
uri = "http://aserver.com/thing.pdf"
|
174
|
+
@sdp.encryption_key = uri
|
175
|
+
@sdp.encryption_key.should == uri
|
176
|
+
end
|
177
|
+
|
178
|
+
it "prompt" do
|
179
|
+
@sdp.encryption_method = 'prompt'
|
180
|
+
@sdp.encryption_method.should == 'prompt'
|
181
|
+
@sdp.encryption_key.should be_nil
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context "attributes" do
|
186
|
+
it "one attribute with value" do
|
187
|
+
new_values = { :attribute => 'rtpmap',
|
188
|
+
:value => "99 h263-1998/90000" }
|
189
|
+
@sdp.attributes << new_values
|
190
|
+
@sdp.attributes.first.should == new_values
|
191
|
+
end
|
192
|
+
|
193
|
+
it "one attribute with empty value" do
|
194
|
+
new_values = { :attribute => 'rtpmap',
|
195
|
+
:value => "" }
|
196
|
+
@sdp.attributes << new_values
|
197
|
+
@sdp.attributes.first.should == new_values
|
198
|
+
end
|
199
|
+
|
200
|
+
it "one attribute with nil value" do
|
201
|
+
new_values = { :attribute => 'rtpmap' }
|
202
|
+
@sdp.attributes << new_values
|
203
|
+
@sdp.attributes.first.should == new_values
|
204
|
+
end
|
205
|
+
|
206
|
+
it "two attributes" do
|
207
|
+
new_values1 = { :attribute => 'test' }
|
208
|
+
new_values2 = { :attribute => 'rtpmap',
|
209
|
+
:value => "99 h263-1998/90000" }
|
210
|
+
@sdp.attributes << new_values1
|
211
|
+
@sdp.attributes << new_values2
|
212
|
+
@sdp.attributes.should == [new_values1, new_values2]
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context "media_sections" do
|
217
|
+
it "can add a basic media section" do
|
218
|
+
new_values = { :media => 'audio',
|
219
|
+
:port => 12345,
|
220
|
+
:protocol => 'RTP/AVP',
|
221
|
+
:format => 99 }
|
222
|
+
@sdp.media_sections << new_values
|
223
|
+
@sdp.media_sections.first.should == new_values
|
224
|
+
end
|
225
|
+
|
226
|
+
it "can add a basic media section with attributes" do
|
227
|
+
new_values = { :media => 'audio',
|
228
|
+
:port => 12345,
|
229
|
+
:protocol => 'RTP/AVP',
|
230
|
+
:format => 99,
|
231
|
+
:attributes => [
|
232
|
+
{
|
233
|
+
:attribute => "rtpmap",
|
234
|
+
:value => "99 h263-1998/90000"
|
235
|
+
}
|
236
|
+
]
|
237
|
+
}
|
238
|
+
@sdp.media_sections << new_values
|
239
|
+
@sdp.media_sections.first.should == new_values
|
240
|
+
end
|
241
|
+
|
242
|
+
it "can add 2 basic media sections" do
|
243
|
+
new_values = []
|
244
|
+
new_values << { :media => 'audio',
|
245
|
+
:port => 12345,
|
246
|
+
:protocol => 'RTP/AVP',
|
247
|
+
:format => 99 }
|
248
|
+
@sdp.media_sections << new_values[0]
|
249
|
+
|
250
|
+
new_values << { :media => 'video',
|
251
|
+
:port => 5678,
|
252
|
+
:protocol => 'RTP/AVP',
|
253
|
+
:format => 33 }
|
254
|
+
@sdp.media_sections << new_values[1]
|
255
|
+
|
256
|
+
@sdp.media_sections.class.should == Array
|
257
|
+
@sdp.media_sections[0].should == new_values[0]
|
258
|
+
@sdp.media_sections[1].should == new_values[1]
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
context "#to_s" do
|
264
|
+
it "contains required session section values" do
|
265
|
+
@sdp.to_s.should match /v=0/
|
266
|
+
@sdp.to_s.should match /o=/
|
267
|
+
@sdp.to_s.should match /s=/
|
268
|
+
@sdp.to_s.should match /t=/
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
context "#valid?" do
|
273
|
+
before :each do
|
274
|
+
@sdp = SDP::Description.new
|
275
|
+
|
276
|
+
@sdp.protocol_version = 0
|
277
|
+
@sdp.username = "jdoe"
|
278
|
+
@sdp.id = 12345
|
279
|
+
@sdp.version = 12345
|
280
|
+
@sdp.network_type = :IN
|
281
|
+
@sdp.address_type = :IP4
|
282
|
+
@sdp.unicast_address = "127.0.0.1"
|
283
|
+
@sdp.name = "This is a test"
|
284
|
+
@sdp.start_time = 12345678
|
285
|
+
@sdp.stop_time = 12345680
|
286
|
+
@sdp.media_sections << { :media => "audio", :port => 123,
|
287
|
+
:protocol => "RTP/AVP", :format => 99 }
|
288
|
+
end
|
289
|
+
|
290
|
+
it "is valid when all required fields have values" do
|
291
|
+
@sdp.valid?.should be_true
|
292
|
+
end
|
293
|
+
|
294
|
+
it "is NOT valid when protocol_version isn't set" do
|
295
|
+
@sdp.protocol_version = nil
|
296
|
+
@sdp.valid?.should be_false
|
297
|
+
end
|
298
|
+
|
299
|
+
it "is NOT valid when username isn't set" do
|
300
|
+
@sdp.username = nil
|
301
|
+
@sdp.valid?.should be_false
|
302
|
+
end
|
303
|
+
|
304
|
+
it "is NOT valid when id isn't set" do
|
305
|
+
@sdp.id = nil
|
306
|
+
@sdp.valid?.should be_false
|
307
|
+
end
|
308
|
+
|
309
|
+
it "is NOT valid when version isn't set" do
|
310
|
+
@sdp.version = nil
|
311
|
+
@sdp.valid?.should be_false
|
312
|
+
end
|
313
|
+
|
314
|
+
it "is NOT valid when network_type isn't set" do
|
315
|
+
@sdp.network_type = nil
|
316
|
+
@sdp.valid?.should be_false
|
317
|
+
end
|
318
|
+
|
319
|
+
it "is NOT valid when address_type isn't set" do
|
320
|
+
@sdp.address_type = nil
|
321
|
+
@sdp.valid?.should be_false
|
322
|
+
end
|
323
|
+
|
324
|
+
it "is NOT valid when unicast_address isn't set" do
|
325
|
+
@sdp.unicast_address = nil
|
326
|
+
@sdp.valid?.should be_false
|
327
|
+
end
|
328
|
+
|
329
|
+
it "is NOT valid when name isn't set" do
|
330
|
+
@sdp.name = nil
|
331
|
+
@sdp.valid?.should be_false
|
332
|
+
end
|
333
|
+
|
334
|
+
it "is valid when name is ' '" do
|
335
|
+
@sdp.name = ' '
|
336
|
+
@sdp.valid?.should be_true
|
337
|
+
end
|
338
|
+
|
339
|
+
it "is NOT valid when start_time isn't set" do
|
340
|
+
@sdp.start_time = nil
|
341
|
+
@sdp.valid?.should be_false
|
342
|
+
end
|
343
|
+
|
344
|
+
it "is NOT valid when stop_time isn't set" do
|
345
|
+
@sdp.stop_time = nil
|
346
|
+
@sdp.valid?.should be_false
|
347
|
+
end
|
348
|
+
|
349
|
+
it "is NOT valid when media_sections is empty" do
|
350
|
+
@sdp[:media_sections] = []
|
351
|
+
@sdp.valid?.should be_false
|
352
|
+
end
|
353
|
+
end
|
354
|
+
|
355
|
+
context "bad initialize values" do
|
356
|
+
it "ensures a Hash is passed in" do
|
357
|
+
lambda do
|
358
|
+
SDP::Description.new 1
|
359
|
+
end.should raise_error SDP::RuntimeError
|
360
|
+
end
|
361
|
+
|
362
|
+
it "handles a Hash with irrelvant keys" do
|
363
|
+
session_values = { :bobo => "thing" }
|
364
|
+
|
365
|
+
lambda do
|
366
|
+
SDP::Description.new session_values
|
367
|
+
end.should raise_error SDP::RuntimeError
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|