# Copyright (c) 2012 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Functions that deal with local and device ports."""

import contextlib
import fcntl
import httplib
import logging
import os
import re
import socket
import traceback

import cmd_helper
import constants


# The following two methods are used to allocate the port source for various
# types of test servers. Because some net-related tests can be run on shards at
# same time, it's important to have a mechanism to allocate the port
# process-safe. In here, we implement the safe port allocation by leveraging
# flock.
def ResetTestServerPortAllocation():
  """Resets the port allocation to start from TEST_SERVER_PORT_FIRST.

  Returns:
    Returns True if reset successes. Otherwise returns False.
  """
  try:
    with open(constants.TEST_SERVER_PORT_FILE, 'w') as fp:
      fp.write('%d' % constants.TEST_SERVER_PORT_FIRST)
    if os.path.exists(constants.TEST_SERVER_PORT_LOCKFILE):
      os.unlink(constants.TEST_SERVER_PORT_LOCKFILE)
    return True
  except Exception as e:
    logging.error(e)
  return False


def AllocateTestServerPort():
  """Allocates a port incrementally.

  Returns:
    Returns a valid port which should be in between TEST_SERVER_PORT_FIRST and
    TEST_SERVER_PORT_LAST. Returning 0 means no more valid port can be used.
  """
  port = 0
  ports_tried = []
  try:
    fp_lock = open(constants.TEST_SERVER_PORT_LOCKFILE, 'w')
    fcntl.flock(fp_lock, fcntl.LOCK_EX)
    # Get current valid port and calculate next valid port.
    if not os.path.exists(constants.TEST_SERVER_PORT_FILE):
      ResetTestServerPortAllocation()
    with open(constants.TEST_SERVER_PORT_FILE, 'r+') as fp:
      port = int(fp.read())
      ports_tried.append(port)
      while IsHostPortUsed(port):
        port += 1
        ports_tried.append(port)
      if (port > constants.TEST_SERVER_PORT_LAST or
          port < constants.TEST_SERVER_PORT_FIRST):
        port = 0
      else:
        fp.seek(0, os.SEEK_SET)
        fp.write('%d' % (port + 1))
  except Exception as e:
    logging.info(e)
  finally:
    if fp_lock:
      fcntl.flock(fp_lock, fcntl.LOCK_UN)
      fp_lock.close()
  if port:
    logging.info('Allocate port %d for test server.', port)
  else:
    logging.error('Could not allocate port for test server. '
                  'List of ports tried: %s', str(ports_tried))
  return port


def IsHostPortUsed(host_port):
  """Checks whether the specified host port is used or not.

  Uses -n -P to inhibit the conversion of host/port numbers to host/port names.

  Args:
    host_port: Port on host we want to check.

  Returns:
    True if the port on host is already used, otherwise returns False.
  """
  port_info = '(\*)|(127\.0\.0\.1)|(localhost):%d' % host_port
  # TODO(jnd): Find a better way to filter the port. Note that connecting to the
  # socket and closing it would leave it in the TIME_WAIT state. Setting
  # SO_LINGER on it and then closing it makes the Python HTTP server crash.
  re_port = re.compile(port_info, re.MULTILINE)
  if re_port.search(cmd_helper.GetCmdOutput(['lsof', '-nPi:%d' % host_port])):
    return True
  return False


def IsDevicePortUsed(adb, device_port, state=''):
  """Checks whether the specified device port is used or not.

  Args:
    adb: Instance of AndroidCommands for talking to the device.
    device_port: Port on device we want to check.
    state: String of the specified state. Default is empty string, which
           means any state.

  Returns:
    True if the port on device is already used, otherwise returns False.
  """
  base_url = '127.0.0.1:%d' % device_port
  netstat_results = adb.RunShellCommand('netstat', log_result=False)
  for single_connect in netstat_results:
    # Column 3 is the local address which we want to check with.
    connect_results = single_connect.split()
    if connect_results[0] != 'tcp':
      continue
    if len(connect_results) < 6:
      raise Exception('Unexpected format while parsing netstat line: ' +
                      single_connect)
    is_state_match = connect_results[5] == state if state else True
    if connect_results[3] == base_url and is_state_match:
      return True
  return False


def IsHttpServerConnectable(host, port, tries=3, command='GET', path='/',
                            expected_read='', timeout=2):
  """Checks whether the specified http server is ready to serve request or not.

  Args:
    host: Host name of the HTTP server.
    port: Port number of the HTTP server.
    tries: How many times we want to test the connection. The default value is
           3.
    command: The http command we use to connect to HTTP server. The default
             command is 'GET'.
    path: The path we use when connecting to HTTP server. The default path is
          '/'.
    expected_read: The content we expect to read from the response. The default
                   value is ''.
    timeout: Timeout (in seconds) for each http connection. The default is 2s.

  Returns:
    Tuple of (connect status, client error). connect status is a boolean value
    to indicate whether the server is connectable. client_error is the error
    message the server returns when connect status is false.
  """
  assert tries >= 1
  for i in xrange(0, tries):
    client_error = None
    try:
      with contextlib.closing(httplib.HTTPConnection(
          host, port, timeout=timeout)) as http:
        # Output some debug information when we have tried more than 2 times.
        http.set_debuglevel(i >= 2)
        http.request(command, path)
        r = http.getresponse()
        content = r.read()
        if r.status == 200 and r.reason == 'OK' and content == expected_read:
          return (True, '')
        client_error = ('Bad response: %s %s version %s\n  ' %
                        (r.status, r.reason, r.version) +
                        '\n  '.join([': '.join(h) for h in r.getheaders()]))
    except (httplib.HTTPException, socket.error) as e:
      # Probably too quick connecting: try again.
      exception_error_msgs = traceback.format_exception_only(type(e), e)
      if exception_error_msgs:
        client_error = ''.join(exception_error_msgs)
  # Only returns last client_error.
  return (False, client_error or 'Timeout')
