133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Copyright 2012 the V8 project authors. All rights reserved. 233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# Redistribution and use in source and binary forms, with or without 333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# modification, are permitted provided that the following conditions are 433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# met: 533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# 633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Redistributions of source code must retain the above copyright 733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# notice, this list of conditions and the following disclaimer. 833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Redistributions in binary form must reproduce the above 933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# copyright notice, this list of conditions and the following 1033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# disclaimer in the documentation and/or other materials provided 1133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# with the distribution. 1233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# * Neither the name of Google Inc. nor the names of its 1333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# contributors may be used to endorse or promote products derived 1433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# from this software without specific prior written permission. 1533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# 1633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 2833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 2933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport os 3033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport SocketServer 3133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport stat 3233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport subprocess 3333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgimport threading 3433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 3533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom . import compression 3633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom . import constants 3733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom . import signatures 3833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom ..network import endpoint 3933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgfrom ..objects import workpacket 4033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 4133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 4233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass WorkHandler(SocketServer.BaseRequestHandler): 4333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 4433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def handle(self): 4533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org rec = compression.Receiver(self.request) 4633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org while not rec.IsDone(): 4733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org data = rec.Current() 4833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org with self.server.job_lock: 4933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._WorkOnWorkPacket(data) 5033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org rec.Advance() 5133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 5233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _WorkOnWorkPacket(self, data): 5333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org server_root = self.server.daemon.root 5433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org v8_root = os.path.join(server_root, "v8") 5533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org os.chdir(v8_root) 5633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org packet = workpacket.WorkPacket.Unpack(data) 5733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.ctx = packet.context 5833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.ctx.shell_dir = os.path.join("out", 5933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org "%s.%s" % (self.ctx.arch, self.ctx.mode)) 6033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not os.path.isdir(self.ctx.shell_dir): 6133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org os.makedirs(self.ctx.shell_dir) 6233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org for binary in packet.binaries: 6333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not self._UnpackBinary(binary, packet.pubkey_fingerprint): 6433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return 6533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not self._CheckoutRevision(packet.base_revision): 6733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return 6833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 6933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not self._ApplyPatch(packet.patch): 7033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return 7133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 7233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org tests = packet.tests 7333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org endpoint.Execute(v8_root, self.ctx, tests, self.request, self.server.daemon) 7433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse() 7533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 7633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _SendResponse(self, error_message=None): 7733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org try: 7833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if error_message: 7933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org compression.Send([[-1, error_message]], self.request) 8033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org compression.Send(constants.END_OF_STREAM, self.request) 8133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return 8233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org except Exception, e: 8333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org pass # Peer is gone. There's nothing we can do. 8433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org # Clean up. 8533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._Call("git checkout -f") 8633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._Call("git clean -f -d") 8733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._Call("rm -rf %s" % self.ctx.shell_dir) 8833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 8933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _UnpackBinary(self, binary, pubkey_fingerprint): 9033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org binary_name = binary["name"] 9133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if binary_name == "libv8.so": 9233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org libdir = os.path.join(self.ctx.shell_dir, "lib.target") 9333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not os.path.exists(libdir): os.makedirs(libdir) 9433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org target = os.path.join(libdir, binary_name) 9533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org else: 9633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org target = os.path.join(self.ctx.shell_dir, binary_name) 9733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org pubkeyfile = "../trusted/%s.pem" % pubkey_fingerprint 9833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not signatures.VerifySignature(target, binary["blob"], 9933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org binary["sign"], pubkeyfile): 10033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse("Signature verification failed") 10133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return False 10233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org os.chmod(target, stat.S_IRWXU) 10333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return True 10433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 10533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _CheckoutRevision(self, base_svn_revision): 10633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org get_hash_cmd = ( 10733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org "git log -1 --format=%%H --remotes --grep='^git-svn-id:.*@%s'" % 10833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org base_svn_revision) 10933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org try: 11033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org base_revision = subprocess.check_output(get_hash_cmd, shell=True) 11133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not base_revision: raise ValueError 11233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org except: 11333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._Call("git fetch") 11433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org try: 11533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org base_revision = subprocess.check_output(get_hash_cmd, shell=True) 11633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not base_revision: raise ValueError 11733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org except: 11833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse("Base revision not found.") 11933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return False 12033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org code = self._Call("git checkout -f %s" % base_revision) 12133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if code != 0: 12233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse("Error trying to check out base revision.") 12333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return False 12433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org code = self._Call("git clean -f -d") 12533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if code != 0: 12633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse("Failed to reset checkout") 12733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return False 12833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return True 12933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 13033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _ApplyPatch(self, patch): 13133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if not patch: return True # Just skip if the patch is empty. 13233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org patchfilename = "_dtest_incoming_patch.patch" 13333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org with open(patchfilename, "w") as f: 13433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org f.write(patch) 13533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org code = self._Call("git apply %s" % patchfilename) 13633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org if code != 0: 13733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self._SendResponse("Error applying patch.") 13833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return False 13933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return True 14033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 14133e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def _Call(self, cmd): 14233e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org return subprocess.call(cmd, shell=True) 14333e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 14433e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org 14533e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.orgclass WorkSocketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): 14633e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org def __init__(self, daemon): 14733e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org address = (daemon.ip, constants.PEER_PORT) 14833e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org SocketServer.TCPServer.__init__(self, address, WorkHandler) 14933e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.job_lock = threading.Lock() 15033e09c8efd078308de3c77a88301566f65c07befverwaest@chromium.org self.daemon = daemon 151