Listen for pings until stopped.

def run(self):
    """Listen for pings until stopped."""
    self._live = True
    self._sock.settimeout(self.LISTEN_TIMEOUT_S)

    # Passing in INADDR_ANY means the kernel will choose the default interface.
    # The localhost address is used to receive messages sent in "local_only"
    # mode and the default address is used to receive all other messages.
    for interface_ip in (socket.INADDR_ANY, LOCALHOST_ADDRESS):
      self._sock.setsockopt(
          socket.IPPROTO_IP,
          socket.IP_ADD_MEMBERSHIP,
          # IP_ADD_MEMBERSHIP takes the 8-byte group address followed by the IP
          # assigned to the interface on which to listen.
          struct.pack('!4sL', socket.inet_aton(self.address), interface_ip))

    if sys.platform == 'darwin':
      self._sock.setsockopt(socket.SOL_SOCKET,
                            socket.SO_REUSEPORT,
                            1)  # Allow multiple listeners to bind.
    else:
      self._sock.setsockopt(socket.SOL_SOCKET,
                            socket.SO_REUSEADDR,
                            1)  # Allow multiple listeners to bind.
    self._sock.bind((self.address, self.port))

    while self._live:
      try:
        data, address = self._sock.recvfrom(MAX_MESSAGE_BYTES)
        data = data.decode('utf-8')
        log_line = 'Received multicast message from %s: %s' % (address, data)
        response = self._callback(data)
        if response is not None:
          log_line += ', responding with %s bytes' % len(response)
          # Send replies out-of-band instead of with the same multicast socket
          # so that multiple processes on the same host can listen for
          # requests and reply (if they all try to use the multicast socket
          # to reply, they conflict and this sendto fails).
          response = response.encode('utf-8')
          socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(
              response, address)
        _LOG.debug(log_line)
      except socket.timeout:
        pass
      except socket.error:
        _LOG.debug('Error receiving multicast message', exc_info=True)