# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs


import json
import hyper.tls
from collections import deque
from decimal import Decimal
from hyper import HTTP20Connection
from hyper.http20.exceptions import HTTP20Error
from autopush.exceptions import RouterException
        """
        body = json.dumps(payload, cls=ComplexEncoder)
        priority = APNS_PRIORITY_IMMEDIATE if priority else APNS_PRIORITY_LOW
        # NOTE: Hyper requires that all header values be strings. 'Priority'
        # is a integer string, which may be "simplified" and cause an error.
        # The added str() function safeguards against that.
        headers = {
            'apns-id': apns_id,
            'apns-priority': str(priority),
            'apns-topic': topic or self.topic,
        }
        if exp:
            headers['apns-expiration'] = str(exp)
        url = '/3/device/' + router_token
        attempt = 0
        while True:
            try:
                connection = self._get_connection()
                # request auto-opens closed connections, so if a connection
                # has timed out or failed for other reasons, it's automatically
                # re-established.
                stream_id = connection.request(
                    'POST', url=url, body=body, headers=headers)
                # get_response() may return an AttributeError. Not really sure
                # how it happens, but the connected socket may get set to None.
                # We'll treat that as a premature socket closure.
                response = connection.get_response(stream_id)
                if response.status != 200:
                    reason = json.loads(
                            response.read().decode('utf-8'))['reason']

# Path: autopush/exceptions.py
# class RouterException(AutopushException):
#     """Exception if routing has failed, may include a custom status_code and
#     body to write to the response.
# 
#     """
#     def __init__(self, message, status_code=500, response_body="",
#                  router_data=None, headers=None, log_exception=True,
#                  errno=None, logged_status=None, **kwargs):
#         """Create a new RouterException"""
#         super(AutopushException, self).__init__(message)
#         self.status_code = status_code
#         self.headers = {} if headers is None else headers
#         self.log_exception = log_exception
#         self.response_body = response_body or message
#         self.errno = errno
#         self.logged_status = logged_status
#         self.extra = kwargs


# Path: autopush/router/apns2.py
import json
import hyper.tls
from collections import deque
from decimal import Decimal
from hyper import HTTP20Connection
from hyper.http20.exceptions import HTTP20Error
from autopush.exceptions import RouterException

        """
        body = json.dumps(payload, cls=ComplexEncoder)
        priority = APNS_PRIORITY_IMMEDIATE if priority else APNS_PRIORITY_LOW
        # NOTE: Hyper requires that all header values be strings. 'Priority'
        # is a integer string, which may be "simplified" and cause an error.
        # The added str() function safeguards against that.
        headers = {
            'apns-id': apns_id,
            'apns-priority': str(priority),
            'apns-topic': topic or self.topic,
        }
        if exp:
            headers['apns-expiration'] = str(exp)
        url = '/3/device/' + router_token
        attempt = 0
        while True:
            try:
                connection = self._get_connection()
                # request auto-opens closed connections, so if a connection
                # has timed out or failed for other reasons, it's automatically
                # re-established.
                stream_id = connection.request(
                    'POST', url=url, body=body, headers=headers)
                # get_response() may return an AttributeError. Not really sure
                # how it happens, but the connected socket may get set to None.
                # We'll treat that as a premature socket closure.
                response = connection.get_response(stream_id)
                if response.status != 200:
                    reason = json.loads(
                            response.read().decode('utf-8'))['reason']

                    raise RouterException(