aiocoap.transports.udp6 module

This module implements a MessageInterface for UDP based on a variation of the asyncio DatagramProtocol.

This implementation strives to be correct and complete behavior while still only using a single socket; that is, to be usable for all kinds of multicast traffic, to support server and client behavior at the same time, and to work correctly even when multiple IPv6 and IPv4 (using V4MAPPED addresses) interfaces are present, and any of the interfaces has multiple addresses.

This requires using some standardized but not necessarily widely ported features: AI_V4MAPPED to support IPv4 without resorting to less standardized mechanisms for later options, IPV6_RECVPKTINFO to determine incoming packages’ destination addresses (was it multicast) and to return packages from the same address, IPV6_JOIN_GROUP for multicast membership management and recvmsg to obtain data configured with the above options.

To the author’s knowledge, there is no standardized mechanism for receiving ICMP errors in such a setup. On Linux, IPV6_RECVERR and MSG_ERRQUEUE are used to receive ICMP errors from the socket; on other platforms, a warning is emitted that ICMP errors are ignored. Using a simple6 for clients is recommended for those when working as a client only.

Exceeding for the above error handling, no attempts are made to fall back to a kind-of-correct or limited-functionality behavior if these options are unavailable, for the resulting code would be hard to maintain (”ifdef hell”) or would cause odd bugs at users (eg. servers that stop working when an additional IPv6 address gets assigned). If the module does not work for you, and the options can not be added easily to your platform, consider using the simple6 module instead.

class aiocoap.transports.udp6.InterfaceOnlyPktinfo

Bases: bytes

A thin wrapper over bytes that represent a pktinfo built just to select an outgoing interface.

This must not be treated any different than a regular pktinfo, and is just tagged for better debug output. (Ie. if this is replaced everywhere with plain bytes, things must still work).

class aiocoap.transports.udp6.UDP6EndpointAddress(sockaddr, interface, *, pktinfo=None)

Bases: aiocoap.interfaces.EndpointAddress

Remote address type for :cls:`MessageInterfaceUDP6`. Remote address is stored in form of a socket address; local address can be roundtripped by opaque pktinfo data.

For purposes of equality (and thus hashing), the local address is not checked. Neither is the scopeid that is part of the socket address.

>>> interface = type("FakeMessageInterface", (), {})
>>> if1_name = socket.if_indextoname(1)
>>> local = UDP6EndpointAddress(socket.getaddrinfo('127.0.0.1', 5683, type=socket.SOCK_DGRAM, family=socket.AF_INET6, flags=socket.AI_V4MAPPED)[0][-1], interface)
>>> local.is_multicast
False
>>> local.hostinfo
'127.0.0.1'
>>> all_coap_link1 = UDP6EndpointAddress(socket.getaddrinfo('ff02:0:0:0:0:0:0:fd%1', 1234, type=socket.SOCK_DGRAM, family=socket.AF_INET6)[0][-1], interface)
>>> all_coap_link1.is_multicast
True
>>> all_coap_link1.hostinfo == '[ff02::fd%{}]:1234'.format(if1_name)
True
>>> all_coap_site = UDP6EndpointAddress(socket.getaddrinfo('ff05:0:0:0:0:0:0:fd', 1234, type=socket.SOCK_DGRAM, family=socket.AF_INET6)[0][-1], interface)
>>> all_coap_site.is_multicast
True
>>> all_coap_site.hostinfo
'[ff05::fd]:1234'
>>> all_coap4 = UDP6EndpointAddress(socket.getaddrinfo('224.0.1.187', 5683, type=socket.SOCK_DGRAM, family=socket.AF_INET6, flags=socket.AI_V4MAPPED)[0][-1], interface)
>>> all_coap4.is_multicast
True
scheme = 'coap'
interface
netif

Textual interface identifier of the explicitly configured remote interface, or the interface identifier reported in an incoming link-local message. None if not set.

hostinfo

The authority component of URIs that this endpoint represents when request are sent to it

Note that the presence of a hostinfo does not necessarily mean that globally meaningful or even syntactically valid URI can be constructed out of it; use the uri property for this.

hostinfo_local

The authority component of URIs that this endpoint represents when requests are sent from it.

As with hostinfo, this does not necessarily produce sufficient input for a URI; use uri_local instead.

uri_base

The base URI for the peer (typically scheme plus .hostinfo).

This raises error.AnonymousHost when executed on an address whose peer coordinates can not be expressed meaningfully in a URI.

uri_base_local

The base URI for the local side of this remote.

This raises error.AnonymousHost when executed on an address whose local coordinates can not be expressed meaningfully in a URI.

is_multicast

True if the remote address is a multicast address, otherwise false.

is_multicast_locally

True if the local address is a multicast address, otherwise false.

as_response_address()

Address to be assigned to a response to messages that arrived with this message

This can (and does, by default) return self, but gives the protocol the opportunity to react to create a modified copy to deal with variations from multicast.

blockwise_key

A hashable (ideally, immutable) value that is only the same for remotes from which blocks may be combined. (With all current transports that means that the network addresses need to be in there, and the identity of the security context).

It does not just hinge on the identity of the address object, as a first block may come in an OSCORE group request and follow-ups may come in pairwise requests. (And there might be allowed relaxations on the transport under OSCORE, but that’d need further discussion).

class aiocoap.transports.udp6.SockExtendedErr

Bases: aiocoap.transports.udp6._SockExtendedErr

classmethod load(data)
class aiocoap.transports.udp6.MessageInterfaceUDP6(ctx: aiocoap.interfaces.MessageManager, log, loop)

Bases: aiocoap.util.asyncio.recvmsg.RecvmsgDatagramProtocol, aiocoap.interfaces.MessageInterface

ready = None

Future that gets fullfilled by connection_made (ie. don’t send before this is done; handled by create_..._context

send(message)

Send a given Message object

classmethod create_client_transport_endpoint(ctx: aiocoap.interfaces.MessageManager, log, loop)
classmethod create_server_transport_endpoint(ctx: aiocoap.interfaces.MessageManager, log, loop, bind, multicast)
determine_remote(request)

Return a value suitable for the message’s remote property based on its .opt.uri_host or .unresolved_remote.

May return None, which indicates that the MessageInterface can not transport the message (typically because it is of the wrong scheme).

recognize_remote(remote)
shutdown()

Deactivate the complete transport, usually irrevertably. When the coroutine returns, the object must have made sure that it can be destructed by means of ref-counting or a garbage collector run.

connection_made(transport)

Implementation of the DatagramProtocol interface, called by the transport.

datagram_msg_received(data, ancdata, flags, address)

Implementation of the RecvmsgDatagramProtocol interface, called by the transport.

datagram_errqueue_received(data, ancdata, flags, address)

Called when some data is received from the error queue

error_received(exc)

Implementation of the DatagramProtocol interface, called by the transport.

connection_lost(exc)

Called when the connection is lost or closed.

The argument is an exception object or None (the latter meaning a regular EOF is received or the connection was aborted or closed).