coapy.endpoint

copyright:Copyright 2013, Peter A. Bigot
license:Apache-2.0
class coapy.endpoint.Endpoint(sockaddr=None, family=0, security_mode=None, host=None, port=5683)[source]

A CoAP endpoint.

Per CoAP Section 1.2 this is an entity participating in the CoAP protocol. In CoAPy it is used to aggregate all material related to such an endpoint, which is uniquely identified by an IP address, port, and security information. Various constraints in CoAP such as congestion control, default values for options, and re-usability of message IDs, are associated with specific endpoints.

Note that although all endpoints have socket addresses, the base Endpoint class does not provide any communications infrastructure. Subclasses of LocalEndpoint provide the communication methods.

sockaddr, if not None, must be a tuple the first two elements of which are host, port which override the user-provided host and port.

host specifies the host of the endpoint as a Unicode string, representing a host name, an IP address literal, or other unique key.

family is by default socket.AF_UNSPEC supporting resolution of host to any address family. A non-None value is passed to socket.getaddrinfo() when attempting to resolve host as an address; the actual family value will be the one selected by the resolution process (normally socket.AF_INET or socket.AF_INET6) Failure to successfully resolve host will raise socket.gaierror. If you want a dummy endpoint associated with host but that does not have an IP host associated with it, make sure that family is None so that host is left unresolved and instead serves as an name as described in sockaddr.

port is the integer transport-layer port of the endpoint. This would normally be either coapy.COAP_PORT or coapy.COAPS_PORT.

security_mode is used to determine the DTLS protocol used for secure CoAP, and at this time had probably better be left as None.

To ensure consistency, Endpoint instances are unique for a given key comprising family, ip_addr, port, and security_mode. Attempts to instantiate a new endpoint with parameters that match a previously-created one will return a reference to the original instance.

static _canonical_sockinfo(sockaddr=None, family=0, security_mode=None, host=None, port=5683)[source]

Get canonical socket information for an endpoint.

Returns a tuple (family, sockaddr) where sockaddr is a an address as constrained by family.

Failure to resolve the socket host to a numeric IP literal within family (if required) will raise socket.gaierror.

static _key_for_sockaddr(sockaddr, family, security_mode=None)[source]

Create the key used to look up endpoints.

sockaddr must be a tuple the first two elements of which are (host, port). Unless family is None, host must be a text representation of an IP address that can be converted with socket.inet_pton() using family, not a hostname. port must be a numeric port number.

If family is socket.AF_UNSPEC a exception.ValueError exception will be raised as the system does not know how to decode the host.

_reset()[source]

Return all data to its initial state.

This is a back-door for unit-testing from a known state. It’s also used when a new Endpoint is constructed for the first time. Only mutable state is reset; immutable values like family and sockaddr are not affected.

Note

This method uses cooperative super-calling for subclass extension.

base_uri[source]

The base CoAP URI for resources on this endpoint.

This is used by uri_to_options() to avoid the need to specify the protocol and netloc when creating option lists.

create_request(uri, confirmable=False, code=(0, 1), messageID=None, token=None, options=None, payload=None)[source]

Create and return a Request instance to retrieve uri from this endpoint.

uri should generally be a relative URI hosted on the endpoint.

By default this creates a non-confirmable GET message. These features can be overridden with confirmable and code. The messageID normally remains unassigned (it will be assigned to an available ID when it is transmitted). The caller may specify a token; if none is provided, an empty token will be used. Any options are appended to the options derived from uri, and payload is as in the coapy.message.Message constructor. The message destination_endpoint is set to self, and finally the message is returned to the caller.

family[source]

The address family used for sockaddr.

This is normally socket.AF_INET or socket.AF_INET6. It may be None for testing situations where the actual endpoint does not correspond to an network node.

finalize_message(message)[source]

Final checks and refinements for message relative to this endpoint.

The message is validated, then the following final cleanup in its options is done:

The finalized message is returned.

get_peer_endpoint(sockaddr=None, host=None, port=5683)[source]

Find the endpoint at sockaddr that this endpoint can talk to.

This invokes Endpoint with family and security_mode set to the parameters used by this endpoint. It is used to identify the source endpoint of a message received by socket.socket.recvfrom(). sockaddr will be constructed from host and port if not provided explicitly; at least one of sockaddr and host must be given.

in_addr[source]

The address of the endpoint.

The representation is binary data encoding part of sockaddr. Decoding it depends on family:

When family is socket.AF_INET this is the IPv4 address in network byte order.

When family is socket.AF_INET6 this is the IPv6 address in network byte order.

When family is None this is the name in Net-Unicode format.

is_same_host(host)[source]

Determine whether host resolves to the same address as this endpoint.

This is used for the algorithm in CoAP Section 6.4 to determine that a UriHost option may be elided in favor of the default derived from an endpoint. This can only be done if host is an IP-literal or IPv4address equivalent to in_addr in family. DNS resolution is not used.

classmethod lookup_endpoint(sockaddr=None, family=0, security_mode=None, host=None, port=5683)[source]

Look up an endpoint using the same algorithm as endpoint creation.

Returns None if passing these parameters to Endpoint would result in creation of a new endpoint.

port[source]

The transport-level port of the endpoint.

security_mode[source]

The security mode of the endpoint. Generally None though if DTLS CoAP is used it would be some other value.

sockaddr[source]

The Python socket address of the endpoint.

When family is socket.AF_INET this is the tuple (host, port).

When family is socket.AF_INET6 this is the tuple (host, port, flowinfo, scopeid).

When family is None this is the tuple (name, port). name functions like host but is not a resolvable host name.

host will be the text representation of in_addr; it will not be a host name. port will be a numeric port number.

uri_from_options(opts)[source]

Create a URI from endpoint data and the options.

The resulting URI scheme is “coap” unless security_mode is set (in which case it is “coaps”).

The authority is derived from UriHost and UriPort options in opts, defaulting to uri_host and port if the respective options are not provided.

The remainder of the URI is built up from UriPath and UriQuery options in opts.

uri_host[source]

The text value for the host subcomponent of the authority part of a URI involving this endpoint.

This is almost always either an IPv4address or IP-literal as defined by section 3.2.2 of RFC3986. If an Endpoint is created by an application using a host name, the resolved address of the host is used for sockaddr and for this property.

uri_to_options(uri, base_uri=None)[source]

Convert a URI to a list of CoAP options relative to this endpoint.

uri should be an RFC 3986 conformant absolute URI. For convenience, if base_uri is not None the value of uri will be recalculated assuming it is relative to base_uri. base_uri itself will default to base_uri if no non-None value is provided.

The scheme part of uri must be either “coap” or “coaps”.

Options will be returned in a list in the following order.

class coapy.endpoint.LocalEndpoint(sockaddr=None, family=0, security_mode=None, host=None, port=5683)

Bases: coapy.endpoint.Endpoint

Extends Endpoint with methods to send and receive messages.

This is an abstract class; a subclass must implement the underlying communications operations invoked through rawsendto() and rawrecvfrom(). The most likely subclass is SocketEndpoint, but for simulation and testing purposes alternative implementations like tests.support.FIFOEndpoint may be used.

_rawrecvfrom(bufsize)

Receive data from a source_endpoint.

Returns tuple (data, source_endpoint) where data is bytes data and source_endpoint is the instance Endpoint associated with the origin of data.

Subclasses must override this method. The method of communication is determined by the subclass. Whether the call blocks or raises an exception if communication is unavailable is not specified, but if no exception is raised the return value must be as described above.

_rawsendto(data, destination_endpoint)

Send data from this endpoint to destination_endpoint.

data is bytes data. destination_endpoint is an instance of Endpoint.

The mechanism by which the data is transferred depends on subclass support for communications, and a subclass must override this method.

_reset()

Return all data to its initial state.

next_messageID()

Return a new messageID suitable for a message to this endpoint.

This is sequentially generated starting from an initial value that was randomly generated when the state was created. It is filtered so message IDs still present in the sent message cache are not re-used.

rawrecvfrom(bufsize=2048)

Receive data from a source_endpoint.

Returns tuple (data, source_endpoint) where data is bytes data and source_endpoint is the instance Endpoint associated with the origin of data. bufsize is a hint of the maximum expected size of the incoming data.

This method delegates to a subclass implementation of _rawrecvfrom().

rawsendto(data, destination_endpoint)

Send data from this endpoint to destination_endpoint.

data is bytes data. destination_endpoint is an instance of Endpoint.

This method delegates to a subclass implementation of _rawsendto().

receive()

Receive and decode a message from another endpoint.

Returns None if the message is so corrupt it should be ignored, or if the received message is a duplicate. Raises coapy.message.MessageFormatError if the message cannot be fully decoded. Otherwise returns the message, in which destination_endpoint will be set to self and source_endpoint will be set to source_endpoint.

Any message-layer processing (e.g. re-sending duplicate ACK or RST, or sending a RST due to a message format error) will have been done before this call returns.

remote_state(endpoint)

Obtain the RemoteEndpointState instance relevant to communication between self and endpoint.

A new instance is created and returned if endpoint has not been contacted before.

send(msg, destination_endpoint=None)

Send msg to destination_endpoint.

msg must be an instance of coapy.message.Message.

destination_endpoint specifies where the packed message will be sent and defaults to msg‘s destination_endpoint.

The return value is the SentMessageCacheEntry that has message-level transmission state.

class coapy.endpoint.SocketEndpoint(sockaddr=None, family=0, security_mode=None, host=None, port=5683)

Bases: coapy.endpoint.LocalEndpoint

An endpoint that has a Python socket.socket() bound to it to be used for network communications.

While all Endpoint instances have a socket address, only endpoints that belong to the local node have sockets associated with them. These sockets are used to exchange messages with remote endpoints.

_rawrecvfrom(bufsize)

Receive data from a source_endpoint.

Invokes recvfrom on bound_socket and uses the resulting source address to identify the corresponding Endpoint instance as source_endpoint. Returns (data, source_endpoint).

_rawsendto(data, destination_endpoint)

Send data from this endpoint to destination_endpoint.

This invokes sendto on bound_socket to transmit data to the destination_endpoint at its sockaddr.

bound_socket

Return a socket object instance that is bound to sockaddr.

This may only be set for endpoints that are local to the host. It may set to None to disassociate the endpoint from a socket, and may be changed from None to an object that returns sockaddr when socket.getsockname is invoked on it.

See create_bound_endpoint() and set_bound_socket().

classmethod create_bound_endpoint(sockaddr=None, family=0, security_mode=None, host=None, port=5683)

Create an endpoint with a local socket bound to it.

sockaddr, family, security_mode, host, and port are all as used with Endpoint.

For use with a CoAP service on the local host (host as 127.0.0.1 or ::1), port may be 0 in this call. This allows the bind operation to select an unused local port.

Returns the created endpoint with bound_socket initialized and ready to send and receive messages.

set_bound_socket(socket)

Set the bound_socket.

socket may be None, in which case the endpoint is disassociated from any socket.

If socket is not None it must be an object suitable for assignment to bound_socket. The endpoint adopts the socket, in that if/when the endpoint is destroyed the socket will be closed if it remains bound to the endpoint. (Since Endpoint instances are almost impossible to destroy, this has little relevance at this time.)

In either case if the assignment succeed the previous value of bound_socket is returned, with the caller taking responsibility to close it when finished.

Note

For simulation and testing purposes socket might not be a socket object, but it must act like one with respect to the methods CoAPy expects it to provide, including but not limited to:

Message Caches

class coapy.endpoint.MessageCache(endpoint, is_sent_cache)[source]

Bases: object

Dual-view collection used for caches of MessageCacheEntry instances.

The class simulates a dictionary allowing lookup of items using the integer message ID. Most lookup dict operations are supported on the message ID. If a message is used as the key its messageID is substituted automatically.

The collection also implements a priority queue, allowing time-driven events to be processed for cache elements based on time_due. Items in the cache for which no time_due has been specified are held on a pending() FIFO.

Cache entries are placed in a cache when they are created. It is an error to create a new cache entry when one with the same MessageCacheEntry.message_id is already present in that cache.

Entry content may be updated while in the cache (in particular, modifying MessageCacheEntry.time_due will activate or reposition the entry within the queue()). Entries proceed through a defined life cycle; after all active stages have been completed an event to automatically remove the entry from its cache will be scheduled to occur at expire.

_activate(entry)

Move entry from the pending list to its correct location in the queue.

This will be invoked when the underlying coapy.util.TimeDueOrdinal.time_due attribute value is first assigned.

_add(entry)[source]

Add entry to the cache.

_remove(entry)[source]

Remove entry from the cache.

_reposition(entry)[source]

Re-place entry at its correct location in the queue.

This will be invoked whenever the underlying coapy.util.TimeDueOrdinal.time_due attribute value is changed.

clear()[source]

Remove all entries in the cache.

endpoint[source]

The Endpoint to which the cache belongs.

is_sent_cache[source]

True if this cache is the sent-message cache for its endpoint. False if this is the received-message cache.

pending()

The list of pending cache entries in FIFO order. These are cache entries for which no MessageCacheEntry.time_due has been assigned, so their lifecycle has not yet started.

Warning

This method returns a reference to the underlying list. Callers are expected to refrain from changing the list.

queue()[source]

The queue of cache entries sorted by MessageCacheEntry.time_due.

Warning

This method returns a reference to the underlying sorted list. Callers are expected to refrain from changing the list in any way other than through methods exposed on the cache itself.

class coapy.endpoint.MessageCacheEntry(cache, message, activate=True, time_due_offset=None)[source]

Bases: coapy.util.TimeDueOrdinal

A class holding data stored in a MessageCache.

Instances sort based on coapy.util.TimeDueOrdinal.time_due, and may be looked up based on message_id.

cache identifies the MessageCache instance to which this entry will belong. Entries are associated with cache when they are created, and can be removed from that cache. Once removed, an entry cannot be inserted into another cache.

message is a coapy.message.Message instance of type CON or NON. ACK and RST messages cannot be cached. message.messageID is used as the key for cache entry lookups.

activate, if True, starts the cache entry into its lifecycle immediately by setting activated_clk to created_clk and setting time_due to either activated_clk plus time_due_offset if the latter is provided, or to expires_clk if it is not provided.

If activate is False the entry is held pending until something assigns an initial time_due.

_dissociate()[source]

Remove the connection between the instance and the cache.

This is invoked by MessageCache when the entry is removed from its cache.

_get_time_due()[source]

See coapy.util.TimeDueOrdinal.time_due. In this class, modification of the value has the side-effect potentially activating the entry and of moving the entry within the cache queue.

The value assigned to time_due must be an ordinal in the domain of coapy.clock(). It cannot be None if a non-None value had already been assigned.

activated_clk

The coapy.clock() value at the time the cache entry was activated: i.e., it starts executing its lifecycle by defining a non-None time_due. Distinguish this from created_clk.

cache[source]

The MessageCache to which this entry belongs. This is a read-only property, set when the entry is created and cleared when it has been removed from its cache.

created_clk

The coapy.clock() value at the time the cache entry was created. Distinguish this from activated_clk.

expires_clk

The coapy.clock() value at the time the cache entry is obsolete. None is returned if the entry has not been activated.

This is calculated by adding EXCHANGE_LIFETIME (for CON messages) or NON_LIFETIME (for NON messages) to activated_clk. Entries must remain in the cache until this point to detect duplicates.

message

The coapy.message.Message being cached.

message_id

Short-cut access to message.messageID.

process_timeout()

Process a timeout at the cache entry.

This should normally be invoked on an entry by some external system as a consequence of coapy.clock() having reached time_due. Operations performed by this method depend on the state of the entry within its lifecycle. It is an error to invoke this on an entry that is no longer present in its cache. Invoking this may cause an entry to be removed from its cache.

The implementation is provided by a subclass. There is no return value.

Note

The implementation does not attempt to verify that the current time_due has been reached; an entry may be processed early or late. The caller is responsible for determining whether it is appropriate to invoke this method.

time_due

See coapy.util.TimeDueOrdinal.time_due. In this class, modification of the value has the side-effect potentially activating the entry and of moving the entry within the cache queue.

The value assigned to time_due must be an ordinal in the domain of coapy.clock(). It cannot be None if a non-None value had already been assigned.

class coapy.endpoint.SentMessageCacheEntry(cache, message, destination_endpoint)[source]

Bases: coapy.endpoint.MessageCacheEntry

Data related to a message sent from a specific endpoint.

This cache holds a message that originated from a local coapy.message.Message.source_endpoint, along with the necessary state to retransmit it if it is confirmable.

destination_endpoint[source]

The endpoint to which the message is being sent.

reply_message[source]

The coapy.message.Message that was received in response to message.

The value is None unless either an acknowledgement (empty or with a piggy-backed response) or a reset has been received.

stale_at[source]

Return the time at which the content of a response message is outdated.

This is calculated at the time the cache entry is created by adding the coapy.option.MaxAge option value to created_clk. Prior to retransmission callers may wish to update the message options to reflect the change in age on subsequent retransmissions.

The value is None if the message is not a response.

transmissions[source]

Number of times this message has been transmitted.

class coapy.endpoint.RcvdMessageCacheEntry(cache, message)[source]

Bases: coapy.endpoint.MessageCacheEntry

Data related to a message received by a specific endpoint.

This cache holds a message that originated from a remote coapy.message.Message.source_endpoint, along with the necessary state to cache the reply to that message.

cache must be the source endpoint cache for received messages.

message must be a message that originated on that host, and is either a confirmable or non-confirmable message. Acknowledgements and Resets are not recorded in the cache.

reception_count[source]

The number of times a message with this entry’s message_id has been received while this cache entry is live. Diagnostics may be emitted in a situation where it appears a message ID has been re-used prematurely.

reply(reset=False, message=None)[source]

Create the reply_message for the reception in this entry.

If message is provided, it should be an coapy.message.Response message with type ACK that is to be sent as a piggy-backed response.

If message is None, this method will create an empty ACK (reset is False) or RST (reset is True) message.

The reply message will be transmitted to the source endpoint of the received message.

Erroneous use will raise ReplyMessageError.

reply_message[source]

The coapy.message.Message that was sent in response to this message. None until a response is sent, then either an acknowledgement (which may or may not have a piggy-backed response) or a reset message. A non-confirmable message may have no response at all.

class coapy.endpoint.RemoteEndpointState(endpoint)

Bases: object

State relevant to communication with a non-local endpoint from the perspective of a local endpoint.

endpoint

The Endpoint to which the state in this instance applies.

last_heard_clk = None

The coapy.clock() time at which the last message was received from this endpoint. The value contributes to verification that coapy.message.TransmissionParameters.PROBING_RATE is not exceeded.

The value is None if no messages have ever been received from this endpoint.

rcvd_cache = None

A MessageCache instance recording messages from endpoint.

rx_messages = None

The number of messages received from this endpoint, including duplicates.

rx_octets = None

The number of octets received from this endpoint, including duplicates.

tx_messages = None

The number of messages transmitted to this endpoint, including retransmissions.

tx_octets = None

The number of octets transmitted to this endpoint, including retransmissions.

tx_octets_since_heard = None

The number of octets transmitted to this endpoint since last_heard_clk was last updated.

Exceptions

class coapy.endpoint.ReplyMessageError[source]

Bases: coapy.CoAPyException

Exception raised when RcvdMessageCacheEntry.reply() is invoked improperly.

The args are (diagnostic, cache_entry, message) where diagnostic is one of the string values in this class, cache_entry is the RcvdMessageCacheEntry, and message is the proposed reply message that was rejected.

ALREADY_GIVEN = u'Message already has reply'

A reply_message has already been assigned.

ID_MISMATCH = u'Message IDs do not match'

A reply message must match using the messageID attributes.

NOT_RESPONSE = u'Non-empty reply is not a response'

A piggy-backed response must be a response message.

RESPONSE_NOT_ACK = u'Piggy-backed response is not ACK'

A piggy-backed response must have type ACK.

TOKEN_MISMATCH = u'Tokens do not match'

A piggy-backed response must match the Token of the request.

Table Of Contents

Previous topic

coapy.option

Next topic

coapy.resource

This Page