class Pushr::Daemon::ApnsSupport::ConnectionApns
Constants
- APN_ERRORS
- ERROR_TUPLE_BYTES
- IDLE_PERIOD
- SELECT_TIMEOUT
Attributes
configuration[R]
last_write[RW]
name[R]
Public Class Methods
new(configuration, i = nil)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 25 def initialize(configuration, i = nil) @configuration = configuration if i # Apns push connection @name = "#{@configuration.app}: ConnectionApns #{i}" @host = "gateway.#{configuration.sandbox ? 'sandbox.' : ''}push.apple.com" @port = 2195 else @name = "#{@configuration.app}: FeedbackReceiver" @host = "feedback.#{configuration.sandbox ? 'sandbox.' : ''}push.apple.com" @port = 2196 end written end
Public Instance Methods
check_for_error(notification)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 91 def check_for_error(notification) # check for true, because check_for_error can be nil return if @configuration.skip_check_for_error == true if select(SELECT_TIMEOUT) error = nil if tuple = read(ERROR_TUPLE_BYTES) _, code, notification_id = tuple.unpack('ccN') if code.to_i == 8 Pushr::FeedbackApns.create(app: @configuration.app, device: notification.device, follow_up: 'delete', failed_at: Time.now) Pushr::Daemon.logger.info("[#{@name}] Invalid device (error 8), feedback sent, message delivery failed"\ " to #{notification.to_json}") else description = APN_ERRORS[code.to_i] || 'Unknown error. Possible push bug?' error = Pushr::Daemon::DeliveryError.new(code, notification, description, 'APNS') end else error = DisconnectionError.new end begin Pushr::Daemon.logger.error("[#{@name}] Error received, reconnecting...") reconnect ensure fail error if error end end end
close()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 47 def close @ssl_socket.close if @ssl_socket @tcp_socket.close if @tcp_socket rescue IOError end
connect()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 40 def connect @ssl_context = setup_ssl_context @tcp_socket, @ssl_socket = connect_socket rescue Pushr::Daemon.logger.error("#{@name}] Error connection to server, invalid certificate?") end
read(num_bytes)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 53 def read(num_bytes) @ssl_socket ? @ssl_socket.read(num_bytes) : false end
reconnect()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 86 def reconnect close @tcp_socket, @ssl_socket = connect_socket end
select(timeout)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 57 def select(timeout) IO.select([@ssl_socket], nil, nil, timeout) end
write(data)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 61 def write(data) reconnect_idle if idle_period_exceeded? retry_count = 0 begin write_data(data) rescue Errno::EPIPE, Errno::ETIMEDOUT, Errno::ECONNRESET, OpenSSL::SSL::SSLError => e retry_count += 1 if retry_count == 1 Pushr::Daemon.logger.error("[#{@name}] Lost connection to #{@host}:#{@port} (#{e.class.name}), reconnecting...") end if retry_count <= 3 reconnect sleep 1 retry else raise ConnectionError, "#{@name} tried #{retry_count - 1} times to reconnect but failed (#{e.class.name})." end end check_for_error(data) end
Protected Instance Methods
connect_socket()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 151 def connect_socket tcp_socket = TCPSocket.new(@host, @port) tcp_socket.setsockopt(Socket::SOL_SOCKET, Socket::SO_KEEPALIVE, 1) tcp_socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) ssl_socket = OpenSSL::SSL::SSLSocket.new(tcp_socket, @ssl_context) ssl_socket.sync = true ssl_socket.connect Pushr::Daemon.logger.info("[#{@name}] Connected to #{@host}:#{@port}") [tcp_socket, ssl_socket] end
idle_period_exceeded?()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 130 def idle_period_exceeded? Time.now - last_write > IDLE_PERIOD end
reconnect_idle()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 125 def reconnect_idle Pushr::Daemon.logger.info("[#{@name}] Idle period exceeded, reconnecting...") reconnect end
setup_ssl_context()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 144 def setup_ssl_context ssl_context = OpenSSL::SSL::SSLContext.new ssl_context.key = OpenSSL::PKey::RSA.new(configuration.certificate, configuration.certificate_password) ssl_context.cert = OpenSSL::X509::Certificate.new(configuration.certificate) ssl_context end
write_data(data)
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 134 def write_data(data) @ssl_socket.write(data.to_message) @ssl_socket.flush written end
written()
click to toggle source
# File lib/pushr/daemon/apns_support/connection_apns.rb, line 140 def written self.last_write = Time.now end