U
    •uÄc;  ã                   @   sH  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k
r¬   dZY nX 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#ee( e)e*d œ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 | ]}|ˆ krˆ   |¡s|‘qS © )Úadd)Ú.0Úx©Úseenr   úZ/var/www/html/SARATH/school/venv/lib/python3.8/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)ZsnakeÚpartsr   r   r   Ú_camel_case_from_snake_caseE   s    
r,   c                 C   sæ   |j dkr(t|ƒ}t||j||jd�}n2|j dkrNt|jd ƒ}t||d�}ndsZtdƒ‚|j	 
¡ D ]|\}}z|jf ||iŽ W qd ttfk
rÞ   z|jf t|ƒ|iŽ W n, ttfk
rØ   td |j ||¡ƒ‚Y nX Y qdX qd|S )	z3
    Create a WAMP-over-XXX transport factory.
    Z	websocket)ÚurlÚserializersÚproxyZ	rawsocketr   )Ú
serializerFúshould not arrive herez"Unknown {} transport option: {}={})Útyper   r   r-   r/   r   r.   r   ÚAssertionErrorÚoptionsÚitemsZsetProtocolOptionsÚ	TypeErrorÚKeyErrorr,   Ú
ValueErrorÚformat)ÚreactorÚ	transportÚsession_factoryr.   Úfactoryr0   ÚkÚvr   r   r   Ú_create_transport_factoryJ   s2    
ü

ÿÿr@   c                 C   s  t  |¡rt |ƒ}�nò|d dk�rÄ| dd¡}|dkrFtd |¡ƒ‚|d }t|ƒtkrltd t|ƒ¡ƒ‚|d	 }t|ƒtkr’td
 t|ƒ¡ƒ‚| dd¡}t|ƒtkr¼td t|ƒ¡ƒ‚| dd¡}|�r tsÚt	dƒ‚t
 |¡rît
|ƒ}nÐt|tƒ�r†| ¡ D ]}	|	dk�rtd |	¡ƒ‚�q| d|¡}
t|
ƒtk�rJtd |
¡ƒ‚d}| dd¡}|dk	�rxt t|dƒ ¡ ¡}t|
|d�}n8t|tƒ�r˜|}n&|dk�r¬t|ƒ}nt	d t|ƒ¡ƒ‚|dk�rÜt| ||||d�}n"|dk�rðt	dƒ‚nd�sÂtdƒ‚nÂ| d¡�rLzd dl}| ||¡}W n$ tk
�rH   t	d! |¡ƒ‚Y nX nv|dk�rht| |||d�}nZ|dk�r´zd d"lm} W n tk
�r    t	d#ƒ‚Y nX || |||d�}nd�stdƒ‚nD|d d$k�rú|d% }t| dd¡ƒ}t| ||d�}nd�stdƒ‚|S )&zI
    Create a Twisted client endpoint for a WAMP-over-XXX transport.
    r2   ÚtcpÚversioné   )rC   é   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' configrJ   zAinvalid type {} for hostname in TLS client endpoint configurationrK   Úr)Z	trustRootTz4unknown type {} for "tls" configuration in transport)rG   rD   zTLS on IPv6 not implementedFr1   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Úgetr8   r9   r2   ÚstrÚintÚ_TLSÚRuntimeErrorr   Ú
isinstanceÚdictÚkeysr   ZloadPEMÚopenÚreadr
   r   r	   r3   ÚendswithÚtxtorconZTorClientEndpointÚImportErrorr   Útwisted.internet.endpointsrM   r   )r:   Zendpoint_configÚendpointrB   rE   rF   rG   rI   Úcontextr>   rJ   rK   Z
cert_fnamer\   rM   rO   r   r   r   Ú_create_transport_endpointq   sˆ    









ÿÿ

ra   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)rT   rV   r   ÚError)ÚselfÚer   r   r   Ú_is_ssl_errorê   s    zComponent._is_ssl_errorc                 C   sd   t  |¡rnTt|tƒrXd|kr`|d }t|ttfƒr6q`t |¡rBq`t|tƒrNq`tdƒ‚ntdƒ‚d S )NrI   zb'tls' configuration must be a dict, CertificateOptions or IOpenSSLClientConnectionCreator providerzI'endpoint' configuration must be a dict or IStreamClientEndpoint provider)r   rP   rV   rW   Úboolr   r   r8   )rc   r_   rI   r   r   r   Ú_check_native_endpointö   s"    



ÿÿz Component._check_native_endpointc           
         s‚   t |ˆ|ƒ}ˆjr2t|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?)
        rA   rE   rF   )r2   rE   rF   c                    s&   | j ‰ tˆ ƒ‡‡ fdd„ƒ}|| _ d S )Nc                    s"   ˆ| ƒ}t  ˆ ¡st  ˆ | ¡ |S r$   )ÚtxaioZ	is_calledÚreject)ÚfailZrtn)ÚdoneÚorigr   r   Úlost-  s    
zFComponent._connect_transport.<locals>.on_connect_success.<locals>.lost)ZconnectionLostr   )Úprotorm   )rk   )rl   r   Úon_connect_success#  s    z8Component._connect_transport.<locals>.on_connect_successc                    s   ˆ j d7  _ t ˆ | ¡ d S )Nr(   )Zconnect_failuresrh   ri   )Úerr©rk   r;   r   r   Úon_connect_failure5  s    z8Component._connect_transport.<locals>.on_connect_failureN)r@   r/   ra   r_   Úconnectrh   Zadd_callbacks)
rc   r:   r;   r<   rk   Ztransport_factoryZtransport_endpointÚdro   rr   r   rq   r   Ú_connect_transport  s     ýþ	
zComponent._connect_transportNc                 C   s,   |dk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)rc   r:   r   r   r   Ústart>  s    zComponent.start)N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rh   Úmake_loggerrw   r   r<   re   rg   ru   r{   r   r   r   r   r   Ú   s   1r   Úinfo)Ú
componentsÚ	log_levelÚstop_at_closec                    sR   ddl m} |dk	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                    sH   t |tƒrDˆ jd|d� zˆ  d¡ |  ¡  W n tk
rB   Y nX d S )Nz#Something went wrong: {log_failure})ZfailurezStopping reactor ..)rV   r   Úerrorrx   Ústopr   )r:   Úarg©rw   r   r   Údone_callbackq  s    

zrun.<locals>.done_callback)Ztwisted.internet.taskr…   rh   Zstart_loggingr€   r   Ú_run)r‚   rƒ   r„   r…   r‹   r   rŠ   r   r   R  s    	r   )r�   T),Ú	functoolsr   Útypingr   Ztwisted.internet.interfacesr   r^   r   r   Ztwisted.python.failurer   Ztwisted.internet.errorr   rT   r	   Ztwisted.internet.sslr
   r   r   r   ZOpenSSLr   r]   rh   Zautobahn.twisted.websocketr   Zautobahn.twisted.rawsocketr   Zautobahn.wampr   Zautobahn.twisted.wampr   Zautobahn.wamp.serializerr   r   Ú__all__r!   r,   r@   ra   r   rR   rf   r   r   r   r   r   Ú<module>   s6   
'ix