# 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