1# Copyright 2014 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import collections 6 7 8PortPair = collections.namedtuple('PortPair', ['local_port', 'remote_port']) 9PortSet = collections.namedtuple('PortSet', ['http', 'https', 'dns']) 10 11class PortPairs(collections.namedtuple('PortPairs', ['http', 'https', 'dns'])): 12 __slots__ = () 13 14 @classmethod 15 def Zip(cls, local_ports, remote_ports): 16 """Zip a pair of PortSet's into a single PortPairs object.""" 17 with_dns = local_ports.dns is not None and remote_ports.dns is not None 18 return cls( 19 PortPair(local_ports.http, remote_ports.http), 20 PortPair(local_ports.https, remote_ports.https), 21 PortPair(local_ports.dns, remote_ports.dns) if with_dns else None) 22 23 @property 24 def local_ports(self): 25 """Return a tuple of local ports only.""" 26 return PortSet(*[p.local_port if p is not None else None for p in self]) 27 28 @property 29 def remote_ports(self): 30 """Return a tuple of remote ports only.""" 31 return PortSet(*[p.remote_port if p is not None else None for p in self]) 32 33 34class ForwarderFactory(object): 35 36 def Create(self, port_pairs): 37 """Creates a forwarder that maps remote (device) <-> local (host) ports. 38 39 Args: 40 port_pairs: A PortPairs instance that consists of a PortPair mapping 41 for each protocol. http is required. https and dns may be None. 42 """ 43 raise NotImplementedError() 44 45 @property 46 def host_ip(self): 47 return '127.0.0.1' 48 49 50class Forwarder(object): 51 52 def __init__(self, port_pairs): 53 assert port_pairs.http, 'HTTP port mapping is required.' 54 self._port_pairs = PortPairs(*[ 55 PortPair(p.local_port, p.remote_port or p.local_port) 56 if p else None for p in port_pairs]) 57 self._forwarding = True 58 59 @property 60 def host_port(self): 61 return self._port_pairs.http.remote_port 62 63 @property 64 def host_ip(self): 65 return '127.0.0.1' 66 67 @property 68 def port_pairs(self): 69 return self._port_pairs 70 71 @property 72 def url(self): 73 assert self.host_ip and self.host_port 74 return 'http://%s:%i' % (self.host_ip, self.host_port) 75 76 def Close(self): 77 self._port_pairs = None 78 self._forwarding = False 79