o
    @Bi:                     @   sD  d dl mZ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yW   dZY nw d dlZ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 d!Z+dS )#    )absolute_importprint_function)wraps)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/html/Trade-python/venv/lib/python3.10/site-packages/autobahn/twisted/component.py
<listcomp>D   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   g | ]}|  qS r   )
capitalize)r   sr   r   r   r   I   s    z/_camel_case_from_snake_case.<locals>.<listcomp>   )splitjoin)snakepartsr   r   r   _camel_case_from_snake_caseG   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.   r0   r   r/   r   optionsitemssetProtocolOptions	TypeErrorKeyErrorr,   
ValueErrorformat)reactor	transportsession_factoryr/   factoryr2   kvr   r   r   _create_transport_factoryL   s8   



rB   c                 C   s  t |rt |}|S |d dkrS|dd}|dvr#td||d }t|tjkr7tdt||d	 }t|tjvrKtd
t||dd}t|tjvratdt||dd}|rt	sot
dt|ryt|}net|tr| D ]}	|	dvrtd|	q|d|}
t|
tjkrtd|
d}|dd}|durtt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rOzd d"lm} W n tyD   t
d#w || |||d}|S J d|d d$kro|d% }t|dd}t| ||d}|S J d)&zI
    Create a Twisted client endpoint for a WAMP-over-XXX transport.
    r4   tcpversion   )rE      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' configrL   zAinvalid type {} for hostname in TLS client endpoint configurationrM   r)	trustRootTz4unknown type {} for "tls" configuration in transport)rI   rF   zTLS on IPv6 not implementedFr3   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;   r4   six	text_typeinteger_types_TLSRuntimeErrorr   
isinstancedictkeysr   loadPEMuopenreadr   r   r
   endswithtxtorconTorClientEndpointImportErrorr   twisted.internet.endpointsrP   intr   )r<   endpoint_configendpointrD   rG   rH   rI   rK   contextr@   rL   rM   
cert_fnamerb   rP   rR   r   r   r   _create_transport_endpoints   s   
a




)

rk   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)NrK   zb'tls' configuration must be a dict, CertificateOptions or IOpenSSLClientConnectionCreator providerzI'endpoint' configuration must be a dict or IStreamClientEndpoint provider)r   rS   rZ   r[   boolr   r   r:   )rm   rh   rK   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?)
        rC   rG   rH   )r4   rG   rH   c                    s&   | j  t  fdd}|| _ d S )Nc                    s"   | }t  st  |  |S N)txaio	is_calledreject)failrtn)doneorigr   r   lost/  s   
zFComponent._connect_transport.<locals>.on_connect_success.<locals>.lost)connectionLostr   )protorz   )rx   )ry   r   on_connect_success%  s   
z8Component._connect_transport.<locals>.on_connect_successc                    s    j d7  _ t |  d S )Nr'   )connect_failuresrs   ru   )errrx   r=   r   r   on_connect_failure7  s   z8Component._connect_transport.<locals>.on_connect_failureN)rB   r0   rk   rh   connectrs   add_callbacks)
rm   r<   r=   r>   rx   transport_factorytransport_endpointdr}   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)rm   r<   r   r   r   start@  s   zComponent.startrr   )__name__
__module____qualname____doc__rs   make_loggerr   r   r>   ro   rq   r   r   r   r   r   r   r      s    1r   infoc                    sH   ddl m} |durtj|d t   fd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
    :type components: instance or list of :class:`autobahn.twisted.component.Component`

    :param log_level: a valid log-level (or None to avoid calling start_logging)
    :type log_level: string
    r   )reactN)levelc                    s<   t |tr jd|d z|   W d S  ty   Y d S w )Nz#Something went wrong: {log_failure})failure)rZ   r   errorstopr	   )r<   argr   r   r   done_callbackt  s   
zrun.<locals>.done_callback)twisted.internet.taskr   rs   start_loggingr   r   _run)
components	log_levelr   r   r   r   r   r   T  s   r   )r   ),
__future__r   r   	functoolsr   twisted.internet.interfacesr   re   r   r   twisted.python.failurer   twisted.internet.errorr	   rX   r
   twisted.internet.sslr   r   r   r   OpenSSLr   rd   rU   rs   autobahn.twisted.websocketr   autobahn.twisted.rawsocketr   autobahn.wampr   autobahn.twisted.wampr   autobahn.wamp.serializerr   r   __all__r"   r,   rB   rk   r   r   r   r   r   r   <module>   s<   'ix