Extending the clientΒΆ
The client is designed to be as generic as possible. Everything related to
transport layer is put together in pluggable back-ends. The default back-end is
apnsclient.backends.stdio
. It is using raw python sockets for networking,
select()
for IO blocking and pyOpenSSL
as SSL tunnel. The default
back-end will probably fail to work in gevent
environment because
pyOpenSSL
works with POSIX file descriptors directly.
You can write your own back-end that will work in your preferred, probably green, environment. Therefore you have to write the following classes.
your.module.Certificate
SSL certificate instance using SSL library of your choice. Extends from
apnsclient.certificate.BaseCertificate
. The class should implement the following methods:load_context()
- actual certificate loading from file or string.dump_certificate()
- dump certificate for equality check.dump_digest()
- dump certificate digest, such assha1
ormd5
.
your.module.Connection
SSL tunnel using IO and SSL library of your choice. Extends from
apnsclient.backends.BaseConnection
. The class should implement the following methods:reset()
- flush read and write buffers before new transmission.peek()
- non-blocking read, returns bytes directly available in the read buffer.read()
- blocking read.write()
- blocking write.close()
- close underlying connection.closed()
- reports connection state.
your.module.Backend
Factory class for certificates, thread locking and networking connections. Extends from
apnsclient.backends.BaseBackend
. The class should implement the following methods:get_certificate()
- load certificate and returns your custom wrapper.create_lock()
- createtheading.Lock
like semaphore.get_new_connection()
- open ready to use SSL connection.
The main logic behind each of these classes is easy. The certificate is used as
a key in the connection pool, so it should support __eq__
(equality)
operation. The equality check can be performed by comparing whole certificate
dump or just the digest if you don’t like the idea to hold sensitive data in
python’s memory for long. The connection implements basic IO operations. The
connection can be cached in the pool, so it is possible that some stale data
from a previous session will slip into the next session. The remedy is to flush
read an write buffers using Connection.reset()
before sending a new
message. The back-end instance acts as a factory for your certificates, locks
and connections. The locking is dependent on your environment, you don’t have
to monkey patch threading
module therefore.
It is a good idea to look at the source code of the standard back-end
apnsclient.backends.stdio
and elaborate from that. Your back-end can be
supplied to the Session
using fully qualified module name, as a class or as
an initialized instance. If you supply your back-end using module name, then
the name of your back-end class must be Backend
.
If you hit any trouble or if you think your back-end is worth sharing with the rest of the world, then contact me Sardar Yumatov or make an issue/pull-request on APNs Bitbucket page.