
    gj0                       d Z ddlZddlZddlZddlZddlZddlZddlZddl	Z
ddlZddlZddlZddlZddlZddlZddlmZ ddlmZmZmZ ddlmZ ddlmZ ddlmZ dd	lmZmZ d
Z  ejB                         dk(  Z"	  ejF                  dd      jI                  d      Z%	 e" xr e% Z&	 e&r	 ddl'Z'ddl(Z(ddl*Z*e"r) e+ed      r  e+ed      sde_,         e+ed      sde_-         e+ed      s	 erdnde_.        dZ/dZ0dZ1dZ2dZ3dZ4dZ5d Z6d!Z7d"Z8 ejr                  dju                  d#e8f            Z; e<       Z=g d$Z> e+ed%      si e_?         G d& d'      Z@ G d( d)e@      ZA G d* d+      ZB G d, d-      ZC G d. d/      ZD G d0 d1      ZE G d2 d3      ZF G d4 d5      ZG G d6 d7      ZHd8d9d:ZId<d;ZJy# e)$ r 	 dZ&d\  Z'Z(Y w xY w)=a  
A high-speed, production ready, thread pooled, generic HTTP server.

For those of you wanting to understand internals of this module, here's the
basic call flow. The server's listening thread runs a very tight loop,
sticking incoming connections onto a Queue::

    server = HTTPServer(...)
    server.start()
    ->  serve()
        while ready:
            _connections.run()
                while not stop_requested:
                    child = socket.accept()  # blocks until a request comes in
                    conn = HTTPConnection(child, ...)
                    server.process_conn(conn)  # adds conn to threadpool

Worker threads are kept in a pool and poll the Queue, popping off and then
handling each connection in turn. Each connection can consist of an arbitrary
number of requests and their responses, so we run a nested loop::

    while True:
        conn = server.requests.get()
        conn.communicate()
        ->  while True:
                req = HTTPRequest(...)
                req.parse_request()
                ->  # Read the Request-Line, e.g. "GET /page HTTP/1.1"
                    req.rfile.readline()
                    read_headers(req.rfile, req.inheaders)
                req.respond()
                ->  response = app(...)
                    try:
                        for chunk in response:
                            if chunk:
                                req.write(chunk)
                    finally:
                        if hasattr(response, "close"):
                            response.close()
                if req.close_connection:
                    return

For running a server you can invoke :func:`start() <HTTPServer.start()>` (it
will run the server forever) or use invoking :func:`prepare()
<HTTPServer.prepare()>` and :func:`serve() <HTTPServer.serve()>` like this::

    server = HTTPServer(...)
    server.prepare()
    try:
        threading.Thread(target=server.serve).start()

        # waiting/detecting some appropriate stop condition here
        ...

    finally:
        server.stop()

And now for a trivial doctest to exercise the test suite

.. testsetup::

   from cheroot.server import HTTPServer

>>> 'HTTPServer' in globals()
True
    N)	lru_cache   )connectionserrors__version__)bton)IS_PPC)
threadpool)MakeFileStreamWriter)
HTTPRequestHTTPConnection
HTTPServerHeaderReaderDropUnderscoreHeaderReaderSizeCheckWrapperKnownLengthRFileChunkedRFileGatewayget_ssl_adapter_classWindowsSERVER_SOFTWARE zGoogle App Engine/F)NNAF_INET6IPPROTO_IPV6)   IPV6_V6ONLY   SO_PEERCRED         
s   
   	       :   ;       *   /s   %2Fs   (?i))s   Accepts   Accept-Charsets   Accept-Encodings   Accept-Languages   Accept-Rangess   Allows   Cache-Control
   Connections   Content-Encodings   Content-Language   Expects   If-Matchs   If-None-Matchs   Pragmas   Proxy-Authenticates   TEs   Trailer   Transfer-Encodings   Upgrades   Varys   Vias   Warnings   WWW-Authenticate
statisticsc                   $    e Zd ZdZddZd Zd Zy)r   z`Object for reading headers from an HTTP request.

    Interface and default implementation.
    Nc                    |i }	 |j                         }|st        d      |t        k(  r	 |S |j                  t              st        d      |dd t        t
        fv r|j                         }n=	 |j                  t        d      \  }}|j                         }| j                  |      }|}| j                        s|t        v r&|j                        }|rdj                  ||f      }||<   # t        $ r t        d      w xY w)a  
        Read headers from the given stream into the given header dict.

        If hdict is None, a new header dict is created. Returns the populated
        header dict.

        Headers which are repeated are folded together using a comma if their
        specification so dictates.

        This function raises ValueError when the read bytes violate the HTTP
        spec.
        You should probably return "400 Bad Request" if this happens.
        NIllegal end of headers.HTTP requires CRLF terminatorsr   zIllegal header line.s   , )readline
ValueErrorCRLFendswithSPACETABstripsplitCOLON_transform_key_allow_headercomma_separated_headersgetjoin)selfrfilehdictlinevkhnameexistings           #/opt/Tautulli/lib/cheroot/server.py__call__zHeaderReader.__call__   s    =E>>#D !:;;t|: 9 ==& !ABBBQxE3<' JJL=::eQ/DAq GGI''*%%a(++ 99U+

Ha=1AE%LG , " =$%;<<=s   2C4 4D	c                      y)NT r@   key_names     rH   r<   zHeaderReader._allow_header   s    r'   c                 >    |j                         j                         S N)r8   titlerL   s     rH   r;   zHeaderReader._transform_key   s    ~~%%''r'   rO   )__name__
__module____qualname____doc__rI   r<   r;   rK   r'   rH   r   r      s    
6p(r'   r   c                   "     e Zd ZdZ fdZ xZS )r   zDCustom HeaderReader to exclude any headers with underscores in them.c                 :    t         t        |   |      }|xr d|vS )N_)superr   r<   )r@   rM   orig	__class__s      rH   r<   z(DropUnderscoreHeaderReader._allow_header   s%    /DXN+8++r'   )rQ   rR   rS   rT   r<   __classcell__)rZ   s   @rH   r   r      s    N, ,r'   r   c                   J    e Zd ZdZd Zd ZddZddZddZd Z	d	 Z
d
 ZeZy)r   zWraps a file-like object, raising MaxSizeExceeded if too large.

    :param rfile: ``file`` of a limited size
    :param int maxlen: maximum length of the file being read
    c                 .    || _         || _        d| _        y)z%Initialize SizeCheckWrapper instance.r   N)rA   maxlen
bytes_read)r@   rA   r^   s      rH   __init__zSizeCheckWrapper.__init__  s    
r'   c                 x    | j                   r.| j                  | j                   kD  rt        j                         y y rO   )r^   r_   r   MaxSizeExceededr@   s    rH   _check_lengthzSizeCheckWrapper._check_length  s.    ;;4??T[[8((** 9;r'   Nc                     | j                   j                  |      }| xj                  t        |      z  c_        | j	                          |S )Read a chunk from ``rfile`` buffer and return it.

        :param size: amount of data to read
        :type size: int

        :returns: chunk from ``rfile``, limited by size if specified
        :rtype: bytes
        )rA   readr_   lenrd   r@   sizedatas      rH   rg   zSizeCheckWrapper.read  s9     zzt$3t9$r'   c                    |K| j                   j                  |      }| xj                  t        |      z  c_        | j	                          |S g }	 | j                   j                  d      }| xj                  t        |      z  c_        | j	                          |j                  |       t        |      dk  s|dd t        k(  rt        j                  |      S )Read a single line from ``rfile`` buffer and return it.

        :param size: minimum amount of data to read
        :type size: int

        :returns: one line from ``rfile``
        :rtype: bytes
        N   )	rA   r2   r_   rh   rd   appendLFEMPTYr?   )r@   rj   rk   ress       rH   r2   zSizeCheckWrapper.readline  s     ::&&t,DOOs4y(O K ::&&s+DOOs4y(O JJt4y3$rs)r/zz#& r'   c                     d}g }| j                  |      }|rB|j                  |       |t        |      z  }d|cxk  r|k  r	 |S  | j                  |      }|rB|S zRead all lines from ``rfile`` buffer and return them.

        :param sizehint: hint of minimum amount of data to read
        :type sizehint: int

        :returns: lines of bytes read from ``rfile``
        :rtype: list[bytes]
        r   r2   rp   rh   r@   sizehinttotallinesrC   s        rH   	readlineszSizeCheckWrapper.readlines9  m     }}X&LLSYE8$u$ %==*D  r'   c                 8    | j                   j                          yz*Release resources allocated for ``rfile``.NrA   closerc   s    rH   r   zSizeCheckWrapper.closeN      

r'   c                     | S zReturn file iterator.rK   rc   s    rH   __iter__zSizeCheckWrapper.__iter__R      r'   c                     t        | j                        }| xj                  t        |      z  c_        | j	                          |S zGenerate next file chunk.)nextrA   r_   rh   rd   r@   rk   s     rH   __next__zSizeCheckWrapper.__next__V  s3    DJJ3t9$r'   rO   r   )rQ   rR   rS   rT   r`   rd   rg   r2   r{   r   r   r   r   rK   r'   rH   r   r      s6    +'6* Dr'   r   c                   D    e Zd ZdZd Zd
dZd
dZddZd Zd Z	d	 Z
e
Zy)r   zWraps a file-like object, returning an empty string when exhausted.

    :param rfile: ``file`` of a known size
    :param int content_length: length of the file being read
    c                      || _         || _        y)z%Initialize KnownLengthRFile instance.N)rA   	remaining)r@   rA   content_lengths      rH   r`   zKnownLengthRFile.__init__g  s    
'r'   Nc                     | j                   dk(  ry|| j                   }nt        || j                         }| j                  j                  |      }| xj                   t	        |      z  c_         |S )zRead a chunk from ``rfile`` buffer and return it.

        :param size: amount of data to read
        :type size: int

        :rtype: bytes
        :returns: chunk from ``rfile``, limited by size if specified
        r   r'   )r   minrA   rg   rh   ri   s      rH   rg   zKnownLengthRFile.readl  sZ     >>Q<>>DtT^^,Dzzt$#d)#r'   c                     | j                   dk(  ry|| j                   }nt        || j                         }| j                  j                  |      }| xj                   t	        |      z  c_         |S )rm   r   r'   )r   r   rA   r2   rh   ri   s      rH   r2   zKnownLengthRFile.readline  s\     >>Q<>>DtT^^,Dzz""4(#d)#r'   c                     d}g }| j                  |      }|rB|j                  |       |t        |      z  }d|cxk  r|k  r	 |S  | j                  |      }|rB|S ru   rv   rw   s        rH   r{   zKnownLengthRFile.readlines  r|   r'   c                 8    | j                   j                          yr~   r   rc   s    rH   r   zKnownLengthRFile.close  r   r'   c                     | S r   rK   rc   s    rH   r   zKnownLengthRFile.__iter__  r   r'   c                 l    t        | j                        }| xj                  t        |      z  c_        |S r   )r   rA   r   rh   r   s     rH   r   zKnownLengthRFile.__next__  s'    DJJ#d)#r'   rO   r   )rQ   rR   rS   rT   r`   rg   r2   r{   r   r   r   r   rK   r'   rH   r   r   `  s1    (
((* Dr'   r   c                   B    e Zd ZdZd
dZd ZddZddZddZd Z	d	 Z
y)r   a  Wraps a file-like object, returning an empty string when exhausted.

    This class is intended to provide a conforming wsgi.input value for
    request entities that have been encoded with the 'chunked' transfer
    encoding.

    :param rfile: file encoded with the 'chunked' transfer encoding
    :param int maxlen: maximum length of the file being read
    :param int bufsize: size of the buffer used to read the file
    c                 `    || _         || _        d| _        t        | _        || _        d| _        y)z!Initialize ChunkedRFile instance.r   FN)rA   r^   r_   rr   bufferbufsizeclosed)r@   rA   r^   r   s       rH   r`   zChunkedRFile.__init__  s,    
r'   c                    | j                   ry | j                  j                         }| xj                  t	        |      z  c_        | j
                  r9| j                  | j
                  kD  r t        j                  d| j
                        |j                         j                  t        d      }	 |j                  d      }t        |d      }|dk  rd| _         y | j
                  r'| j                  |z   | j
                  kD  rt        d      | j                  j!                  |      }| xj                  t	        |      z  c_        | xj"                  |z  c_        | j                  j!                  d      }|t$        k7  rt        d	t'        |      z   d
z         y # t        $ r t        dj                              w xY w)NRequest Entity Too Larger   r      z)Bad chunked transfer size: {chunk_size!r})
chunk_sizeT   z2Bad chunked transfer coding (expected '\r\n', got ))r   rA   r2   r_   rh   r^   r   rb   r8   r9   	SEMICOLONpopintr3   formatIOErrorrg   r   r4   repr)r@   rC   r   chunkcrlfs        rH   _fetchzChunkedRFile._fetch  sy   ;;zz""$3t9$;;4??T[[8((*DKK  zz|!!)Q/	!JZ,J ?DK ;;4??Z7$++E455


+3u:%uzzq!4<d$&)*  )  	;*- 	s   0F %F?Nc                 :   t         }|dk(  r|S 	 |rt        |      |k\  r|S | j                  s| j                          | j                  s|S |r5|t        |      z
  }|| j                  d| z  }| j                  |d | _        n|| j                  z  }t         | _        )rf   r   N)rr   rh   r   r   )r@   rj   rk   r   s       rH   rg   zChunkedRFile.read  s     19KD	T);;{{K 3t9,	JY//"kk)*5##! r'   c                 Z   t         }|dk(  r|S 	 |rt        |      |k\  r|S | j                  s| j                          | j                  s|S | j                  j	                  t
              }|ry|dk(  r5|t        |      z
  }|| j                  d| z  }| j                  |d | _        nt        |t        |      z
  |      }|| j                  d| z  }| j                  |d | _        nF|dk(  r|| j                  z  }t         | _        n&|| j                  d| z  }| j                  |d | _        )rm   r   ro   N)rr   rh   r   r   findrq   r   )r@   rj   rk   newline_posr   s        rH   r2   zChunkedRFile.readline  s     19KD	T);;{{K++**2.K"$ $s4y 0IDKK
33D"&++ij"9DK #D3t9$4k BIDKK
33D"&++ij"9DK"$DKK'D"'DKDKK55D"&++kl";DK5 r'   c                     d}g }| j                  |      }|rB|j                  |       |t        |      z  }d|cxk  r|k  r	 |S  | j                  |      }|rB|S ru   rv   rw   s        rH   r{   zChunkedRFile.readlinesD  r|   r'   c              #     K   | j                   st        d      	 | j                  j                         }|st        d      | xj                  t        |      z  c_        | j                  r$| j                  | j                  kD  rt        d      |t        k(  ry|j                  t              st        d      | w)zhRead HTTP headers and yield them.

        :yields: CRLF separated lines
        :ytype: bytes

        z:Cannot read trailers until the request body has been read.r0   r   r1   N)
r   r3   rA   r2   r_   rh   r^   r   r4   r5   )r@   rC   s     rH   read_trailer_lineszChunkedRFile.read_trailer_linesY  s      {{L  ::&&(D !:;;OOs4y(O{{t<899t|==& !ABBJ! s   B=B?c                 8    | j                   j                          yr~   r   rc   s    rH   r   zChunkedRFile.closew  r   r'   )i    rO   r   )rQ   rR   rS   rT   r`   r   rg   r2   r{   r   r   rK   r'   rH   r   r     s-    	)V$@(<T*<r'   r   c                       e Zd ZdZdZ	 dZ	 i Z	 g Z	 dZ	 dZ		 dZ
	  e       Z	 ddZd Zd Zd Zd Zdd	Zd
 Zd Zd Zy)r   zrAn HTTP Request (and response).

    A single HTTP connection may consist of multiple request/response pairs.
    NFc                 `   || _         || _        d| _        d| _        d| _        | j                   j
                  d| _        d| _        i | _        d| _        g | _	        d| _
        | j                  j                  | _        d| _        | j                  j                  | _        || _        || _        y)a  Initialize HTTP request container instance.

        Args:
            server (HTTPServer): web server object receiving this request
            conn (HTTPConnection): HTTP connection object for this request
            proxy_mode (bool): whether this HTTPServer should behave as a PROXY
            server for certain requests
            strict_mode (bool): whether we should return a 400 Bad Request when
            we encounter a request that a HTTP compliant client should not be
            making
        Fs   httpNs   httpszHTTP/1.0r   )serverconnreadystarted_requestschemessl_adapterresponse_protocol	inheadersstatus
outheaderssent_headersrZ   close_connectionchunked_readchunked_write
proxy_modestrict_mode)r@   r   r   r   r   s        rH   r`   zHTTPRequest.__init__  s     	
$;;""."DK!+! $ ? ?!!^^99$&r'   c                    t        | j                  j                  | j                  j                        | _        	 | j                         }|sy	 | j                         }|syd| _
        y# t        j                  $ r | j                  dd       Y yw xY w# t        j                  $ r | j                  dd       Y yw xY w)z;Parse the next HTTP request start-line and message-headers.Nz414 Request-URI Too LongzHThe Request-URI sent with the request exceeds the maximum allowed bytes.413 Request Entity Too LargezCThe headers sent with the request exceed the maximum allowed bytes.T)r   r   rA   r   max_request_header_sizeread_request_liner   rb   simple_responseread_request_headersr   )r@   successs     rH   parse_requestzHTTPRequest.parse_request  s    %IIOOKK//

	,,.G 	//1G 
1 %% 	  *!
 	 %% 	  .!
 	s#   A* B *%BB%B=<B=c                 	   | j                   j                         }d| _        |sy|t        k(  r| j                   j                         }|sy|j	                  t              s| j                  dd       y	 |j                         j                  t        d      \  }}}|j                  d      s| j                  dd       y|dd	 j                  d
d      }t        |      dk7  r| j                  dd       yt        t        t        |            }|dkD  r| j                  dd       y	 || _        |j#                         | _        | j&                  r$|| j$                  k7  rd}| j                  d|       y	 t(        j*                  j-                  |      \  }}}	}
}|xs |}| j$                  dk(  r| j0                  r|r|n|	}	n| j$                  dk(  r| j0                  s| j                  d       yt(        j*                  j-                  dj3                  d|f            }|\  }}}}}t4        }	 |j6                  }||k7  xs | xs t9        ||||f      }|r| j                  dd       y|x}}	t4        x}x}
}n| j&                  xr | j0                   xr |}|r	 | j                  dd       y| j&                  xr |j                  t:               xr | }|r	 d}| j                  d|       y|r| j                  dd       y|	| j                  dd       y	 t<        j                  |	      D cg c]!  }t(        j*                  j?                  |      # }}tB        j3                  |      }	|	j                  t:              s	t:        |	z   }	|t4        ur|| _"        || _#        |	| _$        |
| _%        t        | jL                  jN                  d         t        | jL                  jN                  d         f}|d   |d   k7  r| j                  d       y|| _(        dtS        ||      z  | _*        y# t        t        f$ r | j                  dd       Y yw xY w# t.        $ r | j                  dd       Y yw xY w# t        $ r Y Gw xY wc c}w # t        $ r)}| j                  d|j@                  d          Y d	}~yd	}~ww xY w) zRead and parse first line of the HTTP request.

        Returns:
            bool: True if the request line is valid or False if it's malformed.

        TF400 Bad Requestr1   r   s   HTTP/z$Malformed Request-Line: bad protocol   N   .r   z#Malformed Request-Line: bad version)r   r   z505 HTTP Version Not SupportedzCannot fulfill requestzMalformed Request-LinezMalformed method name: According to RFC 2616 (section 5.1.1) and its successors RFC 7230 (section 3.1.1) and RFC 7231 (section 4.1) method names are case-sensitive and uppercase.zMalformed Request-URIs   OPTIONSs   CONNECTz405 Method Not Allowedr'   s   //zFInvalid path in Request-URI: request-target must match authority-form.z2Absolute URI not allowed if server is not a proxy.zInvalid path in Request-URI: request-target must contain origin-form which starts with absolute-path (URI starting with a slash "/").z!Illegal #fragment in Request-URI.zInvalid path in Request-URI.r      z
HTTP/%s.%s)+rA   r2   r   r4   r5   r   r8   r9   r6   
startswithrh   tuplemapr   r3   
IndexErroruriuppermethodr   urllibparseurlsplitUnicodeErrorr   r?   rr   portanyFORWARD_SLASHQUOTED_SLASH_REGEXunquote_to_bytesargsQUOTED_SLASHr   	authoritypathqsr   protocolrequest_protocolr   r   )r@   request_liner   r   req_protocolrprespr   r   r   r   fragmenturi_is_absolute_form	uri_split_scheme
_authority_path_qs	_fragment_portinvalid_pathdisallowed_absolutexatomsexsps                             rH   r   zHTTPRequest.read_request_line  s    zz**,  $4
  ::..0L$$T*  !#C 	(4(:(:(<(B(B5!(L%FC**84$$%'M ab!''a0B2w!|$$%'L s3|$BF{$$46N 	  lln$++ 5A    !2D9	4:LL4I4I#4N1FItR
 !' 3);;*$
 OO(<  	  [[J&??$$%=> --chhs|.DEI9B6GZYE! c! 999Y78 
 $$%8
 ))I%**F*R(    )')(  
 # C$$%H     -}55-,, 
  >2 
 $$%6=$$%7 |$$%2 	
 055d; LL11!4   $$U+D}- 4'D DK"	  %%a()3t{{/C/CA/F+GGa5BqE>  !AB ,!-B!;S J' 	  !24LM	&  	  !24KL	6  b  $$%6
Csm   4AP.  5P. 60P. 5%Q /Q6 R 2&RR .!QQQ32Q36	RRR 	R=R88R=c                 `   	 | j                  | j                  | j                         | j                  j                  }	 t        | j                  j                  dd            }|r||kD  r| j	                  dd       y| j                  d	k(  r'| j                  j                  d
d      dk(  r.d| _        n&| j                  j                  d
d      dk7  rd| _        d}| j                  d	k(  rh| j                  j                  d      }|rK|j                  d      D cg c]1  }|j                         s|j                         j                         3 }}d| _        |r-|D ](  }|dk(  rd| _        | j	                  d       d| _         y | j                  j                  dd      dk(  rldj!                  | j                  j"                  j%                  d      t&        dt(        t(        f      }	 | j*                  j,                  j/                  |       yy# t        $ r)}| j	                  d|j
                  d          Y d}~yd}~ww xY w# t        $ r | j	                  dd       Y yw xY wc c}w # t0        j2                  $ r*}|j
                  d   t4        j6                  vr Y d}~yd}~ww xY w)zRead ``self.rfile`` into ``self.inheaders``.

        Ref: :py:attr:`self.inheaders <HTTPRequest.outheaders>`.

        :returns: success status
        :rtype: bool
        r   r   NF   Content-Lengthz Malformed Content-Length Header.r   CThe entity sent with the request exceeds the maximum allowed bytes.HTTP/1.1r*   r'      closeT
   Keep-Aliver,      ,   chunkedz501 Unimplementedr+   s   100-continueasciis   100 Continue)header_readerrA   r   r3   r   r   r   max_request_body_sizer   r>   r   r   r9   r8   lowerr   r?   r   encoder6   r4   r   wfilewritesocketerrorr   socket_errors_to_ignore)r@   r   mrbsclter   encmsgs           rH   r   z HTTPRequest.read_request_headers  su   	tzz4>>:
 {{00	T^^''(91=>B BI  .!
  !!Z/~~!!-5A(,% ~~!!-5F(,% !!Z/##$89B13$MA1779aggioo'MM! !*$(,D% (()<=,0D) !6 >>i-@ (($$++G4e_d C		%%c* g  	  !2BGGAJ?	  	  !2 	< NT << 771:V%C%CC DsL   &H %I
 I+1 I+.%I0 	III
I('I(0J- J((J-c                 f   | j                   j                  }| j                  r&t        | j                  j
                  |      | _        npt        | j                  j                  dd            }|r$||k  r| j                  s| j                  dd       yt        | j                  j
                  |      | _        | j                   j                  |       j                          | j                  xr | j                          | j                   r&| j                  j"                  j%                  d       yy)z/Call the gateway and write its iterable output.r   r   r   r   Ns   0

)r   r  r   r   r   rA   r   r   r>   r   r   r   gatewayrespondr   ensure_headers_sentr   r	  r
  )r@   r  r  s      rH   r  zHTTPRequest.respond(  s    {{00%diioot<DJT^^''(91=>Br	((((61
 )$))//2>DJD!))+

1t//1IIOO!!,/ r'   c                    t        |      }| j                  j                  d|d}dt        |      z  }d}|j	                  d      |j	                  d      |j	                  d      g}|dd dv r*d	| _        | j                  d
k(  r|j                  d       nd}|j                  t               |r2t        |t               r|j	                  d      }|j                  |       	 | j                  j                  j                  t        j                  |             y# t        j                   $ r*}|j"                  d   t$        j&                  vr Y d}~yd}~ww xY w)z+Write a simple response back to the client. z
zContent-Length: %s
zContent-Type: text/plain

ISO-8859-1N   )413414Tr   s   Connection: close
r   r   )strr   r   rh   r  r   r   rp   r4   
isinstancer   r	  r
  rr   r?   r  r  r   r   r  )r@   r   r  proto_statusr   content_typebufr   s           rH   r   zHTTPRequest.simple_response?  s'   V&*kk&:&:FC1CH<5-!!,/-
 "1:'$(D!%%3 

34 +

4#s#jj.JJsO	IIOO!!%**S/2|| 	wwqz!?!?? @	s   %8D E1 EEc                 L    | j                   sd| _         | j                          yy)z:Ensure headers are sent to the client if not already sent.TN)r   send_headersrc   s    rH   r  zHTTPRequest.ensure_headers_sentd  s$       $D !r'   c                 D   | j                   ro|rmt        t        |            dd j                  d      }|t        |t        g}| j
                  j                  j                  t        j                  |             y| j
                  j                  j                  |       y)z$Write unbuffered data to the client.r   Nr  )
r   hexrh   r  r4   r   r	  r
  rr   r?   )r@   r   chunk_size_hexr!  s       rH   r
  zHTTPRequest.writej  sn    % U_QR077@N!45CIIOO!!%**S/2IIOO!!%(r'   c                    | j                   D cg c]  \  }}|j                          }}}t        | j                  dd       }|dk(  rd| _        nZd|vrV|dk  s|dv rnL| j
                  dk(  xr | j                  d	k7  }|r#d| _        | j                   j                  d
       nd| _        | j                  s| j                  j                  }| | _        d|vr^| j
                  dk(  r(| j                  rC| j                   j                  d       n'| j                  s| j                   j                  d       d| j                   v rP| j                   j                  ddj                  | j                  j                        j                  d      f       | j                  sC| j                  s7t        | j                   dd      }|dkD  r| j                   j#                  |       d|vrJ| j                   j                  dt$        j&                  j)                  d      j                  d      f       d|vr@| j                   j                  d| j                  j*                  j                  d      f       | j                  j,                  j                  d      }|t.        z   | j                  z   t0        z   g}	| j                   D ].  \  }
}|	j                  |
t2        z   t.        z   |z   t0        z          0 |	j                  t0               | j4                  j6                  j9                  t:        j=                  |	             yc c}}w )zAssert, process, and send the HTTP response message-headers.

        You must set ``self.status``, and :py:attr:`self.outheaders
        <HTTPRequest.outheaders>` before calling this.
        Nr  i  Ts   content-length   )      i0  r   s   HEAD)r,   r  s
   connection)r*   r   )r*   r  r  ztimeout={connection_timeout})connection_timeoutr  r   r   s   dates   Date)usegmts   servers   Serverr  )r   r  r   r   r   r   r   r   rp   r   can_add_keepalive_connectionr   timeoutr  r   getattrrA   rg   emailutils
formatdateserver_namer   r6   r4   r:   r   r	  r
  rr   r?   )r@   keyvaluehkeysr   needs_chunkedcan_keepr   protor!  rE   rD   s               rH   r#  zHTTPRequest.send_headerss  s    04?e??T[[!_%S=$(D!e+ |v8 **j8 /w.  !)-D&OO**+MN -1D) $${{??H(0LD!%%%3((OO**+DE ,,OO**+IJ)T__<OO""/$++*=*=>|$	$  %%0A0A  

K;I1}

	*%OO""&&d&3::<H$ 
 E!OO""''..|<$ 
 $$++G4u}t{{*T12OO 	5DAqJJq5y5(1,t34	5

4		ejjo.g @s   M)FT)r   )rQ   rR   rS   rT   r   r   r   r   r   r   r   r   r  r`   r   r   r   r  r   r  r
  r#  rK   r'   rH   r   r   |  s    
 F@DDI$J;E@  M< !NM'B DaF^@0.#J )Y/r'   r   c                       e Zd ZdZdZdZdZej                  Z	ej                  Z
eZdZdZdZefdZd ZdZd Zd Zd Zd	 Zed
        Zed        Zed        Zd Zed        Zed        Zd Zy)r   z#An HTTP connection (active socket).NFc                    || _         || _         ||d| j                        | _         ||d| j                        | _        d| _        | j                   j                  | _        | j                   j                  | _         t        d      | j                        | _
         t        d      | j                        | _        y)aB  Initialize HTTPConnection instance.

        Args:
            server (HTTPServer): web server object receiving this request
            sock (socket._socketobject): the raw socket object (usually
                TCP) for this connection
            makefile (file): a fileobject class for reading from the socket
        rbwbr   r   )maxsizeN)r   r  rbufsizerA   wbufsizer	  requests_seenpeercreds_enabledpeercreds_resolve_enabledr   resolve_peer_credsget_peer_creds)r@   r   sockmakefiles       rH   r`   zHTTPConnection.__init__  s     dD$--8
dD$--8
!%!>!>)-)N)N&
 !Ia !8!89 	 !Ia !4!45 	r'   c                    d}	 | j                  | j                  |       }|j                          | j                  j                  d   r| xj                  dz  c_        |j
                  syd}|j                          |j                  sy	 y# t        j                  $ r}|j                  d   }d}||v r#|rr{|j                  ro| j                  d       n\|t        j                  vrJ| j                  j                  dt!        |      z  t"        j$                  d	       | j                  d
       Y d}~yd}~wt&        t(        f$ r  t        j*                  $ r Y yt        j,                  $ r | j/                         Y yt0        $ rQ}| j                  j                  t!        |      t"        j2                  d	       | j                  d
       Y d}~yd}~ww xY w)zrRead each request and respond appropriately.

        Returns true if the connection should be kept open.
        FEnabledr   Tr   )z	timed outzThe read operation timed outz408 Request Timeoutzsocket.error %slevel	tracebackz500 Internal Server ErrorN)RequestHandlerClassr   r   statsrA  r   r  r   r  r  r   r   _conditional_errorr   r  	error_logr   loggingWARNINGKeyboardInterrupt
SystemExitFatalSSLAlert
NoSSLError_handle_no_ssl	ExceptionERROR)r@   request_seenreqr   errnumtimeout_errss         rH   communicatezHTTPConnection.communicate  s   
 *	F**4;;=C{{  +""a'"99 LKKM'' (< 9 || 	JWWQZFFL%
 %##2E2E++C1FGv===%%%V4!//T &  ''-HI  ":. 	## 	     	%$   	FKK!!R "  ##C)DEE	Fs8   A&B +B GBD88%G#GGAGGc                    |r|j                   ry 	 | j                  j                  }t        |d| j                        | _        d}|j                  d|       d| _	        y # t        $ r | j                  j                  }Y Yw xY w)Nr=  zUThe client sent a plain HTTP request, but this server only speaks HTTPS on this port.r   T)
r   r  _sockAttributeError_socketr   r@  r	  r   linger)r@   r[  	resp_sockr  s       rH   rW  zHTTPConnection._handle_no_ssl.  s~    c&&	,))I ")T4==A
: 	 	-s3  	,++I	,s   A B Bc                     |r|j                   ry	 |j                  |       y# t        j                  $ r Y yt        j                  $ r | j                  |       Y yw xY w)zvRespond with an error.

        Don't bother writing if a response
        has already started being written.
        N)r   r   r   rU  rV  rW  )r@   r[  responses      rH   rO  z!HTTPConnection._conditional_error?  sY     c&&	%)## 	   	%$	%s   # A#AAc                     | j                   j                          | j                  s+| j                          | j                  j                          yy)z,Close the socket underlying this connection.N)rA   r   rc  _close_kernel_socketr  rc   s    rH   r   zHTTPConnection.closeO  s<    

{{%%' KK r'   c                    d}t         s'| j                  j                  t        j                  k7  rt	        d      | j
                  st        d      	 | j                  j                  t        j                  t        j                  t        j                  |            }t        j                  ||      \  }}}|||fS # t        j                  $ r}	 t        |d}~ww xY w)a  Return the PID/UID/GID tuple of the peer socket for UNIX sockets.

        This function uses SO_PEERCRED to query the UNIX PID, UID, GID
        of the peer, which is only available if the bind address is
        a UNIX domain socket.

        Raises:
            NotImplementedError: in case of unsupported socket type
            RuntimeError: in case of SO_PEERCRED lookup unsupported or disabled

        3iz5SO_PEERCRED is only supported in Linux kernel and WSLz0Peer creds lookup is disabled within this serverN)
IS_WINDOWSr  familyAF_UNIXNotImplementedErrorrB  RuntimeError
getsockopt
SOL_SOCKETr   structcalcsizeunpackr  )r@   PEERCRED_STRUCT_DEF
peer_credspiduidgid
socket_errs          rH   rE  zHTTPConnection.get_peer_credsb  s     #++v~~=%G  ''B 	!// !!6#5#5 34	J  #MM*=zJMCcS=  || 	/ J.	/s   AB> >CCCc                 .    | j                         \  }}}|S )z,Return the id of the connected peer process.rE  )r@   rw  rW   s      rH   peer_pidzHTTPConnection.peer_pid  s     '')	Q
r'   c                 .    | j                         \  }}}|S )z1Return the user id of the connected peer process.r|  )r@   rW   rx  s      rH   peer_uidzHTTPConnection.peer_uid  s     '')	3
r'   c                 .    | j                         \  }}}|S )z2Return the group id of the connected peer process.r|  )r@   rW   ry  s      rH   peer_gidzHTTPConnection.peer_gid  s     '')	1c
r'   c                     t         st        d      | j                  st        d      t	        j
                  | j                        j                  }t        j                  | j                        j                  }||fS )a  Look up the username and group tuple of the ``PEERCREDS``.

        :returns: the username and group tuple of the ``PEERCREDS``

        :raises NotImplementedError: if the OS is unsupported
        :raises RuntimeError: if UID/GID lookup is unsupported or disabled
        zUID/GID lookup is unavailable under current platform. It can only be done under UNIX-like OS but not under the Google App Enginez-UID/GID lookup is disabled within this server)IS_UID_GID_RESOLVABLErn  rC  ro  pwdgetpwuidr  pw_namegrpgetgrgidr  gr_name)r@   usergroups      rH   rD  z!HTTPConnection.resolve_peer_creds  sp     %%6 
 //?  ||DMM*22T]]+33U{r'   c                 ,    | j                         \  }}|S )z2Return the username of the connected peer process.rD  )r@   r  rW   s      rH   	peer_userzHTTPConnection.peer_user  s     ))+ar'   c                 ,    | j                         \  }}|S )z/Return the group of the connected peer process.r  )r@   rW   r  s      rH   
peer_groupzHTTPConnection.peer_group  s     **,5r'   c                 *   t        | j                  d| j                  j                        }	  |t        j                         y# t        j
                  $ r Y yt        j                  $ r'}|j                  t        j                  vr Y d}~yd}~ww xY w)z0Terminate the connection at the transport level.sock_shutdownN)	r/  r  shutdown	SHUT_RDWRr   #acceptable_sock_shutdown_exceptionsr  errno$acceptable_sock_shutdown_error_codes)r@   r  es      rH   rh  z#HTTPConnection._close_kernel_socket  sw     KKKK  

	V%%&99 	|| 	wwfIII J	s   A BB+BB) rQ   rR   rS   rT   remote_addrremote_portssl_envioDEFAULT_BUFFER_SIZEr?  r@  r   rM  rB  rC  	last_usedr   r`   r^  rc  rW  rO  r   rE  propertyr}  r  r  rD  r  r  rh  rK   r'   rH   r   r     s    -KKG%%H%%H% % I.6 
61f F"% &)!V  
  
  
0  
  
r'   r   c                      e Zd ZdZdZdZdZ	 dZ	 dZ	 dZ		 dZ
	 dZ	 dZ	 dZ	 dZ	 dj                  e	      Z	 dZ	 d
Z	 dZ	 dZ	 dZ	 eZ	 dZ	 d
Z	 d
Z	 d
Z	 dZ	 	 	 	 d&dZd Zd Z d Z!e"d        Z#e#jH                  d        Z#d Z%d Z&d Z'd Z(e)jT                  d        Z+e"d        Z,d Z-d'dZ.d(dZ/d Z0e1d        Z2e3	 d)d       Z4e1d        Z5e1d         Z6d! Z7e"d"        Z8e"d#        Z9e8jH                  d$        Z8d% Z:y)*r   zAn HTTP server.z	127.0.0.1Nr   r   
   g      ?zCheroot/{version!s})versionFr   Tc	                     || _         || _        t        j                  | |xs d|      | _        |s| j
                  }|| _        || _        |xr || _        || _	        | j                          y)a  Initialize HTTPServer instance.

        Args:
            bind_addr (tuple): network interface to listen to
            gateway (Gateway): gateway for processing HTTP requests
            minthreads (int): minimum number of threads for HTTP thread pool
            maxthreads (int): maximum number of threads for HTTP thread pool
            server_name (str): web server name to be advertised via Server
                HTTP header
            reuse_port (bool): if True SO_REUSEPORT option would be set to
                socket
        r   )r   maxN)	bind_addrr  r
   
ThreadPoolrequestsr  r3  rB  rC  
reuse_portclear_stats)	r@   r  r  
minthreads
maxthreadsr3  rB  rC  r  s	            rH   r`   zHTTPServer.__init__3  ss    $ #"--joA:
 ,,K&!2%;*; 	& %r'   c                     d _         d _        i ddd fdd fdd	dd
 fdd fdd fdd fddddd dd dd dd dd dd di  _         j                  t        j                  d t               z  <   y)!zReset server stat counters..Nr   rI  FzBind Addressc                 .    t        j                        S rO   )r   r  sr@   s    rH   <lambda>z(HTTPServer.clear_stats.<locals>.<lambda>\  s    d4>>&: r'   zRun timec                 <    | d    xr dxs j                         S )NrI  ro   runtimer  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>]  s    q|#3";"Mt||~ r'   AcceptszAccepts/secc                 0    | d   j                         z  S )Nr  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>_  s    Qy\DLLN%B r'   Queuec                 2    t        j                  dd       S )Nqsizer/  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>`  s    wt}}gtD r'   Threadsc                 D    t        t        j                  dg             S )N_threads)rh   r/  r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>a  s    WT]]J%K!L r'   zThreads Idlec                 2    t        j                  dd       S )Nidler  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>b  s    gdmmVT&J r'   zSocket ErrorsRequestsc                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   2   K   | ]  } |d    |        yw)r  NrK   .0ws     rH   	<genexpr>z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>e  s     Ha:q!H   Worker Threadsr   sumvaluesr  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>d  s8    q|#3"; #sH1-=+>+E+E+GH!@ r'   
Bytes Readc                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   2   K   | ]  } |d    |        yw)r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>h  s     J<#Jr  r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>g  s8    9%5$=2 %JQ/?-@-G-G-IJAB r'   Bytes Writtenc                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   2   K   | ]  } |d    |        yw)r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>k  s     M1#?#A&Mr  r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>j  s9    AiL(8'@b (CM2B0C0J0J0LME r'   	Work Timec                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   2   K   | ]  } |d    |        yw)r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>o  s     Iq;"Ir  r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>n  s8    )$4#<" $IA.>,?,F,F,HI1A r'   zRead Throughputc                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   R   K   | ]  } |d    |       |d   |      xs dz   ! yw)r  r  ư>NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>r  s8       $AlOA&.!K.*;*CtD   %'r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>q  s@    a	l*:)B *c/0779 	G r'   zWrite Throughputc                 b    | d    xr dxs$ t        d | d   j                         D        d      S )NrI  ro   c              3   R   K   | ]  } |d    |       |d   |      xs dz   ! yw)r  r  r  NrK   r  s     rH   r  z;HTTPServer.clear_stats.<locals>.<lambda>.<locals>.<genexpr>x  s9       'Ao&q)^Q{^A->-F$Gr  r  r   r  r  s    rH   r  z(HTTPServer.clear_stats.<locals>.<lambda>w  s@    q|+;*C +s/0779 	H r'   r  zCheroot HTTPServer %d)_start_time	_run_timerN  rQ  r-   idrc   s   `rH   r  zHTTPServer.clear_statsV  s   $
u$
:$
 M$
 q	$

 B$
 D$
 L$
 J$
 Q$
  $
  $
   !$
(  )$
.   /$
:  !;$
F bG$

J BF2RX=>r'   c                     | j                   | j                  S | j                  t        j                         | j                   z
  z   S )zReturn server uptime.)r  r  timerc   s    rH   r  zHTTPServer.runtime  s8    #>>!>>TYY[43C3C%CDDr'   c                 h    | j                   d| j                  j                  d| j                  dS )z1Render Server instance representing bind address..(r   )rR   rZ   rQ   r  rc   s    rH   __str__zHTTPServer.__str__  s(     OOT^^44NN
 	
r'   c                     | j                   S )a  Return the interface on which to listen for connections.

        For TCP sockets, a (host, port) tuple. Host values may be any
        :term:`IPv4` or :term:`IPv6` address, or any valid hostname.
        The string 'localhost' is a synonym for '127.0.0.1' (or '::1',
        if your hosts file prefers :term:`IPv6`).
        The string '0.0.0.0' is a special :term:`IPv4` entry meaning
        "any active interface" (INADDR_ANY), and '::' is the similar
        IN6ADDR_ANY for :term:`IPv6`.
        The empty string or :py:data:`None` are not allowed.

        For UNIX sockets, supply the file name as a string.

        Systemd socket activation is automatic and doesn't require tempering
        with this variable.

        .. glossary::

           :abbr:`IPv4 (Internet Protocol version 4)`
              Internet Protocol version 4

           :abbr:`IPv6 (Internet Protocol version 6)`
              Internet Protocol version 6
        )
_bind_addrrc   s    rH   r  zHTTPServer.bind_addr  s    4 r'   c                 V    t        |t              r|d   dv rt        d      || _        y)z5Set the interface on which to listen for connections.r   )r   NzzHost values of '' or None are not allowed. Use '0.0.0.0' (IPv4) or '::' (IPv6) instead to listen on all active interfaces.N)r  r   r3   r  )r@   r5  s     rH   r  zHTTPServer.bind_addr  s6     eU#aJ(> 6 
  r'   c                     	 | j                          y# t        $ r}| j                  }|s|| _        ||d}~wt        $ r}| j                  }|s|| _        ||d}~ww xY w)z4Run the server forever, and stop it cleanly on exit.N)startrS  	interruptrT  )r@   kb_intr_excunderlying_interruptsys_exit_excs       rH   
safe_startzHTTPServer.safe_start  sc    	9JJL  	8#'>> '!,#77 	9#'>> '!-$88		9s    	A4A AAc                    d| _         | j                  d| j                  z  | _        d| _        d}t	        j
                  dd      r9t        j                  dt        j                  t        j                        | _        nt        | j                  t        t        f      r	 | j                  | j                         nx| j                  \  }}	 t        j                  ||t        j                   t        j                  d	t        j"                        }|D ]  }|\  }	}
}}}	 | j)                  |	|
|        n | j                  st        j                  |      | j                  j-                  d       | j                  j/                  | j0                         t3        j4                  |       | _        | j8                  j;                          d| _        t?        j>                         | _         y# t        j                  $ r0}|d| j                  d|d}t        j                  |      |d}~ww xY w# t        j$                  $ rO t        j                  }| j                  }d
|v rt        j&                  }|dz   }|t        j                  d	d|fg}Y w xY w# t        j                  $ rC}|d|d|d}| j                  r| j                  j+                          d| _        Y d}~d}~ww xY w)zPrepare server to serving requests.

        It binds a socket's port, setups the socket to ``listen()`` and does
        other preparing things.
        Nz	%s ServerzNo socket could be created
LISTEN_PIDr  z -- (z: r   r   :)r   r   r   r   T)!
_interruptsoftwarer  r  osgetenvfromfdAF_INETSOCK_STREAMr  r  r  bytesbind_unix_socketr  getaddrinfo	AF_UNSPEC
AI_PASSIVEgaierrorr   bindr   
settimeoutlistenrequest_queue_sizer   ConnectionManager_connectionsr  r  r   r  r  )r@   r  serrhostr   info	sock_typer  rs   afsocktyper9  
_canonnamesas                 rH   preparezHTTPServer.prepare  sZ    == '$,,6DM *99\4( --6>>6;M;MNDKe52%%dnn5 JD$K))$ 0 0&&6+<+<  	'693HeZ'IIb(E2		' {{,,s## 	q!4223 (99$? 	
99;a << 2*-t~~tDll3'T12 ?? K"NN	 NN	$; &I )F 2I"F$6$62yIJK || '.12t<C{{))+"&DKK	'sD   !G+ AH1 J+H.>+H))H.1AJJK,)8K''K,c                    | j                   rK| j                  s?	 | j                  j                  | j                         | j                   r| j                  s?| j                  rG| j                  r"t        j                  d       | j                  r"| j                  r| j                  yy# t
        t        f$ r  t        $ r% | j                  dt        j                  d       Y w xY w)z1Serve requests, after invoking :func:`prepare()`.zError in HTTPServer.serveTrJ  g?N)r   r  r  runexpiration_intervalrS  rT  rX  rP  rQ  rY  _stopping_for_interruptr  sleeprc   s    rH   servezHTTPServer.serve  s    jj!!%%d&>&>? jj >>..

3 ..~~nn$   &z2  /w}}"  s   %B, ,:C)(C)c                 D    | j                          | j                          y)zmRun the server forever.

        It is shortcut for invoking :func:`prepare()` then :func:`serve()`.
        N)r  r  rc   s    rH   r  zHTTPServer.start+  s     	

r'   c              #      K   | j                          t        j                  | j                        }d|_        |j                          	 | | j                          y# | j                          w xY ww)z4Context manager for running this server in a thread.)targetTN)r  	threadingThreadr  daemonr  stop)r@   threads     rH   _run_in_threadzHTTPServer._run_in_thread7  sQ      	!!4	LIIKDIIKs   AA5A  A5 A22A5c                 J    | j                   xr | j                  j                  S )z>Flag whether it is allowed to add a new keep-alive connection.)r   r  r-  rc   s    rH   r-  z'HTTPServer.can_add_keepalive_connectionC  s     zzLd//LLLr'   c                 t    | j                   r| j                  j                  |       y|j                          y)z7Put an idle connection back into the ConnectionManager.N)r   r  putr   r@   r   s     rH   put_connzHTTPServer.put_connH  s(    ::!!$' JJLr'   c                 F   t         j                  j                  dj                  |             t         j                  j	                          |rRt        j                         }t         j                  j                  |       t         j                  j	                          yy)zWrite error message to log.

        Args:
            msg (str): error message
            level (int): logging level
            traceback (bool): add traceback to output or not
        z{msg!s}
)r  N)sysstderrr
  r   flush
traceback_
format_exc)r@   r  rK  rL  tbliness        rH   rP  zHTTPServer.error_logP  sl     	

+++45

 ++-GJJW%JJ r'   c           	          | j                  | j                  |||| j                  | j                  | j                        }| j                  || j                        x}| _        | j                  |      | _        |S )z.Create (or recreate) the actual socket object.)prepare_socketr  nodelayr   r  bind_socketr  resolve_real_bind_addr)r@   rl  typer9  rF  s        rH   r  zHTTPServer.bind`  sl    ""NND%LL$**OO	
 "--dDNNCCt{44T:r'   c           	         t         r	 t        d      d}	 t        j                  | j                         | j                  |t        j                  t        j                  d| j                  | j                  | j                  	      }	 	 t        j                  |j!                         |       d
}	 | j#                  ||      }| j)                  |      }	 	 |s	 t        j*                  ||       d
}|s!| j1                  dt2        j4                         || _        || _	        |S # t
        $ r Y t        $ r}t        |      }d|vr Y d}~d}~wt        $ r#}t        |      }d|vr	d|vrd|vr Y d}~Ad}~ww xY w# t
        $ r d}Y w xY w# t        j$                  $ r |j'                           w xY w# t,        $ r t        j.                  ||d       Y w xY w# t
        $ r Y w xY w)z*Create (or recreate) a UNIX socket object.z0AF_UNIX sockets are not supported under Windows.i  zJremove() argument 1 must be encoded string without null bytes, not unicodeNz'unlink: embedded null character in pathzembedded null bytez0argument must be a string without NUL charactersr   )r  rl  r-  r9  r*  r   r  TF)follow_symlinksz(Failed to set socket fs mode permissions)rK  )rk  r3   r  unlinkr  OSError	TypeErrorr  r)  r  rm  r  r*  r   r  fchmodfilenor+  r  r   r,  lchmodra  chmodrP  rQ  rR  )r@   r  fs_permissionstyp_errerr_msgval_errrF  FS_PERMS_SETs           rH   r  zHTTPServer.bind_unix_socketl  s    B  	IIdnn%0 "">>(:(:!LLd.>.>	 # 
	!BIIdkkm^4L	##D)4D
 //5			COIIi8  $ NN:oo  
 #C  	  	'lG="# 	#
  		'lG(/67,G;4;BC 		.  	! L	!
 || 	JJL	 & OHHYNO  		s}   D# 'E> 0F G F7 .G #	E;.E;6EE;E66E;>FF%F47!GG GG 	G*)G*c                 &   |d d \  }}|dk(  }| j                   t        j                  t        j                  fvrt	        d      |rt	        d      t        t        d      r0| j                  t        j                  t        j                  d       y t        t        d      r0| j                  t        j                  t        j                  d       y t        r0| j                  t        j                  t        j                  d       y t        d      )	Nr   r   zCannot reuse a non-IP socketz"Cannot reuse an ephemeral port (0)SO_REUSEPORT_LBr   SO_REUSEPORTz,Current platform does not support port reuse)rl  r  r  r   r3   hasattr
setsockoptrq  r=  r>  rk  SO_REUSEADDRrn  )socket_r  r  r   IS_EPHEMERAL_PORTs        rH   _make_socket_reusablez HTTPServer._make_socket_reusable  s    r]
d AI>>&..&//!BB;<<ABB 6,-v00&2H2H!LV^,v00&2E2EqIv00&2E2EqI%> r'   c                    t        j                   |||      }t        j                  |       |dd \  }	}
|
dk(  }|r| j                  ||       t        s2|s0	 |j                  t         j                  t         j                  d       |rEt        |t        t        f      s/|j                  t         j                  t         j                  d       ||j                  |      }t        t         d      xr |t         j                  k(  xr |	dv }|r2	 |j                  t         j                   t         j"                  d       |S |S # t$        t         j&                  f$ r Y |S w xY w)z%Create and prepare the socket object.Nr   r   rB  r  r   r   )z::z::0z	::0.0.0.0)r  r   prevent_socket_inheritancerD  rk  r@  rq  rA  r  r  r  IPPROTO_TCPTCP_NODELAYr  r?  r   r   r   ra  r  )clsr  rl  r-  r9  r*  r   r  rF  r  r   rC  listening_ipv6s                rH   r)  zHTTPServer.prepare_socket  sF    }}VT51..t4r]
d AI%%di%H/	 OOF--v/B/BAF:i#u>OOF..0B0BAF"##D)D FJ' 3&//)322 	
 ''););Q t #FLL1  s   /E EEc                 (    | j                  |       | S )z#Bind the socket to given interface.)r  rF  s     rH   r+  zHTTPServer.bind_socket  s     	Yr'   c                     | j                         }| j                  t        j                  t        j                  fv r	 |dd S t        |t              rt        |      }|S )z/Retrieve actual bind address from bound socket.Nr   )getsocknamerl  r  r  r   r  r  r   rF  s     rH   r,  z!HTTPServer.resolve_real_bind_addr  s]    
 '')	>>NNOO
 

 Ra= i'YIr'   c                     	 | j                   j                  |       y# t        j                  $ r |j	                          Y yw xY w)z#Process an incoming HTTPConnection.N)r  r  queueFullr   r  s     rH   process_connzHTTPServer.process_conn*  s5    	MMd#zz 	JJL	s    #AAc                     | j                   S )zFlag interrupt of the server.)r  rc   s    rH   r  zHTTPServer.interrupt2  s     r'   c                 &    | j                   t        u S )z8Return whether the server is responding to an interrupt.)r  _STOPPING_FOR_INTERRUPTrc   s    rH   r  z"HTTPServer._stopping_for_interrupt7  s     "999r'   c                     t         | _        t        |t              r| j	                  d       t        |t
              r| j	                  d       | j                          || _        y)a  Perform the shutdown of this server and save the exception.

        Typically invoked by a worker thread in
        :py:mod:`~cheroot.workers.threadpool`, the exception is raised
        from the thread running :py:meth:`serve` once :py:meth:`stop`
        has completed.
        z!Keyboard Interrupt: shutting downz SystemExit raised: shutting downN)rU  r  r  rS  rP  rT  r  )r@   r  s     rH   r  zHTTPServer.interrupt<  sJ     2i!23NN>?i,NN=>		#r'   c                 4   | j                   syd| _         | j                  4| xj                  t        j                         | j                  z
  z  c_        d| _        | j                  j                          t        | dd      }|rt        | j                  t        t        f      s	 |j                         dd \  }}t        j                  ||t        j                  t        j                        D ]X  }|\  }}}}}	d}
	 t        j                  |||      }
|
j!                  d       |
j#                  ||f       |
j%                          Z 	 t/        |d      r|j%                          d| _        | j                  j%                          | j0                  j                  | j2                         y# t        j&                  $ r |
r|
j%                          Y w xY w# t        j&                  $ r*}|j(                  d   t*        j,                  vr Y d}~d}~ww xY w)z5Gracefully shutdown a server that is serving forever.NFr  r   g      ?r   r   )r   r  r  r  r  r  r/  r  r  r  r  rN  r  r  r  r  r  connectr   r  r   r   r  r?  r  shutdown_timeout)r@   rF  r  r   rs   r  r	  r9  r
  _sar  r   s               rH   r  zHTTPServer.stopP  s   zz
'NNtyy{T-=-==>N tXt,dnnsEl;*!%!1!1!3BQ!7JD$  &11dF$4$4**  * @C<HeZ 
* &b(E BA LL-IItTl3GGI*" tW%

DK!4001  &|| *  !	*3 || wwqz)G)GG 	 Hs+   &G >AF//%GGH- HH)r  ro   NFFF)r      Fr   )F);rQ   rR   rS   rT   r  r  r  r  r  r3  r   r  rY  r.  r  r   r   r  r  r   r   r  r*  r   ConnectionClassr   rB  rC  r  keep_alive_conn_limitr`   r  r  r  r  r  setterr  r  r  r  
contextlibcontextmanagerr  r-  r   rP  r  r  staticmethodrD  classmethodr)  r+  r,  rR  r  r  r  rK   r'   rH   r   r     sC   JJGJFJ K?H&
   GG $**;*?G.H
 EMMLGN$O9K  !&
 J2A 37;@	!F)LVE
  6    (9E'N%*
 	 	 M M 
Qf  2  2 2h  
  *   : : $ $&32r'   r   c                       e Zd ZdZd Zd Zy)r   zDBase class to interface HTTPServer with other systems, such as WSGI.c                     || _         y)zuInitialize Gateway instance with request.

        Args:
            req (HTTPRequest): current HTTP request
        N)r[  )r@   r[  s     rH   r`   zGateway.__init__  s     r'   c                     t         )z>Process the current request. Must be overridden in a subclass.)rn  rc   s    rH   r  zGateway.respond  s    !!r'   N)rQ   rR   rS   rT   r`   r  rK   r'   rH   r   r     s    N"r'   r   z%cheroot.ssl.builtin.BuiltinSSLAdapterz&cheroot.ssl.pyopenssl.pyOpenSSLAdapter)builtin	pyopensslc                    t         | j                            }t        |t              rN|j	                  d      }||dz   d }|d| }	 t
        j                  |   }|
t               	 	 t        ||      }|S |S # t        $ r" t        |t               t               dg      }Y ;w xY w# t        $ r t        d|d|d      w xY w)z/Return an SSL adapter class for the given name.r  r   Nr   'z' object has no attribute ')ssl_adaptersr  r  r  rfindr"  modulesKeyError
__import__globalslocalsr/  ra  )nameadapterlast_dot	attr_namemod_pathmods         rH   r   r     s    4::<(G'3==%HqLM*	9H%	B++h'C{j  	c9-G N7N  	BXwy&(RDAC	B  	 Y( 	s   A8 (B& 8(B#"B#&C)rf  )KrT   r  r  reemail.utilsr0  r  r"  r  rL  r%  rQ  platformrP  r_  r  urllib.parser   	functoolsr   r   r   r   r   _compatr   r	   workersr
   rG  r   r   __all__systemrk  r  r   IS_GAEr  r  r  ImportErrorrr  r?  r   r   r   rq   r4   r7   r6   r:   r   rr   ASTERISKr   r   compiler?   r   rX  rU  r=   r-   r   r   r   r   r   r   r   r   r   rj  r   rK   r'   rH   <module>r     s3  AF 
 	 	   
          . .    , X__)+
 ? 
$b	)	4	45I	J '5v:  N 
  '&*-6>* 6=) v}%
  &2F 	RZZ'<)@ AB  $+   w%GC( C(L, ,^ ^BW Wt DP	/ P	/fB BJo
2 o
2d" "& 79MA  	
 !&Ss   +F. .F?>F?