
    i9                         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	  ej
        d          Z G d d          ZdS )    N   )packet)payloadzengineio.serverc                       e Zd ZddgZg dZddgZdZdZ G d d	          Z	 	 	 	 	 	 d%dZ	d Z
d Zd&dZd Zd Zd Zd Zd Zd Zd Zd Zd'dZd&dZd Zd&dZd  Zd! Zd" Zd# Zd$ Zd
S )(
BaseServergzipdeflate)connect
disconnectmessagepolling	websocketTr   c                   &    e Zd ZdZdZdZdZdZdZdS )BaseServer.reasonzDisconnection reasons.zserver disconnectzclient disconnectzping timeoutztransport closeztransport errorN)	__name__
__module____qualname____doc__SERVER_DISCONNECTCLIENT_DISCONNECTPING_TIMEOUTTRANSPORT_CLOSETRANSPORT_ERROR     ?/usr/local/lib/python3.11/dist-packages/engineio/base_server.pyreasonr      s/        $$//%++r   r   N      @B    Fc                 0    | _         t          |t                    r|d          _        |d          _        n| _        d _        | _        | _        | _        | _        | _	        |	 _
        |
 _        | _        i  _        i  _        t                       _        ||n j         _        d  _        d  _        ||t*          j        _        t          |t0                    s| _        nt4           _         j        j        t8          j        k    rv|r% j                            t8          j                   n$ j                            t8          j                     j        !                    t9          j"                                #                                }|	||v r|gng }d  _$        d  _%        |D ]m}	 tM          j'        d|z             j$         _$        d j$        v r j$        d         nd}| (                                k    rU| _%         n# tR          $ r Y jw xY w j%        tU          d           (                                r%d j$        vs j$        d         stU          d           (                                s%d j$        v r j$        d         rtU          d          |7t          |tV                    r|g} fd	|D             }|stU          d
          |p j,         _-         j        .                    d j%                   d S )Nr   r   zengineio.async_drivers.asyncioFzInvalid async_mode specifiedz1The selected async_mode is not asyncio compatiblezKThe selected async_mode requires asyncio and must use the AsyncServer classc                 &    g | ]}|j         v |S r   )valid_transports).0	transportselfs     r   
<listcomp>z'BaseServer.__init__.<locals>.<listcomp>k   s3     A A A	&$*??? $???r   zNo valid transports providedzServer initialized for %s.)/ping_timeout
isinstancetupleping_intervalping_interval_grace_periodmax_http_buffer_sizeallow_upgradeshttp_compressioncompression_thresholdcookiecors_allowed_originscors_credentialsasync_handlerssocketshandlerssetlog_message_keys_default_monitor_clientsstart_service_taskservice_task_handleservice_task_eventr   Packetjsonboolloggerdefault_loggerlevelloggingNOTSETsetLevelINFOERROR
addHandlerStreamHandlerasync_modes_async
async_mode	importlibimport_moduleis_asyncio_basedImportError
ValueErrorstrr%   
transportsinfo)r(   rN   r-   r*   r/   r0   r1   r2   r3   r4   r5   rB   r@   r6   monitor_clientsrU   kwargsmodesmodeasyncio_baseds   `                   r   __init__zBaseServer.__init__#   s    )mU++ 	0!.q!1D.;A.>D++!.D./D+$8!, 0%:"$8! 0, #* #2/040M 	#' "&!%FM&$'' 		@ DKK(DK{ GN22 8K((6666K((777&&w'<'>'>???  ""!$.%$7$7ZLLRE 	 	D
'5-46 66<  !DK// !%I 6 65:  D$9$9$;$;;;"&   ?";<<<  "" 	+$+--Y' . * + + +$$&& 	?9+C+CI& ,D > ? ? ?!*c** *(\
A A A AZ A A AJ A !?@@@$=(=5tGGGGGs   <AHH
H$#H$c                     dS )NFr   r(   s    r   rQ   zBaseServer.is_asyncio_basedr   s    ur   c                 
    g dS )N)eventletgevent_uwsgigevent	threadingr   r^   s    r   rL   zBaseServer.async_modesu   s    BBBBr   c                 d      j         vrt          d           fd}||S  ||           dS )a  Register an event handler.

        :param event: The event name. Can be ``'connect'``, ``'message'`` or
                      ``'disconnect'``.
        :param handler: The function that should be invoked to handle the
                        event. When this parameter is not given, the method
                        acts as a decorator for the handler function.

        Example usage::

            # as a decorator:
            @eio.on('connect')
            def connect_handler(sid, environ):
                print('Connection request')
                if environ['REMOTE_ADDR'] in blacklisted:
                    return False  # reject

            # as a method:
            def message_handler(sid, msg):
                print('Received message: ', msg)
                eio.send(sid, 'response')
            eio.on('message', message_handler)

        The handler function receives the ``sid`` (session ID) for the
        client as first argument. The ``'connect'`` event handler receives the
        WSGI environment as a second argument, and can return ``False`` to
        reject the connection. The ``'message'`` handler receives the message
        payload as a second argument. The ``'disconnect'`` handler does not
        take a second argument.
        zInvalid eventc                     | j         <   | S N)r8   )handlereventr(   s    r   set_handlerz"BaseServer.on.<locals>.set_handler   s    #*DM% Nr   N)event_namesrS   )r(   rh   rg   ri   s   ``  r   onzBaseServer.onx   sc    > (((_---	 	 	 	 	 	 ?Gr   c                 >    |                      |          j        rdndS )zReturn the name of the transport used by the client.

        The two possible values returned by this function are ``'polling'``
        and ``'websocket'``.

        :param sid: The session of the client.
        r   r   )_get_socketupgraded)r(   sids     r   r'   zBaseServer.transport   s$     #..s33<K{{)Kr   c                 (     | j         d         |i |S )zCreate a queue object using the appropriate async model.

        This is a utility function that applications can use to create a queue
        without having to worry about using the correct call for the selected
        async mode.
        queuerM   r(   argsrX   s      r   create_queuezBaseServer.create_queue         $t{7#T4V444r   c                     | j         d         S )zReturn the queue empty exception for the appropriate async model.

        This is a utility function that applications can use to work with a
        queue without having to worry about using the correct call for the
        selected async mode.
        queue_emptyrr   r^   s    r   get_queue_empty_exceptionz$BaseServer.get_queue_empty_exception   s     {=))r   c                 (     | j         d         |i |S )zCreate an event object using the appropriate async model.

        This is a utility function that applications can use to create an
        event without having to worry about using the correct call for the
        selected async mode.
        rh   rr   rs   s      r   create_eventzBaseServer.create_event   rv   r   c                 $   t          j        t          j        d          | j                            dd          z             }| j        dz   dz  | _        |                    d                              dd                              d	d
          S )zGenerate a unique session id.      bigr   i utf-8/_+-)base64	b64encodesecretstoken_bytessequence_numberto_bytesdecodereplace)r(   ids     r   generate_idzBaseServer.generate_id   s    ##d&:&C&CAu&M&MMO O $ 4q 8HDyy!!))#s33;;CEEEr   c                     |                     dd          dz   |z   }|                                D ]@\  }}|dk    rt          |          r
 |            }|du r	|d|z   z  }2|d|z   dz   |z   z  }A|S )zGenerate the sid cookie.nameio=Tz; )getitemscallable)r(   ro   
attributesr3   	attributevalues         r   _generate_sid_cookiezBaseServer._generate_sid_cookie   s    --3c9 * 0 0 2 2 	9 	9IuF""  }}$**$*S0588r   c                     | j         r |                     |          j        s|dk    rg S | j        d         |                     dd           g S dgS )z=Return the list of possible upgrades for a client connection.r   NzThe WebSocket transport is not available, you must install a WebSocket server that is compatible with your async mode to enable it. See the documentation for details.zno-websocket)r0   rm   rn   rM   _log_error_once)r(   ro   r'   s      r   	_upgradeszBaseServer._upgrades   st    " 	d&6&6s&;&;&D 	[((I;{#+  @ 	     
 I}r   c                     	 | j         |         }n# t          $ r t          d          w xY w|j        r| j         |= t          d          |S )z-Return the socket object for a given session.zSession not foundzSession is disconnected)r7   KeyErrorclosed)r(   ro   ss      r   rm   zBaseServer._get_socket   sg    	0S!AA 	0 	0 	0.///	08 	6S!4555s    *c                     |J|g }|dgz  }d|t          j        |                              |                              d          dS ddgd	dS )
z$Generate a successful HTTP response.N)Content-Typeztext/plain; charset=UTF-8z200 OK)packets)jsonp_indexr   statusheadersresponser   z
text/plains   OK)r   Payloadencode)r(   r   r   r   s       r   _okzBaseServer._ok   s    EFFG&& ' @ @ @ G G$/ !H !1 !117B B B
 ' >? %' ' 'r   c                     |d}t           j        j                            |          }ddg|                    d          dS )z+Generate a bad request HTTP error response.NzBad Requestz400 BAD REQUESTr   r   r   r   r?   r@   dumpsr   r(   r   s     r   _bad_requestzBaseServer._bad_request  sK    ?#G-$**733+:;#NN7335 5 	5r   c                     ddgddS )z0Generate a method not found HTTP error response.z405 METHOD NOT FOUNDr   s   Method Not Foundr   r   r^   s    r   _method_not_foundzBaseServer._method_not_found  s    0:;/1 1 	1r   c                     |d}t           j        j                            |          }ddg|                    d          dS )z,Generate a unauthorized HTTP error response.NUnauthorizedz401 UNAUTHORIZED)r   zapplication/jsonr   r   r   r   s     r   _unauthorizedzBaseServer._unauthorized  sK    ?$G-$**733,@A#NN7335 5 	5r   c           
      v   | j         g }d|v rd|v r|                    d                    |d         |d                              d|v sd|v r|                    d|d                                       d          d                                         }|                    d                    ||                    d|d                                       d          d                                                              n| j         d	k    rd }nt          | j         t                    r	| j         g}nt          | j                   rZ|                    d
          }	 |                      ||          }n%# t          $ r |                      |          }Y nw xY w|r|gng }nd	| j         v rd }n| j         }|S )Nzwsgi.url_scheme	HTTP_HOSTz{scheme}://{host})schemehostHTTP_X_FORWARDED_PROTOHTTP_X_FORWARDED_HOST,r   *HTTP_ORIGIN)
r4   appendformatr   splitstripr+   rT   r   	TypeError)r(   environallowed_originsr   origin
is_alloweds         r   _cors_allowed_originsz BaseServer._cors_allowed_origins  s   $, O G++w0F0F&&':'A'A"#45 - (B (/ (/ 0 0 0 ,w66/7::$[[0 124 449E#JJqBBG%''  $**+>+E+E%GKK3#K0-2 -227% #3% 3%%&-( ).	 ,F ,1 ,1 2 2 2
 &#--"OO1377 	<#89OOd/00 	<[[//F?!66vwGG

 ? ? ?!66v>>


?*4<vhh"OOd///"&"&";s   "E9 9FFc                     | j         g k    rg S g }|                     |          }d|v r|
|d         |v rd|d         fg}|d         dk    r|dgz  }d|v r|d|d         fgz  }| j        r|d	gz  }|S )
z1Return the cross-origin-resource-sharing headers.r   NzAccess-Control-Allow-OriginREQUEST_METHODOPTIONS)zAccess-Control-Allow-MethodszOPTIONS, GET, POST#HTTP_ACCESS_CONTROL_REQUEST_HEADERSzAccess-Control-Allow-Headers)z Access-Control-Allow-Credentialstrue)r4   r   r5   )r(   r   r   r   s       r   _cors_headerszBaseServer._cors_headers?  s    $**I44W==G## (GM,B -! -!5w}7MNOG#$	11NOOG0G;;7 EFH I IG  	FDEEGr   c                     t          j                    }t          j        |d          5 }|                    |           ddd           n# 1 swxY w Y   |                                S )z%Apply gzip compression to a response.w)fileobjrZ   N)r   BytesIOr   GzipFilewritegetvalue)r(   r   bytesiogzs       r   _gzipzBaseServer._gzipS  s    *,,]7555 	HHX	 	 	 	 	 	 	 	 	 	 	 	 	 	 	!!!s   AAAc                 *    t          j        |          S )z(Apply deflate compression to a response.)zlibcompress)r(   r   s     r   _deflatezBaseServer._deflateZ  s    }X&&&r   c                     || j         vr9| j                            |dz              | j                             |           dS | j                            |           dS )zWLog message with logging.ERROR level the first time, then log
        with given level.zC (further occurrences of this error will be logged with level INFO)N)r:   rB   erroraddrV   )r(   r   message_keys      r   r   zBaseServer._log_error_once^  sv     d333Kg )@ @ A A A!%%k22222KW%%%%%r   )Nr   r   r    TTr!   NNTFNTNNrf   )NNN)r   r   r   compression_methodsrj   r%   r;   r   r   r\   rQ   rL   rk   r'   ru   ry   r{   r   r   r   rm   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s       !9-666K!;/#O, , , , , , , , HJ>B>B37;?GKMH MH MH MH^  C C C( ( ( (TL L L5 5 5* * *5 5 5F F F    	 	 	' ' ' '5 5 5 51 1 15 5 5 5! ! !F  (" " "' ' '& & & & &r   r   )r   r   rO   r   rE   r   r    r   r   	getLoggerrC   r   r   r   r   <module>r      s          				               ""#455W& W& W& W& W& W& W& W& W& W&r   