media/webrtc/trunk/build/android/pylib/forwarder.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 2 # Use of this source code is governed by a BSD-style license that can be
michael@0 3 # found in the LICENSE file.
michael@0 4
michael@0 5 import logging
michael@0 6 import os
michael@0 7 import re
michael@0 8 import sys
michael@0 9 import time
michael@0 10
michael@0 11 import android_commands
michael@0 12 import cmd_helper
michael@0 13 import constants
michael@0 14 import ports
michael@0 15
michael@0 16 from pylib import pexpect
michael@0 17
michael@0 18 class Forwarder(object):
michael@0 19 """Class to manage port forwards from the device to the host."""
michael@0 20
michael@0 21 _DEVICE_FORWARDER_PATH = constants.TEST_EXECUTABLE_DIR + '/device_forwarder'
michael@0 22
michael@0 23 # Unix Abstract socket path:
michael@0 24 _DEVICE_ADB_CONTROL_PORT = 'chrome_device_forwarder'
michael@0 25 _TIMEOUT_SECS = 30
michael@0 26
michael@0 27 def __init__(self, adb, port_pairs, tool, host_name, build_type):
michael@0 28 """Forwards TCP ports on the device back to the host.
michael@0 29
michael@0 30 Works like adb forward, but in reverse.
michael@0 31
michael@0 32 Args:
michael@0 33 adb: Instance of AndroidCommands for talking to the device.
michael@0 34 port_pairs: A list of tuples (device_port, host_port) to forward. Note
michael@0 35 that you can specify 0 as a device_port, in which case a
michael@0 36 port will by dynamically assigned on the device. You can
michael@0 37 get the number of the assigned port using the
michael@0 38 DevicePortForHostPort method.
michael@0 39 tool: Tool class to use to get wrapper, if necessary, for executing the
michael@0 40 forwarder (see valgrind_tools.py).
michael@0 41 host_name: Address to forward to, must be addressable from the
michael@0 42 host machine. Usually use loopback '127.0.0.1'.
michael@0 43 build_type: 'Release' or 'Debug'.
michael@0 44
michael@0 45 Raises:
michael@0 46 Exception on failure to forward the port.
michael@0 47 """
michael@0 48 self._adb = adb
michael@0 49 self._host_to_device_port_map = dict()
michael@0 50 self._host_process = None
michael@0 51 self._device_process = None
michael@0 52 self._adb_forward_process = None
michael@0 53
michael@0 54 self._host_adb_control_port = ports.AllocateTestServerPort()
michael@0 55 if not self._host_adb_control_port:
michael@0 56 raise Exception('Failed to allocate a TCP port in the host machine.')
michael@0 57 adb.PushIfNeeded(
michael@0 58 os.path.join(constants.CHROME_DIR, 'out', build_type,
michael@0 59 'device_forwarder'),
michael@0 60 Forwarder._DEVICE_FORWARDER_PATH)
michael@0 61 self._host_forwarder_path = os.path.join(constants.CHROME_DIR,
michael@0 62 'out',
michael@0 63 build_type,
michael@0 64 'host_forwarder')
michael@0 65 forward_string = ['%d:%d:%s' %
michael@0 66 (device, host, host_name) for device, host in port_pairs]
michael@0 67 logging.info('Forwarding ports: %s', forward_string)
michael@0 68 timeout_sec = 5
michael@0 69 host_pattern = 'host_forwarder.*' + ' '.join(forward_string)
michael@0 70 # TODO(felipeg): Rather than using a blocking kill() here, the device
michael@0 71 # forwarder could try to bind the Unix Domain Socket until it succeeds or
michael@0 72 # while it fails because the socket is already bound (with appropriate
michael@0 73 # timeout handling obviously).
michael@0 74 self._KillHostForwarderBlocking(host_pattern, timeout_sec)
michael@0 75 self._KillDeviceForwarderBlocking(timeout_sec)
michael@0 76 self._adb_forward_process = pexpect.spawn(
michael@0 77 'adb', ['-s',
michael@0 78 adb._adb.GetSerialNumber(),
michael@0 79 'forward',
michael@0 80 'tcp:%s' % self._host_adb_control_port,
michael@0 81 'localabstract:%s' % Forwarder._DEVICE_ADB_CONTROL_PORT])
michael@0 82 self._device_process = pexpect.spawn(
michael@0 83 'adb', ['-s',
michael@0 84 adb._adb.GetSerialNumber(),
michael@0 85 'shell',
michael@0 86 '%s %s -D --adb_sock=%s' % (
michael@0 87 tool.GetUtilWrapper(),
michael@0 88 Forwarder._DEVICE_FORWARDER_PATH,
michael@0 89 Forwarder._DEVICE_ADB_CONTROL_PORT)])
michael@0 90
michael@0 91 device_success_re = re.compile('Starting Device Forwarder.')
michael@0 92 device_failure_re = re.compile('.*:ERROR:(.*)')
michael@0 93 index = self._device_process.expect([device_success_re,
michael@0 94 device_failure_re,
michael@0 95 pexpect.EOF,
michael@0 96 pexpect.TIMEOUT],
michael@0 97 Forwarder._TIMEOUT_SECS)
michael@0 98 if index == 1:
michael@0 99 # Failure
michael@0 100 error_msg = str(self._device_process.match.group(1))
michael@0 101 logging.error(self._device_process.before)
michael@0 102 self._CloseProcess()
michael@0 103 raise Exception('Failed to start Device Forwarder with Error: %s' %
michael@0 104 error_msg)
michael@0 105 elif index == 2:
michael@0 106 logging.error(self._device_process.before)
michael@0 107 self._CloseProcess()
michael@0 108 raise Exception('Unexpected EOF while trying to start Device Forwarder.')
michael@0 109 elif index == 3:
michael@0 110 logging.error(self._device_process.before)
michael@0 111 self._CloseProcess()
michael@0 112 raise Exception('Timeout while trying start Device Forwarder')
michael@0 113
michael@0 114 self._host_process = pexpect.spawn(self._host_forwarder_path,
michael@0 115 ['--adb_port=%s' % (
michael@0 116 self._host_adb_control_port)] +
michael@0 117 forward_string)
michael@0 118
michael@0 119 # Read the output of the command to determine which device ports where
michael@0 120 # forwarded to which host ports (necessary if
michael@0 121 host_success_re = re.compile('Forwarding device port (\d+) to host (\d+):')
michael@0 122 host_failure_re = re.compile('Couldn\'t start forwarder server for port '
michael@0 123 'spec: (\d+):(\d+)')
michael@0 124 for pair in port_pairs:
michael@0 125 index = self._host_process.expect([host_success_re,
michael@0 126 host_failure_re,
michael@0 127 pexpect.EOF,
michael@0 128 pexpect.TIMEOUT],
michael@0 129 Forwarder._TIMEOUT_SECS)
michael@0 130 if index == 0:
michael@0 131 # Success
michael@0 132 device_port = int(self._host_process.match.group(1))
michael@0 133 host_port = int(self._host_process.match.group(2))
michael@0 134 self._host_to_device_port_map[host_port] = device_port
michael@0 135 logging.info("Forwarding device port: %d to host port: %d." %
michael@0 136 (device_port, host_port))
michael@0 137 elif index == 1:
michael@0 138 # Failure
michael@0 139 device_port = int(self._host_process.match.group(1))
michael@0 140 host_port = int(self._host_process.match.group(2))
michael@0 141 self._CloseProcess()
michael@0 142 raise Exception('Failed to forward port %d to %d' % (device_port,
michael@0 143 host_port))
michael@0 144 elif index == 2:
michael@0 145 logging.error(self._host_process.before)
michael@0 146 self._CloseProcess()
michael@0 147 raise Exception('Unexpected EOF while trying to forward ports %s' %
michael@0 148 port_pairs)
michael@0 149 elif index == 3:
michael@0 150 logging.error(self._host_process.before)
michael@0 151 self._CloseProcess()
michael@0 152 raise Exception('Timeout while trying to forward ports %s' % port_pairs)
michael@0 153
michael@0 154 def _KillHostForwarderBlocking(self, host_pattern, timeout_sec):
michael@0 155 """Kills any existing host forwarders using the provided pattern.
michael@0 156
michael@0 157 Note that this waits until the process terminates.
michael@0 158 """
michael@0 159 cmd_helper.RunCmd(['pkill', '-f', host_pattern])
michael@0 160 elapsed = 0
michael@0 161 wait_period = 0.1
michael@0 162 while not cmd_helper.RunCmd(['pgrep', '-f', host_pattern]) and (
michael@0 163 elapsed < timeout_sec):
michael@0 164 time.sleep(wait_period)
michael@0 165 elapsed += wait_period
michael@0 166 if elapsed >= timeout_sec:
michael@0 167 raise Exception('Timed out while killing ' + host_pattern)
michael@0 168
michael@0 169 def _KillDeviceForwarderBlocking(self, timeout_sec):
michael@0 170 """Kills any existing device forwarders.
michael@0 171
michael@0 172 Note that this waits until the process terminates.
michael@0 173 """
michael@0 174 processes_killed = self._adb.KillAllBlocking(
michael@0 175 'device_forwarder', timeout_sec)
michael@0 176 if not processes_killed:
michael@0 177 pids = self._adb.ExtractPid('device_forwarder')
michael@0 178 if pids:
michael@0 179 raise Exception('Timed out while killing device_forwarder')
michael@0 180
michael@0 181 def _CloseProcess(self):
michael@0 182 if self._host_process:
michael@0 183 self._host_process.close()
michael@0 184 if self._device_process:
michael@0 185 self._device_process.close()
michael@0 186 if self._adb_forward_process:
michael@0 187 self._adb_forward_process.close()
michael@0 188 self._host_process = None
michael@0 189 self._device_process = None
michael@0 190 self._adb_forward_process = None
michael@0 191
michael@0 192 def DevicePortForHostPort(self, host_port):
michael@0 193 """Get the device port that corresponds to a given host port."""
michael@0 194 return self._host_to_device_port_map.get(host_port)
michael@0 195
michael@0 196 def Close(self):
michael@0 197 """Terminate the forwarder process."""
michael@0 198 self._CloseProcess()

mercurial