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 CHANGED
@@ -7,26 +7,21 @@ module Sipatra
7
7
 
8
8
  class Base
9
9
  include HelperMethods
10
- attr_accessor :sip_factory, :context, :session, :msg, :params
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, @msg = args
20
+ @context, @sip_factory, @session, @message, @log = args
19
21
  session.extend Sipatra::SessionExtension
20
- msg.extend Sipatra::MessageExtension
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
- !msg.respond_to?(:getRequest)
58
+ !message.respond_to?(:getRequest)
54
59
  end
55
60
 
56
61
  def response?
57
- msg.respond_to?(:getRequest)
62
+ message.respond_to?(:getRequest)
58
63
  end
59
64
 
60
65
  private
61
66
 
62
- def msg_type
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 msg.requestURI.to_s
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 == msg.status))
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, msg.method)
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(msg_type = nil, &block)
186
- add_filter(:before, msg_type, &block)
231
+ def before(message_type = nil, &block)
232
+ add_filter(:before, message_type, &block)
187
233
  end
188
234
 
189
- def after(msg_type = nil, &block)
190
- add_filter(:after, msg_type, &block)
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, message_type = nil, &block)
216
- if message_type
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
@@ -1,146 +1,146 @@
1
1
  module Sipatra
2
2
  STATUS_CODES_MAP = {
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,
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 => 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,
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.msg.get#{address ? "Address" : ""}Header#{plural ? "s" : ""}(name.to_s)#{plural ? ".to_a" : ""}
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.msg.removeHeader(name)
78
+ @app.message.removeHeader(name)
79
79
  if !values.nil?
80
- values.each do |value|
81
- @app.msg.add#{address ? "Address" : ""}Header(name, value#{address ? ", true" : ".to_s"})
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.msg.set#{address ? "Address" : ""}Header(name.to_s, value)
90
+ @app.message.set#{address ? "Address" : ""}Header(name.to_s, value)
91
91
  else
92
- @app.msg.removeHeader(name.to_s)
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 = msg.requestURI
107
+ uri = message.requestURI
108
108
  else
109
109
  uri = sip_factory.createURI(uri)
110
110
  end
111
- proxy = msg.getProxy()
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
- msg.addHeader(name.to_s, value)
133
+ message.addHeader(name.to_s, value)
134
134
  end
135
-
135
+
136
136
  def add_address_header(name, value, first = true)
137
- msg.addAddressHeader(name.to_s, value, first)
137
+ message.addAddressHeader(name.to_s, value, first)
138
138
  end
139
-
139
+
140
140
  def header?(name)
141
- !msg.getHeader(name.to_s).nil?
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
- msg.removeHeader(name.to_s)
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 = msg.createResponse(*create_args)
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
- if block_given?
173
- yield response
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
- msg.pushRoute(sip_factory.createAddress(route))
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: return symbol_or_int
196
- when Symbol:
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