updated api
This commit is contained in:
parent
ee0c6b9bd5
commit
9e8d239d73
@ -86,7 +86,6 @@ class SpiderCrawl(object):
|
|||||||
"""
|
"""
|
||||||
Handle the result of an iteration in C{_find}.
|
Handle the result of an iteration in C{_find}.
|
||||||
"""
|
"""
|
||||||
print "got some responses: ", responses
|
|
||||||
toremove = []
|
toremove = []
|
||||||
for peerid, response in responses.items():
|
for peerid, response in responses.items():
|
||||||
# response will be a tuple of (<response received>, <value>)
|
# response will be a tuple of (<response received>, <value>)
|
||||||
@ -113,7 +112,7 @@ class Server(object):
|
|||||||
to start listening as an active node on the network.
|
to start listening as an active node on the network.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, ksize=20, alpha=3):
|
def __init__(self, ksize=20, alpha=3, id=None):
|
||||||
"""
|
"""
|
||||||
Create a server instance. This will start listening on the given port.
|
Create a server instance. This will start listening on the given port.
|
||||||
|
|
||||||
@ -125,11 +124,17 @@ class Server(object):
|
|||||||
self.alpha = alpha
|
self.alpha = alpha
|
||||||
self.log = Logger(system=self)
|
self.log = Logger(system=self)
|
||||||
storage = ForgetfulStorage()
|
storage = ForgetfulStorage()
|
||||||
self.node = Node(None, None, digest(random.getrandbits(255)))
|
self.node = Node(id or digest(random.getrandbits(255)))
|
||||||
self.protocol = KademliaProtocol(self.node.id, storage, ksize)
|
self.protocol = KademliaProtocol(self.node.id, storage, ksize)
|
||||||
self.refreshLoop = LoopingCall(self.refreshTable).start(3600)
|
self.refreshLoop = LoopingCall(self.refreshTable).start(3600)
|
||||||
|
|
||||||
def listen(self, port):
|
def listen(self, port):
|
||||||
|
"""
|
||||||
|
Start listening on the given port.
|
||||||
|
|
||||||
|
This is the same as calling:
|
||||||
|
C{reactor.listenUDP(port, server.protocol)}
|
||||||
|
"""
|
||||||
return reactor.listenUDP(port, self.protocol)
|
return reactor.listenUDP(port, self.protocol)
|
||||||
|
|
||||||
def refreshTable(self):
|
def refreshTable(self):
|
||||||
@ -139,12 +144,24 @@ class Server(object):
|
|||||||
"""
|
"""
|
||||||
ds = []
|
ds = []
|
||||||
for id in self.protocol.getRefreshIDs():
|
for id in self.protocol.getRefreshIDs():
|
||||||
node = Node(None, None, id)
|
node = Node(id)
|
||||||
nearest = self.protocol.router.findNeighbors(node, self.alpha)
|
nearest = self.protocol.router.findNeighbors(node, self.alpha)
|
||||||
spider = SpiderCrawl(self.protocol, node, nearest)
|
spider = SpiderCrawl(self.protocol, node, nearest)
|
||||||
ds.append(spider.findNodes())
|
ds.append(spider.findNodes())
|
||||||
return defer.gatherResults(ds)
|
return defer.gatherResults(ds)
|
||||||
|
|
||||||
|
def bootstrappableNeighbors(self):
|
||||||
|
"""
|
||||||
|
Get a C{list} of (ip, port) C{tuple}s suitable for use as an argument
|
||||||
|
to the bootstrap method.
|
||||||
|
|
||||||
|
The server should have been bootstrapped
|
||||||
|
already - this is just a utility for getting some neighbors and then
|
||||||
|
storing them if this server is going down for a while. When it comes
|
||||||
|
back up, the list of nodes can be used to bootstrap.
|
||||||
|
"""
|
||||||
|
return self.protocol.router.findNeighbors(self.node)
|
||||||
|
|
||||||
def bootstrap(self, addrs):
|
def bootstrap(self, addrs):
|
||||||
"""
|
"""
|
||||||
Bootstrap the server by connecting to other known nodes in the network.
|
Bootstrap the server by connecting to other known nodes in the network.
|
||||||
@ -155,7 +172,7 @@ class Server(object):
|
|||||||
nodes = []
|
nodes = []
|
||||||
for addr, result in results.items():
|
for addr, result in results.items():
|
||||||
if result[0]:
|
if result[0]:
|
||||||
nodes.append(Node(addr[0], addr[1], result[1]))
|
nodes.append(Node(result[1], addr[0], addr[1]))
|
||||||
spider = SpiderCrawl(self.protocol, self.node, nodes, self.ksize, self.alpha)
|
spider = SpiderCrawl(self.protocol, self.node, nodes, self.ksize, self.alpha)
|
||||||
return spider.findNodes()
|
return spider.findNodes()
|
||||||
|
|
||||||
@ -170,7 +187,7 @@ class Server(object):
|
|||||||
|
|
||||||
@return: C{None} if not found, the value otherwise.
|
@return: C{None} if not found, the value otherwise.
|
||||||
"""
|
"""
|
||||||
node = Node(None, None, digest(key))
|
node = Node(digest(key))
|
||||||
nearest = self.protocol.router.findNeighbors(node)
|
nearest = self.protocol.router.findNeighbors(node)
|
||||||
spider = SpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
|
spider = SpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
|
||||||
return spider.findValue()
|
return spider.findValue()
|
||||||
@ -189,7 +206,7 @@ class Server(object):
|
|||||||
ds = [self.protocol.callStore(node, dkey, value) for node in nodes]
|
ds = [self.protocol.callStore(node, dkey, value) for node in nodes]
|
||||||
return defer.gatherResults(ds)
|
return defer.gatherResults(ds)
|
||||||
|
|
||||||
node = Node(None, None, dkey)
|
node = Node(dkey)
|
||||||
nearest = self.protocol.router.findNeighbors(node)
|
nearest = self.protocol.router.findNeighbors(node)
|
||||||
spider = SpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
|
spider = SpiderCrawl(self.protocol, node, nearest, self.ksize, self.alpha)
|
||||||
return spider.findNodes().addCallback(store)
|
return spider.findNodes().addCallback(store)
|
||||||
|
@ -3,10 +3,10 @@ import heapq
|
|||||||
|
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
def __init__(self, ip, port, id):
|
def __init__(self, id, ip=None, port=None):
|
||||||
|
self.id = id
|
||||||
self.ip = ip
|
self.ip = ip
|
||||||
self.port = port
|
self.port = port
|
||||||
self.id = id
|
|
||||||
self.long_id = long(id.encode('hex'), 16)
|
self.long_id = long(id.encode('hex'), 16)
|
||||||
|
|
||||||
def sameHomeAs(self, node):
|
def sameHomeAs(self, node):
|
||||||
@ -22,7 +22,7 @@ class Node:
|
|||||||
return iter([self.ip, self.port, self.id])
|
return iter([self.ip, self.port, self.id])
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return repr([self.ip, self.port, self.long_id])
|
return repr([self.long_id, self.ip, self.port])
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "%s:%s" % (self.ip, str(self.port))
|
return "%s:%s" % (self.ip, str(self.port))
|
||||||
|
@ -24,25 +24,25 @@ class KademliaProtocol(RPCProtocol):
|
|||||||
return ids
|
return ids
|
||||||
|
|
||||||
def rpc_ping(self, sender, nodeid):
|
def rpc_ping(self, sender, nodeid):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
return self.sourceID
|
return self.sourceID
|
||||||
|
|
||||||
def rpc_store(self, sender, nodeid, key, value):
|
def rpc_store(self, sender, nodeid, key, value):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
self.log.debug("got a store request from %s, storing value" % str(sender))
|
self.log.debug("got a store request from %s, storing value" % str(sender))
|
||||||
self.storage[key] = value
|
self.storage[key] = value
|
||||||
|
|
||||||
def rpc_find_node(self, sender, nodeid, key):
|
def rpc_find_node(self, sender, nodeid, key):
|
||||||
self.log.info("finding neighbors of %i in local table" % long(nodeid.encode('hex'), 16))
|
self.log.info("finding neighbors of %i in local table" % long(nodeid.encode('hex'), 16))
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
node = Node(None, None, key)
|
node = Node(key)
|
||||||
return map(tuple, self.router.findNeighbors(node, exclude=source))
|
return map(tuple, self.router.findNeighbors(node, exclude=source))
|
||||||
|
|
||||||
def rpc_find_value(self, sender, nodeid, key):
|
def rpc_find_value(self, sender, nodeid, key):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
value = self.storage.get(key, None)
|
value = self.storage.get(key, None)
|
||||||
if value is None:
|
if value is None:
|
||||||
|
@ -11,7 +11,7 @@ from kademlia.tests.utils import mknode
|
|||||||
class NodeTest(unittest.TestCase):
|
class NodeTest(unittest.TestCase):
|
||||||
def test_longID(self):
|
def test_longID(self):
|
||||||
rid = hashlib.sha1(str(random.getrandbits(255))).digest()
|
rid = hashlib.sha1(str(random.getrandbits(255))).digest()
|
||||||
n = Node(None, None, rid)
|
n = Node(rid)
|
||||||
self.assertEqual(n.long_id, long(rid.encode('hex'), 16))
|
self.assertEqual(n.long_id, long(rid.encode('hex'), 16))
|
||||||
|
|
||||||
def test_distanceCalculation(self):
|
def test_distanceCalculation(self):
|
||||||
@ -19,8 +19,8 @@ class NodeTest(unittest.TestCase):
|
|||||||
ridtwo = hashlib.sha1(str(random.getrandbits(255)))
|
ridtwo = hashlib.sha1(str(random.getrandbits(255)))
|
||||||
|
|
||||||
shouldbe = long(ridone.hexdigest(), 16) ^ long(ridtwo.hexdigest(), 16)
|
shouldbe = long(ridone.hexdigest(), 16) ^ long(ridtwo.hexdigest(), 16)
|
||||||
none = Node(None, None, ridone.digest())
|
none = Node(ridone.digest())
|
||||||
ntwo = Node(None, None, ridtwo.digest())
|
ntwo = Node(ridtwo.digest())
|
||||||
self.assertEqual(none.distanceTo(ntwo), shouldbe)
|
self.assertEqual(none.distanceTo(ntwo), shouldbe)
|
||||||
|
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ class NodeHeapTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_iteration(self):
|
def test_iteration(self):
|
||||||
heap = NodeHeap(5)
|
heap = NodeHeap(5)
|
||||||
nodes = [mknode(id=digest(x)) for x in range(10)]
|
nodes = [mknode(digest(x)) for x in range(10)]
|
||||||
for index, node in enumerate(nodes):
|
for index, node in enumerate(nodes):
|
||||||
heap.push(index, node)
|
heap.push(index, node)
|
||||||
for index, node in enumerate(heap):
|
for index, node in enumerate(heap):
|
||||||
@ -46,7 +46,7 @@ class NodeHeapTest(unittest.TestCase):
|
|||||||
|
|
||||||
def test_remove(self):
|
def test_remove(self):
|
||||||
heap = NodeHeap(5)
|
heap = NodeHeap(5)
|
||||||
nodes = [mknode(id=digest(x)) for x in range(10)]
|
nodes = [mknode(digest(x)) for x in range(10)]
|
||||||
for index, node in enumerate(nodes):
|
for index, node in enumerate(nodes):
|
||||||
heap.push(index, node)
|
heap.push(index, node)
|
||||||
|
|
||||||
|
@ -9,14 +9,14 @@ from kademlia.node import Node
|
|||||||
from kademlia.routing import RoutingTable
|
from kademlia.routing import RoutingTable
|
||||||
|
|
||||||
|
|
||||||
def mknode(ip=None, port=None, id=None, intid=None):
|
def mknode(id=None, ip=None, port=None, intid=None):
|
||||||
"""
|
"""
|
||||||
Make a node. Created a random id if not specified.
|
Make a node. Created a random id if not specified.
|
||||||
"""
|
"""
|
||||||
if intid is not None:
|
if intid is not None:
|
||||||
id = pack('>l', intid)
|
id = pack('>l', intid)
|
||||||
id = id or hashlib.sha1(str(random.getrandbits(255))).digest()
|
id = id or hashlib.sha1(str(random.getrandbits(255))).digest()
|
||||||
return Node(ip, port, id)
|
return Node(id, ip, port)
|
||||||
|
|
||||||
|
|
||||||
class FakeProtocol(object):
|
class FakeProtocol(object):
|
||||||
@ -35,25 +35,25 @@ class FakeProtocol(object):
|
|||||||
return ids
|
return ids
|
||||||
|
|
||||||
def rpc_ping(self, sender, nodeid):
|
def rpc_ping(self, sender, nodeid):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
return self.sourceID
|
return self.sourceID
|
||||||
|
|
||||||
def rpc_store(self, sender, nodeid, key, value):
|
def rpc_store(self, sender, nodeid, key, value):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
self.log.debug("got a store request from %s, storing value" % str(sender))
|
self.log.debug("got a store request from %s, storing value" % str(sender))
|
||||||
self.storage[key] = value
|
self.storage[key] = value
|
||||||
|
|
||||||
def rpc_find_node(self, sender, nodeid, key):
|
def rpc_find_node(self, sender, nodeid, key):
|
||||||
self.log.info("finding neighbors of %i in local table" % long(nodeid.encode('hex'), 16))
|
self.log.info("finding neighbors of %i in local table" % long(nodeid.encode('hex'), 16))
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
node = Node(None, None, key)
|
node = Node(key)
|
||||||
return map(tuple, self.router.findNeighbors(node, exclude=source))
|
return map(tuple, self.router.findNeighbors(node, exclude=source))
|
||||||
|
|
||||||
def rpc_find_value(self, sender, nodeid, key):
|
def rpc_find_value(self, sender, nodeid, key):
|
||||||
source = Node(sender[0], sender[1], nodeid)
|
source = Node(nodeid, sender[0], sender[1])
|
||||||
self.router.addContact(source)
|
self.router.addContact(source)
|
||||||
value = self.storage.get(key, None)
|
value = self.storage.get(key, None)
|
||||||
if value is None:
|
if value is None:
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
from twisted.application import service, internet
|
from twisted.application import service, internet
|
||||||
|
from twisted.python.log import ILogObserver
|
||||||
|
|
||||||
import sys, os
|
import sys, os
|
||||||
sys.path.append(os.path.dirname(__file__))
|
sys.path.append(os.path.dirname(__file__))
|
||||||
from kademlia.network import Server
|
from kademlia.network import Server
|
||||||
|
from kademlia import log
|
||||||
|
|
||||||
application = service.Application("kademlia")
|
application = service.Application("kademlia")
|
||||||
|
application.setComponent(ILogObserver, log.FileLogObserver(sys.stdout, log.INFO).emit)
|
||||||
kserver = Server()
|
kserver = Server()
|
||||||
server = internet.UDPServer(1234, kserver.protocol)
|
server = internet.UDPServer(1234, kserver.protocol)
|
||||||
server.setServiceParent(application)
|
server.setServiceParent(application)
|
||||||
|
Loading…
Reference in New Issue
Block a user