o
    >h;                     @   sJ  d dl mZ d dlmZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ z d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 W n eyU   dZY nw d dlZd dl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#dd Z$dd Z%dd Z&dd Z'G dd dej(Z(d%d ee( d!e)d"e*fd#d$Z+dS )&    )wraps)List)IStreamClientEndpoint)UNIXClientEndpoint)TCP4ClientEndpoint)Failure)ReactorNotRunningT)SSL4ClientEndpoint)optionsForClientTLSCertificateOptionsCertificate)IOpenSSLClientConnectionCreator)SSLFN)WampWebSocketClientFactory)WampRawSocketClientFactory)	component)Session)create_transport_serializerscreate_transport_serializer)	Componentrunc                    s   t    fdd| D S )zM
    Return a list with unique elements from sequence, preserving order.
    c                    s"   g | ]}| vr  |s|qS  )add).0xseenr   z/var/www/vedio/testing/chatpythonscript.ninositsolution.com/env/lib/python3.10/site-packages/autobahn/twisted/component.py
<listcomp>B   s   " z _unique_list.<locals>.<listcomp>)set)seqr   r   r   _unique_list=   s   r!   c                 C   s.   |  d}|d ddd |dd  D  S )N_r    c                 s   s    | ]}|  V  qd S N)
capitalize)r   sr   r   r   	<genexpr>G   s    z._camel_case_from_snake_case.<locals>.<genexpr>   )splitjoin)snakepartsr   r   r   _camel_case_from_snake_caseE   s   
$r-   c                 C   s   |j dkrt|}t||j||jd}n|j dkr't|jd }t||d}nJ d|j	 D ]=\}}z|j
d
i ||i W q0 ttfym   z|j
d
i t||i W n ttfyj   td|j ||w Y q0w |S )z3
    Create a WAMP-over-XXX transport factory.
    	websocket)urlserializersproxy	rawsocketr   )
serializerFshould not arrive herez"Unknown {} transport option: {}={}Nr   )typer   r   r/   r1   r   r0   r   optionsitemssetProtocolOptions	TypeErrorKeyErrorr-   
ValueErrorformat)reactor	transportsession_factoryr0   factoryr3   kvr   r   r   _create_transport_factoryJ   s8   



rC   c                 C   s  t |rt |}|S |d dkrL|dd}|dvr#td||d }t|tkr6tdt||d	 }t|tkrItd
t||dd}t|tkr^tdt||dd}|rtslt	dt
|rvt
|}nat|tr| D ]}	|	dvrtd|	q|d|}
t|
tkrtd|
d}|dd}|durtt|d }t|
|d}nt|tr|}n|du rt|}n	t	dt||dkrt| ||||d}|S |dkrt	dJ d|drzd dl}|||}W |S  ty   t	d!|w |dkr$t| |||d}|S |dkrHzd d"lm} W n ty=   t	d#w || |||d}|S J d|d d$krh|d% }t|dd}t| ||d}|S J d)&zI
    Create a Twisted client endpoint for a WAMP-over-XXX transport.
    r5   tcpversion   )rF      z6invalid IP version {} in client endpoint configurationhostz9invalid type {} for host in client endpoint configurationportz9invalid type {} for port in client endpoint configurationtimeout
   z<invalid type {} for timeout in client endpoint configurationtlsNzKTLS configured in transport, but TLS support is not installed (eg OpenSSL?))hostname
trust_rootz Invalid key '{}' in 'tls' configrM   zAinvalid type {} for hostname in TLS client endpoint configurationrN   r)	trustRootTz4unknown type {} for "tls" configuration in transport)rJ   rG   zTLS on IPv6 not implementedFr4   z.onionr   zC{} appears to be a Tor Onion service, but txtorcon is not installed)TCP6ClientEndpointz.IPv6 is not supported (please upgrade Twisted)unixpath)r   
providedBygetr;   r<   r5   strint_TLSRuntimeErrorr   
isinstancedictkeysr   loadPEMopenreadr
   r   r	   endswithtxtorconTorClientEndpointImportErrorr   twisted.internet.endpointsrQ   r   )r=   endpoint_configendpointrE   rH   rI   rJ   rL   contextrA   rM   rN   
cert_fnamera   rQ   rS   r   r   r   _create_transport_endpointq   s   
a




)

ri   c                   @   s@   e Zd ZdZe ZeZ	 dd Z	dd Z
dd Zdd	d
ZdS )r   z
    A component establishes a transport and attached a session
    to a realm using the transport for communication.

    The transports a component tries to use can be configured,
    as well as the auto-reconnect strategy.
    c                 C   s   t rt|tjS dS )z
        Internal helper.

        This is so we can just return False if we didn't import any
        TLS/SSL libraries. Otherwise, returns True if this is an
        OpenSSL.SSL.Error
        F)rX   rZ   r   Error)selfer   r   r   _is_ssl_error   s   zComponent._is_ssl_errorc                 C   sj   t |rd S t|tr1d|v r/|d }t|ttfrd S t|r$d S t|tr+d S tdd S td)NrL   zb'tls' configuration must be a dict, CertificateOptions or IOpenSSLClientConnectionCreator providerzI'endpoint' configuration must be a dict or IStreamClientEndpoint provider)r   rT   rZ   r[   boolr   r   r;   )rk   rf   rL   r   r   r   _check_native_endpoint   s$   



z Component._check_native_endpointc           
         s   t ||}jrt|djd jd d}nt|j}||} fdd} fdd}	t||d	 t|d	|	 |S )
z
        Create and connect a WAMP-over-XXX transport.

        :param done: is a Deferred/Future from the parent which we
            should signal upon error if it is not done yet (XXX maybe an
            "on_error" callable instead?)
        rD   rH   rI   )r5   rH   rI   c                    s&   | j  t  fdd}|| _ d S )Nc                    s"   | }t  st  |  |S r$   )txaio	is_calledreject)failrtn)doneorigr   r   lost-  s   
zFComponent._connect_transport.<locals>.on_connect_success.<locals>.lost)connectionLostr   )protorw   )ru   )rv   r   on_connect_success#  s   
z8Component._connect_transport.<locals>.on_connect_successc                    s    j d7  _ t |  d S )Nr(   )connect_failuresrp   rr   )errru   r>   r   r   on_connect_failure5  s   z8Component._connect_transport.<locals>.on_connect_failureN)rC   r1   ri   rf   connectrp   add_callbacks)
rk   r=   r>   r?   ru   transport_factorytransport_endpointdrz   r~   r   r}   r   _connect_transport  s    	
zComponent._connect_transportNc                 C   s,   |du r| j d ddlm} | j|dS )a{  
        This starts the Component, which means it will start connecting
        (and re-connecting) to its configured transports. A Component
        runs until it is "done", which means one of:
        - There was a "main" function defined, and it completed successfully;
        - Something called ``.leave()`` on our session, and we left successfully;
        - ``.stop()`` was called, and completed successfully;
        - none of our transports were able to connect successfully (failure);

        :returns: a Deferred that fires (with ``None``) when we are
            "done" or with a Failure if something went wrong.
        NzUsing default reactorr   )r=   )loop)logwarntwisted.internetr=   _start)rk   r=   r   r   r   start>  s   zComponent.startr$   )__name__
__module____qualname____doc__rp   make_loggerr   r   r?   rm   ro   r   r   r   r   r   r   r      s    1r   info
components	log_levelstop_at_closec                    sR   ddl m} |durtj|d t  |r fdd}nd}|tj| |f dS )a  
    High-level API to run a series of components.

    This will only return once all the components have stopped
    (including, possibly, after all re-connections have failed if you
    have re-connections enabled). Under the hood, this calls
    :meth:`twisted.internet.reactor.run` -- if you wish to manage the
    reactor loop yourself, use the
    :meth:`autobahn.twisted.component.Component.start` method to start
    each component yourself.

    :param components: the Component(s) you wish to run
    :param log_level: a valid log-level (or None to avoid calling start_logging)
    :param stop_at_close: Flag to control whether to stop the reactor when done.
    r   )reactN)levelc                    sJ   t |tr# jd|d z d |   W d S  ty"   Y d S w d S )Nz#Something went wrong: {log_failure})failurezStopping reactor ..)rZ   r   errorr   stopr   )r=   argr   r   r   done_callbackq  s   

zrun.<locals>.done_callback)twisted.internet.taskr   rp   start_loggingr   r   _run)r   r   r   r   r   r   r   r   r   R  s   	r   )r   T),	functoolsr   typingr   twisted.internet.interfacesr   rd   r   r   twisted.python.failurer   twisted.internet.errorr   rX   r	   twisted.internet.sslr
   r   r   r   OpenSSLr   rc   rp   autobahn.twisted.websocketr   autobahn.twisted.rawsocketr   autobahn.wampr   autobahn.twisted.wampr   autobahn.wamp.serializerr   r   __all__r!   r-   rC   ri   r   rV   rn   r   r   r   r   r   <module>   s:   'i x