xref: /aosp_15_r20/prebuilts/build-tools/common/py3-stdlib/asyncio/transports.py (revision cda5da8d549138a6648c5ee6d7a49cf8f4a657be)
1*cda5da8dSAndroid Build Coastguard Worker"""Abstract Transport class."""
2*cda5da8dSAndroid Build Coastguard Worker
3*cda5da8dSAndroid Build Coastguard Worker__all__ = (
4*cda5da8dSAndroid Build Coastguard Worker    'BaseTransport', 'ReadTransport', 'WriteTransport',
5*cda5da8dSAndroid Build Coastguard Worker    'Transport', 'DatagramTransport', 'SubprocessTransport',
6*cda5da8dSAndroid Build Coastguard Worker)
7*cda5da8dSAndroid Build Coastguard Worker
8*cda5da8dSAndroid Build Coastguard Worker
9*cda5da8dSAndroid Build Coastguard Workerclass BaseTransport:
10*cda5da8dSAndroid Build Coastguard Worker    """Base class for transports."""
11*cda5da8dSAndroid Build Coastguard Worker
12*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ('_extra',)
13*cda5da8dSAndroid Build Coastguard Worker
14*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, extra=None):
15*cda5da8dSAndroid Build Coastguard Worker        if extra is None:
16*cda5da8dSAndroid Build Coastguard Worker            extra = {}
17*cda5da8dSAndroid Build Coastguard Worker        self._extra = extra
18*cda5da8dSAndroid Build Coastguard Worker
19*cda5da8dSAndroid Build Coastguard Worker    def get_extra_info(self, name, default=None):
20*cda5da8dSAndroid Build Coastguard Worker        """Get optional transport information."""
21*cda5da8dSAndroid Build Coastguard Worker        return self._extra.get(name, default)
22*cda5da8dSAndroid Build Coastguard Worker
23*cda5da8dSAndroid Build Coastguard Worker    def is_closing(self):
24*cda5da8dSAndroid Build Coastguard Worker        """Return True if the transport is closing or closed."""
25*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
26*cda5da8dSAndroid Build Coastguard Worker
27*cda5da8dSAndroid Build Coastguard Worker    def close(self):
28*cda5da8dSAndroid Build Coastguard Worker        """Close the transport.
29*cda5da8dSAndroid Build Coastguard Worker
30*cda5da8dSAndroid Build Coastguard Worker        Buffered data will be flushed asynchronously.  No more data
31*cda5da8dSAndroid Build Coastguard Worker        will be received.  After all buffered data is flushed, the
32*cda5da8dSAndroid Build Coastguard Worker        protocol's connection_lost() method will (eventually) be
33*cda5da8dSAndroid Build Coastguard Worker        called with None as its argument.
34*cda5da8dSAndroid Build Coastguard Worker        """
35*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
36*cda5da8dSAndroid Build Coastguard Worker
37*cda5da8dSAndroid Build Coastguard Worker    def set_protocol(self, protocol):
38*cda5da8dSAndroid Build Coastguard Worker        """Set a new protocol."""
39*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
40*cda5da8dSAndroid Build Coastguard Worker
41*cda5da8dSAndroid Build Coastguard Worker    def get_protocol(self):
42*cda5da8dSAndroid Build Coastguard Worker        """Return the current protocol."""
43*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
44*cda5da8dSAndroid Build Coastguard Worker
45*cda5da8dSAndroid Build Coastguard Worker
46*cda5da8dSAndroid Build Coastguard Workerclass ReadTransport(BaseTransport):
47*cda5da8dSAndroid Build Coastguard Worker    """Interface for read-only transports."""
48*cda5da8dSAndroid Build Coastguard Worker
49*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
50*cda5da8dSAndroid Build Coastguard Worker
51*cda5da8dSAndroid Build Coastguard Worker    def is_reading(self):
52*cda5da8dSAndroid Build Coastguard Worker        """Return True if the transport is receiving."""
53*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
54*cda5da8dSAndroid Build Coastguard Worker
55*cda5da8dSAndroid Build Coastguard Worker    def pause_reading(self):
56*cda5da8dSAndroid Build Coastguard Worker        """Pause the receiving end.
57*cda5da8dSAndroid Build Coastguard Worker
58*cda5da8dSAndroid Build Coastguard Worker        No data will be passed to the protocol's data_received()
59*cda5da8dSAndroid Build Coastguard Worker        method until resume_reading() is called.
60*cda5da8dSAndroid Build Coastguard Worker        """
61*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
62*cda5da8dSAndroid Build Coastguard Worker
63*cda5da8dSAndroid Build Coastguard Worker    def resume_reading(self):
64*cda5da8dSAndroid Build Coastguard Worker        """Resume the receiving end.
65*cda5da8dSAndroid Build Coastguard Worker
66*cda5da8dSAndroid Build Coastguard Worker        Data received will once again be passed to the protocol's
67*cda5da8dSAndroid Build Coastguard Worker        data_received() method.
68*cda5da8dSAndroid Build Coastguard Worker        """
69*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
70*cda5da8dSAndroid Build Coastguard Worker
71*cda5da8dSAndroid Build Coastguard Worker
72*cda5da8dSAndroid Build Coastguard Workerclass WriteTransport(BaseTransport):
73*cda5da8dSAndroid Build Coastguard Worker    """Interface for write-only transports."""
74*cda5da8dSAndroid Build Coastguard Worker
75*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
76*cda5da8dSAndroid Build Coastguard Worker
77*cda5da8dSAndroid Build Coastguard Worker    def set_write_buffer_limits(self, high=None, low=None):
78*cda5da8dSAndroid Build Coastguard Worker        """Set the high- and low-water limits for write flow control.
79*cda5da8dSAndroid Build Coastguard Worker
80*cda5da8dSAndroid Build Coastguard Worker        These two values control when to call the protocol's
81*cda5da8dSAndroid Build Coastguard Worker        pause_writing() and resume_writing() methods.  If specified,
82*cda5da8dSAndroid Build Coastguard Worker        the low-water limit must be less than or equal to the
83*cda5da8dSAndroid Build Coastguard Worker        high-water limit.  Neither value can be negative.
84*cda5da8dSAndroid Build Coastguard Worker
85*cda5da8dSAndroid Build Coastguard Worker        The defaults are implementation-specific.  If only the
86*cda5da8dSAndroid Build Coastguard Worker        high-water limit is given, the low-water limit defaults to an
87*cda5da8dSAndroid Build Coastguard Worker        implementation-specific value less than or equal to the
88*cda5da8dSAndroid Build Coastguard Worker        high-water limit.  Setting high to zero forces low to zero as
89*cda5da8dSAndroid Build Coastguard Worker        well, and causes pause_writing() to be called whenever the
90*cda5da8dSAndroid Build Coastguard Worker        buffer becomes non-empty.  Setting low to zero causes
91*cda5da8dSAndroid Build Coastguard Worker        resume_writing() to be called only once the buffer is empty.
92*cda5da8dSAndroid Build Coastguard Worker        Use of zero for either limit is generally sub-optimal as it
93*cda5da8dSAndroid Build Coastguard Worker        reduces opportunities for doing I/O and computation
94*cda5da8dSAndroid Build Coastguard Worker        concurrently.
95*cda5da8dSAndroid Build Coastguard Worker        """
96*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
97*cda5da8dSAndroid Build Coastguard Worker
98*cda5da8dSAndroid Build Coastguard Worker    def get_write_buffer_size(self):
99*cda5da8dSAndroid Build Coastguard Worker        """Return the current size of the write buffer."""
100*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
101*cda5da8dSAndroid Build Coastguard Worker
102*cda5da8dSAndroid Build Coastguard Worker    def get_write_buffer_limits(self):
103*cda5da8dSAndroid Build Coastguard Worker        """Get the high and low watermarks for write flow control.
104*cda5da8dSAndroid Build Coastguard Worker        Return a tuple (low, high) where low and high are
105*cda5da8dSAndroid Build Coastguard Worker        positive number of bytes."""
106*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
107*cda5da8dSAndroid Build Coastguard Worker
108*cda5da8dSAndroid Build Coastguard Worker    def write(self, data):
109*cda5da8dSAndroid Build Coastguard Worker        """Write some data bytes to the transport.
110*cda5da8dSAndroid Build Coastguard Worker
111*cda5da8dSAndroid Build Coastguard Worker        This does not block; it buffers the data and arranges for it
112*cda5da8dSAndroid Build Coastguard Worker        to be sent out asynchronously.
113*cda5da8dSAndroid Build Coastguard Worker        """
114*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
115*cda5da8dSAndroid Build Coastguard Worker
116*cda5da8dSAndroid Build Coastguard Worker    def writelines(self, list_of_data):
117*cda5da8dSAndroid Build Coastguard Worker        """Write a list (or any iterable) of data bytes to the transport.
118*cda5da8dSAndroid Build Coastguard Worker
119*cda5da8dSAndroid Build Coastguard Worker        The default implementation concatenates the arguments and
120*cda5da8dSAndroid Build Coastguard Worker        calls write() on the result.
121*cda5da8dSAndroid Build Coastguard Worker        """
122*cda5da8dSAndroid Build Coastguard Worker        data = b''.join(list_of_data)
123*cda5da8dSAndroid Build Coastguard Worker        self.write(data)
124*cda5da8dSAndroid Build Coastguard Worker
125*cda5da8dSAndroid Build Coastguard Worker    def write_eof(self):
126*cda5da8dSAndroid Build Coastguard Worker        """Close the write end after flushing buffered data.
127*cda5da8dSAndroid Build Coastguard Worker
128*cda5da8dSAndroid Build Coastguard Worker        (This is like typing ^D into a UNIX program reading from stdin.)
129*cda5da8dSAndroid Build Coastguard Worker
130*cda5da8dSAndroid Build Coastguard Worker        Data may still be received.
131*cda5da8dSAndroid Build Coastguard Worker        """
132*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
133*cda5da8dSAndroid Build Coastguard Worker
134*cda5da8dSAndroid Build Coastguard Worker    def can_write_eof(self):
135*cda5da8dSAndroid Build Coastguard Worker        """Return True if this transport supports write_eof(), False if not."""
136*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
137*cda5da8dSAndroid Build Coastguard Worker
138*cda5da8dSAndroid Build Coastguard Worker    def abort(self):
139*cda5da8dSAndroid Build Coastguard Worker        """Close the transport immediately.
140*cda5da8dSAndroid Build Coastguard Worker
141*cda5da8dSAndroid Build Coastguard Worker        Buffered data will be lost.  No more data will be received.
142*cda5da8dSAndroid Build Coastguard Worker        The protocol's connection_lost() method will (eventually) be
143*cda5da8dSAndroid Build Coastguard Worker        called with None as its argument.
144*cda5da8dSAndroid Build Coastguard Worker        """
145*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
146*cda5da8dSAndroid Build Coastguard Worker
147*cda5da8dSAndroid Build Coastguard Worker
148*cda5da8dSAndroid Build Coastguard Workerclass Transport(ReadTransport, WriteTransport):
149*cda5da8dSAndroid Build Coastguard Worker    """Interface representing a bidirectional transport.
150*cda5da8dSAndroid Build Coastguard Worker
151*cda5da8dSAndroid Build Coastguard Worker    There may be several implementations, but typically, the user does
152*cda5da8dSAndroid Build Coastguard Worker    not implement new transports; rather, the platform provides some
153*cda5da8dSAndroid Build Coastguard Worker    useful transports that are implemented using the platform's best
154*cda5da8dSAndroid Build Coastguard Worker    practices.
155*cda5da8dSAndroid Build Coastguard Worker
156*cda5da8dSAndroid Build Coastguard Worker    The user never instantiates a transport directly; they call a
157*cda5da8dSAndroid Build Coastguard Worker    utility function, passing it a protocol factory and other
158*cda5da8dSAndroid Build Coastguard Worker    information necessary to create the transport and protocol.  (E.g.
159*cda5da8dSAndroid Build Coastguard Worker    EventLoop.create_connection() or EventLoop.create_server().)
160*cda5da8dSAndroid Build Coastguard Worker
161*cda5da8dSAndroid Build Coastguard Worker    The utility function will asynchronously create a transport and a
162*cda5da8dSAndroid Build Coastguard Worker    protocol and hook them up by calling the protocol's
163*cda5da8dSAndroid Build Coastguard Worker    connection_made() method, passing it the transport.
164*cda5da8dSAndroid Build Coastguard Worker
165*cda5da8dSAndroid Build Coastguard Worker    The implementation here raises NotImplemented for every method
166*cda5da8dSAndroid Build Coastguard Worker    except writelines(), which calls write() in a loop.
167*cda5da8dSAndroid Build Coastguard Worker    """
168*cda5da8dSAndroid Build Coastguard Worker
169*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
170*cda5da8dSAndroid Build Coastguard Worker
171*cda5da8dSAndroid Build Coastguard Worker
172*cda5da8dSAndroid Build Coastguard Workerclass DatagramTransport(BaseTransport):
173*cda5da8dSAndroid Build Coastguard Worker    """Interface for datagram (UDP) transports."""
174*cda5da8dSAndroid Build Coastguard Worker
175*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
176*cda5da8dSAndroid Build Coastguard Worker
177*cda5da8dSAndroid Build Coastguard Worker    def sendto(self, data, addr=None):
178*cda5da8dSAndroid Build Coastguard Worker        """Send data to the transport.
179*cda5da8dSAndroid Build Coastguard Worker
180*cda5da8dSAndroid Build Coastguard Worker        This does not block; it buffers the data and arranges for it
181*cda5da8dSAndroid Build Coastguard Worker        to be sent out asynchronously.
182*cda5da8dSAndroid Build Coastguard Worker        addr is target socket address.
183*cda5da8dSAndroid Build Coastguard Worker        If addr is None use target address pointed on transport creation.
184*cda5da8dSAndroid Build Coastguard Worker        """
185*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
186*cda5da8dSAndroid Build Coastguard Worker
187*cda5da8dSAndroid Build Coastguard Worker    def abort(self):
188*cda5da8dSAndroid Build Coastguard Worker        """Close the transport immediately.
189*cda5da8dSAndroid Build Coastguard Worker
190*cda5da8dSAndroid Build Coastguard Worker        Buffered data will be lost.  No more data will be received.
191*cda5da8dSAndroid Build Coastguard Worker        The protocol's connection_lost() method will (eventually) be
192*cda5da8dSAndroid Build Coastguard Worker        called with None as its argument.
193*cda5da8dSAndroid Build Coastguard Worker        """
194*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
195*cda5da8dSAndroid Build Coastguard Worker
196*cda5da8dSAndroid Build Coastguard Worker
197*cda5da8dSAndroid Build Coastguard Workerclass SubprocessTransport(BaseTransport):
198*cda5da8dSAndroid Build Coastguard Worker
199*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ()
200*cda5da8dSAndroid Build Coastguard Worker
201*cda5da8dSAndroid Build Coastguard Worker    def get_pid(self):
202*cda5da8dSAndroid Build Coastguard Worker        """Get subprocess id."""
203*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
204*cda5da8dSAndroid Build Coastguard Worker
205*cda5da8dSAndroid Build Coastguard Worker    def get_returncode(self):
206*cda5da8dSAndroid Build Coastguard Worker        """Get subprocess returncode.
207*cda5da8dSAndroid Build Coastguard Worker
208*cda5da8dSAndroid Build Coastguard Worker        See also
209*cda5da8dSAndroid Build Coastguard Worker        http://docs.python.org/3/library/subprocess#subprocess.Popen.returncode
210*cda5da8dSAndroid Build Coastguard Worker        """
211*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
212*cda5da8dSAndroid Build Coastguard Worker
213*cda5da8dSAndroid Build Coastguard Worker    def get_pipe_transport(self, fd):
214*cda5da8dSAndroid Build Coastguard Worker        """Get transport for pipe with number fd."""
215*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
216*cda5da8dSAndroid Build Coastguard Worker
217*cda5da8dSAndroid Build Coastguard Worker    def send_signal(self, signal):
218*cda5da8dSAndroid Build Coastguard Worker        """Send signal to subprocess.
219*cda5da8dSAndroid Build Coastguard Worker
220*cda5da8dSAndroid Build Coastguard Worker        See also:
221*cda5da8dSAndroid Build Coastguard Worker        docs.python.org/3/library/subprocess#subprocess.Popen.send_signal
222*cda5da8dSAndroid Build Coastguard Worker        """
223*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
224*cda5da8dSAndroid Build Coastguard Worker
225*cda5da8dSAndroid Build Coastguard Worker    def terminate(self):
226*cda5da8dSAndroid Build Coastguard Worker        """Stop the subprocess.
227*cda5da8dSAndroid Build Coastguard Worker
228*cda5da8dSAndroid Build Coastguard Worker        Alias for close() method.
229*cda5da8dSAndroid Build Coastguard Worker
230*cda5da8dSAndroid Build Coastguard Worker        On Posix OSs the method sends SIGTERM to the subprocess.
231*cda5da8dSAndroid Build Coastguard Worker        On Windows the Win32 API function TerminateProcess()
232*cda5da8dSAndroid Build Coastguard Worker         is called to stop the subprocess.
233*cda5da8dSAndroid Build Coastguard Worker
234*cda5da8dSAndroid Build Coastguard Worker        See also:
235*cda5da8dSAndroid Build Coastguard Worker        http://docs.python.org/3/library/subprocess#subprocess.Popen.terminate
236*cda5da8dSAndroid Build Coastguard Worker        """
237*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
238*cda5da8dSAndroid Build Coastguard Worker
239*cda5da8dSAndroid Build Coastguard Worker    def kill(self):
240*cda5da8dSAndroid Build Coastguard Worker        """Kill the subprocess.
241*cda5da8dSAndroid Build Coastguard Worker
242*cda5da8dSAndroid Build Coastguard Worker        On Posix OSs the function sends SIGKILL to the subprocess.
243*cda5da8dSAndroid Build Coastguard Worker        On Windows kill() is an alias for terminate().
244*cda5da8dSAndroid Build Coastguard Worker
245*cda5da8dSAndroid Build Coastguard Worker        See also:
246*cda5da8dSAndroid Build Coastguard Worker        http://docs.python.org/3/library/subprocess#subprocess.Popen.kill
247*cda5da8dSAndroid Build Coastguard Worker        """
248*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
249*cda5da8dSAndroid Build Coastguard Worker
250*cda5da8dSAndroid Build Coastguard Worker
251*cda5da8dSAndroid Build Coastguard Workerclass _FlowControlMixin(Transport):
252*cda5da8dSAndroid Build Coastguard Worker    """All the logic for (write) flow control in a mix-in base class.
253*cda5da8dSAndroid Build Coastguard Worker
254*cda5da8dSAndroid Build Coastguard Worker    The subclass must implement get_write_buffer_size().  It must call
255*cda5da8dSAndroid Build Coastguard Worker    _maybe_pause_protocol() whenever the write buffer size increases,
256*cda5da8dSAndroid Build Coastguard Worker    and _maybe_resume_protocol() whenever it decreases.  It may also
257*cda5da8dSAndroid Build Coastguard Worker    override set_write_buffer_limits() (e.g. to specify different
258*cda5da8dSAndroid Build Coastguard Worker    defaults).
259*cda5da8dSAndroid Build Coastguard Worker
260*cda5da8dSAndroid Build Coastguard Worker    The subclass constructor must call super().__init__(extra).  This
261*cda5da8dSAndroid Build Coastguard Worker    will call set_write_buffer_limits().
262*cda5da8dSAndroid Build Coastguard Worker
263*cda5da8dSAndroid Build Coastguard Worker    The user may call set_write_buffer_limits() and
264*cda5da8dSAndroid Build Coastguard Worker    get_write_buffer_size(), and their protocol's pause_writing() and
265*cda5da8dSAndroid Build Coastguard Worker    resume_writing() may be called.
266*cda5da8dSAndroid Build Coastguard Worker    """
267*cda5da8dSAndroid Build Coastguard Worker
268*cda5da8dSAndroid Build Coastguard Worker    __slots__ = ('_loop', '_protocol_paused', '_high_water', '_low_water')
269*cda5da8dSAndroid Build Coastguard Worker
270*cda5da8dSAndroid Build Coastguard Worker    def __init__(self, extra=None, loop=None):
271*cda5da8dSAndroid Build Coastguard Worker        super().__init__(extra)
272*cda5da8dSAndroid Build Coastguard Worker        assert loop is not None
273*cda5da8dSAndroid Build Coastguard Worker        self._loop = loop
274*cda5da8dSAndroid Build Coastguard Worker        self._protocol_paused = False
275*cda5da8dSAndroid Build Coastguard Worker        self._set_write_buffer_limits()
276*cda5da8dSAndroid Build Coastguard Worker
277*cda5da8dSAndroid Build Coastguard Worker    def _maybe_pause_protocol(self):
278*cda5da8dSAndroid Build Coastguard Worker        size = self.get_write_buffer_size()
279*cda5da8dSAndroid Build Coastguard Worker        if size <= self._high_water:
280*cda5da8dSAndroid Build Coastguard Worker            return
281*cda5da8dSAndroid Build Coastguard Worker        if not self._protocol_paused:
282*cda5da8dSAndroid Build Coastguard Worker            self._protocol_paused = True
283*cda5da8dSAndroid Build Coastguard Worker            try:
284*cda5da8dSAndroid Build Coastguard Worker                self._protocol.pause_writing()
285*cda5da8dSAndroid Build Coastguard Worker            except (SystemExit, KeyboardInterrupt):
286*cda5da8dSAndroid Build Coastguard Worker                raise
287*cda5da8dSAndroid Build Coastguard Worker            except BaseException as exc:
288*cda5da8dSAndroid Build Coastguard Worker                self._loop.call_exception_handler({
289*cda5da8dSAndroid Build Coastguard Worker                    'message': 'protocol.pause_writing() failed',
290*cda5da8dSAndroid Build Coastguard Worker                    'exception': exc,
291*cda5da8dSAndroid Build Coastguard Worker                    'transport': self,
292*cda5da8dSAndroid Build Coastguard Worker                    'protocol': self._protocol,
293*cda5da8dSAndroid Build Coastguard Worker                })
294*cda5da8dSAndroid Build Coastguard Worker
295*cda5da8dSAndroid Build Coastguard Worker    def _maybe_resume_protocol(self):
296*cda5da8dSAndroid Build Coastguard Worker        if (self._protocol_paused and
297*cda5da8dSAndroid Build Coastguard Worker                self.get_write_buffer_size() <= self._low_water):
298*cda5da8dSAndroid Build Coastguard Worker            self._protocol_paused = False
299*cda5da8dSAndroid Build Coastguard Worker            try:
300*cda5da8dSAndroid Build Coastguard Worker                self._protocol.resume_writing()
301*cda5da8dSAndroid Build Coastguard Worker            except (SystemExit, KeyboardInterrupt):
302*cda5da8dSAndroid Build Coastguard Worker                raise
303*cda5da8dSAndroid Build Coastguard Worker            except BaseException as exc:
304*cda5da8dSAndroid Build Coastguard Worker                self._loop.call_exception_handler({
305*cda5da8dSAndroid Build Coastguard Worker                    'message': 'protocol.resume_writing() failed',
306*cda5da8dSAndroid Build Coastguard Worker                    'exception': exc,
307*cda5da8dSAndroid Build Coastguard Worker                    'transport': self,
308*cda5da8dSAndroid Build Coastguard Worker                    'protocol': self._protocol,
309*cda5da8dSAndroid Build Coastguard Worker                })
310*cda5da8dSAndroid Build Coastguard Worker
311*cda5da8dSAndroid Build Coastguard Worker    def get_write_buffer_limits(self):
312*cda5da8dSAndroid Build Coastguard Worker        return (self._low_water, self._high_water)
313*cda5da8dSAndroid Build Coastguard Worker
314*cda5da8dSAndroid Build Coastguard Worker    def _set_write_buffer_limits(self, high=None, low=None):
315*cda5da8dSAndroid Build Coastguard Worker        if high is None:
316*cda5da8dSAndroid Build Coastguard Worker            if low is None:
317*cda5da8dSAndroid Build Coastguard Worker                high = 64 * 1024
318*cda5da8dSAndroid Build Coastguard Worker            else:
319*cda5da8dSAndroid Build Coastguard Worker                high = 4 * low
320*cda5da8dSAndroid Build Coastguard Worker        if low is None:
321*cda5da8dSAndroid Build Coastguard Worker            low = high // 4
322*cda5da8dSAndroid Build Coastguard Worker
323*cda5da8dSAndroid Build Coastguard Worker        if not high >= low >= 0:
324*cda5da8dSAndroid Build Coastguard Worker            raise ValueError(
325*cda5da8dSAndroid Build Coastguard Worker                f'high ({high!r}) must be >= low ({low!r}) must be >= 0')
326*cda5da8dSAndroid Build Coastguard Worker
327*cda5da8dSAndroid Build Coastguard Worker        self._high_water = high
328*cda5da8dSAndroid Build Coastguard Worker        self._low_water = low
329*cda5da8dSAndroid Build Coastguard Worker
330*cda5da8dSAndroid Build Coastguard Worker    def set_write_buffer_limits(self, high=None, low=None):
331*cda5da8dSAndroid Build Coastguard Worker        self._set_write_buffer_limits(high=high, low=low)
332*cda5da8dSAndroid Build Coastguard Worker        self._maybe_pause_protocol()
333*cda5da8dSAndroid Build Coastguard Worker
334*cda5da8dSAndroid Build Coastguard Worker    def get_write_buffer_size(self):
335*cda5da8dSAndroid Build Coastguard Worker        raise NotImplementedError
336