Module: OverSIP::SIP::TransportManager

Extended by:
Logger
Defined in:
lib/oversip/sip/transport_manager.rb

Class Method Summary collapse

Methods included from Logger

close, fg_system_msg2str, init_logger_mq, load_methods, log_id, syslog_system_msg2str, syslog_user_msg2str

Class Method Details

.add_connection(server, server_class, ip_type, ip, port) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/oversip/sip/transport_manager.rb', line 73

def self.add_connection server, server_class, ip_type, ip, port
  connection_id = case ip_type
    when :ipv4
      "#{ip}_#{port}"
    when :ipv6
      "#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"
    end

  server_class.connections[connection_id] = server

  # Return the connection_id.
  connection_id
end

.add_outbound_connection(connection) ⇒ Object



117
118
119
120
121
# File 'lib/oversip/sip/transport_manager.rb', line 117

def self.add_outbound_connection connection
  outbound_flow_token = ::SecureRandom.hex(5)
  @outbound_connections[outbound_flow_token] = connection
  outbound_flow_token
end

.delete_outbound_connection(outbound_flow_token) ⇒ Object



124
125
126
# File 'lib/oversip/sip/transport_manager.rb', line 124

def self.delete_outbound_connection outbound_flow_token
  @outbound_connections.delete outbound_flow_token
end

.get_connection(klass, ip, port, client_transaction = nil, callback_on_server_tls_handshake = false) ⇒ Object

Get an existing connection or create a new one (TCP/TLS). For UDP it always returns the single UDP reactor instance. client_transaction is passed when creating a new clien transaction. In case the outgoing connection is a TCP/TLS client connection and it’s not connected yet, the client transaction is stored in the @pending_client_transactions of the client connection. This method always returns a connection object, never nil or false.



18
19
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
# File 'lib/oversip/sip/transport_manager.rb', line 18

def self.get_connection klass, ip, port, client_transaction=nil, callback_on_server_tls_handshake=false
  # A normal connection (so we arrive here after RFC 3263 procedures).
  case klass.transport

  # In UDP there is a single connection (the UDP server unique instance).
  when :udp
    conn = klass.connections

  # In TCP/TLS first check if there is an existing connection to the given destination.
  # If not create a new one.
  when :tcp
    case klass.ip_type
      when :ipv4
        conn = klass.connections["#{ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv4, ip, port, ::OverSIP::SIP::IPv4TcpClient, ip, port)

        if conn.is_a? ::OverSIP::SIP::IPv4TcpClient and not conn.connected
          conn.pending_client_transactions << client_transaction
        end
      when :ipv6
        conn = klass.connections["#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv6, ip, port, ::OverSIP::SIP::IPv6TcpClient, ip, port)

        if conn.is_a? ::OverSIP::SIP::IPv6TcpClient and not conn.connected
          conn.pending_client_transactions << client_transaction
        end
      end

  when :tls
    case klass.ip_type
      when :ipv4
        conn = klass.connections["#{ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv4, ip, port, ::OverSIP::SIP::IPv4TlsClient, ip, port)

        if conn.is_a? ::OverSIP::SIP::IPv4TlsClient and not conn.connected
          conn.callback_on_server_tls_handshake = callback_on_server_tls_handshake
          conn.pending_client_transactions << client_transaction
        end
      when :ipv6
        conn = klass.connections["#{::OverSIP::Utils.normalize_ipv6 ip}_#{port}"] || ::EM.oversip_connect_tcp_server(::OverSIP::SIP.local_ipv6, ip, port, ::OverSIP::SIP::IPv6TlsClient, ip, port)

        if conn.is_a? ::OverSIP::SIP::IPv6TlsClient and not conn.connected
          conn.callback_on_server_tls_handshake = callback_on_server_tls_handshake
          conn.pending_client_transactions << client_transaction
        end
      end
  end

  # NOTE: Should never happen.
  unless conn
    ::OverSIP::Launcher.fatal "no connection retrieved from TransportManager.get_connection(), FIXME, it should never occur!!!"
  end

  # Return the created/retrieved connection instance.
  conn
end

.get_outbound_connection(flow_token) ⇒ Object

Return a SIP server instance. It could return nil (if the requested connection no longer exists) or false (if it’s a tampered flow token).



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
# File 'lib/oversip/sip/transport_manager.rb', line 90

def self.get_outbound_connection flow_token
  # If the token flow has been generated for UDP it is "_" followed by the Base64
  # encoded representation of "IP_port", so getbyte(0) would return 95.
  if flow_token.getbyte(0) == 95
    # NOTE: Doing Base64.decode64 automatically removes the leading "_".
    # NOTE: Previously when the Outbound flow token was generated, "=" was replaced with "-" so it becomes
    # valid for a SIP URI param (needed i.e. for the OutboundMangling module).
    ip_type, ip, port = ::OverSIP::Utils.parse_outbound_udp_flow_token(::Base64.decode64 flow_token.gsub(/-/,"="))

    case ip_type
      when :ipv4
        return [ ::OverSIP::SIP::IPv4UdpServer.connections, ip, port ]
      when :ipv6
        return [ ::OverSIP::SIP::IPv6UdpServer.connections, ip, port ]
      else
        log_system_notice "udp flow token does not contain valid IP and port encoded value"
        return false
      end

  # If not, the flow token has been generated for a TCP/TLS/WS/WSS connection so let's lookup
  # it into the Outbound connection collection and return nil for IP and port.
  else
    @outbound_connections[flow_token]
  end
end