2e2c9b64392b9caf1eb3be2e11258ce225187667
[quix0rs-apt-p2p.git] / apt_p2p_Khashmir / knode.py
1 ## Copyright 2002-2004 Andrew Loewenstern, All Rights Reserved
2 # see LICENSE.txt for license information
3
4 """Represents a khashmir node in the DHT."""
5
6 from twisted.python import log
7
8 from node import Node, NULL_ID
9
10 class KNodeBase(Node):
11     """A basic node that can only be pinged and help find other nodes."""
12     
13     def checkSender(self, dict):
14         """Check the sender's info to make sure it meets expectations."""
15         try:
16             senderid = dict['rsp']['id']
17         except KeyError:
18             log.msg("No peer id in response")
19             raise Exception, "No peer id in response."
20         else:
21             if self.id != NULL_ID and senderid != self.id:
22                 log.msg("Got response from different node than expected.")
23                 self.table.invalidateNode(self)
24                 
25         return dict
26
27     def errBack(self, err):
28         """Log an error that has occurred."""
29         log.err(err)
30         return err
31         
32     def ping(self, id):
33         """Ping the node."""
34         df = self.conn.sendRequest('ping', {"id":id})
35         df.addErrback(self.errBack)
36         df.addCallback(self.checkSender)
37         return df
38     
39     def join(self, id):
40         """Use the node to bootstrap into the system."""
41         df = self.conn.sendRequest('join', {"id":id})
42         df.addErrback(self.errBack)
43         df.addCallback(self.checkSender)
44         return df
45     
46     def find_node(self, id, target):
47         """Request the nearest nodes to the target that the node knows about."""
48         df = self.conn.sendRequest('find_node', {"target" : target, "id": id})
49         df.addErrback(self.errBack)
50         df.addCallback(self.checkSender)
51         return df
52
53 class KNodeRead(KNodeBase):
54     """More advanced node that can also find and send values."""
55     
56     def find_value(self, id, key):
57         """Request the nearest nodes to the key that the node knows about."""
58         df =  self.conn.sendRequest('find_value', {"key" : key, "id" : id})
59         df.addErrback(self.errBack)
60         df.addCallback(self.checkSender)
61         return df
62
63     def get_value(self, id, key, num):
64         """Request the values that the node has for the key."""
65         df = self.conn.sendRequest('get_value', {"key" : key, "num": num, "id" : id})
66         df.addErrback(self.errBack)
67         df.addCallback(self.checkSender)
68         return df
69
70 class KNodeWrite(KNodeRead):
71     """Most advanced node that can also store values."""
72     
73     def store_value(self, id, key, value, token):
74         """Store a value in the node."""
75         df = self.conn.sendRequest('store_value', {"key" : key, "value" : value, "token" : token, "id": id})
76         df.addErrback(self.errBack)
77         df.addCallback(self.checkSender)
78         return df