Class: OverSIP::SIP::TlsClient

Inherits:
TcpClient show all
Defined in:
lib/oversip/sip/listeners/tls_client.rb

Direct Known Subclasses

IPv4TlsClient, IPv6TlsClient

Constant Summary collapse

TLS_HANDSHAKE_MAX_TIME =
4

Constants inherited from TcpConnection

OverSIP::SIP::TcpConnection::HEADERS_MAX_SIZE

Constants included from MessageProcessor

MessageProcessor::MSG_TYPE

Instance Attribute Summary collapse

Attributes inherited from TcpClient

#connected, #pending_client_transactions

Attributes inherited from Connection

#cvars

Instance Method Summary collapse

Methods inherited from TcpClient

#record_route, #remote_desc

Methods inherited from TcpConnection

#get_body, #parse_headers, #process_received_data, #receive_data, #remote_ip, #remote_ip_type, #remote_port

Methods inherited from Connection

#open?, outbound_listener?, #receive_senderror, reliable_transport_listener?, #transport

Methods included from Logger

fg_system_msg2str, load_methods, #log_id

Constructor Details

#initialize(ip, port) ⇒ TlsClient

Returns a new instance of TlsClient.



11
12
13
14
# File 'lib/oversip/sip/listeners/tls_client.rb', line 11

def initialize ip, port
  super
  @pending_messages = []
end

Instance Attribute Details

#callback_on_server_tls_handshake=(value) ⇒ Object (writeonly)

Sets the attribute callback_on_server_tls_handshake

Parameters:

  • value

    the value to set the attribute callback_on_server_tls_handshake to.



8
9
10
# File 'lib/oversip/sip/listeners/tls_client.rb', line 8

def callback_on_server_tls_handshake=(value)
  @callback_on_server_tls_handshake = value
end

Instance Method Details

#connection_completedObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/oversip/sip/listeners/tls_client.rb', line 17

def connection_completed
  @server_pems = []
  @server_last_pem = false

  start_tls({
    :verify_peer => @callback_on_server_tls_handshake,
    :cert_chain_file => ::OverSIP.tls_public_cert,
    :private_key_file => ::OverSIP.tls_private_cert,
    :use_tls => true
  })

  # If the remote server does never send us a TLS certificate
  # after the TCP connection we would leak by storing more and
  # more messages in @pending_messages array.
  @timer_tls_handshake = ::EM::Timer.new(TLS_HANDSHAKE_MAX_TIME) do
    unless @connected
      log_system_notice "TLS handshake not performed within #{TLS_HANDSHAKE_MAX_TIME} seconds, closing the connection"
      close_connection
    end
  end
end

#send_sip_msg(msg, ip = nil, port = nil) ⇒ Object

In TLS client, we must wait until ssl_handshake_completed is completed before sending data. If not, data will be sent in plain TCP.

http://dev.sipdoc.net/issues/457


108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/oversip/sip/listeners/tls_client.rb', line 108

def send_sip_msg msg, ip=nil, port=nil
  if self.error?
    log_system_notice "SIP message could not be sent, connection is closed"
    return false
  end

  if @connected
    send_data msg
  else
    log_system_debug "TLS handshake not completed yet, waiting before sending the message"  if $oversip_debug
    @pending_messages << msg
  end
  true
end

#ssl_handshake_completedObject

This is called after all the calls to ssl_verify_peer().



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
# File 'lib/oversip/sip/listeners/tls_client.rb', line 57

def ssl_handshake_completed
  log_system_debug("TLS connection established to " << remote_desc)  if $oversip_debug

  # @connected in TlsClient means "TLS connection" rather than
  # just "TCP connection".
  @connected = true
  @timer_tls_handshake.cancel  if @timer_tls_handshake

  # Run OverSIP::SipEvents.on_server_tls_handshake.
  ::Fiber.new do
    if @callback_on_server_tls_handshake
      log_system_debug "running OverSIP::SipEvents.on_server_tls_handshake()..."  if $oversip_debug
      begin
        ::OverSIP::SipEvents.on_server_tls_handshake self, @server_pems
      rescue ::Exception => e
        log_system_error "error calling OverSIP::SipEvents.on_server_tls_handshake():"
        log_system_error e
        close_connection
      end

      # If the user or peer has closed the connection in the on_server_tls_handshake() callback
      # then notify pending transactions.
      if @local_closed or error?
        log_system_debug "connection closed, aborting"  if $oversip_debug
        @pending_client_transactions.each do |client_transaction|
          client_transaction.tls_validation_failed
        end
        @pending_client_transactions.clear
        @pending_messages.clear
        @state = :ignore
      end
    end

    @pending_client_transactions.clear
    @pending_messages.each do |msg|
      send_data msg
    end
    @pending_messages.clear
  end.resume
end

#ssl_verify_peer(pem) ⇒ Object

Called for every certificate provided by the peer. This is just called in case @callback_on_server_tls_handshake is true.



42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/oversip/sip/listeners/tls_client.rb', line 42

def ssl_verify_peer pem
  # TODO: Dirty workaround for bug https://github.com/eventmachine/eventmachine/issues/194.
  return true  if @server_last_pem == pem

  @server_last_pem = pem
  @server_pems << pem

  log_system_debug "received certificate num #{@server_pems.size} from server"  if $oversip_debug

  # Validation must be done in ssl_handshake_completed after receiving all the certs, so return true.
  return true
end

#unbind(cause = nil) ⇒ Object



98
99
100
101
102
# File 'lib/oversip/sip/listeners/tls_client.rb', line 98

def unbind cause=nil
  super
  @timer_tls_handshake.cancel  if @timer_tls_handshake
  @pending_messages.clear
end