Class: Rpush::Daemon::TcpConnection

Inherits:
Object
  • Object
show all
Includes:
Loggable, Reflectable
Defined in:
lib/rpush/daemon/tcp_connection.rb

Constant Summary collapse

OSX_TCP_KEEPALIVE =

Defined in <netinet/tcp.h>

0x10
KEEPALIVE_INTERVAL =
5
KEEPALIVE_IDLE =
5
KEEPALIVE_MAX_FAIL_PROBES =
1
TCP_ERRORS =
[SystemCallError, OpenSSL::OpenSSLError, IOError]

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Loggable

#log_debug, #log_error, #log_info, #log_warn

Methods included from Reflectable

#reflect

Constructor Details

#initialize(app, host, port) ⇒ TcpConnection


22
23
24
25
26
27
28
29
30
31
# File 'lib/rpush/daemon/tcp_connection.rb', line 22

def initialize(app, host, port)
  @app = app
  @host = host
  @port = port
  @certificate = app.certificate
  @password = app.password
  @connected = false
  @connection_callbacks = []
  touch
end

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host


16
17
18
# File 'lib/rpush/daemon/tcp_connection.rb', line 16

def host
  @host
end

#last_touchObject

Returns the value of attribute last_touch


15
16
17
# File 'lib/rpush/daemon/tcp_connection.rb', line 15

def last_touch
  @last_touch
end

#portObject (readonly)

Returns the value of attribute port


16
17
18
# File 'lib/rpush/daemon/tcp_connection.rb', line 16

def port
  @port
end

Class Method Details

.idle_periodObject


18
19
20
# File 'lib/rpush/daemon/tcp_connection.rb', line 18

def self.idle_period
  30.minutes
end

Instance Method Details

#closeObject


54
55
56
57
58
# File 'lib/rpush/daemon/tcp_connection.rb', line 54

def close
  @ssl_socket.close if @ssl_socket
  @tcp_socket.close if @tcp_socket
rescue IOError # rubocop:disable HandleExceptions
end

#connectObject


38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/rpush/daemon/tcp_connection.rb', line 38

def connect
  @ssl_context = setup_ssl_context
  @tcp_socket, @ssl_socket = connect_socket
  @connected = true

  @connection_callbacks.each do |blk|
    begin
      blk.call
    rescue StandardError => e
      log_error(e)
    end
  end

  @connection_callbacks.clear
end

#on_connect(&blk) ⇒ Object


33
34
35
36
# File 'lib/rpush/daemon/tcp_connection.rb', line 33

def on_connect(&blk)
  raise 'already connected' if @connected
  @connection_callbacks << blk
end

#read(num_bytes) ⇒ Object


60
61
62
# File 'lib/rpush/daemon/tcp_connection.rb', line 60

def read(num_bytes)
  @ssl_socket.read(num_bytes) if @ssl_socket
end

#reconnectObject


100
101
102
103
# File 'lib/rpush/daemon/tcp_connection.rb', line 100

def reconnect
  close
  @tcp_socket, @ssl_socket = connect_socket
end

#reconnect_with_rescueObject


94
95
96
97
98
# File 'lib/rpush/daemon/tcp_connection.rb', line 94

def reconnect_with_rescue
  reconnect
rescue StandardError => e
  log_error(e)
end

#select(timeout) ⇒ Object


64
65
66
# File 'lib/rpush/daemon/tcp_connection.rb', line 64

def select(timeout)
  IO.select([@ssl_socket], nil, nil, timeout) if @ssl_socket
end

#write(data) ⇒ Object


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
# File 'lib/rpush/daemon/tcp_connection.rb', line 68

def write(data)
  connect unless @connected
  reconnect_idle if idle_period_exceeded?

  retry_count = 0

  begin
    write_data(data)
  rescue *TCP_ERRORS => e
    retry_count += 1

    if retry_count == 1
      log_error("Lost connection to #{@host}:#{@port} (#{e.class.name}, #{e.message}), reconnecting...")
      reflect(:tcp_connection_lost, @app, e)
    end

    if retry_count <= 3
      reconnect_with_rescue
      sleep 1
      retry
    else
      raise TcpConnectionError, "#{@app.name} tried #{retry_count - 1} times to reconnect but failed (#{e.class.name}, #{e.message})."
    end
  end
end