21
21
22
22
__all__ = ["Connection" ]
23
23
24
- logger = logging .getLogger (__name__ )
25
-
26
24
27
25
class Connection :
28
26
"""
29
- Threaded implementation of a WebSocket connection.
27
+ :mod:`threading` implementation of a WebSocket connection.
30
28
31
29
:class:`Connection` provides APIs shared between WebSocket servers and
32
30
clients.
@@ -82,15 +80,15 @@ def __init__(
82
80
self .close_deadline : Optional [Deadline ] = None
83
81
84
82
# Mapping of ping IDs to pong waiters, in chronological order.
85
- self .pings : Dict [bytes , threading .Event ] = {}
83
+ self .ping_waiters : Dict [bytes , threading .Event ] = {}
86
84
87
85
# Receiving events from the socket.
88
86
self .recv_events_thread = threading .Thread (target = self .recv_events )
89
87
self .recv_events_thread .start ()
90
88
91
89
# Exception raised in recv_events, to be chained to ConnectionClosed
92
90
# in the user thread in order to show why the TCP connection dropped.
93
- self .recv_events_exc : Optional [BaseException ] = None
91
+ self .recv_exc : Optional [BaseException ] = None
94
92
95
93
# Public attributes
96
94
@@ -198,7 +196,7 @@ def recv(self, timeout: Optional[float] = None) -> Data:
198
196
try :
199
197
return self .recv_messages .get (timeout )
200
198
except EOFError :
201
- raise self .protocol .close_exc from self .recv_events_exc
199
+ raise self .protocol .close_exc from self .recv_exc
202
200
except RuntimeError :
203
201
raise RuntimeError (
204
202
"cannot call recv while another thread "
@@ -229,9 +227,10 @@ def recv_streaming(self) -> Iterator[Data]:
229
227
230
228
"""
231
229
try :
232
- yield from self .recv_messages .get_iter ()
230
+ for frame in self .recv_messages .get_iter ():
231
+ yield frame
233
232
except EOFError :
234
- raise self .protocol .close_exc from self .recv_events_exc
233
+ raise self .protocol .close_exc from self .recv_exc
235
234
except RuntimeError :
236
235
raise RuntimeError (
237
236
"cannot call recv_streaming while another thread "
@@ -273,7 +272,7 @@ def send(self, message: Union[Data, Iterable[Data]]) -> None:
273
272
274
273
Raises:
275
274
ConnectionClosed: When the connection is closed.
276
- RuntimeError: If a connection is busy sending a fragmented message.
275
+ RuntimeError: If the connection is sending a fragmented message.
277
276
TypeError: If ``message`` doesn't have a supported type.
278
277
279
278
"""
@@ -449,15 +448,15 @@ def ping(self, data: Optional[Data] = None) -> threading.Event:
449
448
450
449
with self .send_context ():
451
450
# Protect against duplicates if a payload is explicitly set.
452
- if data in self .pings :
451
+ if data in self .ping_waiters :
453
452
raise RuntimeError ("already waiting for a pong with the same data" )
454
453
455
454
# Generate a unique random payload otherwise.
456
- while data is None or data in self .pings :
455
+ while data is None or data in self .ping_waiters :
457
456
data = struct .pack ("!I" , random .getrandbits (32 ))
458
457
459
458
pong_waiter = threading .Event ()
460
- self .pings [data ] = pong_waiter
459
+ self .ping_waiters [data ] = pong_waiter
461
460
self .protocol .send_ping (data )
462
461
return pong_waiter
463
462
@@ -504,22 +503,22 @@ def acknowledge_pings(self, data: bytes) -> None:
504
503
"""
505
504
with self .protocol_mutex :
506
505
# Ignore unsolicited pong.
507
- if data not in self .pings :
506
+ if data not in self .ping_waiters :
508
507
return
509
508
# Sending a pong for only the most recent ping is legal.
510
509
# Acknowledge all previous pings too in that case.
511
510
ping_id = None
512
511
ping_ids = []
513
- for ping_id , ping in self .pings .items ():
512
+ for ping_id , ping in self .ping_waiters .items ():
514
513
ping_ids .append (ping_id )
515
514
ping .set ()
516
515
if ping_id == data :
517
516
break
518
517
else :
519
518
raise AssertionError ("solicited pong not found in pings" )
520
- # Remove acknowledged pings from self.pings .
519
+ # Remove acknowledged pings from self.ping_waiters .
521
520
for ping_id in ping_ids :
522
- del self .pings [ping_id ]
521
+ del self .ping_waiters [ping_id ]
523
522
524
523
def recv_events (self ) -> None :
525
524
"""
@@ -541,18 +540,18 @@ def recv_events(self) -> None:
541
540
self .logger .debug ("error while receiving data" , exc_info = True )
542
541
# When the closing handshake is initiated by our side,
543
542
# recv() may block until send_context() closes the socket.
544
- # In that case, send_context() already set recv_events_exc .
545
- # Calling set_recv_events_exc () avoids overwriting it.
543
+ # In that case, send_context() already set recv_exc .
544
+ # Calling set_recv_exc () avoids overwriting it.
546
545
with self .protocol_mutex :
547
- self .set_recv_events_exc (exc )
546
+ self .set_recv_exc (exc )
548
547
break
549
548
550
549
if data == b"" :
551
550
break
552
551
553
552
# Acquire the connection lock.
554
553
with self .protocol_mutex :
555
- # Feed incoming data to the connection .
554
+ # Feed incoming data to the protocol .
556
555
self .protocol .receive_data (data )
557
556
558
557
# This isn't expected to raise an exception.
@@ -568,7 +567,7 @@ def recv_events(self) -> None:
568
567
# set by send_context(), in case of a race condition
569
568
# i.e. send_context() closes the socket after recv()
570
569
# returns above but before send_data() calls send().
571
- self .set_recv_events_exc (exc )
570
+ self .set_recv_exc (exc )
572
571
break
573
572
574
573
if self .protocol .close_expected ():
@@ -595,7 +594,7 @@ def recv_events(self) -> None:
595
594
# Breaking out of the while True: ... loop means that we believe
596
595
# that the socket doesn't work anymore.
597
596
with self .protocol_mutex :
598
- # Feed the end of the data stream to the connection .
597
+ # Feed the end of the data stream to the protocol .
599
598
self .protocol .receive_eof ()
600
599
601
600
# This isn't expected to generate events.
@@ -609,7 +608,7 @@ def recv_events(self) -> None:
609
608
# This branch should never run. It's a safety net in case of bugs.
610
609
self .logger .error ("unexpected internal error" , exc_info = True )
611
610
with self .protocol_mutex :
612
- self .set_recv_events_exc (exc )
611
+ self .set_recv_exc (exc )
613
612
# We don't know where we crashed. Force protocol state to CLOSED.
614
613
self .protocol .state = CLOSED
615
614
finally :
@@ -668,7 +667,6 @@ def send_context(
668
667
wait_for_close = True
669
668
# If the connection is expected to close soon, set the
670
669
# close deadline based on the close timeout.
671
-
672
670
# Since we tested earlier that protocol.state was OPEN
673
671
# (or CONNECTING) and we didn't release protocol_mutex,
674
672
# it is certain that self.close_deadline is still None.
@@ -710,11 +708,11 @@ def send_context(
710
708
# original_exc is never set when wait_for_close is True.
711
709
assert original_exc is None
712
710
original_exc = TimeoutError ("timed out while closing connection" )
713
- # Set recv_events_exc before closing the socket in order to get
711
+ # Set recv_exc before closing the socket in order to get
714
712
# proper exception reporting.
715
713
raise_close_exc = True
716
714
with self .protocol_mutex :
717
- self .set_recv_events_exc (original_exc )
715
+ self .set_recv_exc (original_exc )
718
716
719
717
# If an error occurred, close the socket to terminate the connection and
720
718
# raise an exception.
@@ -745,16 +743,16 @@ def send_data(self) -> None:
745
743
except OSError : # socket already closed
746
744
pass
747
745
748
- def set_recv_events_exc (self , exc : Optional [BaseException ]) -> None :
746
+ def set_recv_exc (self , exc : Optional [BaseException ]) -> None :
749
747
"""
750
- Set recv_events_exc , if not set yet.
748
+ Set recv_exc , if not set yet.
751
749
752
750
This method requires holding protocol_mutex.
753
751
754
752
"""
755
753
assert self .protocol_mutex .locked ()
756
- if self .recv_events_exc is None :
757
- self .recv_events_exc = exc
754
+ if self .recv_exc is None :
755
+ self .recv_exc = exc
758
756
759
757
def close_socket (self ) -> None :
760
758
"""
0 commit comments