Remove TCP/UDP echo modes from the SpawnedTestServer.

Extensions, the only consumer of these modes, have been migrated off of
the SpawnedTestServer, so we can remove them.

Bug: 492672
Change-Id: I105e8f4314a356a27a890f24583ca2681bc99f83
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2513788
Commit-Queue: Matt Menke <mmenke@chromium.org>
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Andrew Grieve <agrieve@chromium.org>
Cr-Commit-Position: refs/heads/master@{#823453}
GitOrigin-RevId: e1a1503cddd1dab06d6125b6418a6313877aa428
diff --git a/echo_message.py b/echo_message.py
deleted file mode 100644
index b2f7b04..0000000
--- a/echo_message.py
+++ /dev/null
@@ -1,385 +0,0 @@
-# Copyright (c) 2011 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.
-
-"""Provides utility functions for TCP/UDP echo servers and clients.
-
-This program has classes and functions to encode, decode, calculate checksum
-and verify the "echo request" and "echo response" messages. "echo request"
-message is an echo message sent from the client to the server. "echo response"
-message is a response from the server to the "echo request" message from the
-client.
-
-The format of "echo request" message is
-<version><checksum><payload_size><payload>. <version> is the version number
-of the "echo request" protocol. <checksum> is the checksum of the <payload>.
-<payload_size> is the size of the <payload>. <payload> is the echo message.
-
-The format of "echo response" message is
-<version><checksum><payload_size><key><encoded_payload>.<version>,
-<checksum> and <payload_size> are same as what is in the "echo request" message.
-<encoded_payload> is encoded version of the <payload>. <key> is a randomly
-generated key that is used to encode/decode the <payload>.
-"""
-
-__author__ = 'rtenneti@google.com (Raman Tenneti)'
-
-
-from itertools import cycle
-from itertools import izip
-import random
-
-
-class EchoHeader(object):
-  """Class to keep header info of the EchoRequest and EchoResponse messages.
-
-  This class knows how to parse the checksum, payload_size from the
-  "echo request" and "echo response" messages. It holds the checksum,
-  payload_size of the "echo request" and "echo response" messages.
-  """
-
-  # This specifies the version.
-  VERSION_STRING = '01'
-
-  # This specifies the starting position of the checksum and length of the
-  # checksum. Maximum value for the checksum is less than (2 ** 31 - 1).
-  CHECKSUM_START = 2
-  CHECKSUM_LENGTH = 10
-  CHECKSUM_FORMAT = '%010d'
-  CHECKSUM_END = CHECKSUM_START + CHECKSUM_LENGTH
-
-  # This specifies the starting position of the <payload_size> and length of the
-  # <payload_size>. Maximum number of bytes that can be sent in the <payload> is
-  # 9,999,999.
-  PAYLOAD_SIZE_START = CHECKSUM_END
-  PAYLOAD_SIZE_LENGTH = 7
-  PAYLOAD_SIZE_FORMAT = '%07d'
-  PAYLOAD_SIZE_END = PAYLOAD_SIZE_START + PAYLOAD_SIZE_LENGTH
-
-  def __init__(self, checksum=0, payload_size=0):
-    """Initializes the checksum and payload_size of self (EchoHeader).
-
-    Args:
-      checksum: (int)
-        The checksum of the payload.
-      payload_size: (int)
-        The size of the payload.
-    """
-    self.checksum = checksum
-    self.payload_size = payload_size
-
-  def ParseAndInitialize(self, echo_message):
-    """Parses the echo_message and initializes self with the parsed data.
-
-    This method extracts checksum, and payload_size from the echo_message
-    (echo_message could be either echo_request or echo_response messages) and
-    initializes self (EchoHeader) with checksum and payload_size.
-
-    Args:
-      echo_message: (string)
-        The string representation of EchoRequest or EchoResponse objects.
-    Raises:
-      ValueError: Invalid data
-    """
-    if not echo_message or len(echo_message) < EchoHeader.PAYLOAD_SIZE_END:
-      raise ValueError('Invalid data:%s' % echo_message)
-    self.checksum = int(echo_message[
-        EchoHeader.CHECKSUM_START:EchoHeader.CHECKSUM_END])
-    self.payload_size = int(echo_message[
-        EchoHeader.PAYLOAD_SIZE_START:EchoHeader.PAYLOAD_SIZE_END])
-
-  def InitializeFromPayload(self, payload):
-    """Initializes the EchoHeader object with the payload.
-
-    It calculates checksum for the payload and initializes self (EchoHeader)
-    with the calculated checksum and size of the payload.
-
-    This method is used by the client code during testing.
-
-    Args:
-      payload: (string)
-        The payload is the echo string (like 'hello').
-    Raises:
-      ValueError: Invalid data
-    """
-    if not payload:
-      raise ValueError('Invalid data:%s' % payload)
-    self.payload_size = len(payload)
-    self.checksum = Checksum(payload, self.payload_size)
-
-  def __str__(self):
-    """String representation of the self (EchoHeader).
-
-    Returns:
-      A string representation of self (EchoHeader).
-    """
-    checksum_string = EchoHeader.CHECKSUM_FORMAT % self.checksum
-    payload_size_string = EchoHeader.PAYLOAD_SIZE_FORMAT % self.payload_size
-    return EchoHeader.VERSION_STRING + checksum_string + payload_size_string
-
-
-class EchoRequest(EchoHeader):
-  """Class holds data specific to the "echo request" message.
-
-  This class holds the payload extracted from the "echo request" message.
-  """
-
-  # This specifies the starting position of the <payload>.
-  PAYLOAD_START = EchoHeader.PAYLOAD_SIZE_END
-
-  def __init__(self):
-    """Initializes EchoRequest object."""
-    EchoHeader.__init__(self)
-    self.payload = ''
-
-  def ParseAndInitialize(self, echo_request_data):
-    """Parses and Initializes the EchoRequest object from the echo_request_data.
-
-    This method extracts the header information (checksum and payload_size) and
-    payload from echo_request_data.
-
-    Args:
-      echo_request_data: (string)
-        The string representation of EchoRequest object.
-    Raises:
-      ValueError: Invalid data
-    """
-    EchoHeader.ParseAndInitialize(self, echo_request_data)
-    if len(echo_request_data) <= EchoRequest.PAYLOAD_START:
-      raise ValueError('Invalid data:%s' % echo_request_data)
-    self.payload = echo_request_data[EchoRequest.PAYLOAD_START:]
-
-  def InitializeFromPayload(self, payload):
-    """Initializes the EchoRequest object with payload.
-
-    It calculates checksum for the payload and initializes self (EchoRequest)
-    object.
-
-    Args:
-      payload: (string)
-        The payload string for which "echo request" needs to be constructed.
-    """
-    EchoHeader.InitializeFromPayload(self, payload)
-    self.payload = payload
-
-  def __str__(self):
-    """String representation of the self (EchoRequest).
-
-    Returns:
-      A string representation of self (EchoRequest).
-    """
-    return EchoHeader.__str__(self) + self.payload
-
-
-class EchoResponse(EchoHeader):
-  """Class holds data specific to the "echo response" message.
-
-  This class knows how to parse the "echo response" message. This class holds
-  key, encoded_payload and decoded_payload of the "echo response" message.
-  """
-
-  # This specifies the starting position of the |key_| and length of the |key_|.
-  # Minimum and maximum values for the |key_| are 100,000 and 999,999.
-  KEY_START = EchoHeader.PAYLOAD_SIZE_END
-  KEY_LENGTH = 6
-  KEY_FORMAT = '%06d'
-  KEY_END = KEY_START + KEY_LENGTH
-  KEY_MIN_VALUE = 0
-  KEY_MAX_VALUE = 999999
-
-  # This specifies the starting position of the <encoded_payload> and length
-  # of the <encoded_payload>.
-  ENCODED_PAYLOAD_START = KEY_END
-
-  def __init__(self, key='', encoded_payload='', decoded_payload=''):
-    """Initializes the EchoResponse object."""
-    EchoHeader.__init__(self)
-    self.key = key
-    self.encoded_payload = encoded_payload
-    self.decoded_payload = decoded_payload
-
-  def ParseAndInitialize(self, echo_response_data=None):
-    """Parses and Initializes the EchoResponse object from echo_response_data.
-
-    This method calls EchoHeader to extract header information from the
-    echo_response_data and it then extracts key and encoded_payload from the
-    echo_response_data. It holds the decoded payload of the encoded_payload.
-
-    Args:
-      echo_response_data: (string)
-        The string representation of EchoResponse object.
-    Raises:
-      ValueError: Invalid echo_request_data
-    """
-    EchoHeader.ParseAndInitialize(self, echo_response_data)
-    if len(echo_response_data) <= EchoResponse.ENCODED_PAYLOAD_START:
-      raise ValueError('Invalid echo_response_data:%s' % echo_response_data)
-    self.key = echo_response_data[EchoResponse.KEY_START:EchoResponse.KEY_END]
-    self.encoded_payload = echo_response_data[
-        EchoResponse.ENCODED_PAYLOAD_START:]
-    self.decoded_payload = Crypt(self.encoded_payload, self.key)
-
-  def InitializeFromEchoRequest(self, echo_request):
-    """Initializes EchoResponse with the data from the echo_request object.
-
-    It gets the checksum, payload_size and payload from the echo_request object
-    and then encodes the payload with a random key. It also saves the payload
-    as decoded_payload.
-
-    Args:
-      echo_request: (EchoRequest)
-        The EchoRequest object which has "echo request" message.
-    """
-    self.checksum = echo_request.checksum
-    self.payload_size = echo_request.payload_size
-    self.key = (EchoResponse.KEY_FORMAT %
-                random.randrange(EchoResponse.KEY_MIN_VALUE,
-                                 EchoResponse.KEY_MAX_VALUE))
-    self.encoded_payload = Crypt(echo_request.payload, self.key)
-    self.decoded_payload = echo_request.payload
-
-  def __str__(self):
-    """String representation of the self (EchoResponse).
-
-    Returns:
-      A string representation of self (EchoResponse).
-    """
-    return EchoHeader.__str__(self) + self.key + self.encoded_payload
-
-
-def Crypt(payload, key):
-  """Encodes/decodes the payload with the key and returns encoded payload.
-
-  This method loops through the payload and XORs each byte with the key.
-
-  Args:
-    payload: (string)
-      The string to be encoded/decoded.
-    key: (string)
-      The key used to encode/decode the payload.
-
-  Returns:
-    An encoded/decoded string.
-  """
-  return ''.join(chr(ord(x) ^ ord(y)) for (x, y) in izip(payload, cycle(key)))
-
-
-def Checksum(payload, payload_size):
-  """Calculates the checksum of the payload.
-
-  Args:
-    payload: (string)
-      The payload string for which checksum needs to be calculated.
-    payload_size: (int)
-      The number of bytes in the payload.
-
-  Returns:
-    The checksum of the payload.
-  """
-  checksum = 0
-  length = min(payload_size, len(payload))
-  for i in range (0, length):
-    checksum += ord(payload[i])
-  return checksum
-
-
-def GetEchoRequestData(payload):
-  """Constructs an "echo request" message from the payload.
-
-  It builds an EchoRequest object from the payload and then returns a string
-  representation of the EchoRequest object.
-
-  This is used by the TCP/UDP echo clients to build the "echo request" message.
-
-  Args:
-    payload: (string)
-      The payload string for which "echo request" needs to be constructed.
-
-  Returns:
-    A string representation of the EchoRequest object.
-  Raises:
-    ValueError: Invalid payload
-  """
-  try:
-    echo_request = EchoRequest()
-    echo_request.InitializeFromPayload(payload)
-    return str(echo_request)
-  except (IndexError, ValueError):
-    raise ValueError('Invalid payload:%s' % payload)
-
-
-def GetEchoResponseData(echo_request_data):
-  """Verifies the echo_request_data and returns "echo response" message.
-
-  It builds the EchoRequest object from the echo_request_data and then verifies
-  the checksum of the EchoRequest is same as the calculated checksum of the
-  payload. If the checksums don't match then it returns None. It checksums
-  match, it builds the echo_response object from echo_request object and returns
-  string representation of the EchoResponse object.
-
-  This is used by the TCP/UDP echo servers.
-
-  Args:
-    echo_request_data: (string)
-      The string that echo servers send to the clients.
-
-  Returns:
-    A string representation of the EchoResponse object. It returns None if the
-    echo_request_data is not valid.
-  Raises:
-    ValueError: Invalid echo_request_data
-  """
-  try:
-    if not echo_request_data:
-      raise ValueError('Invalid payload:%s' % echo_request_data)
-
-    echo_request = EchoRequest()
-    echo_request.ParseAndInitialize(echo_request_data)
-
-    if Checksum(echo_request.payload,
-                echo_request.payload_size) != echo_request.checksum:
-      return None
-
-    echo_response = EchoResponse()
-    echo_response.InitializeFromEchoRequest(echo_request)
-
-    return str(echo_response)
-  except (IndexError, ValueError):
-    raise ValueError('Invalid payload:%s' % echo_request_data)
-
-
-def DecodeAndVerify(echo_request_data, echo_response_data):
-  """Decodes and verifies the echo_response_data.
-
-  It builds EchoRequest and EchoResponse objects from the echo_request_data and
-  echo_response_data. It returns True if the EchoResponse's payload and
-  checksum match EchoRequest's.
-
-  This is used by the TCP/UDP echo clients for testing purposes.
-
-  Args:
-    echo_request_data: (string)
-      The request clients sent to echo servers.
-    echo_response_data: (string)
-      The response clients received from the echo servers.
-
-  Returns:
-    True if echo_request_data and echo_response_data match.
-  Raises:
-    ValueError: Invalid echo_request_data or Invalid echo_response
-  """
-
-  try:
-    echo_request = EchoRequest()
-    echo_request.ParseAndInitialize(echo_request_data)
-  except (IndexError, ValueError):
-    raise ValueError('Invalid echo_request:%s' % echo_request_data)
-
-  try:
-    echo_response = EchoResponse()
-    echo_response.ParseAndInitialize(echo_response_data)
-  except (IndexError, ValueError):
-    raise ValueError('Invalid echo_response:%s' % echo_response_data)
-
-  return (echo_request.checksum == echo_response.checksum and
-          echo_request.payload == echo_response.decoded_payload)
diff --git a/testserver.py b/testserver.py
index 5540485..0d1e43a 100755
--- a/testserver.py
+++ b/testserver.py
@@ -55,16 +55,13 @@
 import tlslite
 import tlslite.api
 
-import echo_message
 import testserver_base
 
 SERVER_HTTP = 0
 SERVER_FTP = 1
-SERVER_TCP_ECHO = 2
-SERVER_UDP_ECHO = 3
-SERVER_BASIC_AUTH_PROXY = 4
-SERVER_WEBSOCKET = 5
-SERVER_PROXY = 6
+SERVER_BASIC_AUTH_PROXY = 2
+SERVER_WEBSOCKET = 3
+SERVER_PROXY = 4
 
 # Default request queue size for WebSocketServer.
 _DEFAULT_REQUEST_QUEUE_SIZE = 128
@@ -260,46 +257,6 @@
   pass
 
 
-class TCPEchoServer(testserver_base.ClientRestrictingServerMixIn,
-                    SocketServer.TCPServer):
-  """A TCP echo server that echoes back what it has received."""
-
-  def server_bind(self):
-    """Override server_bind to store the server name."""
-
-    SocketServer.TCPServer.server_bind(self)
-    host, port = self.socket.getsockname()[:2]
-    self.server_name = socket.getfqdn(host)
-    self.server_port = port
-
-  def serve_forever(self):
-    self.stop = False
-    self.nonce_time = None
-    while not self.stop:
-      self.handle_request()
-    self.socket.close()
-
-
-class UDPEchoServer(testserver_base.ClientRestrictingServerMixIn,
-                    SocketServer.UDPServer):
-  """A UDP echo server that echoes back what it has received."""
-
-  def server_bind(self):
-    """Override server_bind to store the server name."""
-
-    SocketServer.UDPServer.server_bind(self)
-    host, port = self.socket.getsockname()[:2]
-    self.server_name = socket.getfqdn(host)
-    self.server_port = port
-
-  def serve_forever(self):
-    self.stop = False
-    self.nonce_time = None
-    while not self.stop:
-      self.handle_request()
-    self.socket.close()
-
-
 class TestPageHandler(testserver_base.BasePageHandler):
   # Class variables to allow for persistence state between page handler
   # invocations
@@ -1616,52 +1573,6 @@
     self.wfile.write(self.ca_issuers_response)
 
 
-class TCPEchoHandler(SocketServer.BaseRequestHandler):
-  """The RequestHandler class for TCP echo server.
-
-  It is instantiated once per connection to the server, and overrides the
-  handle() method to implement communication to the client.
-  """
-
-  def handle(self):
-    """Handles the request from the client and constructs a response."""
-
-    data = self.request.recv(65536).strip()
-    # Verify the "echo request" message received from the client. Send back
-    # "echo response" message if "echo request" message is valid.
-    try:
-      return_data = echo_message.GetEchoResponseData(data)
-      if not return_data:
-        return
-    except ValueError:
-      return
-
-    self.request.send(return_data)
-
-
-class UDPEchoHandler(SocketServer.BaseRequestHandler):
-  """The RequestHandler class for UDP echo server.
-
-  It is instantiated once per connection to the server, and overrides the
-  handle() method to implement communication to the client.
-  """
-
-  def handle(self):
-    """Handles the request from the client and constructs a response."""
-
-    data = self.request[0].strip()
-    request_socket = self.request[1]
-    # Verify the "echo request" message received from the client. Send back
-    # "echo response" message if "echo request" message is valid.
-    try:
-      return_data = echo_message.GetEchoResponseData(data)
-      if not return_data:
-        return
-    except ValueError:
-      return
-    request_socket.sendto(return_data, self.client_address)
-
-
 class ProxyRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
   """A request handler that behaves as a proxy server. Only CONNECT, GET and
   HEAD methods are supported.
@@ -2065,20 +1976,6 @@
           (scheme, host, server.server_port)
       server_data['port'] = server.server_port
       websocket_options.use_basic_auth = self.options.ws_basic_auth
-    elif self.options.server_type == SERVER_TCP_ECHO:
-      # Used for generating the key (randomly) that encodes the "echo request"
-      # message.
-      random.seed()
-      server = TCPEchoServer((host, port), TCPEchoHandler)
-      print 'Echo TCP server started on port %d...' % server.server_port
-      server_data['port'] = server.server_port
-    elif self.options.server_type == SERVER_UDP_ECHO:
-      # Used for generating the key (randomly) that encodes the "echo request"
-      # message.
-      random.seed()
-      server = UDPEchoServer((host, port), UDPEchoHandler)
-      print 'Echo UDP server started on port %d...' % server.server_port
-      server_data['port'] = server.server_port
     elif self.options.server_type == SERVER_PROXY:
       ProxyRequestHandler.redirect_connect_to_localhost = \
           self.options.redirect_connect_to_localhost
@@ -2137,14 +2034,6 @@
                                   const=SERVER_FTP, default=SERVER_HTTP,
                                   dest='server_type',
                                   help='start up an FTP server.')
-    self.option_parser.add_option('--tcp-echo', action='store_const',
-                                  const=SERVER_TCP_ECHO, default=SERVER_HTTP,
-                                  dest='server_type',
-                                  help='start up a tcp echo server.')
-    self.option_parser.add_option('--udp-echo', action='store_const',
-                                  const=SERVER_UDP_ECHO, default=SERVER_HTTP,
-                                  dest='server_type',
-                                  help='start up a udp echo server.')
     self.option_parser.add_option('--proxy', action='store_const',
                                   const=SERVER_PROXY,
                                   default=SERVER_HTTP, dest='server_type',
diff --git a/testserver.pydeps b/testserver.pydeps
index eb133f3..e6b32e3 100644
--- a/testserver.pydeps
+++ b/testserver.pydeps
@@ -75,7 +75,6 @@
 ../../../third_party/tlslite/tlslite/x509.py
 ../../../third_party/tlslite/tlslite/x509certchain.py
 asn1.py
-echo_message.py
 minica.py
 testserver.py
 testserver_base.py