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.

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. Also Exception for unknown errors. See Exceptions.

Parameters:
  • loop (Loop) – libuv event-loop
  • config (Config) – chirp config
  • recv – Recv callback
identity()[source]
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:

concurrent.futures.Future

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. Also Exception 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
stop()[source]

Stop the chirp-instance.

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.

See Modes of operation

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
CERT_CHAIN_PEM

Get the path to the verification certificate. Python string.

Return type:str
DH_PARAMS_PEM

Get the path to the file containing DH parameters. Python string.

Return type:str
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
PORT

Get the Port for listening to connections. (uint16_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
TIMEOUT

Get send- and connect-timeout scaling in seconds.

Send-timeout will be TIMEOUT seconds. Connect-timeout will be min(TIMEOUT * 2, 60) seconds. (float)

Return type:float

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")
run()[source]

Run the event loop.

running

Return True if event-loop is running.

stop()[source]

Stop the event-loop.

For convenience stop() will wait for the last chirp instance to stop.

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
data

Get the data of the message.

Return type:bytes
has_slot

Return if the message has a slot.

If libchirp.Config.AUTO_RELEASE is False, you have to call release_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
serial

Get the serial number of the message. (uint32_t).

Increases monotonic. Be aware of overflows, if want to use it for ordering use the delta: serialA - serialB. (read-only)

Return type:int