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
12 KRPC_ERROR_METHOD_UNKNOWN = 2
13 KRPC_ERROR_RECEIVED_UNKNOWN = 3
14 KRPC_ERROR_TIMEOUT = 4
16 class KRPC(basic.NetstringReceiver):
21 def stringReceived(self, str):
26 print "response decode error: " + `e`
30 if msg['typ'] == 'req':
33 # tell factory to handle
34 f = getattr(self.factory ,"krpc_" + msg['req'], None)
36 msg['arg']['_krpc_sender'] = self.transport.addr
38 ret = apply(f, (), msg['arg'])
41 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' :`e`})
47 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : ret})
49 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : []})
56 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' : KRPC_ERROR_METHOD_UNKNOWN})
60 print "%s >>> (%s, %s) - %s %s %s" % (self.transport.addr, self.factory.node.host, self.factory.node.port,
61 ilen, msg['req'], olen)
62 elif msg['typ'] == 'rsp':
65 if self.tids.has_key(msg['tid']):
66 df = self.tids[msg['tid']]
68 df.callback(msg['rsp'])
69 del(self.tids[msg['tid']])
70 # no tid, perhaps this transaction timed out already...
71 elif msg['typ'] == 'err':
74 df = self.tids[msg['tid']]
76 df.errback(msg['err'])
77 del(self.tids[msg['tid']])
79 # unknown message type
80 df = self.tids[msg['tid']]
82 df.errback(KRPC_ERROR_RECEIVED_UNKNOWN)
83 del(self.tids[msg['tid']])
85 def sendRequest(self, method, args):
88 msg = {'tid' : hash.newID(), 'typ' : 'req', 'req' : method, 'arg' : args}
92 self.tids[msg['tid']] = d
94 def timeOut(tids = self.tids, id = msg['tid']):
98 df.errback(KRPC_ERROR_TIMEOUT)
99 reactor.callLater(KRPC_TIMEOUT, timeOut)