<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def send( self, arg1, arg2, arg3, headers=None, retry_limit=None, ttl=None, ):
 """Make a request to the Peer. :param arg1: String or Stream containing the contents of arg1. If None, an empty stream is used. :param arg2: String or Stream containing the contents of arg2. If None, an empty stream is used. :param arg3: String or Stream containing the contents of arg3. If None, an empty stream is used. :param headers: Headers will be put in the message as protocol header. :param retry_limit: Maximum number of retries will perform on the message. If the number is 0, it means no retry. :param ttl: Timeout for each request (second). :return: Future that contains the response from the peer. """


        # find a peer connection
        # If we can't find available peer at the first time, we throw
        # NoAvailablePeerError. Later during retry, if we can't find available
        # peer, we throw exceptions from retry not NoAvailablePeerError.
        peer, connection = yield self._get_peer_connection()

        arg1, arg2, arg3 = (
            maybe_stream(arg1), maybe_stream(arg2), maybe_stream(arg3)
        )

        if retry_limit is None:
            retry_limit = DEFAULT_RETRY_LIMIT

        ttl = ttl or DEFAULT_TIMEOUT
        # hack to get endpoint from arg_1 for trace name
        arg1.close()
        endpoint = yield read_full(arg1)

        # set default transport headers
        headers = headers or {}
        for k, v in self.headers.iteritems():
            headers.setdefault(k, v)

        if self.tracing_span is None:
            tracer = ClientTracer(channel=self.tchannel)
            self.tracing_span, _ = tracer.start_span(
                service=self.service, endpoint=endpoint,
                hostport=self._hostport, encoding=self.headers.get('as')
            )

        request = Request(
            service=self.service,
            argstreams=[InMemStream(endpoint), arg2, arg3],
            id=connection.writer.next_message_id(),
            headers=headers,
            endpoint=endpoint,
            ttl=ttl,
            tracing=tracing.span_to_tracing_field(self.tracing_span)
        )

        # only retry on non-stream request
        if request.is_streaming_request or self._hostport:
            retry_limit = 0

        if request.is_streaming_request:
            request.ttl = 0

        try:
            with self.tracing_span:  # to ensure span is finished
                response = yield self.send_with_retry(
                    request, peer, retry_limit, connection
                )
        except Exception as e:
            # event: on_exception
            exc_info = sys.exc_info()
            yield self.tchannel.event_emitter.fire(
                EventType.on_exception, request, e,
            )
            six.reraise(*exc_info)

        log.debug("Got response %s", response)

        raise gen.Return(response)