docs: def RunOnce(self):
      """Makes a single request to the GRR server.
  
      Returns:
        A Status() object indicating how the last POST went.
      """
      # Attempt to fetch and load server certificate.
      if not self._FetchServerCertificate():
        self.timer.Wait()
        return HTTPObject(code=500)
  
      # Here we only drain messages if we were able to connect to the server in
      # the last poll request. Otherwise we just wait until the connection comes
      # back so we don't expire our messages too fast.
      if self.http_manager.consecutive_connection_errors == 0:
        # Grab some messages to send
        message_list = self.client_worker.Drain(
            max_size=config.CONFIG["Client.max_post_size"])
      else:
        message_list = rdf_flows.MessageList()
  
      # If any outbound messages require fast poll we switch to fast poll mode.
      for message in message_list.job:
        if message.require_fastpoll:
          self.timer.FastPoll()
          break
  
      # Make new encrypted ClientCommunication rdfvalue.
      payload = rdf_flows.ClientCommunication()
  
      # If our memory footprint is too large, we advertise that our input queue
      # is full. This will prevent the server from sending us any messages, and
      # hopefully allow us to work down our memory usage, by processing any
      # outstanding messages.
      if self.client_worker.MemoryExceeded():
        logging.info("Memory exceeded, will not retrieve jobs.")
        payload.queue_size = 1000000
      else:
        # Let the server know how many messages are currently queued in
        # the input queue.
        payload.queue_size = self.client_worker.InQueueSize()
  
      nonce = self.communicator.EncodeMessages(message_list, payload)
      payload_data = payload.SerializeToString()
      response = self.MakeRequest(payload_data)
  
      # Unable to decode response or response not valid.
      if response.code != 200 or response.messages is None:
        # We don't print response here since it should be encrypted and will
        # cause ascii conversion errors.
        logging.info("%s: Could not connect to server at %s, status %s",
                     self.communicator.common_name,
                     self.http_manager.active_base_url, response.code)
  
        # Force the server pem to be reparsed on the next connection.
        self.server_certificate = None
  
        # Reschedule the tasks back on the queue so they get retried next time.
        messages = list(message_list.job)
        for message in messages:
          message.require_fastpoll = False
          message.ttl -= 1
          if message.ttl > 0:
            self.client_worker.QueueResponse(message)
          else:
            logging.info("Dropped message due to retransmissions.")
  
        return response
  
      # Check the decoded nonce was as expected.
      if response.nonce != nonce:
        logging.info("Nonce not matched.")
        response.code = 500
        return response
  
      if response.source != self.communicator.server_name:
        logging.info("Received a message not from the server "
                     "%s, expected %s.", response.source,
                     self.communicator.server_name)
        response.code = 500
        return response
  
      # Check to see if any inbound messages want us to fastpoll. This means we
      # drop to fastpoll immediately on a new request rather than waiting for the
      # next beacon to report results.
      for message in response.messages:
        if message.require_fastpoll:
          self.timer.FastPoll()
          break
  
      # Process all messages. Messages can be processed by clients in
      # any order since clients do not have state.
      self.client_worker.QueueMessages(response.messages)
  
      cn = self.communicator.common_name
      logging.info(
          "%s: Sending %s(%s), Received %s messages in %s sec. "
          "Sleeping for %s sec.", cn, len(message_list), len(payload_data),
          len(response.messages), response.duration, self.timer.sleep_time)
  
      return response