class APN::Client

Constants

DEFAULTS

Public Class Methods

new(options = {}) click to toggle source
# File lib/apn/client.rb, line 6
def initialize(options = {})
  options = DEFAULTS.merge options.reject{|k,v| v.nil?}
  @apn_cert, @cert_pass = options[:certificate], options[:password]
  @host, @port = options[:host], options[:port]
  self
end

Public Instance Methods

feedback() click to toggle source
# File lib/apn/client.rb, line 32
def feedback
  if bunch = socket.read(38)
    f = bunch.strip.unpack('N1n1H140')
    APN::FeedbackItem.new(Time.at(f[0]), f[2])
  end
end
push(message) click to toggle source
# File lib/apn/client.rb, line 13
def push(message)
  socket.write(message.to_s)
  socket.flush

  if IO.select([socket], nil, nil, 1) && error = socket.read(6)
    error = error.unpack("ccN")
    APN.log(:error, "Error on message: #{error}")
    return false
  end

  APN.log(:debug, "Message sent.")
  true
rescue OpenSSL::SSL::SSLError, Errno::EPIPE, Errno::ETIMEDOUT => e
  APN.log(:error, "[##{self.object_id}] Exception occurred: #{e.inspect}, socket state: #{socket.inspect}")
  reset_socket
  APN.log(:debug, "[##{self.object_id}] Socket reestablished, socket state: #{socket.inspect}")
  retry
end
socket() click to toggle source
# File lib/apn/client.rb, line 39
def socket
  @socket ||= setup_socket
end

Private Instance Methods

reset_socket() click to toggle source
# File lib/apn/client.rb, line 58
def reset_socket
  @socket.close if @socket
  @socket = nil
  socket
end
setup_certificate() click to toggle source
# File lib/apn/client.rb, line 64
def setup_certificate
  ctx = OpenSSL::SSL::SSLContext.new
  ctx.cert = OpenSSL::X509::Certificate.new(@apn_cert)
  if @cert_pass
    ctx.key = OpenSSL::PKey::RSA.new(@apn_cert, @cert_pass)
    APN.log(:debug, "Setting up certificate using a password.")

  else
    ctx.key = OpenSSL::PKey::RSA.new(@apn_cert)
  end
  ctx
end
setup_socket() click to toggle source

Open socket to Apple's servers

# File lib/apn/client.rb, line 46
def setup_socket
  ctx = setup_certificate

  APN.log(:debug, "Connecting to #{@host}:#{@port}...")

  socket_tcp = TCPSocket.new(@host, @port)
  OpenSSL::SSL::SSLSocket.new(socket_tcp, ctx).tap do |s|
    s.sync = true
    s.connect
  end
end