-
Notifications
You must be signed in to change notification settings - Fork 12
Writing a controller
Pierre St Juste edited this page Dec 14, 2013
·
3 revisions
This file explains the main components of controller design. It is important to do the following before things can start working:
- Create and register a UDP socket for communication with tincan
- Set the local uid and IPv4/IPv6
- Login to the XMPP service
- Call get_state to update local state
- Listen on UDP sockets and process the different packet types
class UdpServer(object):
def __init__(self, user, password, host, ip4):
# this dict stores the local user state
self.state = {}
# this dict store the state for each peer
self.peers = {}
# this set keeps track of unique
self.peerlist = set()
# this creates the UDP socket for communication with tincan
if socket.has_ipv6:
self.sock = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
else:
self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.sock.bind(("", 0))
# creates a random 20-byte uid and translates it to a hex string
uid = binascii.b2a_hex(os.urandom(CONFIG["uid_size"]/2))
# enables logging
do_set_logging(self.sock)
# sets the callback in tincan in order to receive event notifications
do_set_cb_endpoint(self.sock, self.sock.getsockname())
# configures the ipop interface and sets uid for XMPP network
do_set_local_ip(self.sock, uid, ip4, gen_ip6(uid))
# connects to XMPP service
do_register_service(self.sock, user, password, host)
# requests tincan to get state
do_get_state(self.sock)
def create_connection(self, uid, data, overlay_id, sec, cas, ip4):
# keeps track of unique peers
self.peerlist.add(uid)
# creates a new connection to a peer
do_create_link(self.sock, uid, data, overlay_id, sec, cas)
# assigns an ip address to a remote peer
do_set_remote_ip(self.sock, uid, ip4, gen_ip6(uid))
def trim_connections(self):
# this function is called about every 30 seconds and deletes
# offline connections, it is important to delete old connections
# because tincan will not allow reconnections if old connections
# are still around
for k, v in self.peers.iteritems():
if "fpr" in v and v["status"] == "offline":
if v["last_time"] > CONFIG["wait_time"] * 2:
do_trim_link(self.sock, k)
def serve(self):
# waits for incoming connections
socks = select.select([self.sock], [], [], CONFIG["wait_time"])
for sock in socks[0]:
# receive packet from tincan
data, addr = sock.recvfrom(CONFIG["buf_size"])
if data[0] == '{':
# transforms input to python objects
msg = json.loads(data)
logging.debug("recv %s %s" % (addr, data))
# get message type from object
msg_type = msg.get("type", None)
# this is the local state object, so we save it
if msg_type == "local_state": self.state = msg
# this is a peer state object, so we save it too
elif msg_type == "peer_state": self.peers[msg["uid"]] = msg
# we ignore connection status notification for now
elif msg_type == "con_stat": pass
# we create a connection if we see these types of messages
elif msg_type == "con_req" or msg_type == "con_resp":
fpr_len = len(self.state["_fpr"])
fpr = msg["data"][:fpr_len]
cas = msg["data"][fpr_len + 1:]
# gets an IP address for the new connection
ip4 = gen_ip4(msg["uid"], self.peerlist, self.state["_ip4"])
# create a connection from the con_req/con_resp
self.create_connection(msg["uid"], fpr, 1, CONFIG["sec"],
cas, ip4)
- Building the code
- IPOP packages
- Running SocialVPN nodes
- Running GroupVPN nodes
- Deploying OSN and NAT traversal services
- Test and monitoring
- Extending the code
- General documentation