Class: Ably::Realtime::Connection::WebsocketTransport Private

Inherits:
EventMachine::Connection
  • Object
show all
Extended by:
Modules::Enum
Includes:
Modules::EventEmitter, Modules::StateEmitter
Defined in:
lib/ably/realtime/connection/websocket_transport.rb

Overview

This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.

EventMachine WebSocket transport

Constant Summary collapse

STATE =

This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.

Valid WebSocket connection states

ruby_enum('STATE',
  :initialized,
  :connecting,
  :connected,
  :disconnecting,
  :disconnected
)

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Modules::StateEmitter

#once_or_if, #once_state_changed, #state, #state=, #state?, #unsafe_once_or_if, #unsafe_once_state_changed

Methods included from Modules::EventEmitter

#emit, #off, #on, #once, #unsafe_off, #unsafe_on, #unsafe_once

Constructor Details

#initialize(connection, url) ⇒ WebsocketTransport

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns a new instance of WebsocketTransport.



23
24
25
26
27
28
29
30
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 23

def initialize(connection, url)
  @connection = connection
  @state      = STATE.Initialized
  @url        = url
  @host       = URI.parse(url).hostname

  setup_event_handlers
end

Instance Attribute Details

#hostObject (readonly)

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



21
22
23
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 21

def host
  @host
end

Instance Method Details

#__incoming_protocol_msgbus__Ably::Util::PubSub

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Websocket Transport internal incoming protocol message bus.

Returns:



141
142
143
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 141

def __incoming_protocol_msgbus__
  @__incoming_protocol_msgbus__ ||= create_pub_sub_message_bus
end

#__outgoing_protocol_msgbus__Ably::Util::PubSub

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Returns Websocket Transport internal outgoing protocol message bus.

Returns:



148
149
150
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 148

def __outgoing_protocol_msgbus__
  @__outgoing_protocol_msgbus__ ||= create_pub_sub_message_bus
end

#certificate_storeObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



126
127
128
129
130
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 126

def certificate_store
  @certificate_store ||= OpenSSL::X509::Store.new.tap do |store|
    store.set_default_paths
  end
end

#connection_completedObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Remote TCP connection attempt completes successfully Required EventMachine::Connection interface



57
58
59
60
61
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 57

def connection_completed
  change_state STATE.Connected
  start_tls(tls_opts) if client.use_tls?
  driver.start
end

#disconnectvoid

This method returns an undefined value.

Disconnect the socket transport connection and write all pending text. If Disconnected state is not automatically emitted, it will be emitted automatically



38
39
40
41
42
43
44
45
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 38

def disconnect
  close_connection_after_writing
  change_state STATE.Disconnecting
  create_timer(2) do
    # if connection is not disconnected within 2s, set state as disconnected
    change_state STATE.Disconnected unless disconnected?
  end
end

#post_initObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Network connection has been established Required EventMachine::Connection interface



49
50
51
52
53
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 49

def post_init
  clear_timer
  change_state STATE.Connecting
  setup_driver
end

#ready_for_release?Boolean

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

True if socket connection is ready to be released i.e. it is not currently connecting or connected

Returns:

  • (Boolean)


134
135
136
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 134

def ready_for_release?
  !connecting? && !connected?
end

#receive_data(data) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Called by the event loop whenever data has been received by the network connection. Simply pass onto the WebSocket driver to process and determine content boundaries. Required EventMachine::Connection interface



66
67
68
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 66

def receive_data(data)
  driver.parse(data)
end

#ssl_handshake_completedObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.



117
118
119
120
121
122
123
124
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 117

def ssl_handshake_completed
  unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host)
    disconnect_with_reason "Websocket host '#{host}' returned an invalid TLS certificate"
    false
  else
    true
  end
end

#ssl_verify_peer(cert_string) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

TLS verification support, original implementation by Mislav Marohnić:

github.com/lostisland/faraday/commit/63cf47c95b573539f047c729bd9ad67560bc83ff



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
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 90

def ssl_verify_peer(cert_string)
  cert = nil
  begin
    cert = OpenSSL::X509::Certificate.new(cert_string)
  rescue OpenSSL::X509::CertificateError => e
    disconnect_with_reason "Websocket host '#{host}' returned an invalid TLS certificate: #{e.message}"
    return false
  end

  @last_seen_cert = cert

  if certificate_store.verify(@last_seen_cert)
    begin
      certificate_store.add_cert(@last_seen_cert)
    rescue OpenSSL::X509::StoreError => e
      unless e.message == 'cert already in hash table'
        disconnect_with_reason "Websocket host '#{host}' returned an invalid TLS certificate: #{e.message}"
        return false
      end
    end
    true
  else
    disconnect_with_reason "Websocket host '#{host}' returned an invalid TLS certificate"
    false
  end
end

#unbindObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Called whenever a connection (either a server or client connection) is closed Required EventMachine::Connection interface



72
73
74
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 72

def unbind
  change_state STATE.Disconnected, reason_closed || 'Websocket connection closed unexpectedly'
end

#urlObject

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

URL end point including initialization configuration WebSocket::Driver interface



78
79
80
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 78

def url
  @url
end

#write(data) ⇒ Object

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

WebSocket::Driver interface



83
84
85
# File 'lib/ably/realtime/connection/websocket_transport.rb', line 83

def write(data)
  send_data(data)
end