Home | History | Annotate | Download | only in server
      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