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 stringReceived(self, str):
27 print "response decode error: " + `e`
31 if msg['typ'] == 'req':
34 # tell factory to handle
35 f = getattr(self.factory ,"krpc_" + msg['req'], None)
37 msg['arg']['_krpc_sender'] = self.transport.addr
39 ret = apply(f, (), msg['arg'])
42 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' :`e`})
48 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : ret})
50 str = bencode({'tid' : msg['tid'], 'typ' : 'rsp', 'rsp' : []})
57 str = bencode({'tid':msg['tid'], 'typ':'err', 'err' : KRPC_ERROR_METHOD_UNKNOWN})
61 print "%s %s >>> %s - %s %s %s" % (time.asctime(), self.transport.addr, self.factory.node.port,
62 ilen, msg['req'], olen)
63 elif msg['typ'] == 'rsp':
66 if self.tids.has_key(msg['tid']):
67 df = self.tids[msg['tid']]
69 df.callback(msg['rsp'])
70 del(self.tids[msg['tid']])
71 # no tid, perhaps this transaction timed out already...
72 elif msg['typ'] == 'err':
75 df = self.tids[msg['tid']]
77 df.errback(msg['err'])
78 del(self.tids[msg['tid']])
80 # unknown message type
81 df = self.tids[msg['tid']]
83 df.errback(KRPC_ERROR_RECEIVED_UNKNOWN)
84 del(self.tids[msg['tid']])
86 def sendRequest(self, method, args):
89 msg = {'tid' : hash.newID(), 'typ' : 'req', 'req' : method, 'arg' : args}
93 self.tids[msg['tid']] = d
95 def timeOut(tids = self.tids, id = msg['tid']):
99 df.errback(KRPC_ERROR_TIMEOUT)
100 reactor.callLater(KRPC_TIMEOUT, timeOut)