
    Gi7                         S r SSKrSSKrSSKJr  SSKJr  SSKJr  SSKJ	r	  SSK
Jr  SSKJr  S	 r " S
 S5      r " S S\R                   5      rg)z
ASGI protocol handler for gunicorn.

Implements asyncio.Protocol to handle HTTP/1.x and HTTP/2 connections
and dispatch to ASGI applications.
    N)datetime)AsyncUnreader)AsyncRequest)AsyncUWSGIRequest)
NoMoreData)UWSGIParseExceptionc                 0    U (       a  [        U SS 5      $ S$ )zNormalize socket address to ASGI-compatible (host, port) tuple.

ASGI spec requires server/client to be (host, port) tuples.
IPv6 sockets return 4-tuples (host, port, flowinfo, scope_id),
so we extract just the first two elements.
N   )tuple)sockaddrs    `/var/www/fortnox.synktek.com/backend/venv/lib/python3.13/site-packages/gunicorn/asgi/protocol.py_normalize_sockaddrr      s     #+5"144    c                       \ rS rSrSrS rSrg)ASGIResponseInfo!   z;Simple container for ASGI response info for access logging.c                    Xl         X0l        / U l        U Hm  u  pE[        U[        5      (       a  UR                  S5      n[        U[        5      (       a  UR                  S5      nU R                  R                  XE45        Mo     g )Nlatin-1)statussentheaders
isinstancebytesdecodeappend)selfr   r   r   namevalues         r   __init__ASGIResponseInfo.__init__$   si    	"KD$&&{{9-%''Y/LL. #r   )r   r   r   N)__name__
__module____qualname____firstlineno____doc__r   __static_attributes__ r   r   r   r   !   s
    E
/r   r   c                       \ 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 rSS jrS rS rS rS rS rS rS rSrg)ASGIProtocol1   zzHTTP/1.1 protocol handler for ASGI applications.

Handles connection lifecycle, request parsing, and ASGI app invocation.
c                     Xl         UR                  U l        UR                  U l        UR                  U l        S U l        S U l        S U l        S U l        SU l	        SU l
        S U l        g )Nr   F)workercfglogasgiapp	transportreaderwriter_task	req_count_closed_receive_queue)r   r,   s     r   r   ASGIProtocol.__init__7   s\    ::::;;
 "r   c                 $   Xl         U R                  =R                  S-  sl        UR                  S5      nU(       a{  [	        US5      (       aj  UR                  5       nUS:X  aT  [        R                  " 5       U l        U R                  R                  R                  U R                  X5      5      U l        g[        R                  " 5       U l        Xl        U R                  R                  R                  U R                  5       5      U l        g)z(Called when a connection is established.   
ssl_objectselected_alpn_protocolh2N)r1   r,   nr_connsget_extra_infohasattrr<   asyncioStreamReaderr2   loopcreate_task_handle_http2_connectionr4   r3   _handle_connection)r   r1   r;   alpns       r   connection_madeASGIProtocol.connection_madeG   s    "! --l;
'*.FGG446Dt| &224![[--9911)H
  **, [[%%11$2I2I2KL
r   c                 ^    U R                   (       a  U R                   R                  U5        gg)z/Called when data is received on the connection.N)r2   	feed_data)r   datas     r   data_receivedASGIProtocol.data_receiveda   s     ;;KK!!$' r   c                 R   U R                   (       a  gSU l         U R                  =R                  S-  sl        U R                  (       a  U R                  R	                  5         U R
                  b  U R
                  R                  SS05        U R                  (       a  U R                  R                  5       (       di  [        U R                  SS5      nUS:  a1  U R                  R                  R                  UU R                  5        gU R                  R                  5         ggg)	a\  Called when the connection is lost or closed.

Instead of immediately cancelling the task, we signal a disconnect
event and send an http.disconnect message to the receive queue.
This allows the ASGI app to clean up resources (like database
connections) gracefully before the task is cancelled.

See: https://github.com/benoitc/gunicorn/issues/3484
NTr:   typehttp.disconnectasgi_disconnect_grace_period   r   )r6   r,   r>   r2   feed_eofr7   
put_nowaitr4   donegetattrr-   rC   
call_later_cancel_task_if_pendingcancel)r   excgrace_periods      r   connection_lostASGIProtocol.connection_lostf   s     <<!;;KK  " ***F4E+FG ::djjoo//"488-KQOLa  ++ 00 

!!# 0:r   c                     U R                   (       a;  U R                   R                  5       (       d  U R                   R                  5         ggg)z9Cancel the task if it's still pending after grace period.N)r4   rV   rZ   r   s    r   rY   $ASGIProtocol._cancel_task_if_pending   s0    ::djjoo//JJ 0:r   c                 F    U R                   R                  U5        g! [         ag  nUR                  [        R                  [        R
                  [        R                  4;  a   U R                  R                  S5         SnAg SnAgSnAf[        [        4 a     gf = f)aH  Write data to transport, handling connection errors gracefully.

Catches exceptions that occur when the client has disconnected:
- OSError with errno EPIPE, ECONNRESET, ENOTCONN
- RuntimeError when transport is closing/closed
- AttributeError when transport is None

These are silently ignored since the client is already gone.
zSocket error writing response.N)r1   writeOSErrorerrnoEPIPE
ECONNRESETENOTCONNr.   	exceptionRuntimeErrorAttributeError)r   rL   es      r   _safe_writeASGIProtocol._safe_write   sw    	NN  & 	Ewwu{{E,<,<ennMM""#CDD Nn- 		s    
B AB

B B c                   #    [        U R                  5      n U R                  R                  S5      nU R                  R                  S5      nU R                  (       Gd  U =R
                  S-  sl         [        U R                  SS5      nUS:X  a6  [        R                  " U R                  UUU R
                  5      I Sh  vN nO6[        R                  " U R                  UUU R
                  5      I Sh  vN n U R                  U5      (       a  U R!                  XSU5      I Sh  vN   GO U R#                  XSU5      I Sh  vN nU R$                  =R&                  S-  sl        U R$                  R&                  U R$                  R(                  :  a.  U R                  R+                  S	5        S
U R$                  l        S
nU(       a  U R$                  R,                  (       d  OHU R                  R.                  (       d  O,UR1                  5       I Sh  vN   U R                  (       d  GM  U R;                  5         g GN GNL! [         a     M$  [         a'  nU R                  R                  SU5         SnAMO  SnAff = f GN^ GNE Nu! [2        R4                   a     Nu[6         a&  nU R                  R9                  SU5         SnANSnAff = f! U R;                  5         f = f7f)z/Main request handling loop for this connection.peernamesocknamer:   protocolhttpuwsgiNzuWSGI parse error: %s,Autorestarting worker after current request.FzError handling connection: %s)r   r2   r1   r?   r6   r5   rW   r-   r   parser   r   r   r.   debug_is_websocket_upgrade_handle_websocket_handle_http_requestr,   nrmax_requestsinfoalive	keepalive
drain_bodyrA   CancelledError	Exceptionri   _close_transport)r   unreaderrp   rq   rr   requestrl   r   s           r   rF   ASGIProtocol._handle_connection   sO     -A	$~~44Z@H~~44Z@Hlll!#&txxVDH7*(9(?(? HH$$ NN	) # )5(:(: HH$$ NN	) # --g6600HMMM #'";";x# 	
 !# ;;>>T[[%=%==HHMM"PQ(-DKK% %I (9(9 xx)) ((***m lllz !!#m## " * HHNN#:A> N* +%% 	 	CHH>BB	C !!#s  K.AJ 7AI	 II	 	J 
0I	 :I;I	 ?,J +J	,J 0K 2J JB!J )K *J K J JJ 2K.I	 I	 	
JJ K 	JJ;J ?K JJ J J K%K '	K0KK KK K++K.c                     UR                   S:w  a  gSnSnUR                   H5  u  pEUS:X  a  UR                  5       nM  US:X  d  M%  UR                  5       nM7     US:H  =(       a    U=(       a    SU;   $ )zCheck if request is a WebSocket upgrade.

Per RFC 6455 Section 4.1, the opening handshake requires:
- HTTP method MUST be GET
- Upgrade header MUST be "websocket" (case-insensitive)
- Connection header MUST contain "Upgrade"
GETFNUPGRADE
CONNECTION	websocketupgrade)methodr   lower)r   r   r   
connectionr   r   s         r   rx   "ASGIProtocol._is_websocket_upgrade   so     >>U"
"??KDy ++-%"[[]
	 +
 +%P*Pj9PPr   c                    #    SSK Jn  U R                  XU5      nU" U R                  U R                  XPR
                  U R                  5      nUR                  5       I Sh  vN   g N7f)z!Handle WebSocket upgrade request.r   )WebSocketProtocolN)gunicorn.asgi.websocketr   _build_websocket_scoper1   r2   r0   r.   run)r   r   rq   rp   r   scopews_protocols          r   ry   ASGIProtocol._handle_websocket   sO     =++GxH'NNDKK$((
 oos   AA)!A'"A)c           	      D	  ^ ^^^^^^^^^^#    T R                  TX#5      nSmSmSmSmSm/ mSm[        R                  " 5       mTT l        SmTR                  S:X  a1  TR
                  (       d   TR                  SSSS.5      I Sh  vN   SmO&[        R                  " T R                  TT5      5        UUU 4S	 jnUUUUUUUU U4	S
 jnT R                  TX#5      nSn [        R                  " 5       n	T R                  R                  T R                  T5        T R                  XEU5      I Sh  vN   Tb  TeT(       d  T R!                  SS5      I Sh  vN   SmST l         [        R                  " 5       U	-
  n
[)        TTT5      nT R$                  R+                  UTXz5        T R                  R-                  T R                  TXx5        TR3                  5       (       a  gT R                  R4                  =(       a    T R                  R6                  $  GN N N! [        R"                   a    T R$                  R'                  S5         ST l         [        R                  " 5       W	-
  n
[)        TTT5      nT R$                  R+                  UTXz5        T R                  R-                  T R                  TXx5        g! [.         a    T R$                  R1                  S5         gf = f[.         a    T R$                  R1                  S5        T(       d  T R!                  SS5      I Sh  vN    Sm ST l         [        R                  " 5       W	-
  n
[)        TTT5      nT R$                  R+                  UTXz5        T R                  R-                  T R                  TXx5        g! [.         a    T R$                  R1                  S5         gf = ff = f! [.         a    T R$                  R1                  S5         GN/f = f! ST l         [        R                  " 5       W	-
  n
[)        TTT5      nT R$                  R+                  UTXz5        T R                  R-                  T R                  TXx5        f ! [.         a    T R$                  R1                  S5         f f = f= f7f)zHandle a single HTTP request.FN  r   http.requestr   rP   body	more_bodyTc                     >#    TR                   (       a  T(       a  SS0$ TR                  5       I S h  vN n U R                  S5      S:X  a  U R                  SS5      (       d  SmU $  N47f)NrP   rQ   r   r   T)r6   get)msgbody_completereceive_queuer   s    r   receive2ASGIProtocol._handle_http_request.<locals>.receive%  s_      || 122%))++C wwv.0d9S9S $J ,s   0A*A(5A*c                 "  >	#    TR                   (       a  g U S   nUS:X  a>  U R                  S5      nU R                  S/ 5      nTR                  X#T5      I S h  vN   g US:X  a  T(       a  [        S5      mg SmU S   mU R                  S/ 5      m
[	        S T
 5       5      nU(       d!  TR
                  S	:  a  Sm[        T
5      S
/-   m
TR                  TT
T5      I S h  vN   g US:X  a  T(       d  [        S5      mg T	(       a  [        S5      mg U R                  SS5      nU R                  SS5      nU(       a&  TR                  UTS9I S h  vN   T[        U5      -  mU(       d  T(       a  TR                  S5        Sm	g g g  GN/ N N;7f)NrP   http.response.informationalr   r   http.response.startResponse already startedTc              3     #    U  H~  u  p[        U[        5      (       a  UR                  5       OUR                  5       S :H  =(       d8    [        U[        5      (       a  UR                  5       OUR                  5       S:H  v   M     g7f)s   content-lengthzcontent-lengthN)r   strr   ).0r   _s      r   	<genexpr>BASGIProtocol._handle_http_request.<locals>.send.<locals>.<genexpr>N  sj      ) $4 &0c%:%:TZZ\

Qbb e(24(=(=

4::<Tdde#3s   BBr:   r:   )s   transfer-encodings   chunkedhttp.response.bodyResponse not startedResponse already completer   r   r   F)chunkeds   0

)r6   r   _send_informationalrj   anyversionlist_send_response_start
_send_bodylenrm   )messagemsg_typeinfo_statusinfo_headershas_content_lengthr   r   exc_to_raiser   response_completeresponse_headersresponse_sentresponse_startedresponse_statusr   use_chunkeds          r   send/ASGIProtocol._handle_http_request.<locals>.send3  s     ||vH88%kk(3&{{9b9..{'RRR00##/0J#KL#' ")("3#*;;y"#=  &) ) $4) &" *goo.G"&K'+,<'=Ac@d'd$//AQSZ[[[11'#/0F#GL$#/0K#LL{{63/#KKU;	//$/DDD!SY.M "((6(,%	 ! 23 S. \ Es8   AFFBF!F"A/FF7FFFInternal Server Errorz'Request cancelled (client disconnected)Exception in post_request hookError in ASGI application)_build_http_scoperA   Queuer7   content_lengthr   putrD   _read_body_to_queue_build_environr   nowr-   pre_requestr,   r0   _send_error_responser   r.   rw   r   accesspost_requestr   ri   should_closer~   r   )r   r   rq   rp   r   r   r   environresprequest_startrequest_timer   r   r   r   r   r   r   r   r   s   ``         @@@@@@@@@r   rz   !ASGIProtocol._handle_http_request  s    &&wC !   + !!Q&w##&"%   
 !M  8 8- PQ	;	- ;	-| %%gxB#	E$LLNMHH  g6((54000'"" $//5LMMM"% #'DE'||~='9I=YgwE%%dkk7GJ
 !!{{  7TXX%7%77Ez 1 N %% 	HHNNDE #'DE'||~='9I=YgwE%%dkk7GJ E""#CDE!  	HH:;#//5LMMM"% #'DE'||~='9I=YgwE%%dkk7GJ E""#CDE!	   E""#CDE #'DE'||~='9I=YgwE%%dkk7GJ E""#CDEs"  A8R HAR AH .H/%H HH R #A)O A
R H H /OO? R A)J> =R >%K&#R %K&&R )A O)L,*O1O? 2R :A)N$ #R $%O	R OR OO? %O<8R ;O<<R ?RA)Q21R2%RRRRR c                 x  #      UR                  S5      I Sh  vN nU(       a  UR                  SUSS.5      I Sh  vN   OUR                  SSSS.5      I Sh  vN   gM^   NI N' N! [         aD  nU R                  R	                  SU5        UR                  SSSS.5      I Sh  vN     SnAgSnAff = f7f)	z.Read request body and put chunks on the queue.Ti   Nr   r   r   FzError reading body: %s)	read_bodyr   r   r.   rw   )r   r   queuechunkrl   s        r   r    ASGIProtocol._read_body_to_queue  s     	%//66)) . %%)%     )) . #%*%   
  6  	HHNN3Q7))&"   	sl   B:A) A##A) A%A) A'A)  B:!A) %A) 'A) )
B734B2'B*(B2-B:2B77B:c                 ,   / nUR                    HD  u  pVUR                  UR                  5       R                  S5      UR                  S5      45        MF     [	        U5      n[	        U5      nSSSS.UR
                  S    SUR
                  S    3UR                  UR                  UR                  UR                  (       a  UR                  R                  S5      OS	UR                  (       a  UR                  R                  S5      OS	U R                  R                  =(       d    S
UUUS.n	[        U R                  S5      (       a  U R                  R                  U	S'   [        US5      (       a  SUR                  UR                   S.0U	S'   U	$ )z*Build ASGI HTTP scope from parsed request.r   rs   3.02.4r   spec_versionr   .r:   r    rP   r/   http_versionr   schemepathraw_pathquery_string	root_pathr   serverclientstatepriority_weighthttp.response.priorityweight
depends_on
extensions)r   r   r   encoder   r   r   r   r   queryr-   r   r@   r,   r   r   priority_depends_on)
r   r   rq   rp   r   r   r   r   r   r   s
             r   r   ASGIProtocol._build_http_scope  sX    "??KDNNDJJL//	:ELL<STU + %X.$X.  %u=&q12!GOOA4F3GHnnnnLL:A,,++I6C?F}}GMM00;RU++1r
  4;;((![[..E'N 7-..(%55")"="=+#E, r   c           	      .   UR                   UR                  UR                  UR                  =(       d    SSUR                  S    SUR                  S    3U(       a  US   OSS.nUR
                   H  u  pVSUR                  SS	5      -   nXdU'   M      U$ )
z8Build minimal WSGI-like environ dict for access logging.r   HTTP/r   r   r:   -REQUEST_METHODRAW_URI	PATH_INFOQUERY_STRINGSERVER_PROTOCOLREMOTE_ADDRHTTP_r   )r   urir   r   r   r   replacer   r   rq   rp   r   r   r   keys           r   r   ASGIProtocol._build_environ  s     &nn{{ #MM/R!&wq'9&:!GOOA<N;OP*28A;
 #??KDDLLc22C CL + r   c                 n   / nUR                    HD  u  pVUR                  UR                  5       R                  S5      UR                  S5      45        MF     / nUR                    H;  u  pVUS:X  d  M  UR	                  S5       Vs/ s H  oR                  5       PM     nn  O   [        U5      n	[        U5      n
SSSS.UR                  S    S	UR                  S
    3UR                  S:X  a  SOSUR                  UR                  (       a  UR                  R                  S5      OSUR                  (       a  UR                  R                  S5      OSU R                  R                  =(       d    SUU	U
US.n[        U R                  S5      (       a  U R                  R                  US'   U$ s  snf )z/Build ASGI WebSocket scope from parsed request.r   zSEC-WEBSOCKET-PROTOCOL,r   r   r   r   r   r   r:   httpswsswsr   r   )rP   r/   r   r   r   r   r   r   r   r   r   subprotocolsr   )r   r   r   r   splitstripr   r   r   r   r   r-   r   r@   r,   r   )r   r   rq   rp   r   r   r   r  sr   r   r   s               r   r   #ASGIProtocol._build_websocket_scope  sq    "??KDNNDJJL//	:ELL<STU + "??KD//38;;s3CD3Ca	3CD +
 %X.$X.   %u=&q12!GOOA4F3GH&~~8edLL:A,,++I6C?F}}GMM00;RU++1r(
  4;;((![[..E'N3  Es   F2c           	        #    UR                   S:  a  gU R                  U5      nSUR                   S    SUR                   S    SU SU S3	nU H[  u  pg[        U[        5      (       a  UR	                  S	5      n[        U[        5      (       a  UR	                  S	5      nXV S
U S3-  nM]     US-  nU R                  UR                  S	5      5        g7f)a7  Send an informational response (1xx) such as 103 Early Hints.

Args:
    status: HTTP status code (100-199)
    headers: List of (name, value) header tuples
    request: The parsed request object

Note: Informational responses are only sent for HTTP/1.1 or later.
HTTP/1.0 clients do not support 1xx responses.
r   Nr   r   r   r:    
r   : )r   _get_reason_phraser   r   r   rm   r   )r   r   r   r   reasonresponser   r   s           r   r    ASGIProtocol._send_informational  s      ??V#((07??1-.a0B/C1VHAfXUYZ"KD$&&{{9-%''Y/&5'..H # 	F34s   CCc           	        #    U R                  U5      nSUR                  S    SUR                  S    SU SU S3	n/ nU Hh  u  px[        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S
R                  U5      -   S-   n	U R                  U	R                  S5      5        g7f)z&Send HTTP response status and headers.r   r   r   r:   r  r  r   r  zServer: gunicorn/asgi
r   N)	r  r   r   r   r   r   joinrm   r   )
r   r   r   r   r  status_lineheader_linesr   r   r  s
             r   r   !ASGIProtocol._send_response_start5  s      ((0gooa017??13E2FaxqQWPXX\] "KD$&&{{9-%''Y/4&5' 67 # 	78!66?34s   C4C6c                    #    U(       aO  U(       a6  [        U5      S S3R                  S5      U-   S-   nU R                  U5        gU R                  U5        gg7f)zSend response body chunk.xr  r   s   
N)r   r   rm   )r   r   r   r   s       r   r   ASGIProtocol._send_bodyK  sS     t9Q-t,33I>EO  '  & s   AAc                    #    UR                  S5      nSU SU S[        U5       S3nU R                  UR                  S5      5        U R                  U5        g7f)zSend an error response.zutf-8z	HTTP/1.1 r  z,
Content-Type: text/plain
Content-Length: z
Connection: close

r   N)r   r   rm   )r   r   r   r   r  s        r   r   !ASGIProtocol._send_error_responseU  sd     ~~g&xq	 *"4yk * 	 	34s   AAc                     0 SS_SS_SS_SS_S	S
_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS_SS _S!S"_0 S#S$_S%S&_S'S(_S)S*_S+S,_S-S._S/S0_S1S2_S3S4_S5S6_S7S8_S9S:_S;S<_S=S>_S?S@_SASB_EnUR                  USC5      $ )Dz'Get HTTP reason phrase for status code.d   Continuee   zSwitching Protocolsg   zEarly Hints   OK   Created   Accepted   z
No Content   zPartial Contenti-  zMoved Permanentlyi.  Foundi/  z	See Otheri0  zNot Modifiedi3  zTemporary Redirecti4  zPermanent Redirecti  zBad Requesti  Unauthorizedi  	Forbiddeni  z	Not Foundi  zMethod Not Allowedi  zRequest Timeouti  Conflicti  Gonei  zLength Requiredi  zPayload Too Largei  zURI Too Longi  zUnsupported Media Typei  zUnprocessable Entityi  zToo Many Requestsr   r   i  zNot Implementedi  zBad Gatewayi  zService Unavailablei  zGateway TimeoutUnknown)r   )r   r   reasonss      r   r  ASGIProtocol._get_reason_phraseb  s   "
"
&"
 "
 	"

 "
 "
 "
 ""
 $"
 "
 "
 "
 %"
 %"
 "
  !"
" #"
$ %"
& %'"
( ")"
* +"
, -"
. "/"
0 $1"
2 3"
4 )5"
6 '7"
8 $9"
: (;"
< "="
> ?"
@ &A"
B "C"
F {{69--r   c                 "   U R                   (       an  U R                  (       d\   U R                   R                  5       (       a  U R                   R                  5         U R                   R	                  5         SU l        ggg! [
         a     Nf = f)zClose the transport safely.

Calls write_eof() first if supported to signal end of writing,
which helps ensure buffered data is flushed before closing.
TN)r1   r6   can_write_eof	write_eofcloser   r`   s    r   r   ASGIProtocol._close_transport  sm     >>$,,>>//11NN,,.$$&  DL #/>  s   AB 
BBc           	        #     SSK Jn  UR                  S5      nUR                  S5      nU R                  n[        R
                  " U5      n[        R                  " XX`R                  R                  5      nU" U R                  XhU5      n	U	R                  5       I Sh  vN   Xl        U	R                  (       Gd/  U R                  R                  (       Ga   U	R                  SS9I Sh  vN n
U
 HC  n U R'                  XXT5      I Sh  vN   U	R3                  UR,                  R.                  5        ME     U R                  =R4                  [7        U
5      -  sl        U R                  R4                  U R                  R8                  :  a-  U R"                  R;                  S5        SU R                  l        O/U	R                  (       d  U R                  R                  (       a  GM  [?        U S5      (       a#   U R                  RA                  5       I Sh  vN   U RC                  5         g GN GNH! [        R                   a     GM  [          a'  nU R"                  R%                  SU5         SnAM  SnAff = f GNv! [          au  nU R"                  R)                  S	5         U	R+                  UR,                  R.                  S
[1        U5      5      I Sh  vN     SnAGN! [          a      SnAGNf = fSnAff = f! U	R3                  UR,                  R.                  5        f = f! [        R<                   a     GN\[          a'  nU R"                  R)                  SU5         SnAGNSnAff = f GN`! [          a     GNkf = f! [?        U S5      (       a5   U R                  RA                  5       I Sh  vN    O! [          a     Of = fU RC                  5         f = f7f)zHandle an HTTP/2 connection.r   )AsyncHTTP2Connectionrp   rq   Ng      ?)timeoutzHTTP/2 receive error: %szError handling HTTP/2 requestr   ru   FzHTTP/2 connection error: %s_h2_conn)"gunicorn.http2.async_connectionrE  r?   r2   rA   StreamReaderProtocolStreamWriterr,   rC   r-   initiate_connectionrG  	is_closedr~   receive_dataTimeoutErrorr   r.   rw   _handle_http2_requestri   
send_errorstream	stream_idr   cleanup_streamr{   r   r|   r}   r   r@   rB  r   )r   r1   r;   rE  rp   rq   r2   rr   r3   h2_connrequestsrl   reqs                r   rE   %ASGIProtocol._handle_http2_connection  s)    C	$L //
;H //
;H [[F33F;H))V[[-=-=F
 +&(G --///#M '''DKK,=,=,=%,%9%9#%9%FFH $CE"88(    ..szz/C/CD $" #h-/ ;;>>T[[%=%==HHMM"PQ(-DKK%A ''DKK,=,=,=N tZ((----/// !!#c 0  G++   HHNN#=qA % !**+JK!")"4"4 #

 4 4c3q6#    ) ! !!  ..szz/C/CD %% 	 	AHH<a@@	A
 0   tZ((----///  !!#s  O*BL1  H1!8L1 H7 ,H4-H7 1L1 7JJJB+L1 <N =,L1 ,O*>M> M;M>  O*1L1 4H7 7I?L1 	I?I:4L1 8N :I??L1 J
LK?+3K*K!K*$L*
K<4K?5L;K<<K??LL'L..L1 1M8N 	M8M3-N 3M88N ;M> >
NO*NO*O'"O?O OO'
OO'OO''O*c           	      .  ^^^^^^^^^^#    TR                   R                  mU R                  TX45      nSmSmSmSm/ mSm/ mU4S jnUUUUUUUUU4	S jnU R                  TX45      n[        R
                  " 5       n	 U R                  R                  U R                  T5        U R                  XVU5      I Sh  vN   Tb  TeT(       Ga  / n
T Hc  u  p[        U[        5      (       a  UR                  S5      n[        U[        5      (       a  UR                  S5      nU
R                  X45        Me     T(       a  S[        T5      4/nU
 H/  u  pUR                  UR                  5       [        U5      45        M1     TR                   R#                  TUSS	9  TR$                  T   nUR#                  USS	9  TR'                  5       I Sh  vN   T(       aC  TR                   R)                  TTSS	9  UR)                  TSS	9  TR'                  5       I Sh  vN   TR+                  TT5      I Sh  vN   O;TR-                  TTU
T5      I Sh  vN   OTR/                  TSS
5      I Sh  vN   Sm  [        R
                  " 5       U	-
  n[7        TT[9        T5      5      nU R2                  R;                  UTX5        U R                  R=                  U R                  TUU5        g GN. GN N N N N! [0         aC    U R2                  R5                  S5        T(       d  TR/                  TSS
5      I Sh  vN    Sm Nf = f! [0         a    U R2                  R5                  S5         gf = f!  [        R
                  " 5       U	-
  n[7        TT[9        T5      5      nU R2                  R;                  UTX5        U R                  R=                  U R                  TUU5        f ! [0         a    U R2                  R5                  S5         f f = f= f7f)zHandle a single HTTP/2 request.FNr   r   c                  L   >#    TR                   R                  5       n SU SS.$ 7f)Nr   Fr   )r   read)r   r   s    r   r   3ASGIProtocol._handle_http2_request.<locals>.receive  s+     <<$$&D&" s   !$c                    >	#    U S   nUS:X  a  U R                  S5      nU R                  S/ 5      n/ nU Hc  u  pV[        U[        5      (       a  UR                  S5      n[        U[        5      (       a  UR                  S5      nUR	                  XV45        Me     TR                  TX$5      I S h  vN   g US:X  a-  T(       a  [        S5      mg SmU S   mU R                  S/ 5      mg US	:X  aa  T(       d  [        S
5      mg T(       a  [        S5      mg U R                  SS5      nU R                  SS5      nU(       a  TU-  mU(       d  Smg g US:X  a  T(       d  [        S5      mg U R                  S/ 5      n	/ n
U	 Hc  u  pV[        U[        5      (       a  UR                  S5      n[        U[        5      (       a  UR                  S5      nU
R	                  XV45        Me     TR                  U
5        g g  GNI7f)NrP   r   r   r   r   r   r   Tr   r   r   r   r   r   Fhttp.response.trailersz)Cannot send trailers before body complete)r   r   r   r   r   send_informationalrj   extend)r   r   r   r   r   r   r   r   r   trailer_headerstrailersr   rT  response_bodyr   r   r   r   response_trailersrR  s              r   r   0ASGIProtocol._handle_http2_request.<locals>.send  s     vH88%kk(3&{{9b9#/KD!$..#{{95!%// %Y 7NND=1 $0 00KQQQ00##/0J#KL#' ")("3#*;;y"#= 11'#/0F#GL$#/0K#LL{{63/#KKU;	!T)M (,% ! 55(#/0[#\L")++i"<#2KD!$..#{{95!%// %Y 7OOTM2 $3 "((2 69 Rs   B/G>2G;3E	G>r   z:status)
end_streamr   r   r   )rQ  rR  _build_http2_scope_build_http2_environr   r   r-   r   r,   r0   r   r   r   r   r   r   rT  send_headersstreams_send_pending_data	send_datasend_trailerssend_responserP  r   r.   ri   r   r   r   r   )r   r   rT  rq   rp   r   r   r   r   r   r   r   r   response_hdrsrQ  r   r   r   rb  r   r   r   r   rc  rR  s    ``              @@@@@@@@r   rO  "ASGIProtocol._handle_http2_request  s    NN,,	''D !	;	3 ;	3| ++GXH <	EHH  g6((54000'""  #3KD!$..#{{95!%// %Y 7NND=1 $4 %&/_1E%F$GM'.%,,djjlCJ-GH (/ OO00MV[0\$__Y7F''%'H!44666 %11)]W\1]((5(I%88::: "//	;LMMM!//!?G]   ((C9PQQQ"%E'||~='#%5s=7I gwE%%dkk7GTJq 14 7 ; N R  	&HH:;#((C9PQQQ"%		&  E""#CDEE'||~='#%5s=7I gwE%%dkk7GTJ E""#CDEs  A2P?;K6 :K(;DK6 K+A	K6 K.K6 2K03K6 7M1 8K6 K2K6 M1 K6 +K4,K6 2M1 4A3M 'P(K6 +K6 .K6 0K6 2K6 4K6 6AM8L;9M M1 MM1 %M.+P-M..P1P3A3O'&P'%PPPPPc                     / nUR                    HD  u  pVUR                  UR                  5       R                  S5      UR                  S5      45        MF     [	        U5      n[	        U5      nSSSS.SUR
                  UR                  UR                  UR                  (       a  UR                  R                  S5      OSUR                  (       a  UR                  R                  S5      OSU R                  R                  =(       d    SUUUS	.n	[        U R                  S
5      (       a  U R                  R                  U	S
'   0 n
[        US5      (       a  UR                  UR                  S.U
S'   0 U
S'   XS'   U	$ )z*Build ASGI HTTP scope from HTTP/2 request.r   rs   r   r   r   2r   r   r   r   r   r   r   r]  r   )r   r   r   r   r   r   r   r   r   r-   r   r@   r,   r   r   r   )r   r   rq   rp   r   r   r   r   r   r   r   s              r   rf  ASGIProtocol._build_http2_scopev  sN   "??KDNN

##I.Y'  + %X.$X.  %u=nnnnLL:A,,++I6C?F}}GMM00;RU++1r
 4;;((![[..E'N 
7-..!11%994J/0
 02
+,(lr   c                     UR                   UR                  UR                  UR                  =(       d    SSU(       a  US   OSS.nUR                   H  u  pVSUR                  SS5      -   nXdU'   M      U$ )z.Build minimal environ dict for access logging.r   zHTTP/2r   r   r  r  r   )r   r	  r   r   r   r
  r  s           r   rg  !ASGIProtocol._build_http2_environ  so     &nn{{ #MM/R'*28A;
 #??KDDLLc22C CL + r   )r6   rG  r7   r4   r0   r-   r.   r2   r5   r1   r,   r3   N)F)r!   r"   r#   r$   r%   r   rH   rM   r]   rY   rm   rF   rx   ry   rz   r   r   r   r   r   r   r   r   r  r   rE   rO  rf  rg  r&   r'   r   r   r)   r)   1   s    
# M4(
!$F 
&E$NQ* V8p4&P$$L585,'%.N  E$NTEl)Vr   r)   )r%   rA   re   r   gunicorn.asgi.unreaderr   gunicorn.asgi.messager   gunicorn.asgi.uwsgir   gunicorn.http.errorsr   gunicorn.uwsgi.errorsr   r   r   Protocolr)   r'   r   r   <module>r{     sG   
    0 . 1 + 55/ / 7## r   