class APN::Client

Public Class Methods

new(options = {}) click to toggle source
# File lib/apn/client.rb, line 6
def initialize(options = {})
  @cert = options[:cert]
  @password = options[:password]
  @host = options[:host]
  @port = options[:port]
end

Public Instance Methods

connect!() click to toggle source
# File lib/apn/client.rb, line 13
def connect!
  APN.log(:info, 'Connecting...')

  cert = self.setup_certificate
  @socket = self.setup_socket(cert)

  APN.log(:info, 'Connected!')

  @socket
end
feedback() click to toggle source
# File lib/apn/client.rb, line 78
def feedback
  if bunch = socket.read(38)
    f = bunch.strip.unpack('N1n1H140')
    APN::FeedbackItem.new(Time.at(f[0]), f[2])
  end
end
push(notification) click to toggle source
# File lib/apn/client.rb, line 55
def push(notification)
  begin
    APN.log(:info, "Sending #{notification.device_token}: #{notification.json_payload}")
    socket.write(notification.to_bytes)
    socket.flush

    if IO.select([socket], nil, nil, 1) && error = socket.read(6)
      error = error.unpack('ccN')
      APN.log(:error, "Encountered error in push method: #{error}, backtrace #{error.backtrace}")
      return false
    end

    APN.log(:info, 'Message sent')

    true
  rescue OpenSSL::SSL::SSLError, Errno::EPIPE => e
    APN.log(:error, "Encountered error: #{e}, backtrace #{e.backtrace}")
    APN.log(:info, 'Trying to reconnect...')
    reset_socket
    APN.log(:info, 'Reconnected')
  end
end
reset_socket() click to toggle source
# File lib/apn/client.rb, line 44
def reset_socket
  @socket.close if @socket
  @socket = nil

  connect!
end
setup_certificate() click to toggle source
# File lib/apn/client.rb, line 24
def setup_certificate
  APN.log(:info, 'Setting up certificate...')
  @context      = OpenSSL::SSL::SSLContext.new
  @context.cert = OpenSSL::X509::Certificate.new(File.read(@cert))
  @context.key  = OpenSSL::PKey::RSA.new(File.read(@cert), @password)
  APN.log(:info, 'Certificate created!')

  @context
end
setup_socket(ctx) click to toggle source
# File lib/apn/client.rb, line 34
def setup_socket(ctx)
  APN.log(:info, 'Connecting...')

  socket_tcp = TCPSocket.new(@host, @port)
  OpenSSL::SSL::SSLSocket.new(socket_tcp, ctx).tap do |s|
    s.sync = true
    s.connect
  end
end
socket() click to toggle source
# File lib/apn/client.rb, line 51
def socket
  @socket ||= connect!
end