sipatra 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/sipatra/base.rb +89 -30
- data/lib/sipatra/helpers.rb +129 -104
- data/lib/sipatra/log4j-1.2.16.jar +0 -0
- data/lib/sipatra/sipatra-0.1.0-SNAPSHOT.jar +0 -0
- data/lib/sipatra/slf4j-api-1.6.1.jar +0 -0
- data/lib/sipatra/slf4j-log4j12-1.6.1.jar +0 -0
- data/spec/base_spec.rb +530 -0
- data/spec/classic_style_spec.rb +19 -0
- data/spec/helper.rb +46 -0
- data/spec/helpers_spec.rb +352 -0
- data/spec/sipatra_spec.rb +26 -0
- data/test/integration/sipapp/WEB-INF/sip.xml +14 -0
- data/test/integration/sipapp/WEB-INF/sipatra/application.rb +26 -0
- data/test/integration/sipatra.xml +9 -0
- data/test/integration/sipp/uac.xml +122 -0
- metadata +77 -63
- data/lib/sipatra/sipatra-0.0.3-SNAPSHOT.jar +0 -0
- data/lib/sipatra/slf4j-api-1.4.0.jar +0 -0
- data/lib/sipatra/slf4j-log4j12-1.4.0.jar +0 -0
data/lib/sipatra/base.rb
CHANGED
@@ -7,26 +7,21 @@ module Sipatra
|
|
7
7
|
|
8
8
|
class Base
|
9
9
|
include HelperMethods
|
10
|
-
attr_accessor :sip_factory, :context, :session, :
|
11
|
-
|
10
|
+
attr_accessor :sip_factory, :context, :session, :message, :params, :log
|
11
|
+
alias :request :message
|
12
|
+
alias :response :message
|
13
|
+
|
12
14
|
def initialize()
|
13
|
-
@params = Hash.new {|hash,key| hash[key.to_s] if Symbol === key }
|
15
|
+
@params = Hash.new { |hash,key| hash[key.to_s] if Symbol === key }
|
14
16
|
end
|
15
17
|
|
16
18
|
# called from Java to set SIP servlet bindings
|
17
19
|
def set_bindings(*args)
|
18
|
-
@context, @sip_factory, @session, @
|
20
|
+
@context, @sip_factory, @session, @message, @log = args
|
19
21
|
session.extend Sipatra::SessionExtension
|
20
|
-
|
22
|
+
message.extend Sipatra::MessageExtension
|
21
23
|
end
|
22
|
-
|
23
|
-
def session=(session)
|
24
|
-
@session = session
|
25
|
-
class << @session
|
26
|
-
include SessionExtension
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
24
|
+
|
30
25
|
# called to process a SIP request
|
31
26
|
def do_request
|
32
27
|
call! self.class.req_handlers
|
@@ -36,7 +31,17 @@ module Sipatra
|
|
36
31
|
def do_response
|
37
32
|
call! self.class.resp_handlers
|
38
33
|
end
|
39
|
-
|
34
|
+
|
35
|
+
# Access settings defined with Base.set.
|
36
|
+
def self.settings
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
# Access settings defined with Base.set.
|
41
|
+
def settings
|
42
|
+
self.class.settings
|
43
|
+
end
|
44
|
+
|
40
45
|
# Exit the current block, halts any further processing
|
41
46
|
# of the message.
|
42
47
|
# TODO: handle a response (as param)
|
@@ -50,16 +55,28 @@ module Sipatra
|
|
50
55
|
end
|
51
56
|
|
52
57
|
def request?
|
53
|
-
!
|
58
|
+
!message.respond_to?(:getRequest)
|
54
59
|
end
|
55
60
|
|
56
61
|
def response?
|
57
|
-
|
62
|
+
message.respond_to?(:getRequest)
|
58
63
|
end
|
59
64
|
|
60
65
|
private
|
61
66
|
|
62
|
-
def
|
67
|
+
def session=(session)
|
68
|
+
@session = session
|
69
|
+
class << @session
|
70
|
+
include SessionExtension
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# Retrieve the OUTBOUND_INTERFACES value from cipango.
|
75
|
+
def get_addresses
|
76
|
+
context.getAttribute('javax.servlet.sip.outboundInterfaces')
|
77
|
+
end
|
78
|
+
|
79
|
+
def message_type
|
63
80
|
response? ? :response : :request
|
64
81
|
end
|
65
82
|
|
@@ -75,7 +92,7 @@ module Sipatra
|
|
75
92
|
#clear (for multi usage)
|
76
93
|
@params.clear
|
77
94
|
if request?
|
78
|
-
match = arg.match
|
95
|
+
match = arg.match message.requestURI.to_s
|
79
96
|
if match
|
80
97
|
eval_options(opts)
|
81
98
|
if keys.any?
|
@@ -89,7 +106,7 @@ module Sipatra
|
|
89
106
|
return true
|
90
107
|
end
|
91
108
|
else
|
92
|
-
if ((arg == 0) or (arg ==
|
109
|
+
if ((arg == 0) or (arg == message.status))
|
93
110
|
eval_options(opts)
|
94
111
|
return true
|
95
112
|
end
|
@@ -117,7 +134,7 @@ module Sipatra
|
|
117
134
|
def call!(handlers)
|
118
135
|
filter! :before
|
119
136
|
catch(:halt) do
|
120
|
-
process_handler(handlers,
|
137
|
+
process_handler(handlers, message.method)
|
121
138
|
process_handler(handlers, "_")
|
122
139
|
end
|
123
140
|
ensure
|
@@ -131,7 +148,36 @@ module Sipatra
|
|
131
148
|
def configure(*envs, &block)
|
132
149
|
yield self if envs.empty? || envs.include?(environment.to_sym)
|
133
150
|
end
|
134
|
-
|
151
|
+
|
152
|
+
# Sets an option to the given value. If the value is a proc,
|
153
|
+
# the proc will be called every time the option is accessed.
|
154
|
+
def set(option, value=self, &block)
|
155
|
+
raise ArgumentError if block && value != self
|
156
|
+
value = block if block
|
157
|
+
if value.kind_of?(Proc)
|
158
|
+
metadef(option, &value)
|
159
|
+
metadef("#{option}?") { !!__send__(option) }
|
160
|
+
metadef("#{option}=") { |val| metadef(option, &Proc.new{val}) }
|
161
|
+
elsif value == self && option.respond_to?(:each)
|
162
|
+
option.each { |k,v| set(k, v) }
|
163
|
+
elsif respond_to?("#{option}=")
|
164
|
+
__send__ "#{option}=", value
|
165
|
+
else
|
166
|
+
set option, Proc.new{value}
|
167
|
+
end
|
168
|
+
self
|
169
|
+
end
|
170
|
+
|
171
|
+
# Same as calling `set :option, true` for each of the given options.
|
172
|
+
def enable(*opts)
|
173
|
+
opts.each { |key| set(key, true) }
|
174
|
+
end
|
175
|
+
|
176
|
+
# Same as calling `set :option, false` for each of the given options.
|
177
|
+
def disable(*opts)
|
178
|
+
opts.each { |key| set(key, false) }
|
179
|
+
end
|
180
|
+
|
135
181
|
# Methods defined in the block and/or in the module
|
136
182
|
# arguments available to handlers.
|
137
183
|
def helpers(*modules, &block)
|
@@ -182,12 +228,12 @@ module Sipatra
|
|
182
228
|
end
|
183
229
|
end
|
184
230
|
|
185
|
-
def before(
|
186
|
-
add_filter(:before,
|
231
|
+
def before(message_type = nil, &block)
|
232
|
+
add_filter(:before, message_type, &block)
|
187
233
|
end
|
188
234
|
|
189
|
-
def after(
|
190
|
-
add_filter(:after,
|
235
|
+
def after(message_type = nil, &block)
|
236
|
+
add_filter(:after, message_type, &block)
|
191
237
|
end
|
192
238
|
|
193
239
|
def reset!
|
@@ -210,10 +256,14 @@ module Sipatra
|
|
210
256
|
filters[:after]
|
211
257
|
end
|
212
258
|
|
259
|
+
def invoke_hook(name, *args)
|
260
|
+
extensions.each { |e| e.send(name, *args) if e.respond_to?(name) }
|
261
|
+
end
|
262
|
+
|
213
263
|
private
|
214
264
|
|
215
|
-
def add_filter(type,
|
216
|
-
if
|
265
|
+
def add_filter(type, msg_type = nil, &block)
|
266
|
+
if msg_type
|
217
267
|
add_filter(type) do
|
218
268
|
next unless msg_type == message_type
|
219
269
|
instance_eval(&block)
|
@@ -222,7 +272,15 @@ module Sipatra
|
|
222
272
|
filters[type] << block
|
223
273
|
end
|
224
274
|
end
|
225
|
-
|
275
|
+
|
276
|
+
def metadef(message, &block)
|
277
|
+
(class << self; self; end).
|
278
|
+
send :define_method, message, &block
|
279
|
+
if !['?', '='].include?(message.to_s[-1, 1])
|
280
|
+
invoke_hook(:option_set, self, message)
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
226
284
|
# compiles a URI pattern
|
227
285
|
def compile_uri_pattern(uri)
|
228
286
|
keys = []
|
@@ -241,6 +299,7 @@ module Sipatra
|
|
241
299
|
end
|
242
300
|
|
243
301
|
def handler(method_name, verb, pattern, keys, options={}, &block)
|
302
|
+
raise ArgumentError, "A block should be given to a handler definition method" if block.nil?
|
244
303
|
define_method method_name, &block
|
245
304
|
unbound_method = instance_method(method_name)
|
246
305
|
block =
|
@@ -287,7 +346,7 @@ module Sipatra
|
|
287
346
|
delegate :ack, :bye, :cancel, :info, :invite, :message,
|
288
347
|
:notify, :options, :prack, :publish, :refer,
|
289
348
|
:register, :subscribe, :update,
|
290
|
-
:helpers, :configure,
|
349
|
+
:helpers, :configure, :settings, :set, :enable, :disable,
|
291
350
|
:before, :after, :request, :response
|
292
351
|
end
|
293
352
|
|
@@ -298,4 +357,4 @@ module Sipatra
|
|
298
357
|
def self.register_extension(*extensions, &block)
|
299
358
|
Application.register_extension(*extensions, &block)
|
300
359
|
end
|
301
|
-
end
|
360
|
+
end
|
data/lib/sipatra/helpers.rb
CHANGED
@@ -1,146 +1,146 @@
|
|
1
1
|
module Sipatra
|
2
2
|
STATUS_CODES_MAP = {
|
3
|
-
:accepted
|
4
|
-
:address_incomplete
|
5
|
-
:alternative_service
|
6
|
-
:ambiguous
|
7
|
-
:bad_event
|
8
|
-
:bad_extension
|
9
|
-
:bad_gateway
|
10
|
-
:bad_identity_info
|
11
|
-
:bad_request
|
12
|
-
:busy_everywhere
|
13
|
-
:busy_here
|
14
|
-
:call_being_forwarded
|
15
|
-
:call_leg_done
|
16
|
-
:call_queued
|
17
|
-
:conditional_request_failed
|
18
|
-
:decline
|
19
|
-
:does_not_exit_anywhere
|
20
|
-
:extension_required
|
21
|
-
:forbidden
|
22
|
-
:gone
|
23
|
-
:interval_too_brief
|
24
|
-
:invalid_identity_header
|
25
|
-
:loop_detected
|
26
|
-
:message_too_large
|
27
|
-
:method_not_allowed
|
28
|
-
:moved_permanently
|
29
|
-
:moved_temporarily
|
30
|
-
:multiple_choices
|
31
|
-
:not_acceptable
|
32
|
-
:not_acceptable_anywhere
|
33
|
-
:not_acceptable_here
|
34
|
-
:not_found
|
35
|
-
:not_implemented
|
36
|
-
:ok
|
37
|
-
:payment_required
|
38
|
-
:precondition_failure
|
39
|
-
:provide_referer_identity
|
3
|
+
:accepted => 202,
|
4
|
+
:address_incomplete => 484,
|
5
|
+
:alternative_service => 380,
|
6
|
+
:ambiguous => 485,
|
7
|
+
:bad_event => 489,
|
8
|
+
:bad_extension => 420,
|
9
|
+
:bad_gateway => 502,
|
10
|
+
:bad_identity_info => 436,
|
11
|
+
:bad_request => 400,
|
12
|
+
:busy_everywhere => 600,
|
13
|
+
:busy_here => 486,
|
14
|
+
:call_being_forwarded => 181,
|
15
|
+
:call_leg_done => 481,
|
16
|
+
:call_queued => 182,
|
17
|
+
:conditional_request_failed => 412,
|
18
|
+
:decline => 603,
|
19
|
+
:does_not_exit_anywhere => 604,
|
20
|
+
:extension_required => 421,
|
21
|
+
:forbidden => 403,
|
22
|
+
:gone => 410,
|
23
|
+
:interval_too_brief => 423,
|
24
|
+
:invalid_identity_header => 438,
|
25
|
+
:loop_detected => 482,
|
26
|
+
:message_too_large => 513,
|
27
|
+
:method_not_allowed => 405,
|
28
|
+
:moved_permanently => 301,
|
29
|
+
:moved_temporarily => 302,
|
30
|
+
:multiple_choices => 300,
|
31
|
+
:not_acceptable => 406,
|
32
|
+
:not_acceptable_anywhere => 606,
|
33
|
+
:not_acceptable_here => 488,
|
34
|
+
:not_found => 404,
|
35
|
+
:not_implemented => 501,
|
36
|
+
:ok => 200,
|
37
|
+
:payment_required => 402,
|
38
|
+
:precondition_failure => 580,
|
39
|
+
:provide_referer_identity => 429,
|
40
40
|
:proxy_authentication_required => 407,
|
41
|
-
:request_entity_too_large
|
42
|
-
:request_pending
|
43
|
-
:request_terminated
|
44
|
-
:request_timeout
|
45
|
-
:request_uri_too_long
|
46
|
-
:ringing
|
47
|
-
:security_agreement_required
|
48
|
-
:server_internal_error
|
49
|
-
:server_timeout
|
50
|
-
:service_unavailable
|
51
|
-
:session_interval_too_small
|
52
|
-
:session_progress
|
53
|
-
:temporarily_unavailable
|
54
|
-
:too_many_hops
|
55
|
-
:trying
|
56
|
-
:unauthorized
|
57
|
-
:undecipherable
|
58
|
-
:unsupported_certificate
|
59
|
-
:unsupported_media_type
|
60
|
-
:unsupported_uri_scheme
|
61
|
-
:use_identity_header
|
62
|
-
:use_proxy
|
63
|
-
:version_not_supported
|
41
|
+
:request_entity_too_large => 413,
|
42
|
+
:request_pending => 491,
|
43
|
+
:request_terminated => 487,
|
44
|
+
:request_timeout => 408,
|
45
|
+
:request_uri_too_long => 414,
|
46
|
+
:ringing => 180,
|
47
|
+
:security_agreement_required => 494,
|
48
|
+
:server_internal_error => 500,
|
49
|
+
:server_timeout => 504,
|
50
|
+
:service_unavailable => 503,
|
51
|
+
:session_interval_too_small => 422,
|
52
|
+
:session_progress => 183,
|
53
|
+
:temporarily_unavailable => 480,
|
54
|
+
:too_many_hops => 483,
|
55
|
+
:trying => 100,
|
56
|
+
:unauthorized => 401,
|
57
|
+
:undecipherable => 493,
|
58
|
+
:unsupported_certificate => 437,
|
59
|
+
:unsupported_media_type => 415,
|
60
|
+
:unsupported_uri_scheme => 416,
|
61
|
+
:use_identity_header => 428,
|
62
|
+
:use_proxy => 305,
|
63
|
+
:version_not_supported => 505,
|
64
64
|
}
|
65
|
-
|
65
|
+
|
66
66
|
class HeadersWrapper
|
67
67
|
def initialize(app, plural = false, address = false)
|
68
68
|
@app = app
|
69
69
|
method_definitions = <<-RUBY
|
70
70
|
def [](name)
|
71
|
-
@app.
|
71
|
+
@app.message.get#{address ? "Address" : ""}Header#{plural ? "s" : ""}(name.to_s)#{plural ? ".to_a" : ""}
|
72
72
|
end
|
73
73
|
RUBY
|
74
74
|
if plural
|
75
75
|
method_definitions += <<-RUBY
|
76
76
|
def []=(name, values)
|
77
77
|
name = name.to_s
|
78
|
-
@app.
|
78
|
+
@app.message.removeHeader(name)
|
79
79
|
if !values.nil?
|
80
|
-
values.each do |value|
|
81
|
-
@app.
|
80
|
+
values.each do |value|
|
81
|
+
@app.message.add#{address ? "Address" : ""}Header(name, value#{address ? ", true" : ".to_s"})
|
82
82
|
end
|
83
83
|
end
|
84
|
-
end
|
84
|
+
end
|
85
85
|
RUBY
|
86
86
|
else
|
87
87
|
method_definitions += <<-RUBY
|
88
88
|
def []=(name, value)
|
89
89
|
if !value.nil?
|
90
|
-
@app.
|
90
|
+
@app.message.set#{address ? "Address" : ""}Header(name.to_s, value)
|
91
91
|
else
|
92
|
-
@app.
|
92
|
+
@app.message.removeHeader(name.to_s)
|
93
93
|
end
|
94
|
-
end
|
94
|
+
end
|
95
95
|
RUBY
|
96
96
|
end
|
97
97
|
class << self; self; end.class_eval method_definitions
|
98
|
-
end
|
98
|
+
end
|
99
99
|
end
|
100
|
-
|
101
|
-
module HelperMethods
|
100
|
+
|
101
|
+
module HelperMethods
|
102
102
|
def proxy(*args)
|
103
103
|
uri = args.shift
|
104
104
|
uri, options = nil, uri if uri.kind_of? Hash
|
105
105
|
options ||= args.shift || {}
|
106
106
|
if uri.nil?
|
107
|
-
uri =
|
107
|
+
uri = message.requestURI
|
108
108
|
else
|
109
109
|
uri = sip_factory.createURI(uri)
|
110
110
|
end
|
111
|
-
proxy =
|
111
|
+
proxy = message.proxy
|
112
112
|
proxy.setRecordRoute(options[:record_route]) if options.has_key? :record_route
|
113
113
|
proxy.proxyTo(uri)
|
114
|
-
end
|
115
|
-
|
114
|
+
end
|
115
|
+
|
116
116
|
def header
|
117
117
|
@header_wrapper ||= HeadersWrapper::new(self)
|
118
118
|
end
|
119
|
-
|
119
|
+
|
120
120
|
def headers
|
121
121
|
@headers_wrapper ||= HeadersWrapper::new(self, true)
|
122
122
|
end
|
123
|
-
|
123
|
+
|
124
124
|
def address_header
|
125
125
|
@address_header_wrapper ||= HeadersWrapper::new(self, false, true)
|
126
126
|
end
|
127
|
-
|
127
|
+
|
128
128
|
def address_headers
|
129
129
|
@address_headers_wrapper ||= HeadersWrapper::new(self, true, true)
|
130
130
|
end
|
131
|
-
|
131
|
+
|
132
132
|
def add_header(name, value)
|
133
|
-
|
133
|
+
message.addHeader(name.to_s, value)
|
134
134
|
end
|
135
|
-
|
135
|
+
|
136
136
|
def add_address_header(name, value, first = true)
|
137
|
-
|
137
|
+
message.addAddressHeader(name.to_s, value, first)
|
138
138
|
end
|
139
|
-
|
139
|
+
|
140
140
|
def header?(name)
|
141
|
-
!
|
141
|
+
!message.getHeader(name.to_s).nil?
|
142
142
|
end
|
143
|
-
|
143
|
+
|
144
144
|
def modify_header(header_name, pattern = nil, new_value = nil)
|
145
145
|
#FIXME: "JAVA" Code
|
146
146
|
if pattern
|
@@ -154,46 +154,71 @@ module Sipatra
|
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end
|
157
|
-
|
157
|
+
|
158
158
|
def remove_header(name)
|
159
|
-
|
159
|
+
message.removeHeader(name.to_s)
|
160
|
+
end
|
161
|
+
|
162
|
+
class ResponseEnvironment
|
163
|
+
instance_methods.each do |m|
|
164
|
+
undef_method m unless m.to_s =~ /^__|respond_to?|instance_eval/
|
165
|
+
end
|
166
|
+
|
167
|
+
attr_reader :response, :app
|
168
|
+
alias :message :response
|
169
|
+
|
170
|
+
def initialize(app, response)
|
171
|
+
@app, @response = app, response
|
172
|
+
end
|
173
|
+
|
174
|
+
# TODO: complete with some direct access to app ?
|
160
175
|
end
|
161
|
-
|
162
|
-
def send_response(status, *args)
|
176
|
+
|
177
|
+
def send_response(status, *args, &block)
|
163
178
|
create_args = [convert_status_code(status)]
|
164
179
|
create_args << args.shift unless args.empty? || args.first.kind_of?(Hash)
|
165
|
-
response =
|
180
|
+
response = message.createResponse(*create_args)
|
166
181
|
unless args.empty?
|
167
182
|
raise ArgumentError, "last argument should be a Hash" unless args.first.kind_of? Hash
|
168
183
|
args.first.each_pair do |name, value|
|
169
184
|
response.addHeader(name.to_s, value.to_s)
|
170
185
|
end
|
171
186
|
end
|
172
|
-
|
173
|
-
|
187
|
+
unless block.nil?
|
188
|
+
ResponseEnvironment::new(self, response).instance_eval(&block)
|
174
189
|
end
|
175
190
|
response.send
|
176
191
|
end
|
177
|
-
|
192
|
+
|
178
193
|
def create_address(addr, options = {})
|
179
194
|
addr = addr.to_s # TODO: Handle URI instances
|
180
195
|
address = sip_factory.createAddress(addr)
|
181
196
|
address.setExpires(options[:expires]) if options.has_key? :expires
|
182
197
|
address.setDisplayName(options[:display_name]) if options.has_key? :display_name
|
183
|
-
|
184
|
-
address
|
198
|
+
|
199
|
+
address
|
185
200
|
end
|
186
|
-
|
201
|
+
|
202
|
+
def create_uri(value, params = {})
|
203
|
+
uri = sip_factory.createURI(value)
|
204
|
+
if uri.respond_to? :setLrParam
|
205
|
+
uri.setLrParam(params.has_key?(:lr) ? params.delete(:lr) : true)
|
206
|
+
end
|
207
|
+
params.each { |name, value| uri.setParameter(name.to_s, value.to_s) }
|
208
|
+
uri
|
209
|
+
end
|
210
|
+
|
187
211
|
def push_route(route)
|
188
|
-
|
189
|
-
end
|
190
|
-
|
212
|
+
message.pushRoute(sip_factory.createAddress(route))
|
213
|
+
end
|
214
|
+
|
191
215
|
private
|
192
|
-
|
216
|
+
|
193
217
|
def convert_status_code(symbol_or_int)
|
194
218
|
case symbol_or_int
|
195
|
-
when Integer
|
196
|
-
|
219
|
+
when Integer
|
220
|
+
return symbol_or_int
|
221
|
+
when Symbol
|
197
222
|
code = STATUS_CODES_MAP[symbol_or_int]
|
198
223
|
raise ArgumentError, "Unknown status code symbol: '#{symbol_or_int}'" unless code
|
199
224
|
code
|
@@ -202,4 +227,4 @@ module Sipatra
|
|
202
227
|
end
|
203
228
|
end
|
204
229
|
end
|
205
|
-
end
|
230
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|