sdp 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.
- 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
|