Class: ApnsSimple::Client

Inherits:
Object
  • Object
show all
Defined in:
lib/apns_simple/client.rb

Defined Under Namespace

Classes: CertificateActivenessTimeError

Constant Summary collapse

DEFAULT_CERTIFICATE_PASSWORD =
''
DEFAULT_GATEWAY_URI =
'apn://gateway.push.apple.com:2195'
ERROR_BYTES_COUNT =
6
COMMAND =
8
CODES =
{
  0 => 'No errors encountered',
  1 => 'Processing error',
  2 => 'Missing device token',
  3 => 'Missing topic',
  4 => 'Missing payload',
  5 => 'Invalid token size',
  6 => 'Invalid topic size',
  7 => 'Invalid payload size',
  8 => 'Invalid token',
  10 => 'Shutdown',
  255 => 'Unknown error'
}
TIMEOUT =

In seconds

5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options) ⇒ Client

Returns a new instance of Client.



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/apns_simple/client.rb', line 30

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

Instance Attribute Details

#hostObject (readonly)

Returns the value of attribute host.



9
10
11
# File 'lib/apns_simple/client.rb', line 9

def host
  @host
end

#portObject (readonly)

Returns the value of attribute port.



9
10
11
# File 'lib/apns_simple/client.rb', line 9

def port
  @port
end

#ssl_contextObject (readonly)

Returns the value of attribute ssl_context.



9
10
11
# File 'lib/apns_simple/client.rb', line 9

def ssl_context
  @ssl_context
end

Instance Method Details

#push(notification) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/apns_simple/client.rb', line 48

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