class ApnsSimple::Client

Constants

CODES
COMMAND
DEFAULT_CERTIFICATE_PASSWORD
DEFAULT_GATEWAY_URI
ERROR_BYTES_COUNT
INVALID_TOKEN_CODE
TIMEOUT

Attributes

host[R]
port[R]
ssl_context[R]

Public Class Methods

new(options) click to toggle source
# File lib/apns_simple/client.rb, line 31
def initialize(options)
  certificate = options.fetch(:certificate)
  current_time = Time.now.utc
  cert = OpenSSL::X509::Certificate.new(certificate)
  if current_time < cert.not_before || current_time > cert.not_after
    raise CertificateActivenessTimeError, "CURRENT_TIME: #{current_time}, NOT_BEFORE: #{cert.not_before}, NOT_AFTER: #{cert.not_after}"
  end

  @ssl_context = OpenSSL::SSL::SSLContext.new
  ssl_context.cert = cert

  passphrase = options[:passphrase] || DEFAULT_CERTIFICATE_PASSWORD
  ssl_context.key = OpenSSL::PKey::RSA.new(certificate, passphrase)
  
  gateway_uri = options[:gateway_uri] || DEFAULT_GATEWAY_URI
  @host, @port = parse_gateway_uri(gateway_uri)
end

Public Instance Methods

push(notification) click to toggle source
# File lib/apns_simple/client.rb, line 49
def push(notification)
  unless notification.error
    begin
      sock = TCPSocket.new(host, port)
      ssl = OpenSSL::SSL::SSLSocket.new(sock, ssl_context)
      ssl.sync = true
      ssl.connect
      ssl.write(notification.payload)

      if (ready = IO.select([ssl], [], [], TIMEOUT))
        readable_ssl_socket = ready.first.first
        if (error = readable_ssl_socket.read(ERROR_BYTES_COUNT))
          command, code, _index = error.unpack('ccN')
          notification.error = true
          if command == COMMAND
            notification.error_code = code
            notification.error_message = "CODE: #{code}, DESCRIPTION: #{CODES[code]}"
          else
            notification.error_message = "Unknown command received from APNS server: #{command}"
          end
        end
      end
    ensure
      ssl.close if ssl
      sock.close if sock
    end
  end
end

Private Instance Methods

parse_gateway_uri(uri) click to toggle source
# File lib/apns_simple/client.rb, line 80
def parse_gateway_uri(uri)
  first, last = uri.sub('apn://', '').split(':')
  [first, last.to_i]
end