2 from twisted.internet.defer import Deferred
3 from twisted.protocols import basic
4 from bencode import bencode, bdecode
5 from twisted.internet import reactor
13 KRPC_ERROR_METHOD_UNKNOWN = 2
14 KRPC_ERROR_RECEIVED_UNKNOWN = 3
15 KRPC_ERROR_TIMEOUT = 4
17 class KRPC(basic.NetstringReceiver):
22 def resetConnection(self):
24 self._readerState = basic.LENGTH
25 self._readerLength = 0
27 def stringReceived(self, str):
33 print "response decode error: " + `e`
37 if msg['typ'] == 'req':
40 # tell factory to handle
41 f = getattr(self.factory ,"krpc_" + msg['req'], None)
43 msg['arg']['_krpc_sender'] = self.transport.addr
45 ret = apply(f, (), msg['arg'])
48 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' :`e`})
54 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : ret})
56 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : {}})
63 print "don't know about method %s" % msg['req']
65 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' : KRPC_ERROR_METHOD_UNKNOWN})
69 print "%s %s >>> %s - %s %s %s" % (time.asctime(), self.transport.addr, self.factory.node.port,
70 ilen, msg['req'], olen)
71 elif msg['typ'] == 'rsp':
74 if self.tids.has_key(msg['tid']):
75 df = self.tids[msg['tid']]
77 del(self.tids[msg['tid']])
78 df.callback({'rsp' : msg['rsp'], '_krpc_sender': self.transport.addr})
79 # no tid, this transaction timed out already...
80 elif msg['typ'] == 'err':
83 df = self.tids[msg['tid']]
85 df.errback(msg['err'])
86 del(self.tids[msg['tid']])
88 # unknown message type
89 df = self.tids[msg['tid']]
91 df.errback(KRPC_ERROR_RECEIVED_UNKNOWN)
92 del(self.tids[msg['tid']])
94 def sendRequest(self, method, args):
97 msg = {'tid' : hash.newID(), 'typ' : 'req', 'req' : method, 'arg' : args}
100 self.tids[msg['tid']] = d
101 def timeOut(tids = self.tids, id = msg['tid']):
105 print ">>>>>> KRPC_ERROR_TIMEOUT"
106 df.errback(KRPC_ERROR_TIMEOUT)
107 reactor.callLater(KRPC_TIMEOUT, timeOut)