U
    @f                  	   @   s  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 d dl	Z	d dl
Z
d dlZd dlZd dlZzd dlmZmZ W n, ek
r   d dlmZ d dlmZ Y nX d dlmZ d dlmZ d d	lmZ d d
lmZ dD ]:Zzeei i dgZW n ek
r   dZY qX  qqejejejhZdZ ddgZ!dZ"e#e$e%dde$e%dd e$e%dd e$e%dd Z&G dd de'Z(G dd dZ)G dd dZ*G dd de'Z+G dd de'Z,G d d! d!e-Z.G d"d# d#e*Z/dS )$    N)Random)error)md5sha1)r   )sha)	semaphore)wsgi)socket)	get_errno)zwsaccel.utf8validatorzautobahn.utf8validator i   WebSocketWSGI	WebSockets$   258EAFA5-E914-47DA-95CA-C5AB0DC85B11  i    i  i  i  i  c                       s   e Zd Zd fdd	Z  ZS )
BadRequest400 Bad RequestNc                    s$   t t|   || _|| _|| _d S N)super	Exception__init__statusbodyheaders)selfr   r   r   	__class__ L/var/www/html/chatgpt/venv/lib/python3.8/site-packages/eventlet/websocket.pyr   9   s    zBadRequest.__init__)r   NN__name__
__module____qualname__r   __classcell__r   r   r   r   r   8   s   r   c                   @   sb   e Zd ZdZefddZedddZdd	 Zd
d Z	dd Z
dd Zdd Zdd Zdd ZdS )r   a  Wraps a websocket handler function in a WSGI application.

    Use it like this::

      @websocket.WebSocketWSGI
      def my_handler(ws):
          from_browser = ws.wait()
          ws.send("from server")

    The single argument to the function will be an instance of
    :class:`WebSocket`.  To close the socket, simply return from the
    function.  Note that the server will log the websocket request at
    the time of closure.

    An optional argument max_frame_length can be given, which will set the
    maximum incoming *uncompressed* payload length of a frame. By default, this
    is set to 8MiB. Note that excessive values here might create a DOS attack
    vector.
    c                 C   s(   || _ d | _d| _g | _d | _|| _d S )NT)handlerprotocol_versionsupport_legacy_versionssupported_protocolsorigin_checkermax_frame_length)r   r#   r(   r   r   r   r   U   s    zWebSocketWSGI.__init__NFc                    s&    fdd}|d kr|S ||S )Nc                    s"    | }|_ |_r|_|S r   )r%   r'   r&   )r#   instclsr'   r%   r&   r   r   	decoratorc   s    z+WebSocketWSGI.configured.<locals>.decoratorr   )r+   r#   r&   r'   r%   r,   r   r*   r   
configured]   s    zWebSocketWSGI.configuredc           	   
   C   s@  dd | dd dD }d|kr<| dd dksL|d	d
g g S z0d|krb| |}n| jrt| |}nt W nV tk
r } z8|j}|jpd}|j	pg }||d
g|  |g W Y S d }~X Y nX d|kr|d   z| 
| W n4 tk
r( } zt|tkr W 5 d }~X Y nX |d dtj_g S )Nc                 S   s   g | ]}|  qS r   strip).0partr   r   r   
<listcomp>o   s   z*WebSocketWSGI.__call__.<locals>.<listcomp>ZHTTP_CONNECTIONr   ,upgradeZHTTP_UPGRADEZ	websocketr   )
ConnectioncloseHTTP_SEC_WEBSOCKET_VERSION    zeventlet.set_idleT)getlowersplit_handle_hybi_requestr%   _handle_legacy_requestr   r   r   r   r#   OSErrorr
   ACCEPTABLE_CLIENT_ERRORS_send_closing_framer   Z
WSGI_LOCALZalready_handled)	r   environZstart_responseZhttp_connection_partswser   r   r   r   r   r   __call__n   s@    




zWebSocketWSGI.__call__c                 C   s  d|kr|d   }nd|kr(|d }ntdd|krNd| _d|krTt nd| _| jdkr| |d }| |d }d|d	 _|d	 d}td
||| }t	|
 }d}|ddkrd}d||d|d|df }	|d}
|
d k	r|	d|
 7 }	| jdkr8d|d  d |	  d }nP| jdkrd|d  d |dd  d |	  d | }ntd|| t||| jS )Neventlet.inputgunicorn.socket8No eventlet.input or gunicorn.socket present in environ.ZHTTP_SEC_WEBSOCKET_KEY1L   ZHTTP_SEC_WEBSOCKET_KEY2K      z
wsgi.inputz>IIrB   zwsgi.url_schemehttpswssz%s://%s%s%s	HTTP_HOSTSCRIPT_NAME	PATH_INFOZQUERY_STRING?sg   HTTP/1.1 101 Web Socket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
WebSocket-Origin: HTTP_ORIGINs   
WebSocket-Location:    

sj   HTTP/1.1 101 WebSocket Protocol Handshake
Upgrade: WebSocket
Connection: Upgrade
Sec-WebSocket-Origin: s   
Sec-WebSocket-Protocol: HTTP_SEC_WEBSOCKET_PROTOCOLdefaults   
Sec-WebSocket-Location: z#Unknown WebSocket protocol version.)
get_socketr   r$   r   _extract_numbercontent_lengthreadstructpackr   digestr9   encode
ValueErrorsendallr   )r   rA   sockkey1key2Zkey3keyresponseschemelocationqshandshake_replyr   r   r   r=      sx    





z$WebSocketWSGI._handle_legacy_requestc                 C   s   |d krd S i }| dD ]}| d}i }|dd  D ]V}| d}t|dkrhd||d   < q8|d  d ||d   < q8||d   g | q|S )Nr3   ;   =Tr   ")r;   lenr/   r:   
setdefaultappend)r   headerresextpartsconfigr1   Zkey_valr   r   r   _parse_extension_header   s    

( z%WebSocketWSGI._parse_extension_headerc                 C   s   |sd S | d}|d krd S |D ]}| dd| ddd}ttjd}| d}|d k	r|dkrp||d< n0t| d||d< d	|d   krdksq" q"| d
}|d k	r|dkr||d
< n0t| d
||d
< d	|d
   krdksq" q"|  S d S )Npermessage-deflateserver_no_context_takeoverFclient_no_context_takeover)rv   rw      server_max_window_bitsTrJ   client_max_window_bits)r9   minzlib	MAX_WBITSint)r   
extensionsdeflaters   Zwant_configZ	max_wbitsZmwbr   r   r   _negotiate_permessage_deflate   s8    






z+WebSocketWSGI._negotiate_permessage_deflatec                 C   s   |sd S g }|  D ]p\}}| g}|  D ]D\}}|dkr@q.|dkrX||  q.|d|t|f   q.|d| qd|S )NFTz%s=%ss   ; s   , )itemsr\   rn   strjoin)r   parsed_extensionsrr   namers   Z	ext_partsrb   valuer   r   r   _format_extension_header  s    
z&WebSocketWSGI._format_extension_headerc                 C   s  d|kr|d   }nd|kr(|d }ntd|d }|dkrNtddgdt|| _d	|krft |d
| jdkr|ddnd}| jd k	r| |d|stdd|dd }d }|rdd |dD D ]}|| jkr|} qq|d	 }t	
t| t  }	dddd|	 g}
|r8|
d|   i }| |d}| |}|d k	rh||d< | |}|d k	r|
d|  |d|
d  t||| j||| jdS ) NrE   rF   rG   r7   )8Z13z426 Upgrade Required)zSec-WebSocket-Versionz8, 13)r   r   ZHTTP_SEC_WEBSOCKET_KEYrQ   rJ   ZHTTP_SEC_WEBSOCKET_ORIGINr   rM   z403 Forbidden)r   rS   c                 s   s   | ]}|  V  qd S r   r.   r0   ir   r   r   	<genexpr>6  s     z5WebSocketWSGI._handle_hybi_request.<locals>.<genexpr>r3   s    HTTP/1.1 101 Switching Protocolss   Upgrade: websockets   Connection: Upgrades   Sec-WebSocket-Accept: s   Sec-WebSocket-Protocol: ZHTTP_SEC_WEBSOCKET_EXTENSIONSru   s   Sec-WebSocket-Extensions: s   
rR   )protocolr   r(   )rU   r   r   r~   r$   r9   r'   r;   r&   base64	b64encoder   r\   PROTOCOL_GUIDr[   rn   rt   r   r   r^   r   RFC6455WebSocketr(   )r   rA   r_   Zhybi_versionorigin	protocolsZnegotiated_protocolprb   rc   rg   r   r   r   Zformatted_extr   r   r   r<     sh    









z"WebSocketWSGI._handle_hybi_requestc                 C   sB   d}d}|D ](}|t jkr$||7 }q|dkr|d7 }qt|| S )z
        Utility function which, given a string like 'g98sd  5[]221@1', will
        return 9852211. Used to parse the Sec-WebSocket-Key headers.
        r   r    ri   )stringdigitsr~   )r   r   outspacescharr   r   r   rV   U  s    


zWebSocketWSGI._extract_number)NNNF)r   r    r!   __doc__DEFAULT_MAX_FRAME_LENGTHr   classmethodr-   rD   r=   rt   r   r   r<   rV   r   r   r   r   r   @   s       *>&9c                   @   sL   e Zd ZdZdddZdd Zdd Zd	d
 Zdd ZdddZ	dd Z
dS )r   a{  A websocket object that handles the details of
    serialization/deserialization to the socket.

    The primary way to interact with a :class:`WebSocket` object is to
    call :meth:`send` and :meth:`wait` in order to pass messages back
    and forth with the browser.  Also available are the following
    properties:

    path
        The path value of the request.  This is the same as the WSGI PATH_INFO variable,
        but more convenient.
    protocol
        The value of the Websocket-Protocol header.
    origin
        The value of the 'Origin' header.
    environ
        The full WSGI environment for this request.

    rH   c                 C   s   | dtj| _dj| d| dd| dd | d| dd	| _|| _| d
| _| d| _| d| _	|| _
|| _d| _d| _t | _t | _dS )z
        :param socket: The eventlet socket
        :type socket: :class:`eventlet.greenio.GreenSocket`
        :param environ: The wsgi environment
        :param version: The WebSocket spec version to follow (default is 76)
        zwsgi.errorsz-server={shost}/{spath} client={caddr}:{cport}rM   rN   r   rO   ZREMOTE_ADDRZREMOTE_PORT)ZshostZspathZcaddrZcportrQ   ZHTTP_WEBSOCKET_PROTOCOLFr8   N)r9   sysstderrlogformatlog_contextr	   r   r   pathrA   versionwebsocket_closed_bufcollectionsdeque_msgsr   	Semaphore	_sendlock)r   r_   rA   r   r   r   r   r   y  s"     
zWebSocket.__init__c                 C   s<   t |tr|d}nt |ts,t| }d| d }|S )zwPack the message inside ``00`` and ``FF``

        As per the dataframing section (5.3) for the websocket spec
        utf-8       )
isinstancer   r\   bytesr   messagepackedr   r   r   _pack_message  s    

zWebSocket._pack_messagec                 C   s   g }d}| j }|r|d }|dkrb|d}|dkr6q||d| dd ||d d }q|dkr|d dkstd	| d
| _qqtd| q|| _ |S )a1   Parses for messages in the buffer *buf*.  It is assumed that
        the buffer contains the start character for a message, but that it
        may contain only part of the rest of the message.

        Returns an array of messages, and the buffer remainder that
        didn't contain any full messages.r   r   ri   r   replaceN   z Unexpected closing handshake: %rTz6Don't understand how to parse this type of message: %r)r   findrn   decodeAssertionErrorr   r]   )r   msgsZend_idxbufZ
frame_typer   r   r   _parse_messages  s$    
zWebSocket._parse_messagesc                 C   s6   |  |}| j  z| j| W 5 | j  X dS )zSend a message to the browser.

        *message* should be convertable to a string; unicode objects should be
        encodable as utf-8.  Raises socket.error with errno of 32
        (broken pipe) if the socket has already been closed by the client.N)r   r   acquirereleaser	   r^   r   r   r   r   send  s
    

zWebSocket.sendc                 C   sV   | j sL| jrdS | jd}|dkr(dS |  j|7  _|  }| j | q | j  S )a"  Waits for and deserializes messages.

        Returns a single message; the oldest not yet processed. If the client
        has already closed the connection, returns None.  This is different
        from normal socket behavior because the empty string is a valid
        websocket message.Ni  r8   )r   r   r	   recvr   r   extendpopleft)r   deltar   r   r   r   wait  s    zWebSocket.waitFc                 C   sF   | j dkrB| jsBz| jd W n tk
r:   |s6 Y nX d| _dS )z3Sends the closing frame to the client, if required.rH   s    TN)r   r   r	   r^   r>   )r   ignore_send_errorsr   r   r   r@     s    zWebSocket._send_closing_framec              
   C   sx   zfz| d | j d W nF tk
rb } z(|jtjkrR| jdj	| j
|d W 5 d}~X Y nX W 5 | j   X dS )cForcibly close the websocket; generally it is preferable to
        return from the handler method.T {ctx} socket shutdown error: {e}ctxrC   N)r	   r6   r@   shutdownr>   errnoENOTCONNr   writer   r   )r   rC   r   r   r   r6     s    
.zWebSocket.closeN)rH   )F)r   r    r!   r   r   r   r   r   r   r@   r6   r   r   r   r   r   d  s   

c                   @   s   e Zd ZdS )ConnectionClosedErrorNr   r    r!   r   r   r   r   r     s   r   c                       s   e Zd Z fddZ  ZS )FailedConnectionErrorc                    s   t  || || _|| _d S r   )r   r   r   r   )r   r   r   r   r   r   r     s    zFailedConnectionError.__init__r   r   r   r   r   r     s   r   c                   @   s   e Zd ZdS )ProtocolErrorNr   r   r   r   r   r     s   r   c                       s   e Zd Zddddef fdd	ZG dd dZdd	 Zd
d Zdd ZG dd dZ	e
d&ddZdd Zdd Zd'ddZd(ddZdd Zdd Zd d! Zd)d"d#Zd*d$d%Z  ZS )+r      NFc                    sL   t  ||| |  | _|| _|| _|p,i | _d | _d | _|| _	d | _
d S r   )r   r   _iter_framesiteratorclientr   r   _deflate_enc_deflate_decr(   _remote_close_data)r   r_   rA   r   r   r   r   r(   r   r   r   r     s    

zRFC6455WebSocket.__init__c                   @   s&   e Zd Zdd Zdd Zd	ddZdS )
zRFC6455WebSocket.UTF8Decoderc                 C   s,   t rt  | _nd | _td}| | _d S )Nutf8)utf8validatorZUtf8Validator	validatorcodecsgetincrementaldecoderdecoder)r   Zdecoderclassr   r   r   r     s
    
z%RFC6455WebSocket.UTF8Decoder.__init__c                 C   s   | j r| j   | j  d S r   )r   resetr   )r   r   r   r   r     s    
z"RFC6455WebSocket.UTF8Decoder.resetFc                 C   s4   | j r&| j |\}}}}|s&td| j||S )NzData is not valid unicode)r   validater]   r   r   )r   datafinalZvalidZeocpZc_iZt_ir   r   r   r   !  s
    z#RFC6455WebSocket.UTF8Decoder.decodeN)F)r   r    r!   r   r   r   r   r   r   r   UTF8Decoder  s   r   c                    s\   j d  d krd S  fdd} jr4dndr@| S jd krR| _jS d S )Nru   c                      s(   t t jt j jrdndt j S )Nrz   ry   )r|   compressobjZ_DEFAULT_COMPRESSIONDEFLATEDr9   r   r}   r   optionsr   r   r   _make-  s    z;RFC6455WebSocket._get_permessage_deflate_enc.<locals>._makerw   rv   )r   r9   r   r   )r   r   r   r   r   _get_permessage_deflate_enc(  s    
z,RFC6455WebSocket._get_permessage_deflate_encc                    s`   j d  d ks|sd S  fdd} jr8dndrD| S jd krV| _jS d S )Nru   c                      s    t  jrdndt j S )Nry   rz   )r|   decompressobjr9   r   r}   r   r   r   r   r   A  s    z;RFC6455WebSocket._get_permessage_deflate_dec.<locals>._makerv   rw   )r   r9   r   r   )r   rsv1r   r   r   r   _get_permessage_deflate_dec<  s    
z,RFC6455WebSocket._get_permessage_deflate_decc                 C   s<   d}t ||k r8| j|t | }|s.t || }q|S )Nr8   )rl   r	   r   r   )r   numbytesr   dr   r   r   
_get_bytesO  s    
zRFC6455WebSocket._get_bytesc                   @   s(   e Zd Zd	ddZd
ddZdd ZdS )zRFC6455WebSocket.MessageNc                 C   s(   || _ g | _d| _|| _|| _|| _d S )NF)r   r   finishedopcodedecompressorr(   )r   r   r(   r   r   r   r   r   r   Y  s    z!RFC6455WebSocket.Message.__init__Fc                 C   s   || _ | j| d S r   )r   r   rn   )r   r   r   r   r   r   pusha  s    zRFC6455WebSocket.Message.pushc                 C   sd   d | j}| jd@ sJ| jrJ| j|d | j}| jjrJtdd| j| j	r`| j	
|| j}|S )Nr8   rJ          z;Incoming compressed frame exceeds length limit of {} bytes.)r   r   r   r   
decompressr(   unconsumed_tailr   r   r   r   r   )r   r   r   r   r   getvaluee  s    
z!RFC6455WebSocket.Message.getvalue)NN)F)r   r    r!   r   r   r   r   r   r   r   MessageX  s   

r   r   c                    s4   |d krt  }t|}d fdd|D S )Nr8   c                 3   s,   | ]$}t  | | d   A fV  qdS )   N)r   r   r   maskoffsetr   r   r   w  s     z/RFC6455WebSocket._apply_mask.<locals>.<genexpr>)rl   ranger   )r   r   lengthr   Zcntr   r   r   _apply_maskr  s    zRFC6455WebSocket._apply_maskc              	   C   s   |dkr|| _ |sd}nxt|dkrtd|d }|r@|tkrJtddz|  |dd  d	}W q tt	fk
r   tdd
Y qX nd}| j
|dfd t n,|dkr| j|dd n|dkrn
tddd S )NrJ   r   ri   !Hr     zUnexpected close status code.   Tz)Close message data should be valid UTF-8.r   
close_data	   
   control_codezUnknown control frame received.)r   rl   rY   unpack_fromVALID_CLOSE_STATUSr   r   r   UnicodeDecodeErrorr]   r6   r   r   )r   r   r   r   r   r   r   _handle_control_framey  s:     z&RFC6455WebSocket._handle_control_framec                 c   s   d }z`| j |d}|jd@ r0| |j|  q|rD||k	rDtd|}|jr| }d }|V  qW nj tk
r   t \}}}| j	|j
|jfd Y n6 tk
r   Y d S  tk
r   | j	dd  Y nX d S )N)r   rJ   zUnexpected message change.r  )i  zInternal Server Error)_recv_framer   r  r   RuntimeErrorr   r   r   exc_infor6   r   r   r   r   )r   Zfragmented_messager   r   Zexc_typexc_valexc_tbr   r   r   r     s0    
 zRFC6455WebSocket._iter_framesc              	   C   sL  | j }|d}td|\}}|d? dk}|d? d@ }|d@ }|rZ|rZd| jkrZtdd|d	@ }	|	d
krttdd|d@ dk}
|
s| jstdd|d@ }|	d@ r|stdd|dkrtddn&|	r|rtddn|	s|stdd|dkrtd|dd }n|dkr*td|dd }|| jkrJtdd|| j|
r`td|d}d}|rt|	d@ r|	dkr|  nd }| 	|}| j
|	| j||d}|s|jd|d n||k rH| j|| }|st t|}|
r| j||||d}|| }z|j||d W n$ ttfk
rB   td d!Y nX q|S )"Nr  z!BB   ri   r   ru   r  zhRSV1, RSV2, RSV3: MUST be 0 unless an extension is negotiated that defines meanings for non-zero values.rx   )r   ri   r  rJ   r  r	  zUnknown opcode received.   z9A client MUST mask all frames that it sends to the server   rJ   z&Control frames must not be fragmented.}   zBAll control frames MUST have a payload length of 125 bytes or lessz=Received a non-continuation opcode within fragmented message.zAReceived continuation opcode with no previous fragments received.~   r  r   z!Qr   z=Incoming frame of {} bytes is above length limit of {} bytes.!BBBB)r   r   r8   )r   )r  r   r   zText data must be valid utf-8)r   rY   unpackr   r   r   r(   r   r   r   r   r   r	   r   r   rl   r  r  r]   )r   r   r   ro   abr   Zrsv123r   r   maskedr  r   Zreceivedr   r   r   dlenr   r   r   r    s    





 

 zRFC6455WebSocket._recv_frameTc                    s  d}t |tr|d}d}d}|  }|p.dd@ }	|r~|r~|	s~||}||tj7 }|dd  dksnt|d d }d}t	|}
|
sd}|r|d	krt
d
|s|st
d|
dkrt
dtd|dB }n0|rdn|rdnd|B }td||rdndB }|rdnd}|
dkr0td|dB |
}n.|
dkrNtd|dB |
}ntd||
B }|rtt   fddtdD }t|||
}tjd| }nd}d||||fS )NFr   Tr   rJ   r   @   )rJ   r  r	  zUnknown control opcode.z#Control frame cannot be a fragment.r  z$Control frame data too large (>125).z!Br  ri   r  i  z!BQr  z!BHr  c                    s   g | ]}  d qS )rJ   )getrandbits)r0   _Zrandr   r   r2   0  s     z2RFC6455WebSocket._pack_message.<locals>.<listcomp>r   r  r8   )r  )r   r   r\   r   compressflushr|   Z_SYNC_FLUSHr   rl   r   rY   rZ   r   timer   r   r  r   )r   r   r  Zcontinuationr   r  Zis_textZcompress_bitZ
compressorZis_control_framer  ro   r   Z
lengthdatar   Zmaskdatar   r$  r   r     sN    




zRFC6455WebSocket._pack_messagec                 C   s   | j D ]
}|  S d S r   )r   )r   r   r   r   r   r   8  s    
zRFC6455WebSocket.waitc                 C   s,   | j   z| j| W 5 | j   X d S r   )r   r   r   r	   r^   )r   framer   r   r   _send<  s    
zRFC6455WebSocket._sendc                 K   s&   | j |d< | j|f|}| | d S )Nr  )r   r   r*  )r   r   kwpayloadr   r   r   r   C  s    
zRFC6455WebSocket.sendc                 C   s   | j dkr~| js~|d k	rF|\}}t|tr4|d}td|| }nd}z| j|dd W n tk
rv   |sr Y nX d| _d S )N)rJ   r   r   r  r   rJ   r
  T)	r   r   r   r   r\   rY   rZ   r   r>   )r   r   r  r   msgr   r   r   r   r@   H  s    

z$RFC6455WebSocket._send_closing_framec              
   C   s~   zlz | j|dd | j t j W nF tk
rh } z(|jtjkrX| j	dj
| j|d W 5 d}~X Y nX W 5 | j   X dS )r   T)r  r   r   r   N)r	   r6   r@   r   SHUT_WRr>   r   r   r   r   r   r   )r   r  rC   r   r   r   r6   Z  s    .zRFC6455WebSocket.close)Nr   )N)FFTN)FN)N)r   r    r!   r   r   r   r   r   r   r   staticmethodr  r  r   r  r   r   r*  r   r@   r6   r"   r   r   r   r   r     s.   	
M      
<
r   )0r   r   r   r   randomr   r	   r   SocketErrorr   rY   r   r(  r|   hashlibr   r   ImportErrorr   Zeventletr   r   Zeventlet.greenZeventlet.supportr
   _mod
__import__r   
ECONNRESETEPIPE	ESHUTDOWNr?   r   __all__r   setlistr   r  r   r   r   r   r   r   r]   r   r   r   r   r   r   <module>   s`   
  & 