Class: OverSIP::SIP::Proxy

Inherits:
Client
  • Object
show all
Defined in:
lib/oversip/sip/proxy.rb

Instance Attribute Summary

Attributes inherited from Client

#current_target, #request

Instance Method Summary collapse

Methods inherited from Client

#abort_routing, #add_target_to_blacklist, #clear_callbacks, #clear_on_canceled, #clear_on_error, #clear_on_failure_response, #clear_on_invite_timeout, #clear_on_provisional_response, #clear_on_success_response, #clear_on_target, #client_timeout, #connection_failed, #initialize, #on_canceled, #on_error, #on_failure_response, #on_invite_timeout, #on_provisional_response, #on_success_response, #on_target, #tls_validation_failed

Methods included from Logger

fg_system_msg2str, load_methods, #log_id

Constructor Details

This class inherits a constructor from OverSIP::SIP::Client

Instance Method Details

#drop_response(response = nil) ⇒ Object

If a SIP response is given then this method may offer other features such as replying 199.



6
7
8
9
10
11
12
13
14
15
16
17
# File 'lib/oversip/sip/proxy.rb', line 6

def drop_response response=nil
  @drop_response = true

  # RFC 6228 (199 response).
  # http://tools.ietf.org/html/rfc6228#section-6
  if response and response.status_code >= 300 and
     @request.sip_method == :INVITE and
     @request.supported and @request.supported.include?("199")

    @request.send :reply_199, response
  end
end

#invite_timeoutObject

Timer C for INVITE (method called by the client transaction).



167
168
169
170
171
172
173
174
# File 'lib/oversip/sip/proxy.rb', line 167

def invite_timeout
  run_on_invite_timeout_cbs

  unless @drop_response
    @request.reply 408, "INVITE Timeout"
  end
  @drop_response = true  # Ignore the possible 487 got from the callee.
end

#receive_cancel(cancel) ⇒ Object

Since we don’t implement parallel forking, directly send our CANCEL downstream.



156
157
158
159
160
161
162
163
# File 'lib/oversip/sip/proxy.rb', line 156

def receive_cancel cancel
  log_system_debug "server transaction canceled, cancelling pending client transaction"  if $oversip_debug

  @canceled = true
  run_on_canceled_cbs

  @client_transaction.do_cancel cancel
end

#receive_response(response) ⇒ Object



121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/oversip/sip/proxy.rb', line 121

def receive_response response
  log_system_debug "received response #{response.status_code}"  if $oversip_debug

  response.delete_header_top "Via"

  if @request.server_transaction.valid_response? response.status_code
    if response.status_code < 200 && ! @canceled
      run_on_provisional_response_cbs response
    elsif response.status_code >= 200 && response.status_code <= 299
      run_on_success_response_cbs response
    elsif response.status_code >= 300 && ! @canceled
      if response.status_code == 503
        if @conf[:dns_failover_on_503]
          try_next_target nil, nil, response
          return
        else
          # If the response is 503 convert it into 500 (RFC 3261 16.7).
          response.status_code = 500
          run_on_failure_response_cbs response
        end
      else
        run_on_failure_response_cbs response
      end
    end
  end

  unless @drop_response
    @request.reply_full response
  else
    @drop_response = false
  end
end

#route(request, dst_host = nil, dst_port = nil, dst_transport = nil) ⇒ Object



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/oversip/sip/proxy.rb', line 20

def route request, dst_host=nil, dst_port=nil, dst_transport=nil
  unless (@request = request).is_a? ::OverSIP::SIP::Request
    raise ::OverSIP::RuntimeError, "request must be a OverSIP::SIP::Request instance"
  end

  @log_id = "Proxy #{@conf[:name]} #{@request.via_branch_id}"

  # Create the server transaction if it doesn't exist yet.
  @server_transaction = @request.server_transaction or case @request.sip_method
    # Here it can arrive an INVITE, ACK-for-2XX and any method but CANCEL.
    when :INVITE
      InviteServerTransaction.new @request
    when :ACK
    else
      NonInviteServerTransaction.new @request
    end
  @request.server_transaction ||= @server_transaction

  # Set this core layer to the server transaction.
  @request.server_transaction.core = self  if @request.server_transaction

  # NOTE: Routing can be based on incoming request for an Outbound (RFC 5626) connection
  # or based on normal RFC 3263 procedures.

  # If it's an incoming Outbound connection get the associated connection (but if dst_host is
  # set then don't honor the Outbound connection).

  if @request.incoming_outbound_requested? and not dst_host
    @client_transaction = (::OverSIP::SIP::ClientTransaction.get_class @request).new self, @request, @conf, @request.route_outbound_flow_token

    if @client_transaction.connection
      add_routing_headers
      @client_transaction.send_request
    else
      unless @request.sip_method == :ACK
        log_system_debug "flow failed"  if $oversip_debug

        run_on_error_cbs 430, "Flow Failed", :flow_failed
        unless @drop_response
          @request.reply 430, "Flow Failed"
        else
          @drop_response = false
        end
      else
        log_system_debug "flow failed for received ACK"  if $oversip_debug
      end
    end

    return
  end


  # If it's not an incoming Outbound connection (or explicit destination is set),
  # let's perform RFC 3263 procedures.

  # Check the request destination.
  # If a destination is given use it. If not route based on request headers.

  # Force the destination.
  if dst_host
    dst_scheme = :sip
    dst_host_type = ::OverSIP::Utils.ip_type(dst_host) || :domain

  # Or use top Route header.
  elsif @request.routes
    top_route = @request.routes[0]
    dst_scheme = top_route.scheme
    dst_host = top_route.host
    dst_host_type = top_route.host_type
    dst_port = top_route.port
    dst_transport = top_route.transport_param

  # Or use the Request URI.
  else
    dst_scheme = @request.ruri.scheme
    dst_host = @request.ruri.host
    dst_host_type = @request.ruri.host_type
    dst_port = @request.ruri.port
    dst_transport = @request.ruri.transport_param
  end

  # If the destination uri_host is an IPv6 reference, convert it to real IPv6.
  if dst_host_type == :ipv6_reference
    dst_host = ::OverSIP::Utils.normalize_ipv6(dst_host, true)
    dst_host_type = :ipv6
  end

  # Loockup in the DNS cache of this proxy.
  result = check_dns_cache dst_scheme, dst_host, dst_host_type, dst_port, dst_transport

  case result
  when true
    return
  else  # It can be String or nil, so use it as dns_cache_key param.
    # Perform RFC 3263 procedures.
    do_dns result, @request.via_branch_id, dst_scheme, dst_host, dst_host_type, dst_port, dst_transport
  end

end