
     if3                         S r SSKrSSKrSSKrSSKrSrSrSrSrSr	Sr
SrS	rS
rSrSrSrSrSrSrSrSrSr " S S5      rg)ze
WebSocket protocol handler for ASGI.

Implements RFC 6455 WebSocket protocol for ASGI applications.
    N         	   
   i  i  i  i  i  i  i  i  i  i  i  s$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11c                   v    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rS rS rS rS rS rSS jrSrg)WebSocketProtocol*   zWebSocket connection handler for ASGI applications.

Uses callback-based data feeding instead of StreamReader for efficiency.
Data is fed via feed_data() from the parent protocol's data_received().
c                    Xl         X l        X0l        X@l        SU l        SU l        SU l        SU l        / U l        SU l	        [        R                  " 5       U l        [        5       U l        [        R                  " 5       U l        SU l        g)zInitialize WebSocket protocol handler.

Args:
    transport: asyncio transport for writing
    scope: ASGI WebSocket scope dict
    app: ASGI application callable
    log: Logger instance
FN )	transportscopeapplogacceptedclosed
close_codeclose_reason
_fragments_fragment_opcodeasyncioQueue_receive_queue	bytearray_bufferEvent_data_event_eof)selfr   r   r   r   s        I/var/www/ias/venv/lib/python3.13/site-packages/gunicorn/asgi/websocket.py__init__WebSocketProtocol.__init__1   sv     #
  $ &mmo !{"==?	    c                 ~    U(       a6  U R                   R                  U5        U R                  R                  5         gg)zqFeed incoming data from the parent protocol's data_received().

Args:
    data: bytes received on the connection
N)r   extendr   set)r   datas     r    	feed_dataWebSocketProtocol.feed_dataP   s0     LL%  " r#   c                 F    SU l         U R                  R                  5         g)z+Signal that the connection has been closed.TN)r   r   r&   r   s    r    feed_eofWebSocketProtocol.feed_eofZ   s    	r#   c                 d  #    U R                   R                  SS05      I Sh  vN   [        R                  " U R	                  5       5      n U R                  U R                  U R                  U R                  5      I Sh  vN   UR                  5          UI Sh  vN   U R                  (       d1  U R                  (       a  U R!                  ["        S5      I Sh  vN   ggg N Nd! [         a    U R                  R                  S5         Nf = f Nv! [        R                   a     Nf = f NR! UR                  5          UI Sh  vN    O! [        R                   a     Of = fU R                  (       d2  U R                  (       a   U R!                  ["        S5      I Sh  vN    f f f = f7f)z#Run the WebSocket ASGI application.typezwebsocket.connectNz#Error in WebSocket ASGI applicationzApplication error)r   putr   create_task_read_framesr   r   _receive_send	Exceptionr   	exceptioncancelCancelledErrorr   r   _send_closeCLOSE_INTERNAL_ERROR)r   	read_tasks     r    runWebSocketProtocol.run_   sf     !!%%v/B&CDDD ''(9(9(;<		R((4::t}}djjAAA 
 ;;4==&&';=PQQQ $1;# 	E B 	FHHDE	F
  )) 
 R ))  ;;4==&&';=PQQQ $1;s   !F0C$(F04C( C&C( F0D DD !;F0D/F0&C( (%DD1 DD1 D D,)F0+D,,F01F-EE	EF-E&#F-%E&&>F-$F'%F--F0c                 R   #    U R                   R                  5       I Sh  vN $  N7f)zASGI receive callable.N)r   getr+   s    r    r3   WebSocketProtocol._receivev   s      ((,,....s   '%'c                   #    US   nUS:X  a=  U R                   (       a  [        S5      eU R                  U5      I Sh  vN   SU l         gUS:X  a  U R                   (       d  [        S5      eU R                  (       a  [        S5      eS	U;   a1  U R	                  [
        US	   R                  S
5      5      I Sh  vN   gSU;   a"  U R	                  [        US   5      I Sh  vN   ggUS:X  aI  UR                  S[        5      nUR                  SS5      nU R                  X45      I Sh  vN   SU l        gg N N NZ N7f)zASGI send callable.r/   zwebsocket.acceptzWebSocket already acceptedNTzwebsocket.sendzWebSocket not acceptedzWebSocket closedtextutf-8byteszwebsocket.closecodereasonr   )r   RuntimeError_send_acceptr   _send_frameOPCODE_TEXTencodeOPCODE_BINARYr?   CLOSE_NORMALr9   )r   messagemsg_typerE   rF   s        r    r4   WebSocketProtocol._sendz   s'    6?))}}"#?@@##G,,, DM))=="#;<<{{"#566 &&{GFO4J4J74STTTG#&&}gg6FGGG $ **;;v|4D[[2.F""4000DK	 + - UG
 1sG   <ED9A;E:D;;'E"D=#AE+D?,E;E=E?Ec                   #    SnU R                   S    H  u  p4US:X  d  M  Un  O   U(       d  [        S5      e[        R                  " [        R
                  " U[        -   5      R                  5       5      R                  S5      nSSSS	U S
3/nUR                  S5      nU(       a  UR                  SU S
35        UR                  S/ 5      nU Hh  u  p4[        U[        5      (       a  UR                  S5      n[        U[        5      (       a  UR                  S5      nUR                  U SU S
35        Mj     UR                  S
5        U R                  R                  SR                  U5      R!                  S5      5        g7f)z)Send WebSocket handshake accept response.Nheaderss   sec-websocket-keyz Missing Sec-WebSocket-Key headerasciiz"HTTP/1.1 101 Switching Protocols
zUpgrade: websocket
zConnection: Upgrade
zSec-WebSocket-Accept: z
subprotocolzSec-WebSocket-Protocol: zlatin-1z: r   )r   rG   base64	b64encodehashlibsha1WS_GUIDdigestdecoder?   append
isinstancerD   r   writejoinrK   )	r   rN   ws_keynamevalue
accept_keyrR   rT   extra_headerss	            r    rH   WebSocketProtocol._send_accept   sc     ::i0KD++ 1
 ABB %%LL')*113

&/ 	 3$%$ZL5	
 kk-0NN5k]$GH  Ir2(KD$&&{{9-%''Y/NNdV2eWD12 ) 	vRWWW-44Y?@s   F	E(F	c                   #     U R                   (       Gd!  U R                  5       I Sh  vN nUc  GOUu  p#U[        :X  a  U R                  U5      I Sh  vN   OU[        :X  a  U R                  [        U5      I Sh  vN   OU[        :X  a  OU[        :X  a6  U R                  R                  SUR                  S5      S.5      I Sh  vN   OTU[        :X  a'  U R                  R                  SUS.5      I Sh  vN   O#U[        :X  a  U R                  U5      I Sh  vN   U R                   (       d  GM!  U R                   (       dE  SU l         U R                  R                  SU R&                  =(       d    [(        S	.5      I Sh  vN   gg GNe GN< GN N N N|! [        R                   a    e [          a&  nU R"                  R%                  SU5         SnANSnAff = f N\! U R                   (       dF  SU l         U R                  R                  SU R&                  =(       d    [(        S	.5      I Sh  vN    f f = f7f)
z+Read and process incoming WebSocket frames.Nzwebsocket.receiverC   )r/   rB   )r/   rD   zWebSocket read error: %sTzwebsocket.disconnect)r/   rE   )r   _read_frameOPCODE_CLOSE_handle_closeOPCODE_PINGrI   OPCODE_PONGrJ   r   r0   r[   rL   OPCODE_CONTINUATION_handle_continuationr   r8   r5   r   debugr   CLOSE_ABNORMAL)r   frameopcodepayloades        r    r2   WebSocketProtocol._read_frames   s    *	kkk"..00="'\),,W555[(**;@@@{*{*--11 3 'w 73    },--11 3!(3    2233G<<<9 kkkH ;;"))--2 OO=~/    G 1 6 A

 =%% 	 	:HHNN5q99	: ;;"))--2 OO=~/    s   I%F FF G& "F FF G& #F >F?A
F 	F
0F :F;#F FF 7AIG$IF F F F F F G!;GG& G!!G& $I&AH?7H:8H??Ic                   #    U R                  S5      I Sh  vN nU(       d  gUS   US   p2US-	  S-  nUS-	  S-  nUS-	  S-  nUS-	  S-  nUS	-  nU(       d  U(       d  U(       a  U R                  [        S
5      I Sh  vN   gUS-	  S-  n	US-  n
U	(       d  U R                  [        S5      I Sh  vN   gU
S:X  a<  U R                  S5      I Sh  vN nU(       d  g[        R                  " SU5      S   n
OAU
S:X  a;  U R                  S5      I Sh  vN nU(       d  g[        R                  " SU5      S   n
U R                  S5      I Sh  vN nU(       d  gU R                  U
5      I Sh  vN nUc  gU R                  X5      nU[        :X  a  U R                  c  U R                  [        S5      I Sh  vN   gU R                  R                  U5        U(       a8  SR                  U R                  5      nU R                  n/ U l        SU l        X4$ [        S4$ U[        [        4;   a   U(       d  Xl        U/U l        [        S4$ X4$ X4$  GN? GN GN GN GNM GN N N7f)zcRead a single WebSocket frame.

Returns:
    tuple: (opcode, payload) or None if connection closed
r   Nr   r                  zRSV bits set   zFrame not masked~   !Hr   !QzUnexpected continuationr#   )_read_exactr9   CLOSE_PROTOCOL_ERRORstructunpack_unmaskrl   r   r   r\   r_   rJ   rL   )r   header
first_bytesecond_bytefinrsv1rsv2rsv3rq   maskedpayload_lenext_lenmasking_keyrr   full_payloadfinal_opcodes                   r    rg   WebSocketProtocol._read_frame   st     ''**"()VAYKQ!#a1$a1$a1$d" 44""#7HHH"a'!D( ""#79KLLL # ,,Q//G --g6q9KC ,,Q//G --g6q9K !,,Q// ((55? ,,w4 (($$,&&';=VWWWOO""7+"xx8#44"$(,%$33'--]33(.%#*)+S11$$ $$S + I M
 0
 0 0
 6 Xs   I,IA(I, I2I,3I4I,IAI,I":I,I% I,1I(2A	I,;I*<BI,I,I,I,"I,%I,(I,*I,c                   #    [        U R                  5      U:  a  U R                  (       a  gU R                  R	                  5         [        U R                  5      U:  a  OhU R                  R                  5       I Sh  vN   U R                  (       a  [        U R                  5      U:  a  g[        U R                  5      U:  a  M  [        U R                  SU 5      nU R                  SU2	 U$  Ns7f)zpRead exactly n bytes from internal buffer.

Waits for data via the callback-fed buffer instead of StreamReader.
N)lenr   r   r   clearwaitrD   )r   nr'   s      r    r   WebSocketProtocol._read_exact?  s     
 $,,!#yy""$ 4<< A%""'')))yyS.2 $,,!# T\\"1%&LL! *s   A=C5?C3 AC5
*C5c                 R   ^ U(       d  U$ [        U4S j[        U5       5       5      $ )zUnmask WebSocket payload data.c              3   >   >#    U  H  u  pUTUS -     -  v   M     g7f)ry   N ).0ibr   s      r    	<genexpr>,WebSocketProtocol._unmask.<locals>.<genexpr>Y  s#     K8JQQU++8Js   )rD   	enumerate)r   rr   r   s     `r    r   WebSocketProtocol._unmaskT  s!    NK	'8JKKKr#   c                 T  #    [        U5      S:  a;  [        R                  " SUSS 5      S   U l        USS R	                  SSS9U l        O[        U l        SU l        U R                  (       d.  U R                  U R                  U R
                  5      I Sh  vN   S	U l        g N7f)
zHandle incoming close frame.r   r}   Nr   rC   replace)errorsr   T)	r   r   r   r   r[   r   CLOSE_NO_STATUSr   r9   r   rr   s     r    ri   WebSocketProtocol._handle_close[  s     w<1$mmD'"1+>qADO ' 2 279 2 MD-DO "D {{""4??D4E4EFFF Gs   BB(B&B(c                    #    g7f)z=Handle continuation frame (already processed in _read_frame).Nr   r   s     r    rm   &WebSocketProtocol._handle_continuationj  s     s   c                 .  #    [        U[        5      (       a  UR                  S5      n[        U5      n[	        5       nUR                  SU-  5        US:  a  UR                  U5        OuUS:  a8  UR                  S5        UR                  [        R                  " SU5      5        O7UR                  S5        UR                  [        R                  " SU5      5        UR                  U5        U R                  R                  [        U5      5        g7f)	zBSend a WebSocket frame.

Server frames are not masked (RFC 6455).
rC      r|   i   r}   r{   r~   N)r]   strrK   r   r   r\   r%   r   packr   r^   rD   )r   rq   rr   lengthrp   s        r    rI   WebSocketProtocol._send_framen  s     
 gs##nnW-GW 	TF]# C<LL e^LLLLT623LLLLT623 	WU5\*s   DDc                    #    [         R                  " SU5      nU(       a  X2R                  S5      SS -  nU R                  [        U5      I Sh  vN   SU l        g N7f)zSend a close frame.r}   rC   N{   T)r   r   rK   rI   rh   r   )r   rE   rF   rr   s       r    r9   WebSocketProtocol._send_close  sR     ++dD)}}W-ds33G|W555 	6s   AAAA)r   r   r   r   r   r   r   r   r   r   r   r   r   r   N)r   )__name__
__module____qualname____firstlineno____doc__r!   r(   r,   r<   r3   r4   rH   r2   rg   r   r   ri   rm   rI   r9   __static_attributes__r   r#   r    r	   r	   *   sZ    >#
R./6(AT,\P%d*LL+:r#   r	   )r   r   rU   rW   r   rl   rJ   rL   rh   rj   rk   rM   CLOSE_GOING_AWAYr   CLOSE_UNSUPPORTEDr   ro   CLOSE_INVALID_DATACLOSE_POLICY_VIOLATIONCLOSE_MESSAGE_TOO_BIGCLOSE_MANDATORY_EXTr:   rY   r	   r   r#   r    <module>r      s   
                2g gr#   