Coder Social home page Coder Social logo

pyapns's Introduction

pyapns

A universal Apple Push Notification Service (APNS) provider.

Features:

  • XML-RPC Based, works with any client in any language
  • Native Python API with Django and Pylons support
  • Native Ruby API with Rails/Rack support
  • Scalable, fast and easy to distribute behind a proxy
  • Based on Twisted
  • Multi-application and dual environment support
  • Simplified feedback interface

pyapns is an APNS provider that you install on your server and access through XML-RPC. To install you will need Python, Twisted and pyOpenSSL. It's also recommended to install python-epoll for best performance (if epoll is not available, like on Mac OS X, you may want to use another library, like py-kqueue). If you like easy_install try (it should take care of the dependancies for you):

$ sudo easy_install pyapns

pyapns is a service that runs persistently on your machine. To start it:

$ twistd -r epoll web --class=pyapns.server.APNSServer --port=7077

This will create a twistd.pid file in your current directory that can be used to kill the process. twistd is a launcher used for running network persistent network applications. It takes many more options that can be found by running man twistd or using a web man page.

To get started right away, use the included client:

$ python
>>> from pyapns import configure, provision, notify
>>> configure({'HOST': 'http://localhost:7077/'})
>>> provision('myapp', open('cert.pem').read(), 'sandbox')
>>> notify('myapp', 'hexlified_token_str', {'aps':{'alert': 'Hello!'}})

The Multi-Application Model

pyapns supports multiple applications. Before pyapns can send notifications, you must first provision the application with an Application ID, the environment (either 'sandbox' or 'production') and the certificate file. The provision method takes 4 arguments, app_id, path_to_cert_or_cert, environment and timeout. A connection is kept alive for each application provisioned for the fastest service possible. The application ID is an arbitrary identifier and is not used in communication with the APNS servers.

When a connection can not be made within the specified timeout a timeout error will be thrown by the server. This usually indicates that the wrong [type of] certification file is being used, a blocked port or the wrong environment.

Attempts to provision the same application id multiple times are ignored.

Sending Notifications

Calling notify will send the message immediately if a connection is already established. The first notification may be delayed a second while the server connects. notify takes app_id, token_or_token_list and notification_or_notification_list. Multiple notifications can be batched for better performance by using paired arrays of token/notifications. When performing batched notifications, the token and notification arrays must be exactly the same length.

The full notification dictionary must be included as the notification:

{'aps': {
    'sound': 'flynn.caf',
    'badge': 0,
    'message': 'Hello from pyapns :)'
  }
} # etc...

Retrieving Inactive Tokens

Call feedback with the app_id. A list of tuples will be retrieved from the APNS server that it deems inactive. These are returned as a list of 2-element lists with a Datetime object and the token string.

XML-RPC Methods

These methods can be called on the server you started the server on. Be sure you are not including /RPC2 in the URL.

provision

  Arguments
      app_id        String            the application id for the provided
                                      certification
      cert          String            a path to a .pem file or the a
                                      string with the entie file
      environment   String            the APNS server to use - either
                                      'production' or 'sandbox'
      timeout       Integer           timeout for connection attempts to
                                      the APS servers
  Returns
      None

notify

  Arguments
      app_id        String            the application id to send the
                                      message to
      tokens        String or Array   an Array of tokens or a single
                                      token string
      notifications String or Array   an Array of notification
                                      dictionaries or a single
                                      notification dictionary
  
  Returns
      None

feedback

  Arguments
      app_id        String            the application id to retrieve
                                      retrieve feedback for
  
  Returns
      Array(Array(Datetime(time_expired), String(token)), ...)

The Python API

pyapns also provides a Python API that makes the use of pyapns even simpler. The Python API must be configured before use but configuration files make it easier. The pyapns client module currently supports configuration from Django settings and Pylons config. To configure using Django, the following must be present in your settings file:

PYAPNS_CONFIG = {
  'HOST': 'http://localhost:8077/',
  'TIMEOUT': 15,                    # OPTIONAL, host timeout in seconds
  'INITIAL': [                      # OPTIONAL, see below
    ('craigsfish', '/home/samsutch/craigsfish/apscert.pem', 'sandbox'),
  ]
}

Optionally, with Django settings, you can skip manual provisioning by including a list of (name, path, environment) tuples that are guaranteed to be provisioned by the time you call notify or feedback.

Configuring for pylons is just as simple, but automatic provisioning isn't possible, in your configuration file include:

pyapns_host = http://localhost:8077/
pyapns_timeout = 15

For explanations of the configuration variables see the docs for pyapns.client.configure.

Each of these functions can be called synchronously and asynchronously. To make them perform asynchronously simply supply a callback and pass async=True to the function. The request will then be made in another thread and your callback will be executed with the results. When calling asynchronously no value will be returned:

def got_feedback(tuples):
  trim_inactive_tokens(tuples)
feedback('myapp', async=True, callback=got_feedback)

pyapns.client.configure(opts)

Takes a dictionary of options and configures the client. 
Currently configurable options are 'HOST', 'TIMEOUT' and 'INITIAL' 
the latter of which is only read once.

Config Options:
    HOST        - A full host name with port, ending with a forward slash
    TIMEOUT     - An integer specifying how many seconds to timeout a
                  connection to the pyapns server (prevents deadlocking
                  the parent thread).
    INITIAL     - A List of tuples to be supplied to provision when
                  the first configuration happens.

pyapns.client.provision(app_id, path_to_cert_or_cert, environment, timeout=15, async=False, callback=None, errback=None)

Provisions the app_id and initializes a connection to the APNS server.
Multiple calls to this function will be ignored by the pyapns daemon
but are still sent so pick a good place to provision your apps, optimally
once.

Arguments:
    app_id                 the app_id to provision for APNS
    path_to_cert_or_cert   absolute path to the APNS SSL cert or a 
                           string containing the .pem file
    environment            either 'sandbox' or 'production'
    timeout                number of seconds to timeout connection
                           attempts to the APPLE APS SERVER
    async                  pass something truthy to execute the request in a 
                           background thread
    callback               a function to be executed with the result
    errback                a function to be executed with the error in case of an error

Returns:
    None

pyapns.client.notify(app_id, tokens, notifications, async=False, callback=None, errback=None)

Sends push notifications to the APNS server. Multiple 
notifications can be sent by sending pairing the token/notification
arguments in lists [token1, token2], [notification1, notification2].

Arguments:
    app_id                 provisioned app_id to send to
    tokens                 token to send the notification or a 
                           list of tokens
    notifications          notification dict or a list of notification dicts
    async                  pass something truthy to execute the request in a 
                           background thread
    callback               a function to be executed with the result when done
    errback                a function to be executed with the error in case of an error

  Returns:
      None

pyapns.client.feedback(app_id, async=False, callback=None, errback=None)

Retrieves a list of inactive tokens from the APNS server and the times
it thinks they went inactive.

Arguments:
    app_id                 the app_id to query
    async                  pass something truthy to execute the request in 
                           a background thread
    callback               a function to be executed with the result when 
                           feedbacks are done fetching
    errback                a function to be executed with the error if there
                           is one during the request

Returns:
    List of feedback tuples like [(datetime_expired, token_str), ...]

The Ruby API

PYAPNS::Client

There's python in my ruby!

The ruby gem can be installed from here

This is a class used to send notifications, provision applications and retrieve feedback using the Apple Push Notification Service.

PYAPNS is a multi-application APS provider, meaning it is possible to send notifications to any number of different applications from the same application and same server. It is also possible to scale the client to any number of processes and servers, simply balanced behind a simple web proxy.

It may seem like overkill for such a bare interface - after all, the APS service is rather simplistic. However, PYAPNS takes no shortcuts when it comes to completeness/compliance with the APNS protocol and allows the user many optimization and scaling vectors not possible with other libraries. No bandwidth is wasted, connections are persistent and the server is asynchronous therefore notifications are delivered immediately.

PYAPNS takes after the design of 3rd party push notification service that charge a fee each time you push a notification, and charge extra for so-called 'premium' service which supposedly gives you quicker access to the APS servers. However, PYAPNS is free, as in beer and offers more scaling opportunities without the financial draw.

Provisioning

To add your app to the PYAPNS server, it must be provisioned at least once. Normally this is done once upon the start-up of your application, be it a web service, desktop application or whatever... It must be done at least once to the server you're connecting to. Multiple instances of PYAPNS will have to have their applications provisioned individually. To provision an application manually use the PYAPNS::Client#provision method.

require 'pyapns'
client = PYAPNS::Client.configure
client.provision :app_id => 'cf', :cert => '/home/ss/cert.pem', :env => 'sandbox', :timeout => 15

This basically says "add an app reference named 'cf' to the server and start a connection using the certification, and if it can't within 15 seconds, raise a PYAPNS::TimeoutException

That's all it takes to get started. Of course, this can be done automatically by using PYAPNS::ClientConfiguration middleware. PYAPNS::Client is a singleton class that is configured using the class method PYAPNS::Client#configure. It is sensibly configured by default, but can be customized by specifying a hash See the docs on PYAPNS::ClientConfiguration for a list of available configuration parameters (some of these are important, and you can specify initial applications) to be configured by default.

Sending Notifications

Once your client is configured, and application provisioned (again, these should be taken care of before you write notification code) you can begin sending notifications to users. If you're wondering how to acquire a notification token, you've come to the wrong place... I recommend using google. However, if you want to send hundreds of millions of notifications to users, here's how it's done, one at a time...

The PYAPNS::Client#notify is a sort of polymorphic method which can notify any number of devices at a time. It's basic form is as follows:

client.notify 'cf', 'long ass app token', {:aps=> {:alert => 'hello?'}}

However, as stated before, it is sort of polymorphic:

client.notify 'cf', ['token', 'token2', 'token3'], [alert, alert2, alert3]

client.notify :app_id => 'cf', :tokens => 'mah token', :notifications => alertHash

client.notify 'cf', 'token', PYAPNS::Notification('hello tits!')

As you can see, the method accepts paralell arrays of tokens and notifications meaning any number of notifications can be sent at once. Hashes will be automatically converted to PYAPNS::Notification objects so they can be optimized for the wire (nil values removed, etc...), and you can pass PYAPNS::Notification objects directly if you wish.

Retrieving Feedback

The APS service offers a feedback functionality that allows application servers to retrieve a list of device tokens it deems to be no longer in use, and the time it thinks they stopped being useful (the user uninstalled your app, better luck next time...) Sounds pretty straight forward, and it is. Apple recommends you do this at least once an hour. PYAPNS will return a list of 2-element lists with the date and the token:

feedbacks = client.feedback 'cf'

Asynchronous Calls

PYAPNS::Client will, by default, perform no funny stuff and operate entirely within the calling thread. This means that certain applications may hang when, say, sending a notification, if only for a fraction of a second. Obviously not a desirable trait, all provision, feedback and notify methods also take a block, which indicates to the method you want to call PYAPNS asynchronously, and it will be done so handily in another thread, calling back your block with a single argument when finished. Note that notify and provision return absolutely nothing (nil, for you rub--wait you are ruby developers!). It is probably wise to always use this form of operation so your calling thread is never blocked (especially important in UI-driven apps and asynchronous servers) Just pass a block to provision/notify/feedback like so:

PYAPNS::Client.instance.feedback do |feedbacks|
  feedbacks.each { |f| trim_token f }
end

PYAPNS::ClientConfiguration

A middleware class to make PYAPNS::Client easy to use in web contexts

Automates configuration of the client in Rack environments using a simple confiuration middleware. To use PYAPNS::Client in Rack environments with the least code possible use PYAPNS::ClientConfiguration (no, really, in some cases, that's all you need!) middleware with an optional hash specifying the client variables. Options are as follows:

 use PYAPNS::ClientConfiguration(
      :host => 'http://localhost/' 
      :port => 7077,
      :initial => [{
          :app_id => 'myapp',
          :cert => '/home/myuser/apps/myapp/cert.pem',
          :env => 'sandbox',
          :timeout => 15
 }])

Where the configuration variables are defined:

:host     String      the host where the server can be found
:port     Number      the port to which the client should connect
:initial  Array       OPTIONAL - an array of INITIAL hashes

INITIAL HASHES:

:app_id   String      the id used to send messages with this certification
                      can be a totally arbitrary value
:cert     String      a path to the certification or the certification file
                      as a string
:env      String      the environment to connect to apple with, always
                      either 'sandbox' or 'production'
:timoeut  Number      The timeout for the server to use when connecting
                      to the apple servers

PYAPNS::Notification

An APNS Notification

You can construct notification objects ahead of time by using this class. However unnecessary, it allows you to programmatically generate a Notification like so:

note = PYAPNS::Notification.new 'alert text', 9, 'flynn.caf', {:extra => 'guid'}

-- or --
note = PYAPNS::Notification.new 'alert text'

These can be passed to PYAPNS::Client#notify the same as hashes

pyapns's People

Contributors

bryant1410 avatar bunnyhero avatar jawj avatar samuraisam avatar ssutch avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyapns's Issues

pyapns fails to start (syntax error)

Occurs with the rest-service branch.

 * Starting pyapns... Traceback (most recent call last):
  File "/usr/local/bin/twistd", line 5, in <module>
    pkg_resources.run_script('Twisted==11.0.0', 'twistd')
  File "build/bdist.linux-i686/egg/pkg_resources.py", line 489, in run_script
  File "build/bdist.linux-i686/egg/pkg_resources.py", line 1207, in run_script
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/EGG-INFO/scripts/twistd", line 19, in <module>
    run()
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/scripts/twistd.py", line 27, in run
    app.run(runApp, ServerOptions)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/application/app.py", line 617, in run
    config.parseOptions()
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/application/app.py", line 595, in parseOptions
    usage.Options.parseOptions(self, options)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/python/usage.py", line 231, in parseOptions
    self.subOptions.parseOptions(rest)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/python/usage.py", line 219, in parseOptions
    self._dispatch[optMangled](optMangled, arg)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/python/usage.py", line 382, in <lambda>
    fn = lambda name, value, m=method: m(value)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/web/tap.py", line 122, in opt_class
    classObj = reflect.namedClass(className)
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/python/reflect.py", line 351, in namedObject
    module = namedModule('.'.join(classSplit[:-1]))
  File "/usr/local/lib/python2.7/site-packages/Twisted-11.0.0-py2.7-linux-x86_64.egg/twisted/python/reflect.py", line 339, in namedModule
    topLevel = __import__(name)
  File "/usr/local/lib/python2.7/site-packages/pyapns-0.3.3-py2.7.egg/pyapns/server.py", line 640
    _list = lambda v: v if type(v) is list else [v]
        ^
SyntaxError: invalid syntax

socket.timeout error

For some reason, I keep getting
socket.timeout: time out error

Traceback (most recent call last):
  File "provider.py", line 4, in <module>
    provision('com.jaychae.EWSApp', open('ews.pem').read(), 'sandbox', 5000)
  File "/Library/Python/2.7/site-packages/pyapns/client.py", line 75, in wrapper
    return func(*a, **kw)
  File "/Library/Python/2.7/site-packages/pyapns/client.py", line 67, in wrapper
    return func(*a, **kw)
  File "/Library/Python/2.7/site-packages/pyapns/client.py", line 85, in provision
    return _xmlrpc_thread(*f_args)
  File "/Library/Python/2.7/site-packages/pyapns/client.py", line 122, in _xmlrpc_thread
    return callback(proxy(*args))
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1224, in __call__
    return self.__send(self.__name, args)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1570, in __request
    verbose=self.__verbose
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1264, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1294, in single_request
    response = h.getresponse(buffering=True)
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 1013, in getresponse
    response.begin()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 402, in begin
    version, status, reason = self._read_status()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/httplib.py", line 360, in _read_status
    line = self.fp.readline()
  File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/socket.py", line 447, in readline
    data = self._sock.recv(self._rbufsize)
socket.timeout: timed out

XMLRPC sends a different message vs python

Works, sent via CLI:

0000206bcda4c0d2cd5fc1835ada95bd25fb1bbad39edb344699fc33e4e975caffc8ab00177b22617073223a207b22616c657274223a202235227d7d

Decoded:

๏ฟฝ๏ฟฝ kรยคร€ร’ร_ร๏ฟฝZรš๏ฟฝยฝ%รป ยบร“๏ฟฝร›4F๏ฟฝรผ3รครฉuรŠรฟรˆยซ๏ฟฝ {"aps": {"alert": "5"}}

Works NOT, sent via XMLRPC:

0000206bcda4c0d2cd5fc1835ada95bd25fb1bbad39edb344699fc33e4e975caffc8ab0019227b27617073273a7b27616c657274273a20273527207d7d22

Decoded:

๏ฟฝ๏ฟฝ kรยคร€ร’ร_ร๏ฟฝZรš๏ฟฝยฝ%รป ยบร“๏ฟฝร›4F๏ฟฝรผ3รครฉuรŠรฟรˆยซ๏ฟฝ "{'aps':{'alert': '5' }}"

Those quotation marks are NOT in the xml payload sent to the XMLRPC server. Ideas?

Fault 500: 'Connection to the APNS server could not be made.'

The XML-RPC client got error <Fault 500: 'Connection to the APNS server could not be made.'>

Server logs:

2012-06-05 04:45:03+0000 [Uninitialized] "errback in apns-service-write : [Failure instance: Traceback: <type 'exceptions.AttributeError'>: 'NoneType' object h
as no attribute 'sendMessage'\n/opt/lib/python2.7/site-packages/pyapns/server.py:74:connectionMade\n/opt/lib/python2.7/site-packages/pyapns/server.py:141:addCl
ient\n/opt/lib/python2.7/site-packages/twisted/internet/defer.py:368:callback\n/opt/lib/python2.7/site-packages/twisted/internet/defer.py:464:_startRunCallback
s\n--- <exception caught here> ---\n/opt/lib/python2.7/site-packages/twisted/internet/defer.py:551:_runCallbacks\n/opt/lib/python2.7/site-packages/pyapns/serve
r.py:210:<lambda>\n]"
2012-06-05 04:45:03+0000 [HTTPChannel,388658,50.18.191.88] 50.18.191.88 - - [05/Jun/2012:04:45:03 +0000] "POST / HTTP/1.1" 500 7058 "-" "xmlrpclib.py/1.0.1 (by
 www.pythonware.com)"
2012-06-05 04:45:03+0000 [HTTPChannel,388659,50.18.191.88] Unhandled Error
        Traceback (most recent call last):
          File "/opt/lib/python2.7/site-packages/twisted/web/http.py", line 1349, in dataReceived
            finishCallback(data[contentLength:])
          File "/opt/lib/python2.7/site-packages/twisted/web/http.py", line 1563, in _finishRequestBody
            self.allContentReceived()
          File "/opt/lib/python2.7/site-packages/twisted/web/http.py", line 1618, in allContentReceived
            req.requestReceived(command, path, version)
          File "/opt/lib/python2.7/site-packages/twisted/web/http.py", line 773, in requestReceived
            self.process()
        --- <exception caught here> ---
          File "/opt/lib/python2.7/site-packages/twisted/web/server.py", line 132, in process
            self.render(resrc)
          File "/opt/lib/python2.7/site-packages/twisted/web/server.py", line 167, in render
            body = resrc.render(self)
          File "/opt/lib/python2.7/site-packages/twisted/web/resource.py", line 216, in render
            return m(request)
          File "/opt/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 160, in render_POST
            function = self.lookupProcedure(functionPath)
          File "/opt/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 232, in lookupProcedure
            handler = self.getSubHandler(prefix)
          File "/opt/lib/python2.7/site-packages/twisted/web/xmlrpc.py", line 140, in getSubHandler
            return self.subHandlers.get(prefix, None)
        exceptions.AttributeError: APNSServer instance has no attribute 'subHandlers'

2012-06-05 04:45:03+0000 [HTTPChannel,388659,50.18.191.88] 50.18.191.88 - - [05/Jun/2012:04:45:03 +0000] "POST / HTTP/1.1" 500 7058 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"

I suspect the relevant piece is <type 'exceptions.AttributeError'>: 'NoneType' object has no attribute 'sendMessage'

Help using pyapns on dotcloud

Hi,
I don't know if it is dotcloud-related or not but I have trouble setting up pyapns :

I want to use master branche of pyapns.
First I tried to add it to my supervisord configuration :

[program pyapns]
directory = $HOME/current/
command = twistd -r epoll web --class=pyapns.server.APNSServer --port=tcp:7077
stderr_logfile = /var/log/supervisor/%(program_name)s_error.log
stdout_logfile = /var/log/supervisor/%(program_name)s.log

It's a bit strange because it didn't appear in process list :

(2.6)dotcloud@managerdev-default-workers-0:~$ ps -edf
UID PID PPID C STIME TTY TIME CMD
dotcloud 143 1 0 08:34 ? 00:00:00 /usr/bin/python /usr/bin/supervisord.real
dotcloud 151 143 0 08:34 ? 00:00:01 python managerdev/manage.py celerybeat -S djcelery.schedulers.DatabaseScheduler
dotcloud 178 146 1 08:34 ? 00:00:02 python managerdev/manage.py celeryd -Q all,default --loglevel INFO --concurrency 1

Anyway, I tried to use it

(2.6)dotcloud@managerdev-default-workers-0:~$ python
>>> from pyapns import configure, provision, notify
>>> configure({'HOST': 'http://localhost:7077/'})
True
>>> provision('myApp',open('code/managerdev/sendingAPI/APNS_pem_files/myApp/apns_prod_myApp.pem').read(),'production')

and here I got :

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/opt/ve/2.6/lib/python2.6/site-packages/pyapns/client.py", line 75, in wrapper
    return func(*a, **kw)
  File "/opt/ve/2.6/lib/python2.6/site-packages/pyapns/client.py", line 67, in wrapper
    return func(*a, **kw)
  File "/opt/ve/2.6/lib/python2.6/site-packages/pyapns/client.py", line 85, in provision
    return _xmlrpc_thread(*f_args)
  File "/opt/ve/2.6/lib/python2.6/site-packages/pyapns/client.py", line 122, in _xmlrpc_thread
    return callback(proxy(*args))
  File "/usr/lib/python2.6/xmlrpclib.py", line 1199, in __call__
    return self.__send(self.__name, args)
  File "/usr/lib/python2.6/xmlrpclib.py", line 1489, in __request
    verbose=self.__verbose
  File "/usr/lib/python2.6/xmlrpclib.py", line 1235, in request
    self.send_content(h, request_body)
  File "/usr/lib/python2.6/xmlrpclib.py", line 1349, in send_content
    connection.endheaders()
  File "/usr/lib/python2.6/httplib.py", line 904, in endheaders
    self._send_output()
  File "/usr/lib/python2.6/httplib.py", line 776, in _send_output
    self.send(msg)
  File "/usr/lib/python2.6/httplib.py", line 735, in send
    self.connect()
  File "/opt/ve/2.6/lib/python2.6/site-packages/pyapns/client.py", line 155, in connect
    httplib.HTTPConnection.connect(self)
  File "/usr/lib/python2.6/httplib.py", line 716, in connect
    self.timeout)
  File "/usr/lib/python2.6/socket.py", line 514, in create_connection
    raise error, msg
socket.error: [Errno 111] Connection refused

Then I tried to follow pyapns guidelines on how to use it with django.

I removed stuff from postinstall and added this to my settings.py :

PYAPNS_CONFIG = {
    'HOST': 'http://localhost:7077/',
    'TIMEOUT': 15,                    # OPTIONAL, host timeout in seconds
    'INITIAL': [                      # OPTIONAL, see below
        ('myApp', os.path.normpath(os.path.join(FILES_ROOT_DIR, "sendingAPI/APNS_pem_files/myApp/apns_prod_myApp.pem")),'production')
    ]
}

And then tried to use it using the django shell.
I have exactly the same error on every 'configure', 'provision' or 'notify' I tried.

Can you help about it?
Maybe there is a problem with the 7077 port on the localhost loop?
Any clue?

push for 'production' doesn't work with pyOpenSSL==0.13

Sorry for my poor english.

I'm using pyapns as ios push server, with Twisted.

When i sent push messages for sandbox, all is good. but for production,

with pyOpenSSL==0.13 library, it shows me a lot of error messages.

In exactly, 'feedback' action did it.

pyOpenSSL==0.10 works well.

followings are error messages for each condition.


pyOpenSSL==0.13

2013-03-26 15:47:12+0900 [HTTPChannel,100,127.0.0.1] 127.0.0.1 - - [26/Mar/2013:06:47:11 +0000] "POST / HTTP/1.0" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2013-03-26 15:47:12+0900 [HTTPChannel,101,127.0.0.1] APNSService read (connecting)
2013-03-26 15:47:12+0900 [HTTPChannel,101,127.0.0.1] APNSClientContextFactory ssl_cert_file={FROM_STRING}
2013-03-26 15:47:12+0900 [HTTPChannel,101,127.0.0.1] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0x1b845a8>
2013-03-26 15:47:12+0900 [HTTPChannel,101,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2013-03-26 15:47:12+0900 [Uninitialized] feedbackHandler connectionMade
2013-03-26 15:47:12+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] feedbackHandler connectionLost [Failure instance: Traceback: <class 'OpenSSL.SSL.Error'>: [('SSL routines', 'SSL3_READ_BYTES', 'sslv3 alert certificate expired'), ('SSL routines', 'SSL3_READ_BYTES', 'ssl handshake failure')]
/usr/local/lib/python2.6/dist-packages/twisted/internet/posixbase.py:614:_doReadOrWrite
/usr/local/lib/python2.6/dist-packages/twisted/internet/tcp.py:215:doRead
/usr/local/lib/python2.6/dist-packages/twisted/internet/tcp.py:221:_dataReceived
/usr/local/lib/python2.6/dist-packages/twisted/protocols/tls.py:419:dataReceived
--- ---
/usr/local/lib/python2.6/dist-packages/twisted/protocols/tls.py:358:_flushReceiveBIO
]
2013-03-26 15:47:12+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] 127.0.0.1 - - [26/Mar/2013:06:47:11 +0000] "POST / HTTP/1.0" 200 138 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2013-03-26 15:47:12+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] APNSFeedbackClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.
]
2013-03-26 15:47:12+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSFeedbackClientFactory instance at 0x1b845a8>


pyOpenSSL==0.10

2013-03-26 16:06:14+0900 [HTTPChannel,14,127.0.0.1] 127.0.0.1 - - [26/Mar/2013:07:06:14 +0000] "POST / HTTP/1.0" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2013-03-26 16:06:14+0900 [HTTPChannel,15,127.0.0.1] APNSService read (connecting)
2013-03-26 16:06:14+0900 [HTTPChannel,15,127.0.0.1] APNSClientContextFactory ssl_cert_file={FROM_STRING}
2013-03-26 16:06:14+0900 [HTTPChannel,15,127.0.0.1] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0x175acf8>
2013-03-26 16:06:14+0900 [HTTPChannel,15,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2013-03-26 16:06:15+0900 [Uninitialized] feedbackHandler connectionMade
2013-03-26 16:06:15+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2013-03-26 16:06:15+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] 127.0.0.1 - - [26/Mar/2013:07:06:15 +0000] "POST / HTTP/1.0" 200 138 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2013-03-26 16:06:15+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] APNSFeedbackClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2013-03-26 16:06:15+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSFeedbackClientFactory instance at 0x175acf8>

clientConnectionLost vs clientConnectionFailed

I apologise if this is a stupid question: I've little-to-no Python or Twisted experience.

Browsing throught the code, I notice that in APNSFeedbackClientFactory, clientConnectionFailed is forwarded to ReconnectingClientFactory.clientConnectionLost (rather than the intuitively more obvious ReconnectingClientFactory.clientConnectionFailed):

def clientConnectionLost(self, connector, reason):
    log.msg('APNSClientFactory clientConnectionLost reason=%s' % reason)
    ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

def clientConnectionFailed(self, connector, reason):
    log.msg('APNSClientFactory clientConnectionFailed reason=%s' % reason)
    ReconnectingClientFactory.clientConnectionLost(self, connector, reason)

I just wanted to check that this was intentional, and not a copy/paste oversight!

Multiple notifications while disconnected

When APNS connection is not established you defer sending the notification with this line:

d.addCallback(lambda p: p.sendMessage(notifications))

When sending multiple notifications those callbacks are chained and second one fails because first one doesn't return p. I think it should be:

def connected(protocol):
protocol.sendMessage(notifications)
return protocol

d.addCallback(connected)

Can not install pyapns with easy_install

sourceforge.net is blocked in China. So when I install pyapns with easy_install, it gives me a 'tImeout' error:

easy_install pyapns
Searching for pyapns
Best match: pyapns 0.4.0
Processing pyapns-0.4.0-py2.4.egg
pyapns 0.4.0 is already the active version in easy-install.pth

Using /usr/lib/python2.4/site-packages/pyapns-0.4.0-py2.4.egg
Processing dependencies for pyapns
Searching for pyOpenSSL>=0.10
Reading http://cheeseshop.python.org/pypi/pyOpenSSL/
Reading http://pyopenssl.sourceforge.net/
error: Download error: (110, 'Connection timed out')

I want to know how can I install it manually?

pyapns.provision() throws an error in Python 2.7

Using Python 2.7, calling pyapns.provision() throws an exception:

  File "<stdin>", line 1, in <module>
  File "PushTester.py", line 23, in registerStuff
    pyapns.provision('pushtest', open('apns-dev.pem').read(), 'sandbox')
  File "/Users/bunnyhero/virtualenvs/push27/src/pyapns/pyapns/client.py", line 46, in provision
    return _xmlrpc_thread('provision', args, lambda r: r)
  File "/Users/bunnyhero/virtualenvs/push27/src/pyapns/pyapns/client.py", line 76, in _xmlrpc_thread
    return callback(proxy(*args))
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1224, in __call__
    return self.__send(self.__name, args)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1570, in __request
    verbose=self.__verbose
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1264, in request
    return self.single_request(host, handler, request_body, verbose)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/xmlrpclib.py", line 1294, in single_request
    response = h.getresponse(buffering=True)
AttributeError: TimeoutHTTP instance has no attribute 'getresponse'

Some googling seems to indicate that Python 2.7 has made changes to xmlrpc. These issues in other software seem to be similar: https://bugzilla.redhat.com/show_bug.cgi?id=619276 and http://www.gossamer-threads.com/lists/xen/devel/182210

Ruby client issues (on 1.9.1)

Trying out the pyapns client on Ruby 1.9.1, I had a couple of issues:

  1. On client.provision, I get:
RuntimeError: wrong/unknown XML-RPC type 'nil'

Some digging into XMLRPC enables me to fix this by setting

XMLRPC::Config::ENABLE_NIL_PARSER = true 

before provisioning. (Update: I've now fixed this in my fork of the project).

  1. The array variant of client.notify works fine -- e.g.
client.notify :app_id => 'cf',  :tokens => ['XYZ'], :notifications => [{:aps => {:alert => 'Ciao!'}}]

But the non-array version (i.e. removing both sets of square brackets from the above) gives:

XMLRPC::FaultException: XMLRPC::FaultException

Feedback handler hanging on timeout from apple

Running v50 branch.

2013-10-16 11:54:38-0400 [-] twistd 13.1.0 (/usr/bin/python 2.6.6) starting up.

Feedback for the sandbox app was called hourly by the client, so 3 prior attempts successful, when the timeout from Apple was handled the following appeared in the log.

The connection to the calling client requesting the feedback check is not disconnected and the connection can hang indefinitely if the client does not timeout (I know as this is a bug in my client code).

Once the client is disconnected, pyapns appears to continue to run without issue.

2013-10-16 17:26:05-0400 [HTTPChannel,18,10.1.1.242] APNSService read (connecting)
2013-10-16 17:26:05-0400 [HTTPChannel,18,10.1.1.242] APNSClientContextFactory ssl_cert_file=XXXXX.pem
2013-10-16 17:26:05-0400 [HTTPChannel,18,10.1.1.242] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0x245e050>
2013-10-16 17:26:05-0400 [HTTPChannel,18,10.1.1.242] APNSFeedbackClientFactory startedConnecting
2013-10-16 17:26:05-0400 [Uninitialized] feedbackHandler connectionMade
2013-10-16 17:26:20-0400 [-] "errback in apns-feedback-read : [Failure instance: Traceback (failure with no frames): <type 'exceptions.Exception'>: Feedbcak fetch timed out after 15 seconds\n]"
2013-10-16 17:26:23-0400 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2013-10-16 17:26:23-0400 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] Unhandled Error
Traceback (most recent call last):
File "/usr/lib64/python2.6/site-packages/twisted/application/app.py", line 323, in runReactorWithLogging
reactor.run()
File "/usr/lib64/python2.6/site-packages/twisted/internet/base.py", line 1192, in run
self.mainLoop()
File "/usr/lib64/python2.6/site-packages/twisted/internet/base.py", line 1204, in mainLoop
self.doIteration(t)
File "/usr/lib64/python2.6/site-packages/twisted/internet/epollreactor.py", line 372, in doPoll
log.callWithLogger(selectable, _drdw, selectable, fd, event)
--- ---
File "/usr/lib64/python2.6/site-packages/twisted/python/log.py", line 88, in callWithLogger
return callWithContext({"system": lp}, func, _args, *_kw)
File "/usr/lib64/python2.6/site-packages/twisted/python/log.py", line 73, in callWithContext
return context.call({ILogContext: newCtx}, func, _args, *_kw)
File "/usr/lib64/python2.6/site-packages/twisted/python/context.py", line 118, in callWithContext
return self.currentContext().callWithContext(ctx, func, _args, *_kw)
File "/usr/lib64/python2.6/site-packages/twisted/python/context.py", line 81, in callWithContext
return func(args,*kw)
File "/usr/lib64/python2.6/site-packages/twisted/internet/posixbase.py", line 614, in _doReadOrWrite
self._disconnectSelectable(selectable, why, inRead)
File "/usr/lib64/python2.6/site-packages/twisted/internet/posixbase.py", line 260, in _disconnectSelectable
selectable.connectionLost(f)
File "/usr/lib64/python2.6/site-packages/twisted/internet/tcp.py", line 485, in connectionLost
self._commonConnection.connectionLost(self, reason)
File "/usr/lib64/python2.6/site-packages/twisted/internet/tcp.py", line 299, in connectionLost
protocol.connectionLost(reason)
File "/usr/lib64/python2.6/site-packages/twisted/protocols/tls.py", line 466, in connectionLost
ProtocolWrapper.connectionLost(self, reason)
File "/usr/lib64/python2.6/site-packages/twisted/protocols/policies.py", line 125, in connectionLost
self.wrappedProtocol.connectionLost(reason)
File "/home/bdavis/github/pyapns/pyapns/server.py", line 113, in connectionLost
self.deferred.callback(self.io.getvalue())
File "/usr/lib64/python2.6/site-packages/twisted/internet/defer.py", line 380, in callback
self._startRunCallbacks(result)
File "/usr/lib64/python2.6/site-packages/twisted/internet/defer.py", line 481, in _startRunCallbacks
raise AlreadyCalledError
twisted.internet.defer.AlreadyCalledError:

Error while sending notification

Hi,

I have configured the pyapns server (with Twistd 12.0.0.) and get errors with both ruby (1.9.3p125) client and python (2.7.2) client when I try the following command and all its polymorphic forms :

    client.notify 'my_app_id', 'my_device_token', {:aps=> {:alert => 'hello?'}}

server side :

    Traceback (most recent call last):
      File "/usr/local/lib/python2.7/dist-packages/Twisted-12.0.0-py2.7-linux-x86_64.egg/twisted/web/server.py", line 132, in process
        self.render(resrc)
      File "/usr/local/lib/python2.7/dist-packages/Twisted-12.0.0-py2.7-linux-x86_64.egg/twisted/web/server.py", line 167, in render
        body = resrc.render(self)
      File "/usr/local/lib/python2.7/dist-packages/Twisted-12.0.0-py2.7-linux-x86_64.egg/twisted/web/resource.py", line 216, in render
        return m(request)
      File "/usr/local/lib/python2.7/dist-packages/Twisted-12.0.0-py2.7-linux-x86_64.egg/twisted/web/xmlrpc.py", line 172, in render_POST
        d = defer.maybeDeferred(function, *args)
    --- <exception caught here> ---
      File "/usr/local/lib/python2.7/dist-packages/Twisted-12.0.0-py2.7-linux-x86_64.egg/twisted/internet/defer.py", line 134, in maybeDeferred
        result = f(*args, **kw)
      File "/usr/local/lib/python2.7/dist-packages/pyapns-0.4.0-py2.7.egg/pyapns/server.py", line 292, in xmlrpc_notify
        aps_dict_or_list))
      File "/usr/local/lib/python2.7/dist-packages/pyapns-0.4.0-py2.7.egg/pyapns/server.py", line 199, in write
        return client.sendMessage(notifications)
      File "/usr/local/lib/python2.7/dist-packages/pyapns-0.4.0-py2.7.egg/pyapns/server.py", line 77, in sendMessage
        log.msg('APNSProtocol sendMessage msg=%s' % binascii.hexlify(msg))
    exceptions.TypeError: must be string or buffer, not None

client side : error 8002

deployment support (init.d, launchd, etc.)

This is truly great, I think you've saved me a ton of time, so thanks! The one thing that's left to make this a drop-in solution would be deployment scripts. I know python pretty well but twisted, not so much, so I'm not sure how to set up an init.d script on my server to keep pyapns running across reboots. There's some relevant information here:

http://twistedmatrix.com/trac/ticket/3434

The foobarplugin script looks interesting but I don't know if pyapns is a "Twisted plugin" suitable for that script. I'm planning on hacking on it a bit to see if I can make it work nonetheless.

Dropped connection on invalid token

It looks like APNS drops your connection if you try to send an invalid token. This is pretty easy to trigger if, say, you accidentally send a sandbox token to the production server. Correct me if I'm mistaken, but it doesn't look like pyapns gives you any indication that something has gone wrong in this situation. It would be nice if notify raised an exception when this happened. It would be even nicer if it contained the token that was sent just before the connection was dropped.

Thanks -- I'm still loving pyapns!

Log files and logging volume

pyapns is working really well for me aside for logging. It logs every message it sends in its entirety and splits off a new log file every 1MB or so, creating tons of log files very quickly. I would love to have some options for logging volume:

  • verbose : the current behavior
  • quiet : only log connect/disconnect from Apple
  • default : log a short note (e.g. "sent a message") each time a notification is successfully sent

I would also really like it if I could ask pyapns to limit itself to some fixed number of logfiles. I think twistd might have some way of configuring such a thing but if so I couldn't figure it out.

Thanks!

I have a problem with 'production' mode.

Hi there I have been successfully using this library.

However, a problem has occurred.
After it was changed to production mode, transfer has been well in the app built in Xcode,
but in the app that downloaded from the store, it does not work properly.

I'm so embarrassed. Because it does not work in the market shortly after the release of the app.
Fortunately, our app did not start the marketing. but if there are people who know about fixing this problem, I want to ask a quick response .


--coding:utf-8--

from pyapns import configure, provision, notify
configure({'HOST': 'http://localhost:7077/'})
provision('app', open('combined.pem').read(), 'production')
notify('app', 'uuid', {'aps':{'alert': 'Goooood.'}})

-> Process finished with exit code 0

But It was not operated.

  • Twisted is operating normally .
  • 'combined.pem' is configured with 'apns pem + unencrypted key'.

Thanks.

Apple Dropping Connection

We should look at tracking if/when a connection is severed by Apple's server.

If it after a specific message it may be an invalid token (debug send to production gateway or vice versa)
If it's unable to connect initially then it's likely the PEM file is screwed.

Very large batches fail

We've been trying to speed up our notification sending by using large batches. When we send a large enough batch, there is nothing logged in the pyapns log and the batch fails to be sent.

Batch of 1000 - success
Batch of 2000 - success
Batch of 3000 - failure, nothing logged to hint at what went wrong

We're using XMLRPC, sent from a php script.

Sudo easy_install pyapns

Hello,

I am having some trouble installing pyapns on teh Ubuntu 13.04 by using the easy_install. I am getting the following error:

@ip-XXX-XX-XX-37:/tmp$ sudo easy_install pyapns
Searching for pyapns
Best match: pyapns 0.4.0
Processing pyapns-0.4.0-py2.7.egg
pyapns 0.4.0 is already the active version in easy-install.pth

Using /usr/local/lib/python2.7/dist-packages/pyapns-0.4.0-py2.7.egg
Processing dependencies for pyapns
Searching for Twisted>=8.2.0
Reading http://pypi.python.org/simple/Twisted/
Best match: Twisted 13.1.0
Downloading https://pypi.python.org/packages/source/T/Twisted/Twisted-13.1.0.tar.bz2#md5=5609c91ed465f5a7da48d30a0e7b6960
Processing Twisted-13.1.0.tar.bz2
Writing /tmp/easy_install-EZJ1mu/Twisted-13.1.0/setup.cfg
Running Twisted-13.1.0/setup.py -q bdist_egg --dist-dir /tmp/easy_install-EZJ1mu/Twisted-13.1.0/egg-dist-tmp-lyq15I
twisted/runner/portmap.c:10:20: fatal error: Python.h: No such file or directory
compilation terminated.
error: Setup script exited with error: command 'x86_64-linux-gnu-gcc' failed with exit status 1

Any help is much appreciated.
Thank you,
Manny

Feedback interface doesn't return feedback

I've got a problem with the feedback service. When I try to retrieve the invalidated device token using the feedback service I get an empty array. My twisted log file states the following:

2011-01-11 09:58:40+0100 [HTTPChannel,1,127.0.0.1] Starting factory     <pyapns.server.APNSFeedbackClientFactory instance at 0x1017e9b48>
2011-01-11 09:58:40+0100 [HTTPChannel,1,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2011-01-11 09:58:40+0100 [Uninitialized] feedbackHandler connectionMade
2011-01-11 09:58:41+0100 [APNSFeedbackHandler,client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2011-01-11 09:58:41+0100 [APNSFeedbackHandler,client] 127.0.0.1 - - [11/Jan/2011:08:58:40 +0000] "POST / HTTP/1.0" 200 138 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2011-01-11 09:58:41+0100 [APNSFeedbackHandler,client] APNSFeedbackClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2011-01-11 09:58:41+0100 [APNSFeedbackHandler,client] Stopping factory <pyapns.server.APNSFeedbackClientFactory instance at 0x1017e9b48>

I first thought that maybe my server was the culprit but when I installed it on my own laptop I got the same error.

I can send notifications to my iPhone so there isn't a problem with my certificates. Is this a common issue?

Michiel

Twisted generates logs like crazy

Hi,

Although I can send push notifications just fine from both sandbox and production, but twisted generates logs like crazy (50 x 1mb files in 2 days):

2012-06-05 11:20:30-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost 2012-06-05 11:20:30-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion. ] 2012-06-05 11:20:30-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x186f248> will retry in 2 seconds 2012-06-05 11:20:30-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x186f3b0> 2012-06-05 11:20:33-0500 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x19e6e60> 2012-06-05 11:20:33-0500 [-] APNSClientFactory startedConnecting 2012-06-05 11:20:33-0500 [Uninitialized] APNSProtocol connectionMade 2012-06-05 11:20:33-0500 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x186f3b0> 2012-06-05 11:20:33-0500 [-] APNSClientFactory startedConnecting 2012-06-05 11:20:33-0500 [Uninitialized] APNSProtocol connectionMade 2012-06-05 11:20:33-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost 2012-06-05 11:20:33-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion. ] 2012-06-05 11:20:33-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x19e6f38> will retry in 2 seconds 2012-06-05 11:20:33-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x19e6e60> 2012-06-05 11:20:34-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost 2012-06-05 11:20:34-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion. ] 2012-06-05 11:20:34-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x186f248> will retry in 2 seconds 2012-06-05 11:20:34-0500 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x186f3b0>

Am i doing something wrong?

token or msg error?

2012-11-03 09:24:13-0400 [HTTPChannel,140,127.0.0.1] APNSProtocol sendMessage msg=000020517797f58004247a4d38a9fb7010d5ffc709264bf4a13beb0c36f892892fc841001a7b22617073223a7b22616c657274223a2248656c6c6f21227d7d
2012-11-03 09:24:13-0400 [HTTPChannel,140,127.0.0.1] 127.0.0.1 - - [03/Nov/2012:13:24:13 +0000] "POST / HTTP/1.1" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2012-11-03 09:24:13-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2012-11-03 09:24:13-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2012-11-03 09:24:13-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x3454dd0> will retry in 2 seconds
2012-11-03 09:24:13-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x3453ea8>
2012-11-03 09:24:15-0400 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x3453ea8>
2012-11-03 09:24:15-0400 [-] APNSClientFactory startedConnecting
2012-11-03 09:24:15-0400 [Uninitialized] APNSProtocol connectionMade

I am trying to send push notification from Heroku pyapns app with django, I am getting below error

from pyapns import configure, provision, notify
configure({'HOST': 'http://smarter-pyapns.herokuapp.com:80/'})
True
provision('575807462', open('apns/certs/ck-dev.pem').read(), 'sandbox')
notify('575807462', 'd5e7b657700eb08e2b7e85423937f86d17abeac6b8d87a19d2511f56fe29a8a0', {'aps':{'alert': 'Hello!'}})
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 75, in wrapper
return func(_a, *_kw)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 67, in wrapper
return func(_a, *_kw)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 97, in notify
return _xmlrpc_thread(*f_args)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 127, in _xmlrpc_thread
errback(e)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 65, in errback_wrapper
errback(e) # not an instance of UnknownAppID - nothing we can do here
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 55, in errback
raise e
xmlrpclib.Fault:

Please help me to find out the reason.

Dropped notifications on apple inactivity disconnection

Running the v50 branch in development and encountered an issue where the APNS connection to Apple is disconnected based on inactivity (normally greater than 30+ minutes) - from Apple's side.

The status of the connection is unknown until the attempt to write is performed - the write fails but doesn't re-send the data once re-connection occurs. (more details on twisted, reconnectingclientfactory, and reliable write http://stackoverflow.com/questions/14129408/twisted-mixing-reconnectingclientfactory-with-ssl-and-have-write-be-reliable)

The REST portion of the API has already responded to the submitting client with a 201, so the client assumes that pyapns handles the delivery.

Use case:

  • 1 app auto provisioned in sandbox mode
  • looking to use batch submission to pyapns - currently testing with 13-16 devices
    pyapns service was running for a couple hours without any requests
  • using REST API, posted a batch of 13 notifications - received 201 from pyapns, but notifications were not delivered to APNS
  • subsequent batch of notifications delivered to APNS without an issue (same number of devices)
  • the first batch appears to have been accepted by pyapns, did not attempt to retry to send the batch, and did not appear in a /disconnects request

log information:
2013-10-03 16:24:54-0400 [HTTPChannel,612,10.1.1.242] APNSProtocol sendMessage msg=.....

2013-10-03 16:24:54-0400 [HTTPChannel,612,10.1.1.242] 10.1.1.242 - - [03/Oct/2013:20:24:54 +0000] "POST /apps//sandbox/notifications HTTP/1.1" 201 26 "-" ""
2013-10-03 16:24:54-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-10-03 16:24:54-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): : Connection to the other side was lost in a non-clean fashion.
]
2013-10-03 16:24:54-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] will retry in 3 seconds
2013-10-03 16:24:54-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory
2013-10-03 16:24:57-0400 [-] Starting factory
2013-10-03 16:24:57-0400 [-] APNSClientFactory startedConnecting
2013-10-03 16:24:57-0400 [Uninitialized] APNSProtocol connectionMade

Some problem with push 16,000,000 token.

I try push 2000 token every one notify().
all token have 16,000,000.

  • i run this python on mac .
  • i delete the twistd.log.* at first.
  • i call notify() for 2000 token every times
  • 5 apps Alternating pushed, app have different appid.

i found some problem:
1.16000000 token are presented in 1 hour , but the click report 1000 in 2hours,
and click report 4000 in 24 hours. You know, the old version of java program, get clicks is 40000.

2.Speed โ€‹โ€‹seems to be very slow, 24 hours continues to push.

No error if environment is not correct

If environment is not 'sandbox', production is used. This caused problems for me. It would be nice if error was returned if 'sandbox' or 'production' were not used.

Un - provisioning an application

If multiple requests for provisioning an appID are ignored, we shouldn't we add a method for killing a provision - to allow for updating PEM files without restarting the server?

error(99, 'Cannot assign requested address') on thousands of privision+notification calls

When i send large number of provisions+notifications sometimes i get error(99, 'Cannot assign requested address') from the client

The server and the client are on the same machine and i send it this way
devices > 2000

for devices in devices
provision()
notify()

I guess the socket can be reused in case i send thousands of

http://stackoverflow.com/questions/7640619/cannot-assign-requested-address-possible-causes

Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/celery/task/trace.py", line 228, in trace_task
R = retval = fun(_args, *_kwargs)
File "/usr/local/lib/python2.7/dist-packages/celery/task/trace.py", line 415, in protected_call
return self.run(_args, *_kwargs)
File "/home/mariuz/notifications/tasks.py", line 37, in task_notifications
provision(settings.CONFIG['APPID'], open(settings.CONFIG['CERTIFICATE']).read(), settings.CONFIG['ENVIRONMENT'])
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 75, in wrapper
return func(_a, *_kw)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 67, in wrapper
return func(_a, *_kw)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 85, in provision
return _xmlrpc_thread(_f_args)
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 122, in _xmlrpc_thread
return callback(proxy(_args))
File "/usr/lib/python2.7/xmlrpclib.py", line 1224, in call
return self.__send(self.__name, args)
File "/usr/lib/python2.7/xmlrpclib.py", line 1578, in __request
verbose=self.__verbose
File "/usr/lib/python2.7/xmlrpclib.py", line 1264, in request
return self.single_request(host, handler, request_body, verbose)
File "/usr/lib/python2.7/xmlrpclib.py", line 1292, in single_request
self.send_content(h, request_body)
File "/usr/lib/python2.7/xmlrpclib.py", line 1439, in send_content
connection.endheaders(request_body)
File "/usr/lib/python2.7/httplib.py", line 954, in endheaders
self._send_output(message_body)
File "/usr/lib/python2.7/httplib.py", line 814, in _send_output
self.send(msg)
File "/usr/lib/python2.7/httplib.py", line 776, in send
self.connect()
File "/usr/local/lib/python2.7/dist-packages/pyapns/client.py", line 155, in connect
httplib.HTTPConnection.connect(self)
File "/usr/lib/python2.7/httplib.py", line 757, in connect
self.timeout, self.source_address)
File "/usr/lib/python2.7/socket.py", line 571, in create_connection
raise err
error: [Errno 99] Cannot assign requested address

APNSClientFactory clientConnectionLost

2013-11-20 08:14:55+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0xb68ee48c> will retry in 2 seconds
2013-11-20 08:14:55+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0xb68ee32c>
2013-11-20 08:14:57+0400 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0xb68ee32c>
2013-11-20 08:14:57+0400 [-] APNSClientFactory startedConnecting
2013-11-20 08:14:58+0400 [Uninitialized] APNSProtocol connectionMade
2013-11-20 08:43:57+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-11-20 08:43:57+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.Conn$
]
2013-11-20 08:43:57+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0xb68f464c> will retry in 2 seconds
2013-11-20 08:43:57+0400 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0xb68ee26c>
2013-11-20 08:43:59+0400 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0xb68ee26c>
2013-11-20 08:43:59+0400 [-] APNSClientFactory startedConnecting
2013-11-20 08:44:00+0400 [Uninitialized] APNSProtocol connectionMade

Should I be worried about "clientConnectionLost" messages?

Should I be worried about the "clientConnectionLost" messages and subsequent retries that show up in my log? I'm using the latest from pypi installed via pip just today. .pem is good -- the messages are sent just fine -- but I get this kind of a log entry with every notification sent.

2012-05-08 21:09:09-0400 [-] APNSClientFactory startedConnecting
2012-05-08 21:09:09-0400 [Uninitialized] APNSProtocol connectionMade
2012-05-08 21:09:09-0400 [Uninitialized] APNSProtocol sendMessage msg=[redacted by comment author]
2012-05-08 21:09:09-0400 [Uninitialized] 127.0.0.1 - - [09/May/2012:01:09:09 +0000] "POST / HTTP/1.1" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2012-05-08 21:09:09-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2012-05-08 21:09:09-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no
frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
        ]
2012-05-08 21:09:09-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0xa267c8c> will retry in 2 seconds
2012-05-08 21:09:09-0400 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0xa267b8c>
2012-05-08 21:09:11-0400 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0xa267b8c>
2012-05-08 21:09:11-0400 [-] APNSClientFactory startedConnecting
2012-05-08 21:09:11-0400 [Uninitialized] APNSProtocol connectionMade

JSON date/time support

Does the default encoder support date/time and decimals? Or should DjangoJSONEncoder be used when available?

Unable to send notification -- Log messages unclear

I have tested sending a notification manually and have confirmed that we can do so successfully. We are looking for a robust solution and have heard great things about pyapns. However this is the log output we see in twistd.log and we never receive the notification.

The key differences in our setup between manually sending notifications and using pyapns are:

  • We are using pyapns
    *We are using a different cert -- specifically, when we manually send the notification we provide both the key and the cert -- and then provide the password to authenticate reading the cert. For pyapns, we create a combined cert + key with the password removed. But we still are unable to receive the notification.

I'm unsure what the root cause is -- if there is an issue with the cert or why we are failing to send the notification.

We installed earlier this week with: sudo easy_install pyapns and are running on EC2 with a ubuntu server.

Below are logs from twistd.log -- thank you for any help!

2012-04-04 01:21:51+0000 [-] Log opened.
2012-04-04 01:21:51+0000 [-] twistd 12.0.0 (/usr/bin/python 2.7.2) starting up.
2012-04-04 01:21:51+0000 [-] reactor class: twisted.internet.epollreactor.EPollReactor.
2012-04-04 01:21:51+0000 [-] Site starting on 7077
2012-04-04 01:21:51+0000 [-] Starting factory <twisted.web.server.Site instance at 0x1f2a908>
2012-04-04 01:31:57+0000 [HTTPChannel,0,127.0.0.1] APNSService __init__
2012-04-04 01:31:57+0000 [HTTPChannel,0,127.0.0.1] 127.0.0.1 - - [04/Apr/2012:01:31:57 +0000] "POST / HTTP/1.1" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2012-04-04 01:34:32+0000 [HTTPChannel,1,127.0.0.1] APNSService write (connecting)
2012-04-04 01:34:32+0000 [HTTPChannel,1,127.0.0.1] APNSClientContextFactory ssl_cert_file={FROM_STRING}
2012-04-04 01:34:32+0000 [HTTPChannel,1,127.0.0.1] Starting factory <pyapns.server.APNSClientFactory instance at 0x2065b48>
2012-04-04 01:34:32+0000 [HTTPChannel,1,127.0.0.1] APNSClientFactory startedConnecting
2012-04-04 01:34:32+0000 [Uninitialized] APNSProtocol connectionMade
2012-04-04 01:34:32+0000 [Uninitialized] APNSProtocol sendMessage msg=00002079d7b66de69c6f5e78e5eef9d37d5c69b7b6e7adbdeba75ef5af5ce3b737dde7001a7b22617073223a7b22616c657274223a
2248656c6c6f21227d7d
2012-04-04 01:34:32+0000 [Uninitialized] 127.0.0.1 - - [04/Apr/2012:01:34:31 +0000] "POST / HTTP/1.1" 200 114 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2012-04-04 01:34:32+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2012-04-04 01:34:32+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <clas
s 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2012-04-04 01:34:32+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x2065c68> will retry in 2 seconds
2012-04-04 01:34:32+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x2065b48>
2012-04-04 01:34:35+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x2065b48>
2012-04-04 01:34:35+0000 [-] APNSClientFactory startedConnecting
2012-04-04 01:34:35+0000 [Uninitialized] APNSProtocol connectionMade
2012-04-04 01:34:53+0000 [HTTPChannel,2,127.0.0.1] APNSService read (connecting)
2012-04-04 01:34:53+0000 [HTTPChannel,2,127.0.0.1] APNSClientContextFactory ssl_cert_file={FROM_STRING}
2012-04-04 01:34:53+0000 [HTTPChannel,2,127.0.0.1] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0x206ccb0>
2012-04-04 01:34:53+0000 [HTTPChannel,2,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2012-04-04 01:34:53+0000 [Uninitialized] feedbackHandler connectionMade
2012-04-04 01:34:53+0000 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twist
ed.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2012-04-04 01:34:53+0000 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] 127.0.0.1 - - [04/Apr/2012:01:34:53 +0000] "POST / HTTP/1.1" 200 138 "-" "xmlrpclib.py/1.0.1 (by ww
w.pythonware.com)"
2012-04-04 01:34:53+0000 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] APNSFeedbackClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no
 frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2012-04-04 01:34:53+0000 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSFeedbackClientFactory instance at 0x206ccb0>

strange error when comunicating with remote server from django, cant serialize useDateTime

Traceback (most recent call last):
  File "/src/mycupid/notifications/tests.py", line 79, in test_send_single_notification
    send_apns_notification(user, 'poke', 'test title', 'test msg')
  File "/src/mycupid/notifications/__init__.py", line 16, in send_apns_notification
    pyapns.client.notify(settings.PYAPNS_APP_ID, (t.device_token for t in targets), status_update.as_apns_dict())
  File "/libs/pyapns/client.py", line 54, in notify
    return _xmlrpc_thread('notify', args, lambda r: r)
  File "/libs/pyapns/client.py", line 68, in _xmlrpc_thread
    if not configure({}):
  File "/libs/pyapns/client.py", line 35, in configure
    provision(*args)
  File "/libs/pyapns/client.py", line 46, in provision
    return _xmlrpc_thread('provision', args, lambda r: r)
  File "/libs/pyapns/client.py", line 76, in _xmlrpc_thread
    return callback(proxy(*args))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xmlrpclib.py", line 1199, in __call__
    return self.__send(self.__name, args)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xmlrpclib.py", line 1489, in __request
    verbose=self.__verbose
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xmlrpclib.py", line 1253, in request
    return self._parse_response(h.getfile(), sock)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xmlrpclib.py", line 1392, in _parse_response
    return u.close()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/xmlrpclib.py", line 838, in close
    raise Fault(**self._stack[0])
Fault: <Fault 8002: "Can't deserialize input: APNSServer instance has no attribute 'useDateTime'">

exceptions.KeyError: 10 from disconnections

I got another disconnect in the same manner as in #54, but this time something was recorded and I'm attempting to fetch the disconnections list. That, however, results in the following exception.

2013-09-06 07:05:46+0000 [HTTPChannel,51,127.0.0.1] Unhandled Error
    Traceback (most recent call last):
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/protocols/basic.py", line 581, in dataReceived
        why = self.lineReceived(line)
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/http.py", line 1611, in lineReceived
        self.allContentReceived()
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/http.py", line 1686, in allContentReceived
        req.requestReceived(command, path, version)
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/http.py", line 790, in requestReceived
        self.process()
    --- <exception caught here> ---
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/server.py", line 192, in process
        self.render(resrc)
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/server.py", line 241, in render
        body = resrc.render(self)
      File "/home/appcorn/lib/python2.7/Twisted-13.0.0-py2.7-linux-x86_64.egg/twisted/web/resource.py", line 250, in render
        return m(request)
      File "build/bdist.linux-x86_64/egg/pyapns/rest_service.py", line 171, in render_GET

      File "build/bdist.linux-x86_64/egg/pyapns/model.py", line 282, in to_simple

    exceptions.KeyError: 10

2013-09-06 07:05:46+0000 [HTTPChannel,51,127.0.0.1] 127.0.0.1 - - [06/Sep/2013:07:05:46 +0000] "GET /apps/***/production/disconnections HTTP/1.1" 500 4948 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 OpenSSL/1.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

The crashing line of code: https://github.com/samuraisam/pyapns/blob/v50/pyapns/model.py#L282

I guess I can try to do some kind of workaround myself, but can I close the service without the disconnections list being cleared?

Contacting the feedback service logs does not look correct.

I use pyapns 0.4.0 via Django 1.4.1 for passbook pass update.
Sending push notification works, but contacting the feedback service logs connection lost, which does not look correct.
I'm passing the cert as a file path.

2012-11-26 17:02:48+0900 [HTTPChannel,198,127.0.0.1] APNSService read (connecting)
2012-11-26 17:02:48+0900 [HTTPChannel,198,127.0.0.1] APNSClientContextFactory ssl_cert_file=/path/to/cert_file.pem
2012-11-26 17:02:48+0900 [HTTPChannel,198,127.0.0.1] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0xb6c0f96c>
2012-11-26 17:02:48+0900 [HTTPChannel,198,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2012-11-26 17:02:48+0900 [Uninitialized] feedbackHandler connectionMade
2012-11-26 17:02:48+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2012-11-26 17:02:48+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] 127.0.0.1 - - [26/Nov/2012:08:02:48 +0000] "POST / HTTP/1.0" 200 138 "-" "xmlrpclib.py/1.0.1 (by www.pythonware.com)"
2012-11-26 17:02:48+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] APNSFeedbackClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
]
2012-11-26 17:02:48+0900 [APNSFeedbackHandler (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSFeedbackClientFactory instance at 0xb6c0f96c>

pyapns hangs while waiting for notify

If a sandbox cert or expired cert is used when connecting to production, the notify will hang and wait as pyapns.server retries the connection every two seconds.

There should be some kind of configurable timeout.

"RuntimeErro: maximum recursion depth exceeded" is raised when "UnknownAppID" error occurs

Our code was calling the client.notify function with an app_id that wasn't used to exist in the settings. And we were getting "RuntimeErro: maximum recursion depth exceeded" in our error logger.

Actually, the reprovision_and_retry decorator retries the call infinitely if an UnknownAppID error occurs. And as we are making synchronous calls, it was reaching the maximum recursion depth.

def reprovision_and_retry(func):
  """
  Wraps the `errback` callback of the API functions, automatically trying to
  re-provision if the app ID can not be found during the operation. If that's
  unsuccessful, it will raise the UnknownAppID error.
  """
  @functools.wraps(func)
  def wrapper(*a, **kw):
    errback = kw.get('errback', None)
    if errback is None:
      def errback(e):
        raise e
    def errback_wrapper(e):
      if isinstance(e, UnknownAppID) and 'INITIAL' in OPTIONS:
        try:
          for initial in OPTIONS['INITIAL']:
            provision(*initial) # retry provisioning the initial setup
          func(*a, **kw) # and try the function once more          ------*1
        except Exception, new_exc:
          errback(new_exc) # throwing the new exception
      else:
        errback(e) # not an instance of UnknownAppID - nothing we can do here
    kw['errback'] = errback_wrapper           -------*2
    return func(*a, **kw)
  return wrapper

Here at *1, the keyword argument dict kw would have errback_wrapper function in 'errback' key (as stated at *2). And hence, if errback is called from func (which is done when UnknownAppID error occurs) the code will go into infinite recursion.

Mysterious disconnect

Hi,

I encountered this weird disconnection this morning on the v50 branch. 5 pushes was suppose to be sent out, but it resulted in none at all. When I tried again 45 minutes later with a single different token, it worked all right. Now, a few hours later, returning to the problem and trying to reproduce with the same 5 tokens, everything seems to work fine...

This is the log from this morning, with a disconnect problem Connection to the other side was lost in a non-clean fashion.

2013-09-04 05:31:36+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 05:31:36+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 05:31:36+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x17b5050> will retry in 2 seconds
2013-09-04 05:31:36+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 05:31:38+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 05:31:38+0000 [-] APNSClientFactory startedConnecting
2013-09-04 05:31:39+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 06:00:37+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 06:00:37+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 06:00:37+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x18275f0> will retry in 2 seconds
2013-09-04 06:00:37+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 06:00:39+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 06:00:39+0000 [-] APNSClientFactory startedConnecting
2013-09-04 06:00:39+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 09:01:02+0000 [HTTPChannel,20,127.0.0.1] APNSProtocol sendMessage msg=01000000010000000000***
2013-09-04 09:01:02+0000 [HTTPChannel,20,127.0.0.1] 127.0.0.1 - - [04/Sep/2013:09:01:01 +0000] "POST /apps/***/production/notifications HTTP/1.1" 201 29 "-" "-"
2013-09-04 09:01:02+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 09:01:02+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionLost'>: Connection to the other side was lost in a non-clean fashion.
    ]
2013-09-04 09:01:02+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x18275f0> will retry in 2 seconds
2013-09-04 09:01:02+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 09:01:05+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 09:01:05+0000 [-] APNSClientFactory startedConnecting
2013-09-04 09:01:05+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 09:45:03+0000 [HTTPChannel,21,127.0.0.1] APNSProtocol sendMessage msg=01000000010000000000***
2013-09-04 09:45:03+0000 [HTTPChannel,21,127.0.0.1] 127.0.0.1 - - [04/Sep/2013:09:45:03 +0000] "POST /apps/***/production/notifications HTTP/1.1" 201 29 "-" "-"

I now tried the disconnections and feedback services, but nothing:

curl http://localhost:23480/apps/***/production/disconnections
{"code": 200, "response": []}
curl http://localhost:23480/apps/***/production/feedback
{"code": 200, "response": []}

Looking at my log from earlier, there is a lot of disconnections at what it seems like somewhat regular intervals (at least even-ish 30 minutes).

2013-09-04 00:00:26+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 00:00:26+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 00:00:26+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x18275f0> will retry in 2 seconds
2013-09-04 00:00:26+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 00:00:29+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 00:00:29+0000 [-] APNSClientFactory startedConnecting
2013-09-04 00:00:29+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 01:31:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 01:31:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 01:31:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x17b5050> will retry in 2 seconds
2013-09-04 01:31:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 01:31:32+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 01:31:32+0000 [-] APNSClientFactory startedConnecting
2013-09-04 01:31:32+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 02:00:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 02:00:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 02:00:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x18275f0> will retry in 2 seconds
2013-09-04 02:00:30+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 02:00:33+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 02:00:33+0000 [-] APNSClientFactory startedConnecting
2013-09-04 02:00:33+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 03:31:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 03:31:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 03:31:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x17b5050> will retry in 2 seconds
2013-09-04 03:31:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 03:31:35+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x17b0e18>
2013-09-04 03:31:35+0000 [-] APNSClientFactory startedConnecting
2013-09-04 03:31:35+0000 [Uninitialized] APNSProtocol connectionMade
2013-09-04 04:00:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSProtocol connectionLost
2013-09-04 04:00:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] APNSClientFactory clientConnectionLost reason=[Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connection was closed cleanly.
    ]
2013-09-04 04:00:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] <twisted.internet.tcp.Connector instance at 0x18275f0> will retry in 2 seconds
2013-09-04 04:00:33+0000 [APNSProtocol (TLSMemoryBIOProtocol),client] Stopping factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 04:00:36+0000 [-] Starting factory <pyapns.server.APNSClientFactory instance at 0x18274d0>
2013-09-04 04:00:36+0000 [-] APNSClientFactory startedConnecting
2013-09-04 04:00:36+0000 [Uninitialized] APNSProtocol connectionMade

I'm running via twistd, making sure it's alive via crontab:

*/5 * * * * ~/bin/twistd -y ~/pyapns/pyapns.tac

Looking at my processes, this is shown:

    PID USER      PRI  NI  VIRT   RES   SHR S CPU% MEM%   TIME+  Command
 879769 ***        20   0  283M 14628  2688 S  0.0  0.1  0:00.06 /usr/local/bin/python2.7 /home/***/bin/twistd -y /home/***/pyapns/pyapns.tac
 797678 ***        20   0  283M 14628  2688 S  0.0  0.1  0:00.00 /usr/local/bin/python2.7 /home/***/bin/twistd -y /home/***/pyapns/pyapns.tac
 865573 ***        20   0  283M 14628  2688 S  0.0  0.1  5:26.57 /usr/local/bin/python2.7 /home/***/bin/twistd -y /home/***/pyapns/pyapns.tac

Am I doing stuff right? Do my setup or logs look weird in any way?

exceptions.AttributeError: 'builtin_function_or_method' object has no attribute 'getValue'

2010-01-21 18:02:42-0500 [HTTPChannel,2,127.0.0.1] Starting factory <pyapns.server.APNSFeedbackClientFactory instance at 0x87916ec>
2010-01-21 18:02:42-0500 [HTTPChannel,2,127.0.0.1] APNSFeedbackClientFactory startedConnecting
2010-01-21 18:02:42-0500 [Uninitialized] feedbackHandler connectionMade
2010-01-21 18:02:42-0500 [APNSFeedbackHandler,client] feedbackHandler connectionLost [Failure instance: Traceback (failure with no frames): <class 'twisted.internet.error.ConnectionDone'>: Connect
ion was closed cleanly.
]
2010-01-21 18:02:42-0500 [APNSFeedbackHandler,client] Unhandled Error
Traceback (most recent call last):
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/application/app.py", line 348, in runReactorWithLogging
reactor.run()
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/base.py", line 1128, in run
self.mainLoop()
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/base.py", line 1140, in mainLoop
self.doIteration(t)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/selectreactor.py", line 140, in doSelect
_logrun(selectable, _drdw, selectable, method, dict)
--- ---
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/python/log.py", line 84, in callWithLogger
return callWithContext({"system": lp}, func, _args, *_kw)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/python/log.py", line 69, in callWithContext
return context.call({ILogContext: newCtx}, func, _args, *_kw)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/python/context.py", line 59, in callWithContext
return self.currentContext().callWithContext(ctx, func, _args, *_kw)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/python/context.py", line 37, in callWithContext
return func(args,*kw)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/selectreactor.py", line 156, in _doReadOrWrite
self._disconnectSelectable(selectable, why, method=="doRead")
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/posixbase.py", line 190, in _disconnectSelectable
selectable.readConnectionLost(f)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/tcp.py", line 509, in readConnectionLost
self.connectionLost(reason)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/tcp.py", line 680, in connectionLost
Connection.connectionLost(self, reason)
File "/usr/local/lib/python2.6/site-packages/Twisted-8.2.0-py2.6-linux-i686.egg/twisted/internet/tcp.py", line 520, in connectionLost
protocol.connectionLost(reason)
File "/usr/local/lib/python2.6/site-packages/pyapns-0.2.5-py2.6.egg/pyapns/server.py", line 88, in connectionLost

exceptions.AttributeError: 'builtin_function_or_method' object has no attribute 'getValue'

The client doesn't report any errors back:

pyapns.client.feedback(app_id)

Doesn't return an exception.

[ERROR] File name too long

For some odd reason, pyapns tells me my .pem file name is too long when i've used even though the name used successfully before.

Further, I've been unable to successful run a push to APN successfully. I'm interested in how to pass the correct parameters with proper formats (i.e., device token and pem file)?

Here's my current error

Note:

I ran a second time and twistd.log spits out that my connection to APNS could not be made. It timed out after 15 seconds.

Remove spaces from payload?

For a few extra bytes of payload, pyapns should strip spaces from the payload.

In server.py line 327, instead of:

return ''.join(map(lambda y: structify(*y), ((binaryify(t), json.dumps(p))

use:

return ''.join(map(lambda y: structify(*y), ((binaryify(t), json.dumps(p, separators=(',',':')))

I haven't tested this code.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.