|  | # Copyright 2012 the V8 project authors. All rights reserved. | 
|  | # Redistribution and use in source and binary forms, with or without | 
|  | # modification, are permitted provided that the following conditions are | 
|  | # met: | 
|  | # | 
|  | #     * Redistributions of source code must retain the above copyright | 
|  | #       notice, this list of conditions and the following disclaimer. | 
|  | #     * Redistributions in binary form must reproduce the above | 
|  | #       copyright notice, this list of conditions and the following | 
|  | #       disclaimer in the documentation and/or other materials provided | 
|  | #       with the distribution. | 
|  | #     * Neither the name of Google Inc. nor the names of its | 
|  | #       contributors may be used to endorse or promote products derived | 
|  | #       from this software without specific prior written permission. | 
|  | # | 
|  | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | 
|  | # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | 
|  | # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | 
|  | # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | 
|  | # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | 
|  | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | 
|  | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | 
|  | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | 
|  | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 
|  | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  |  | 
|  | import socket | 
|  | import SocketServer | 
|  |  | 
|  | from . import compression | 
|  | from . import constants | 
|  |  | 
|  |  | 
|  | def _StatusQuery(peer, query): | 
|  | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) | 
|  | code = sock.connect_ex((peer.address, constants.STATUS_PORT)) | 
|  | if code != 0: | 
|  | # TODO(jkummerow): disconnect (after 3 failures?) | 
|  | return | 
|  | compression.Send(query, sock) | 
|  | compression.Send(constants.END_OF_STREAM, sock) | 
|  | rec = compression.Receiver(sock) | 
|  | data = None | 
|  | while not rec.IsDone(): | 
|  | data = rec.Current() | 
|  | assert data[0] == query[0] | 
|  | data = data[1] | 
|  | rec.Advance() | 
|  | sock.close() | 
|  | return data | 
|  |  | 
|  |  | 
|  | def RequestTrustedPubkeys(peer, server): | 
|  | pubkey_list = _StatusQuery(peer, [constants.LIST_TRUSTED_PUBKEYS]) | 
|  | for pubkey in pubkey_list: | 
|  | if server.IsTrusted(pubkey): continue | 
|  | result = _StatusQuery(peer, [constants.GET_SIGNED_PUBKEY, pubkey]) | 
|  | server.AcceptNewTrusted(result) | 
|  |  | 
|  |  | 
|  | def NotifyNewTrusted(peer, data): | 
|  | _StatusQuery(peer, [constants.NOTIFY_NEW_TRUSTED] + data) | 
|  |  | 
|  |  | 
|  | def ITrustYouNow(peer): | 
|  | _StatusQuery(peer, [constants.TRUST_YOU_NOW]) | 
|  |  | 
|  |  | 
|  | def TryTransitiveTrust(peer, pubkey, server): | 
|  | if _StatusQuery(peer, [constants.DO_YOU_TRUST, pubkey]): | 
|  | result = _StatusQuery(peer, [constants.GET_SIGNED_PUBKEY, pubkey]) | 
|  | server.AcceptNewTrusted(result) | 
|  |  | 
|  |  | 
|  | class StatusHandler(SocketServer.BaseRequestHandler): | 
|  | def handle(self): | 
|  | rec = compression.Receiver(self.request) | 
|  | while not rec.IsDone(): | 
|  | data = rec.Current() | 
|  | action = data[0] | 
|  |  | 
|  | if action == constants.LIST_TRUSTED_PUBKEYS: | 
|  | response = self.server.daemon.ListTrusted() | 
|  | compression.Send([action, response], self.request) | 
|  |  | 
|  | elif action == constants.GET_SIGNED_PUBKEY: | 
|  | response = self.server.daemon.SignTrusted(data[1]) | 
|  | compression.Send([action, response], self.request) | 
|  |  | 
|  | elif action == constants.NOTIFY_NEW_TRUSTED: | 
|  | self.server.daemon.AcceptNewTrusted(data[1:]) | 
|  | pass  # No response. | 
|  |  | 
|  | elif action == constants.TRUST_YOU_NOW: | 
|  | self.server.daemon.MarkPeerAsTrusting(self.client_address[0]) | 
|  | pass  # No response. | 
|  |  | 
|  | elif action == constants.DO_YOU_TRUST: | 
|  | response = self.server.daemon.IsTrusted(data[1]) | 
|  | compression.Send([action, response], self.request) | 
|  |  | 
|  | rec.Advance() | 
|  | compression.Send(constants.END_OF_STREAM, self.request) | 
|  |  | 
|  |  | 
|  | class StatusSocketServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): | 
|  | def __init__(self, daemon): | 
|  | address = (daemon.ip, constants.STATUS_PORT) | 
|  | SocketServer.TCPServer.__init__(self, address, StatusHandler) | 
|  | self.daemon = daemon |