Created
June 21, 2012 16:11
-
-
Save paukul/2966768 to your computer and use it in GitHub Desktop.
eventmachine based apns push service implementation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'eventmachine' | |
module PushService::Gateways::Apns | |
class EMGateway | |
include PushService::Logging | |
class NotConnected < PushService::Error; end | |
def initialize | |
@error_callback = nil | |
end | |
def push(*notifications) | |
connect unless @connected | |
notifications = notifications.flatten | |
logger.debug "Sending notifications #{notifications.map(&:id).inspect}" | |
apn_messages = notifications.map { |notification| notification.to_enhanced_binary_message }.compact | |
@connection.send_data apn_messages | |
end | |
def disconnect | |
@connection.close_connection_after_writing | |
ensure | |
@connection = nil | |
@connected = false | |
end | |
def on_error(&blk) | |
@error_callback = blk | |
end | |
def error(response) | |
@error_callback.call(response) if @error_callback | |
end | |
private | |
def connect | |
logger.debug("Gateway connection not yet established. connecting...") | |
@connection = EM.connect PushService.host, 2195, GatewayHandler, self | |
logger.debug("Gateway connected") | |
@connected = true | |
end | |
end | |
BadResponse = Struct.new(:error, :command, :status, :identifier) | |
class GatewayHandler < EM::Connection | |
include PushService::Logging | |
ERROR_CODES = [:no_error, :processing_error, :missing_device_token, | |
:missing_topic, :missing_payload, :invalid_token_size, | |
:invalid_topic_size, :invalid_payload_size, :invalid_token] | |
def initialize(gateway) | |
@gateway = gateway | |
end | |
def post_init | |
logger.info("establishing ssh connection with certificate #{PushService.certificate}") | |
start_tls(:cert_chain_file => PushService.certificate, :private_key_file => PushService.certificate, :verify_peer => false) | |
end | |
def receive_data(data) | |
# TODO: write a buffer and extract responses on unbind | |
command, status, identifier = data.unpack("ccN") | |
logger.debug "Received response:" | |
# logger.debug "Command : #{command}" | |
# logger.debug "Status : #{status}" | |
# logger.debug "Identifier : #{identifier}" | |
# logger.debug "Error : #{error_for(status)}" | |
response = BadResponse.new(error_for(status), command, status, identifier) | |
@gateway.error(response) | |
end | |
def unbind | |
logger.info "Terminated connection" | |
@gateway.disconnect | |
end | |
def error_for(code) | |
ERROR_CODES[code] || "Unknown errno #{code}" | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment