API Documentation

Here we outline detailed usage of the Cicada API; it explains much more than the technical details under, say, help(swarmlib.swarmnode). For examples and tutorials, see the Tutorials page.

Interacting with Cicada: SwarmPeer

This object is the main way of interacting with the Cicada API as it wraps the lower-level DHT and routing details. It mimics the official socket.socket interface as closely as possible.

Unlike that interface, though, a bind is required, since every peer in the swarm acts like a server for all the others.

class swarmlib.SwarmPeer([hooks={}])

This creates an object, registering a selection of callbacks that hook into various lower-level functionality. The valid keys into hooks are:

  • "send": called for every sent packet. it’s called with the following signature: send(PeerSocket, bytes), where the PeerSocket parameter is responsible for sending the data. this includes all messages, including the ones that occur at a lower level, such as the DHT layer.
  • "recv": called for every time a full high-level data packet is received. it’s called with the following signature: recv(RemoteNode, bytes), where the RemoteNode parameter is the node that the full data packet was received from.
  • "new_peer": called for every time a new SwarmPeer joins the swarm: new_peer(PeerSocket).
SwarmPeer.bind(addr, port[, external_ip=None, external_port=None])

Binds to a particular address, establishing the listener for this member of a Cicada swarm. A subsequent connect() indicates a peer joining an existing swarm, whereas a lack there-of indicates a peer establishing itself as the first member of a swarm. The optional parameters (which must both be specified) set a custom ID for the peer. This is the first method that must be called on a SwarmPeer instance, before any packet operations.

Parameters:
  • addr (str) – either the IP address of a local interface (such as eth0), a hostname like localhost, or an empty string, which would indicate a binding on all interfaces.
  • port (int) – the port to bind on, in the range [1025, 65535)
  • external_ip (int or None) – the external IP address of your host on the network. this applies to NAT traversal situations as seen in the example below where you don’t immediately have access to your external network or a port forwarded on your router. see the traversal module for details.
  • external_port – as with the IP, this is the mapped external port.
from cicada import swarmlib, traversal

peer = swarmlib.SwarmPeer()
with traversal.PortMapping(5000) as pm:
    eip = pm.mapper.external_ip
    peer.bind(pm.local_address, pm.port, eip, pm.eport)
SwarmPeer.connect(network_host, network_port[, timeout=10])

Connects to a peer in an existing swarm.

Parameters:
  • network_host (str) – the IP address or FQDN of an existing Cicada swarm.
  • network_port (int) – similarly, the port of the listening peer
  • timeout (int) – after this amount of time (in seconds), the call will immediately return.
SwarmPeer.broadcast(data[, visited=[]])

Broadcasts data to the entire swarm. For details on the broadcasting algorithm, you can read this blog post.

Parameters:
  • data (bytes) – the raw data to sendtarget (tuple) – one of the following: a 2-tuple (hostname, port); a Hash; or another SwarmPeer instance
  • visited (list) – this parameter is largely used internally to the SwarmPeer object to perform efficient broadcasting, but can be otherwise specified by the caller in order to indicate the specific peers that should be excluded from the broadcast. the list should contain Hash objects.
SwarmPeer.send(target, data[, duplicates=0])

Sends a data packet into the Cicada network.

Parameters:
  • target (tuple) – one of the following: a 2-tuple (hostname, port); a Hash; or another SwarmPeer instance
  • data (bytes) – the raw data to pack and send
  • duplicates (int) – the amount of extra peers to route the message through; this is related to attacker resilience.
SwarmPeer.recv()

Blocks until a data message is received from the Cicada network.

Return type:(SwarmPeer, bytes, bool)
Returns:the source peer that the message came from, the data message we received, and whether or not there are more messages pending

Developer Note

This actually returns RemoteNode instance rather than a SwarmPeer, currently, because I haven’t finished implementing that yet.

NAT Traversal Methods

See the NAT Traversal tutorial for examples.

class traversal.PortMapping(port[, protocol="tcp"])

Establishes an external port mapping using the NAT traversal methods: UPnP, then NAT-PMP. It’s intended to be used using Python’s with construct. See this example for a use-case.

If you wish to use one of the port mapping modules specifically, see the documentation for the UPnP or NatPMP objects.

Parameters:port (int) – this is the requested port to perform an external mapping on. if the port is already mapped, the with clause will exit immediately; see the eport attribute for the resulting port mapping.
PortMapping.eport

Specifies the external port that the mapping succeeded on; this may or may not be the initial port that was passed in.

Low-Level Interaction

Routing

These objects are used in various places to coordinate routing in the Cicada network, such as specifying a send target (instead of a raw address tuple).

class chordlib.routing.Hash([value="", hashed=""])

Either you know the initial value and the hash is computed, or you know the hashed value (and its initial value is – by definition – not determinable) and only that is stored.

Custom Swarm Creation

Maintainer’s Note

The documentation in this area is much less frequently maintained, as its not intended for consumption. It’s merely a starting point for anyone that isn’t really interested in Cicada and more interested in creating their own DHTs.

This section outlines methods for creating custom swarms by interacting directly with the raw distributed hash table (DHT) objects. All of the objects outlined here cannot join or otherwise interact with a Cicada swarm, unless they understand the higher-level protocol’s expectations.

class chordlib.localnode.LocalNode(data, bind_addr[, hooks={}])

Creates an unconnected peer in a Chord DHT.