'Fetches all outstanding requests and responses for this flow.
We first cache all requests and responses for this flow in memory to
prevent round trips.
Args:
session_id: The session_id to get the requests/responses for.
timestamp: Tuple (start, end) with a time range. Fetched requests and
responses will have timestamp in this range.
Yields:
an tuple (request protobufs, list of responses messages) in ascending
order of request ids.
Raises:
MoreDataException: When there is more data available than read by the
limited query.'

def FetchRequestsAndResponses(self, session_id, timestamp=None):

    if (timestamp is None):
        timestamp = (0, (self.frozen_timestamp or rdfvalue.RDFDatetime.Now()))
    num_requests = 0
    for (request, responses) in self.data_store.ReadRequestsAndResponses(session_id, timestamp=timestamp, request_limit=self.request_limit, response_limit=self.response_limit, token=self.token):
        (yield (request, responses))
        num_requests += 1
    if (num_requests >= self.request_limit):
        raise MoreDataException()
