Base Classes¶
libchirp.ChirpBase (loop, config[, recv]) |
Chirp base for async-, queue- and pool-operation. |
libchirp.Config () |
Chirp configuration. |
libchirp.Loop ([run_loop]) |
Initialize and run a libuv event-loop. |
libchirp.MessageThread ([cmsg]) |
Chirp message. |
ChirpBase¶
-
class
libchirp.
ChirpBase
(loop, config, recv=None)[source]¶ Bases:
object
Chirp base for async-, queue- and pool-operation.
libchirp.asyncio.Chirp
: Runs chirp in aasyncio
environment. Messages are received via a handler and sending is await-ablelibchirp.queue.Chirp
: Implements aqueue.Queue
. Concurrency is achieved by sending multiple messages and waiting for results later. Uselibchirp.Message.identity
as key to a dict, to match-up requests and answers.libchirp.pool.Chirp
: Implements aconcurrent.futures.ThreadPoolExecutor
. Used when you have to interface with blocking code. Please only use if really needed.
Creating a chirp instance can raise the exceptions:
OSError
,TimeoutError
,RuntimeError
,ValueError
,MemoryError
. The exception contains the last error message if any generated by chirp. AlsoException
for unknown errors. See Exceptions.Parameters: -
loop
¶ Get the
libchirp.Loop
used by the chirp instance.Return type: Loop
-
request
(msg, auto_release=True)[source]¶ Send a message and wait for an answer.
This method returns a
libchirp.ChirpFuture
.The result() of the will contain the answer to the message. If you don’t intend to consume the result use
send()
instead.By default the message slot used by the response will released. If auto_release is False, you have to release the response-message.
Exceptions, threading and concurrency aspects are the same as
send()
. Issue: If an answer to a request arrives after the timeout it will be delivered at normal message.To wait for the request being sent use
libchirp.ChirpFuture.send_result()
.req = chirp.request(msg) req.send_result() answer = req.result()
Parameters: - msg (MessageThread) – The message to send.
- auto_release (bool) – Release the response (default True)
Return type:
-
send
(msg)[source]¶ Send a message. This method returns a Future.
The result will contain the message that has been sent.
In synchronous-mode the future finishes once the remote has released the message. In asynchronous-mode the future finishes once the message has been passed to the operating-system.
Calling result() can raise the exceptions:
ConnectionError
,TimeoutError
,RuntimeError
,ValueError
,MemoryError
. The exception contains the last error message if any generated by chirp. AlsoException
for unknown errors. See Exceptions.See also Concurrency.
Sending different messages from different threads is thread-safe. Sending the same message twice from different threads will lead to undefined behavior. Sending, waiting for the result, switching the thread synchronized (via queue for example), sending is fine, tough.
Parameters: msg (MessageThread) – The message to send. Return type: concurrent.futures.Future
Config¶
-
class
libchirp.
Config
[source]¶ Bases:
object
Chirp configuration.
The underlaying C type is annotated in parens. CFFI will raise errors if the values overflow (OverflowError) or don’t convert (TypeError).
You can create the certificate using the makepki Makefile on github. If you want to create it manually the chain has to contain:
- The certification authority’s public key
- The client public key (signed by CA)
- The client private key
Any client-key signed by the CA will be able to connect.
-
AUTO_RELEASE
¶ Get if chirp releases messages.
By default chirp will release the message-slot automatically when the handler-callback returns. Python boolean.
Not used in queue-operation: always release the message.
In synchronous-mode the remote will only send the next message when the current message has been released.
In asynchronous-mode when all slots are used up and the TCP-buffers are filled up, the remote will eventually not be able to send more messages. After TIMEOUT seconds messages start to time out.
synchronous-mode/asynchronous-mode are independent from async-, queue- and pool-operation. The modes refer to a single connection, while the operation refers to the interface in python.
-
BACKLOG
¶ Get the TCP-listen socket backlog. (uint8_t).
From man 2 listen:
The backlog argument defines the maximum length to which the queue of pending connections for sockfd may grow. If a connection request arrives when the queue is full, the client may receive an error with an indication of ECONNREFUSED or, if the underlying protocol supports retransmission, the request may be ignored so that a later reattempt at connection succeeds.Return type: int
-
BIND_V4
¶ Override IPv4 bind address.
String representation expected, parsed by
ipaddress.ip_address
.Return type: str
-
BIND_V6
¶ Override IPv6 bind address.
String representation expected, parsed by
ipaddress.ip_address
.Return type: str
-
BUFFER_SIZE
¶ Get the size of the buffer used for a connection.
Defaults to 0, which means use the size requested by libuv. Should not be set below 1024. (uint32_t)
Return type: int
-
DISABLE_ENCRYPTION
¶ Get if encryption is disabled.
Only use if you know what you are doing. Connections to “127.0.0.1” and ”::1” aren’t encrypted anyways. Python boolean expected. Defaults to False.
Return type: bool
-
DISABLE_SIGNALS
¶ Get if signals are disabled.
By default chirp closes on SIGINT (Ctrl-C) and SIGTERM. Python boolean expected. Defaults to False.
Return type: bool
-
IDENTITY
¶ Override the chirp-nodes identity (this chirp instance).
By default chirp will generate a IDENTITY. Python bytes of length 16. Everything else will not be accepted by CFFI.
Return type: bytes
-
MAX_MSG_SIZE
¶ Get the max message size accepted by chirp. (uint32_t).
If you are concerned about memory usage set config.MAX_SLOTS=1 and config.MAX_MSG_SIZE to something small, depending on your use-case. If you do this, a connection will use about:
- conn_buffers_size = config.BUFFER_SIZE +
- min(config.BUFFER_SIZE, CH_ENC_BUFFER_SIZE) + sizeof(ch_connection_t) + sizeof(ch_message_t) + (memory allocated by TLS implementation)
conn_size = conn_buffers_size + config.MAX_MSG_SIZE
With the default config and SSL conn_buffers_size should be about 64k + 16k + 2k + 32k -> 114k. Derived from documentation, no measurement done.
Return type: int
-
MAX_SLOTS
¶ Get the count of message-slots used.
Allowed values are values between 1 and 32. The default is 0: Use 16 slots of SYNCHRONOUS = False and 1 slot if SYNCHRONOUS = True. (uint8_t)
Return type: int
-
REUSE_TIME
¶ Get the time until a connection gets garbage collected.
Until then the connection will be reused. Actual reuse time will be max(REUSE_TIME, TIMEOUT * 3). (float)
Return type: float
-
SYNCHRONOUS
¶ Get if chirp requests and waits for acknowledge messages.
Default True. Makes chirp connection-synchronous. See Modes of operation. Python boolean expected.
Return type: bool
Loop¶
-
class
libchirp.
Loop
(run_loop=True)[source]¶ Bases:
object
Initialize and run a libuv event-loop.
By default the loop is run.
Parameters: run_loop (bool) – Run the loop (True) -
call_soon
(func, *args, **kwargs)[source]¶ Call function in event-loop thread.
The function will be executed asynchronous. If you need a result pass a py:class:concurrent.futures.Future to the function.
For example:
loop.call_soon(print, "hello")
-
running
¶ Return True if event-loop is running.
-
MessageThread¶
-
class
libchirp.
MessageThread
(cmsg=None)[source]¶ Bases:
libchirp.MessageBase
Chirp message. To answer to message just replace the data and send it.
Note
The underlaying C type is annotated in parens. The properties of the message use asserts to check if the value has the correct type, length, range. You can disable these with python -O.
-
address
¶ Get address.
If the message was received: The address of the remote the message was received from.
If the message will be sent: The address to send the message to.
This allows to reply to messages just by replacing
data()
.Returns: String representation generated by py:class:ipaddress.ip_address. Return type: string
-
has_slot
¶ Return if the message has a slot.
If
libchirp.Config.AUTO_RELEASE
is False, you have to callrelease_slot()
Return type: bool
-
header
¶ Get the header used by upper-layer protocols.
Users should not use it, except if you know what you are doing.
Return type: bytes
-
identity
¶ Get identify the message and answers to it. (uint8_t[16]).
The identity can be used to find answers to a message, since replying to the message won’t change the identity.
If you need to uniquely identify the message, use the identity/serial pair, since the serial will change when replying to messages. (read-only)
Return type: bytes
-
port
¶ Get port. (uint16_t).
If the message was received: The port of the remote the message was received from.
If the message will be sent: The port to send the message to.
This allows to reply to messages just by replacing
data()
.Return type: int
-
release
()¶ Release the internal message-slot. This method returns a Future.
Will also acknowledge the message if the remote requested a acknowledge-message.
The result of the future will be set to (identity, serial) once the message is released. If the message had no slot, the result will be set to None.
Releasing a message from a different thread is thread-safe. Releasing the same message from different threads twice will lead to undefined behavior. Releasing, waiting for the result, switching the thread synchronized (via queue for example), releasing is fine, tough.
Return type: Future
-
release_slot
()[source]¶ Release the internal message-slot. This method returns a Future.
Will also acknowledge the message if the remote requested a acknowledge-message.
The result of the future will be set to (identity, serial) once the message is released. If the message had no slot, the result will be set to None.
Releasing a message from a different thread is thread-safe. Releasing the same message from different threads twice will lead to undefined behavior. Releasing, waiting for the result, switching the thread synchronized (via queue for example), releasing is fine, tough.
Return type: Future
-
remote_identity
¶ Detect the remote instance. (uint8_t[16]).
By default a node’s identity will change on each start of chirp. If multiple peers share state, a change in the remote_identity should trigger a reset of the state. Simply use the remote_identity as key in a dictionary of shared state. (read-only)
Return type: bytes
-