1 # Copyright 2012 the V8 project authors. All rights reserved. 2 # Redistribution and use in source and binary forms, with or without 3 # modification, are permitted provided that the following conditions are 4 # met: 5 # 6 # * Redistributions of source code must retain the above copyright 7 # notice, this list of conditions and the following disclaimer. 8 # * Redistributions in binary form must reproduce the above 9 # copyright notice, this list of conditions and the following 10 # disclaimer in the documentation and/or other materials provided 11 # with the distribution. 12 # * Neither the name of Google Inc. nor the names of its 13 # contributors may be used to endorse or promote products derived 14 # from this software without specific prior written permission. 15 # 16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 28 29 import socket 30 import SocketServer 31 import threading 32 try: 33 import ujson as json 34 except: 35 import json 36 37 from . import constants 38 from ..objects import peer 39 40 41 STARTUP_REQUEST = "V8 test peer starting up" 42 STARTUP_RESPONSE = "Let's rock some tests!" 43 EXIT_REQUEST = "V8 testing peer going down" 44 45 46 def GetOwnIP(): 47 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 48 s.connect(("8.8.8.8", 80)) 49 ip = s.getsockname()[0] 50 s.close() 51 return ip 52 53 54 class PresenceHandler(SocketServer.BaseRequestHandler): 55 56 def handle(self): 57 data = json.loads(self.request[0].strip()) 58 59 if data[0] == STARTUP_REQUEST: 60 jobs = data[1] 61 relative_perf = data[2] 62 pubkey_fingerprint = data[3] 63 trusted = self.server.daemon.IsTrusted(pubkey_fingerprint) 64 response = [STARTUP_RESPONSE, self.server.daemon.jobs, 65 self.server.daemon.relative_perf, 66 self.server.daemon.pubkey_fingerprint, trusted] 67 response = json.dumps(response) 68 self.server.SendTo(self.client_address[0], response) 69 p = peer.Peer(self.client_address[0], jobs, relative_perf, 70 pubkey_fingerprint) 71 p.trusted = trusted 72 self.server.daemon.AddPeer(p) 73 74 elif data[0] == STARTUP_RESPONSE: 75 jobs = data[1] 76 perf = data[2] 77 pubkey_fingerprint = data[3] 78 p = peer.Peer(self.client_address[0], jobs, perf, pubkey_fingerprint) 79 p.trusted = self.server.daemon.IsTrusted(pubkey_fingerprint) 80 p.trusting_me = data[4] 81 self.server.daemon.AddPeer(p) 82 83 elif data[0] == EXIT_REQUEST: 84 self.server.daemon.DeletePeer(self.client_address[0]) 85 if self.client_address[0] == self.server.daemon.ip: 86 self.server.shutdown_lock.release() 87 88 89 class PresenceDaemon(SocketServer.ThreadingMixIn, SocketServer.UDPServer): 90 def __init__(self, daemon): 91 self.daemon = daemon 92 address = (daemon.ip, constants.PRESENCE_PORT) 93 SocketServer.UDPServer.__init__(self, address, PresenceHandler) 94 self.shutdown_lock = threading.Lock() 95 96 def shutdown(self): 97 self.shutdown_lock.acquire() 98 self.SendToAll(json.dumps([EXIT_REQUEST])) 99 self.shutdown_lock.acquire() 100 self.shutdown_lock.release() 101 SocketServer.UDPServer.shutdown(self) 102 103 def SendTo(self, target, message): 104 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 105 sock.sendto(message, (target, constants.PRESENCE_PORT)) 106 sock.close() 107 108 def SendToAll(self, message): 109 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 110 ip = self.daemon.ip.split(".") 111 for i in range(1, 254): 112 ip[-1] = str(i) 113 sock.sendto(message, (".".join(ip), constants.PRESENCE_PORT)) 114 sock.close() 115 116 def FindPeers(self): 117 request = [STARTUP_REQUEST, self.daemon.jobs, self.daemon.relative_perf, 118 self.daemon.pubkey_fingerprint] 119 request = json.dumps(request) 120 self.SendToAll(request) 121