1212from . import base_events
1313from . import constants
1414from . import futures
15+ from . import protocols
1516from . import sslproto
1617from . import transports
1718from .log import logger
@@ -91,17 +92,19 @@ def __del__(self):
9192 self .close ()
9293
9394 def _fatal_error (self , exc , message = 'Fatal error on pipe transport' ):
94- if isinstance (exc , base_events ._FATAL_ERROR_IGNORE ):
95- if self ._loop .get_debug ():
96- logger .debug ("%r: %s" , self , message , exc_info = True )
97- else :
98- self ._loop .call_exception_handler ({
99- 'message' : message ,
100- 'exception' : exc ,
101- 'transport' : self ,
102- 'protocol' : self ._protocol ,
103- })
104- self ._force_close (exc )
95+ try :
96+ if isinstance (exc , base_events ._FATAL_ERROR_IGNORE ):
97+ if self ._loop .get_debug ():
98+ logger .debug ("%r: %s" , self , message , exc_info = True )
99+ else :
100+ self ._loop .call_exception_handler ({
101+ 'message' : message ,
102+ 'exception' : exc ,
103+ 'transport' : self ,
104+ 'protocol' : self ._protocol ,
105+ })
106+ finally :
107+ self ._force_close (exc )
105108
106109 def _force_close (self , exc ):
107110 if self ._closing :
@@ -150,6 +153,12 @@ def __init__(self, loop, sock, protocol, waiter=None,
150153 extra = None , server = None ):
151154 super ().__init__ (loop , sock , protocol , waiter , extra , server )
152155 self ._paused = False
156+
157+ if protocols ._is_buffered_protocol (protocol ):
158+ self ._loop_reading = self ._loop_reading__get_buffer
159+ else :
160+ self ._loop_reading = self ._loop_reading__data_received
161+
153162 self ._loop .call_soon (self ._loop_reading )
154163
155164 def is_reading (self ):
@@ -159,6 +168,11 @@ def pause_reading(self):
159168 if self ._closing or self ._paused :
160169 return
161170 self ._paused = True
171+
172+ if self ._read_fut is not None and not self ._read_fut .done ():
173+ self ._read_fut .cancel ()
174+ self ._read_fut = None
175+
162176 if self ._loop .get_debug ():
163177 logger .debug ("%r pauses reading" , self )
164178
@@ -170,11 +184,25 @@ def resume_reading(self):
170184 if self ._loop .get_debug ():
171185 logger .debug ("%r resumes reading" , self )
172186
173- def _loop_reading (self , fut = None ):
187+ def _loop_reading__on_eof (self ):
188+ if self ._loop .get_debug ():
189+ logger .debug ("%r received EOF" , self )
190+
191+ try :
192+ keep_open = self ._protocol .eof_received ()
193+ except Exception as exc :
194+ self ._fatal_error (
195+ exc , 'Fatal error: protocol.eof_received() call failed.' )
196+ return
197+
198+ if not keep_open :
199+ self .close ()
200+
201+ def _loop_reading__data_received (self , fut = None ):
174202 if self ._paused :
175203 return
176- data = None
177204
205+ data = None
178206 try :
179207 if fut is not None :
180208 assert self ._read_fut is fut or (self ._read_fut is None and
@@ -197,7 +225,7 @@ def _loop_reading(self, fut=None):
197225 return
198226
199227 # reschedule a new read
200- self ._read_fut = self ._loop ._proactor .recv (self ._sock , 4096 )
228+ self ._read_fut = self ._loop ._proactor .recv (self ._sock , 32768 )
201229 except ConnectionAbortedError as exc :
202230 if not self ._closing :
203231 self ._fatal_error (exc , 'Fatal read error on pipe transport' )
@@ -216,12 +244,81 @@ def _loop_reading(self, fut=None):
216244 finally :
217245 if data :
218246 self ._protocol .data_received (data )
219- elif data is not None :
220- if self ._loop .get_debug ():
221- logger .debug ("%r received EOF" , self )
222- keep_open = self ._protocol .eof_received ()
223- if not keep_open :
224- self .close ()
247+ elif data == b'' :
248+ self ._loop_reading__on_eof ()
249+
250+ def _loop_reading__get_buffer (self , fut = None ):
251+ if self ._paused :
252+ return
253+
254+ nbytes = None
255+ if fut is not None :
256+ assert self ._read_fut is fut or (self ._read_fut is None and
257+ self ._closing )
258+ self ._read_fut = None
259+ try :
260+ if fut .done ():
261+ nbytes = fut .result ()
262+ else :
263+ # the future will be replaced by next proactor.recv call
264+ fut .cancel ()
265+ except ConnectionAbortedError as exc :
266+ if not self ._closing :
267+ self ._fatal_error (
268+ exc , 'Fatal read error on pipe transport' )
269+ elif self ._loop .get_debug ():
270+ logger .debug ("Read error on pipe transport while closing" ,
271+ exc_info = True )
272+ except ConnectionResetError as exc :
273+ self ._force_close (exc )
274+ except OSError as exc :
275+ self ._fatal_error (exc , 'Fatal read error on pipe transport' )
276+ except futures .CancelledError :
277+ if not self ._closing :
278+ raise
279+
280+ if nbytes is not None :
281+ if nbytes == 0 :
282+ # we got end-of-file so no need to reschedule a new read
283+ self ._loop_reading__on_eof ()
284+ else :
285+ try :
286+ self ._protocol .buffer_updated (nbytes )
287+ except Exception as exc :
288+ self ._fatal_error (
289+ exc ,
290+ 'Fatal error: '
291+ 'protocol.buffer_updated() call failed.' )
292+ return
293+
294+ if self ._closing or nbytes == 0 :
295+ # since close() has been called we ignore any read data
296+ return
297+
298+ try :
299+ buf = self ._protocol .get_buffer ()
300+ except Exception as exc :
301+ self ._fatal_error (
302+ exc , 'Fatal error: protocol.get_buffer() call failed.' )
303+ return
304+
305+ try :
306+ # schedule a new read
307+ self ._read_fut = self ._loop ._proactor .recv_into (self ._sock , buf )
308+ self ._read_fut .add_done_callback (self ._loop_reading )
309+ except ConnectionAbortedError as exc :
310+ if not self ._closing :
311+ self ._fatal_error (exc , 'Fatal read error on pipe transport' )
312+ elif self ._loop .get_debug ():
313+ logger .debug ("Read error on pipe transport while closing" ,
314+ exc_info = True )
315+ except ConnectionResetError as exc :
316+ self ._force_close (exc )
317+ except OSError as exc :
318+ self ._fatal_error (exc , 'Fatal read error on pipe transport' )
319+ except futures .CancelledError :
320+ if not self ._closing :
321+ raise
225322
226323
227324class _ProactorBaseWritePipeTransport (_ProactorBasePipeTransport ,
0 commit comments