Package spade :: Module peer2peer
[hide private]
[frames] | no frames]

Source Code for Module spade.peer2peer

  1  import Behaviour 
  2  import xmpp 
  3  import SocketServer 
  4  import pickle 
  5  import random 
  6   
7 -class P2PBehaviour(Behaviour.Behaviour):
8 - class P2PRequestHandler(SocketServer.StreamRequestHandler):
9 - def handle(self):
10 self.server.requests.append(self.request) 11 try: 12 data = "" 13 while True: 14 #Read message length 15 length = self.rfile.read(8) 16 if not length: 17 #EOF 18 break 19 data = self.rfile.read(int(length)) 20 self.server.owner.DEBUG("P2P message received.","ok") 21 if data: 22 try: 23 #Try with a serialized message 24 ACLmsg = pickle.loads(data) 25 self.server.postMessage(ACLmsg) 26 self.server.owner.DEBUG("The p2p message is serialized.") 27 except: 28 #Try with a jabber message 29 n = xmpp.simplexml.XML2Node(str(data)) 30 m = xmpp.Message(node=n) 31 self.server._jabber_messageCB(None,m,raiseFlag=False) 32 self.server.owner.DEBUG("The p2p message is XML:"+str(m)) 33 data = "" 34 except Exception, e: 35 self.server.owner.DEBUG("P2P Socket Closed to "+ str(self.client_address),"err") #,":",str(e),":",str(length),str(data)
36 37
38 - def _process(self):
39 try: 40 self.server.handle_request() 41 except Exception,e: 42 self.myAgent.DEBUG("P2P server failed: "+str(e),"err")
43
44 - def onEnd(self):
45 self.myAgent.p2p_ready = False 46 self.server.stop() 47 if not self.finished: 48 try: 49 for sock in self.server.requests: 50 try: 51 sock.close() 52 del sock 53 except: 54 pass 55 self.server.socket.close() 56 del self.server 57 except: 58 pass 59 iq = xmpp.Iq("result",queryNS=xmpp.NS_DISCO_INFO) 60 for to in self.myAgent.p2p_routes.keys(): 61 iq.setTo(to) 62 self.myAgent.send(iq) 63 self.finished = True
64
65 - def onStart(self):
66 open = False 67 SocketServer.ThreadingTCPServer.allow_reuse_address = True 68 while open == False: 69 try: 70 self.server = SocketServer.ThreadingTCPServer(('', self.myAgent.P2PPORT), self.P2PRequestHandler) 71 self.server.owner = self.myAgent 72 open = True 73 except: 74 self.myAgent.P2PPORT = random.randint(1025,65535) 75 self.myAgent.DEBUG("Changing P2P port to " + str(self.myAgent.P2PPORT)) 76 77 self.server._jabber_messageCB = self.myAgent._jabber_messageCB 78 self.server.postMessage = self.myAgent.postMessage 79 self.server.requests = [] 80 self.myAgent.DEBUG(self.getName()+": P2P Behaviour Started at port "+ str(self.myAgent.P2PPORT)) 81 self.finished = False #Flag to mark (later) if we have passed through onEnd 82 self.myAgent.p2p_ready = True
83
84 -class StreamInitiationBehaviour(Behaviour.EventBehaviour):
85
86 - def _process(self):
87 self.msg = self._receive(False) 88 if self.msg != None: 89 if self.msg.getType() == "set": 90 if self.msg.getTag("si").getAttr("profile") == "http://jabber.org/protocol/si/profile/spade-p2p-messaging": 91 #P2P Messaging Offer 92 self.myAgent.DEBUG("P2P-Messaging offer from " + str(self.msg.getFrom())) 93 if self.myAgent.p2p_ready: 94 #Take note of sender's p2p address if any 95 if self.msg.getTag("si").getTag("p2p"): 96 remote_address = str(self.msg.getTag("si").getTag("p2p").getData()) 97 d = {"url":remote_address, "p2p":True} 98 self.myAgent.p2p_lock.acquire() 99 if self.myAgent.p2p_routes.has_key(str(self.msg.getFrom().getStripped())): 100 self.myAgent.p2p_routes[str(self.msg.getFrom().getStripped())].update(d) 101 if self.myAgent.p2p_routes[str(self.msg.getFrom().getStripped())].has_key("socket"): 102 self.myAgent.p2p_routes[str(self.msg.getFrom().getStripped())]["socket"].close() 103 else: 104 self.myAgent.p2p_routes[str(self.msg.getFrom().getStripped())] = d 105 self.myAgent.p2p_lock.release() 106 107 #Accept offer 108 reply = self.msg.buildReply("result") 109 si = reply.addChild("si") 110 si.setNamespace("http://jabber.org/protocol/si") 111 p2p = si.addChild("p2p") 112 p2p.setNamespace('http://jabber.org/protocol/si/profile/spade-p2p-messaging') 113 value = p2p.addChild("value") 114 value.setData(self.myAgent.getP2PUrl()) 115 self.myAgent.DEBUG("P2P: Accept offer from "+str(self.msg.getFrom())+"."+str(reply) ) 116 else: 117 #Refuse offer 118 reply = self.msg.buildReply("error") 119 err = reply.addChild("error", attrs={"code":"403","type":"cancel"}) 120 err.addChild("forbidden") 121 err.setNamespace("urn:ietf:params:xml:ns:xmpp-stanzas") 122 self.myAgent.DEBUG("P2P: Refuse offer from "+str(self.msg.getFrom())+"."+str(reply)) 123 124 self.myAgent.send(reply)
125 126
127 -class DiscoBehaviour(Behaviour.EventBehaviour):
128
129 - def _process(self):
130 self.msg = self._receive(False) 131 if self.msg != None: 132 if self.msg.getType() == "get": 133 #Inform of services 134 reply = self.msg.buildReply("result") 135 if self.myAgent.p2p_ready: 136 reply.getTag("query").addChild("feature", {"var":"http://jabber.org/protocol/si"}) 137 reply.getTag("query").addChild("feature", {"var":"http://jabber.org/protocol/si/profile/spade-p2p-messaging"}) 138 self.myAgent.send(reply) 139 self.myAgent.DEBUG(self.myAgent.getName()+": Sent Disco reply to "+ str(reply.getTo())) 140 elif self.msg.getType() == "result": 141 services = [] 142 for child in self.msg.getQueryChildren(): 143 services.append(str(child.getAttr("var"))) 144 if "http://jabber.org/protocol/si/profile/spade-p2p-messaging" not in services: 145 frm = str(self.msg.getFrom().getStripped()) 146 if str(frm) in self.myAgent.p2p_routes.keys(): 147 #This agent does no longer support p2p 148 self.myAgent.p2p_lock.acquire() 149 try: 150 self.myAgent.DEBUG("Deleting "+str(frm)+" from P2P routes: "+ str(self.myAgent.p2p_routes),"warn") 151 del self.myAgent.p2p_routes[frm] 152 except: 153 pass 154 self.myAgent.p2p_lock.release() 155 else: 156 self.myAgent.DEBUG("DiscoBehaviour returned with no message", "warn")
157
158 -class SendStreamInitiationBehav(Behaviour.OneShotBehaviour):
159
160 - def __init__(self,to):
161 Behaviour.OneShotBehaviour.__init__(self) 162 163 self.to = to 164 self.id = 'offer'+str(random.randint(1,10000)) 165 self.temp_iq = xmpp.Iq(attrs={'id':self.id})
166 167
168 - def _process(self):
169 self.result = False 170 #Offer Stream Initiation 171 self.myAgent.DEBUG( "Offer StreamInitiation to" + str(self.to)) 172 iq = xmpp.Iq(attrs={'id':self.id}) 173 iq.setTo(self.to) 174 iq.setType("set") 175 si = xmpp.Node("si", {"profile":"http://jabber.org/protocol/si/profile/spade-p2p-messaging"}) 176 si.setNamespace("http://jabber.org/protocol/si") 177 if self.myAgent.p2p_ready: 178 p2pnode = xmpp.Node("p2p") 179 p2pnode.setNamespace('http://jabber.org/protocol/si/profile/spade-p2p-messaging') 180 p2pnode.setData(self.myAgent.getP2PUrl()) 181 si.addChild(node=p2pnode) 182 iq.addChild(node=si) 183 self.myAgent.send(iq) 184 185 msg = self._receive(True, 4) 186 if msg: 187 self.result = False 188 if msg.getType() =="result": 189 self.myAgent.DEBUG("StreamRequest Agreed","ok") 190 try: 191 remote_address = str(msg.getTag("si").getTag("p2p").getTag("value").getData()) 192 d = {"url":remote_address, "p2p":True} 193 if self.myAgent.p2p_routes.has_key(str(msg.getFrom().getStripped())): 194 self.myAgent.p2p_routes[str(msg.getFrom().getStripped())].update(d) 195 self.result = True 196 else: 197 self.myAgent.p2p_routes[str(msg.getFrom().getStripped())] = d 198 except Exception, e: 199 self.myAgent.DEBUG("Malformed StreamRequest Answer: "+ str(e),"err") 200 self.myAgent.p2p_routes[str(msg.getFrom().getStripped())] = {} 201 elif msg.getType() == "error": 202 self.myAgent.DEBUG("StreamRequest REFUSED","warn") 203 self.myAgent.p2p_routes[str(msg.getFrom().getStripped())] = {'p2p':False} 204 else: 205 #Not message, treat like a refuse 206 self.myAgent.DEBUG("StreamRequest REFUSED","warn") 207 self.myAgent.p2p_routes[str(iq.getTo().getStripped())] = {'p2p':False}
208 209
210 -class RequestDiscoInfoBehav(Behaviour.OneShotBehaviour):
211
212 - def __init__(self,to):
213 Behaviour.OneShotBehaviour.__init__(self) 214 215 self.to = to 216 self.id = 'nsdi'+str(random.randint(1,10000)) 217 self.temp_iq = xmpp.Iq(queryNS=xmpp.NS_DISCO_INFO, attrs={'id':self.id}) 218 self.temp_iq.setType("result")
219 220
221 - def _process(self):
222 self.result = [] 223 iq = xmpp.Iq(queryNS=xmpp.NS_DISCO_INFO, attrs={'id':self.id}) 224 iq.setTo(self.to) 225 iq.setType("get") 226 self.myAgent.DEBUG("Send IQ message: "+str(iq)) 227 228 self.myAgent.send(iq) 229 #msg = self._receive(True, 10) 230 msg = self._receive(True) 231 if msg: 232 if msg.getType() == "result": 233 for child in msg.getQueryChildren(): 234 self.result.append(str(child.getAttr("var"))) 235 self.myAgent.DEBUG("Retrieved services: " + str(self.result)) 236 else: 237 self.myAgent.DEBUG("Disco Info returned no results from " + str(self.to), "warn") 238 else: 239 self.myAgent.DEBUG("No Disco Info retrieved from " + str(self.to), "warn")
240