3
K^Q                @   sX  d dl mZ d dlZd dlZd dlm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 d dlmZ d d	lmZ d d
lmZ d dlmZmZmZmZmZ d dlmZmZ d dlmZmZmZ d dlm Z  d dl!m"Z"m#Z#m$Z$m%Z%m&Z&m'Z'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z- dd Z.G dd deZ/e	G dd de/Z0G dd de0Z1G dd de2Z3dS )    )UnionN)reduce)wamp)publicIdGeneratorObservableMixin)uri)message)types)role)	exception)ApplicationErrorProtocolErrorSessionNotReadySerializationErrorTypeCheckError)IPayloadCodecIAuthenticator)SessionDetailsCloseDetailsEncodedPayload)PayloadExceededError)PublicationSubscriptionHandlerRegistrationEndpointPublishRequestSubscribeRequestUnsubscribeRequestCallRequestInvocationRequestRegisterRequestUnregisterRequestc             C   s   t j| pt j| S )N)inspectismethod
isfunction)f r(   :/tmp/pip-unpacked-wheel-p9ga6z5n/autobahn/wamp/protocol.pyis_method_or_function:   s    r*   c               @   s   e Zd ZdZdZdd Zedd Zedd Zed	d
 Z	edd Z
edd Zedd ZdddZdddZdd ZdS )BaseSessionzi
    WAMP session base class.

    This class implements :class:`autobahn.wamp.interfaces.ISession`.
    Nc             C   st   t j | _| jdddddgd d| _i | _tjttj	t
i| _d| _d| _d| _d| _d| _d| _d| _t | _dS )	z


        joinleavereadyconnect
disconnect)Zvalid_eventsFN)txaioZmake_loggerlogZset_valid_eventstraceback_app_ecls_to_uri_patr   INVALID_PAYLOADr   PAYLOAD_SIZE_EXCEEDEDr   _uri_to_ecls_realm_session_id_authid	_authrole_authmethod_authprovider_payload_codecr   _request_id_gen)selfr(   r(   r)   __init__F   s&    

zBaseSession.__init__c             C   s   | j S )N)r8   )r@   r(   r(   r)   realmr   s    zBaseSession.realmc             C   s   | j S )N)r9   )r@   r(   r(   r)   
session_idv   s    zBaseSession.session_idc             C   s   | j S )N)r:   )r@   r(   r(   r)   authidz   s    zBaseSession.authidc             C   s   | j S )N)r;   )r@   r(   r(   r)   authrole~   s    zBaseSession.authrolec             C   s   | j S )N)r<   )r@   r(   r(   r)   
authmethod   s    zBaseSession.authmethodc             C   s   | j S )N)r=   )r@   r(   r(   r)   authprovider   s    zBaseSession.authproviderc             C   sn   |dkr8t |dst|j| j|< || j|jd j < n2t |d sHttj|tjjg| j|< || j|< dS )zM
        Implements :func:`autobahn.wamp.interfaces.ISession.define`
        N	_wampurisr   )hasattrAssertionErrorrH   r4   r7   r   PatternZURI_TARGET_HANDLER)r@   r   errorr(   r(   r)   define   s    zBaseSession.definec          	   C   s   d}t |drt|j}d}t |dr,|j}|rF|r>||d< nd|i}t|tjrnt|jt	krf|jn|j}n$|j
| jkr| j|j
 d j}nd}d}	| jr| jjd|||}	|	rtj||||	j|	j|	j|	jd}
ntj|||||}
|
S )	a  
        Create a WAMP error message from an exception.

        :param request_type: The request type this WAMP error message is for.
        :type request_type: int

        :param request: The request ID this WAMP error message is for.
        :type request: int

        :param exc: The exception.
        :type exc: Instance of :class:`Exception` or subclass thereof.

        :param tb: Optional traceback. If present, it'll be included with the WAMP error message.
        :type tb: list or None
        Nargskwargs	tracebackr   zwamp.error.runtime_errorF)payloadenc_algoenc_keyenc_serializer)rI   listrN   rO   
isinstancer   r   typerL   str	__class__r4   _urir>   encoder	   ErrorrQ   rR   rS   rT   )r@   request_typerequestexctbrR   rN   rO   rL   encoded_payloadmsgr(   r(   r)   _message_from_exception   s@    



z#BaseSession._message_from_exceptionc       	      C   sr  d}d}|j r| js8d}| jj| ttj||j d}ny6t|j|j |j|j	}| jj
d|j|\}|_|_W nJ tk
r } z.| jjd|d ttjdj||j d}W Y dd}~X n<X |j|kr| jjd||jd	 ttjd
j||j|j d}|r|S |j| jkr| j|j }yL|jrF|jr8||j|j}n|f |j}n|jrZ||j }n| }W n8 tk
r   y| jtj d W n   Y nX Y nX |s
|jr|jrtj|jf|j|j}ntj|jf|j}n*|jrtj|jf|j }ntj|j}t|dr|j |_ t|dr2|j|_t|drF|j|_t|drZ|j|_t|drn|j|_|S )z
        Create a user (or generic) exception from a WAMP error message.

        :param msg: A WAMP error message.
        :type msg: instance of :class:`autobahn.wamp.message.Error`
        Nz5received encoded payload, but no payload codec active)rR   Tz.failed to decrypt application payload 1: {err})errz+failed to decrypt application payload 1: {}zZURI within encrypted payload ('{decrypted_error}') does not match the envelope ('{error}'))decrypted_errorrL   zFURI within encrypted payload ('{}') does not match the envelope ('{}')zWhile re-constructing exceptionrR   calleecallee_authidcallee_authroleforward_for)rR   r>   r2   warnr   ENC_NO_PAYLOAD_CODECr   rQ   rT   rS   decoderL   rN   rO   	ExceptionENC_DECRYPT_ERRORformatENC_TRUSTED_URI_MISMATCHr7   onUserErrorr1   create_failurer   rI   rf   rg   rh   ri   )	r@   rb   r_   enc_errlog_msgra   re   eZeclsr(   r(   r)   _exception_from_message   s~     




z#BaseSession._exception_from_message)N)NN)__name__
__module____qualname____doc__r2   rA   propertyrB   rC   rD   rE   rF   rG   rM   rc   rv   r(   r(   r(   r)   r+   >   s   ,

;r+   c               @   sB  e Zd ZdZd:ddZedd Zedd Zed	d
 Zedd Z	ed;ddZ
edd Zedd Zedd Zedd Zdd Zdd Zdd Zedd Zedd  Zed!d" Zed#d$ Zd%d& Zed'd( Zed<d)d*Zed+d, Zed-d. Zed=d0d1Zd2d3 Zed4d5 Zed>d6d7Zd8d9 ZdS )?ApplicationSessionz 
    WAMP endpoint session.
    Nc             C   s|   t j|  |ptjdd| _tj| _d| _d| _	d| _
d| _d| _i | _i | _i | _i | _i | _i | _i | _i | _i | _dS )zF
        Implements :func:`autobahn.wamp.interfaces.ISession`
        realm1)rB   NF)r+   rA   r
   ComponentConfigconfigr   ZDEFAULT_CLIENT_ROLES_session_roles
_transportr9   r8   _goodbye_sentZ_transport_is_closing_publish_reqs_subscribe_reqs_unsubscribe_reqs
_call_reqs_register_reqs_unregister_reqs_subscriptions_registrations_invocations)r@   r   r(   r(   r)   rA   =  s"    
zApplicationSession.__init__c             C   s    |dkst |tst|| _dS )zX
        Implements :func:`autobahn.wamp.interfaces.ISession.set_payload_codec`
        N)rV   r   rJ   r>   )r@   Zpayload_codecr(   r(   r)   set_payload_codec_  s    z$ApplicationSession.set_payload_codecc             C   s   | j S )zX
        Implements :func:`autobahn.wamp.interfaces.ISession.get_payload_codec`
        )r>   )r@   r(   r(   r)   get_payload_codecg  s    z$ApplicationSession.get_payload_codecc                sL   | _  jd |}tj|d fdd tj| fdd fdd dS )zV
        Implements :func:`autobahn.wamp.interfaces.ITransportHandler.onOpen`
        r/   Nc                s    j | dS )NzWhile notifying 'connect')_swallow_error)fail)r@   r(   r)   <lambda>w  s    z+ApplicationSession.onOpen.<locals>.<lambda>c                s   t j jS )N)r1   	as_future	onConnect)_)r@   r(   r)   r   {  s    c                s    j | dS )NzWhile calling 'onConnect')r   )r   )r@   r(   r)   r   |  s    )r   firer1   add_callbacks)r@   	transportdr(   )r@   r)   onOpenn  s    
zApplicationSession.onOpenc             C   s   | j | jj dS )zP
        Implements :func:`autobahn.wamp.interfaces.ISession.onConnect`
        N)r,   r   rB   )r@   r(   r(   r)   r     s    zApplicationSession.onConnectc	             C   s   |dkst |tkst|dks0t |tks0tt |tkrZx|D ]}	t |	tksBtqBW |dksrt |tksrt|dkst |tkst|dkst |tkst| jrtd|| _d| _t	j
|| j|||||||d	}
| jj|
 dS )zK
        Implements :func:`autobahn.wamp.interfaces.ISession.join`
        Nzalready joinedF)	rB   rolesauthmethodsrD   rE   	authextra	resumableresume_sessionresume_token)rW   rX   rJ   rU   dictr9   rm   r8   r   r	   ZHellor   r   send)r@   rB   r   rD   rE   r   r   r   r   rF   rb   r(   r(   r)   r,     s,    
zApplicationSession.joinc             C   s   | j r| j j  dS )zQ
        Implements :func:`autobahn.wamp.interfaces.ISession.disconnect`
        N)r   close)r@   r(   r(   r)   r0     s    zApplicationSession.disconnectc             C   s
   | j dk	S )zS
        Implements :func:`autobahn.wamp.interfaces.ISession.is_connected`
        N)r   )r@   r(   r(   r)   is_connected  s    zApplicationSession.is_connectedc             C   s   | j dk	o| jdk	S )zR
        Implements :func:`autobahn.wamp.interfaces.ISession.is_attached`
        N)r   r9   )r@   r(   r(   r)   is_attached  s    zApplicationSession.is_attachedc             C   sX   t |dr6t|jtjr6| jjd| jj|jj	 d n| jj
d| jj|tj|d dS )zR
        Implements :func:`autobahn.wamp.interfaces.ISession.onUserError`
        valuez{klass}.onUserError(): "{msg}")klassrb   z*{klass}.onUserError(): "{msg}"
{traceback})r   rb   rP   N)rI   rV   r   r   r   r2   rj   rY   rw   error_messagerL   r1   failure_format_traceback)r@   r   rb   r(   r(   r)   rq     s    zApplicationSession.onUserErrorc             C   sD   y| j || W n. tk
r>   | jjdtjtj d Y nX dS )a  
        This is an internal generic error-handler for errors encountered
        when calling down to on*() handlers that can reasonably be
        expected to be overridden in user code.

        Note that it *cancels* the error, so use with care!

        Specifically, this should *never* be added to the errback
        chain for a Deferred/coroutine that will make it out to user
        code.
        zInternal error: {tb})r`   N)rq   rm   r2   rL   r1   r   rr   )r@   r   rb   r(   r(   r)   r     s    z!ApplicationSession._swallow_errorc                s    fdd}|S )z
        Does parameter type checking and validation against type hints
        and appropriately tells the user code and the caller (through router).
        c                 s   t j f| |}g }x jj D ]\}}||kr"t|dd tkrtt|| |js|jdj	||j
t|| j
 q"t|| |s"|jdj	||j
t|| j
 q"W |rtdj|tj f| |I d H S )NZ
__origin__z'{}' required={} got={}z, )r$   getcallargs__annotations__itemsgetattrr   rV   Z__args__appendro   rw   rW   r   r,   r1   r   )rN   rO   	argumentsresponsenamekind)funcr(   r)   _type_check  s     z2ApplicationSession.type_check.<locals>._type_checkr(   )r@   r   r   r(   )r   r)   
type_check  s    zApplicationSession.type_checkc       "         s   j dkr
ttjrPtjj}fdd}fdd}tj||| nttjrt	j
jj tjj } fdd}fdd}tj||| nbttjrt	jjj}tjj|}fd	d}fd
d}tj||| ntdjjnttjrjs4tj }jj| d_ t	j
jj tjj } fdd}fdd}tj||| nttjrLjjkr8xjj D ]~}|jjp|j}	jrxjsjj djd dS y4t!j"jj#j$}
jj%d|	|
\}_&_'W n6 t(k
r\ } zjj d|jd dS d}~X nX |	|krxjj d dS j)rj)fnt* }j&r|t*j& }j'rj'nt+ }j,rt	j-|j.j/j0j1|	j2jj3d	|j,< fdd}fdd}tjj4f||}tj||| qW ntdjj	nttj5rj6j7krj7j8j6}t9j.|j:d}tj;|j<| ntdjj6	nrttj=r8j6j>kr$j>j8j6}jjkrg jj< t?j|j|j}jj j@| tj;|j<| ntdjj6nttjArj6jBkrjBj8j6}|jCjkrxj|jC D ]}d|_Dq~W j|jC= tj;|j<d ntdjj6n`ttjErj6jFkr~jFj6 }|jGd}jrȈjsd}jj | tHtHjI|}ny4t!j"jj#j$}
jj%d|
\}_&_'W nF t(k
r } z(jj d |d! tHtHjJd"j|}W Y dd}~X n2X |krȈjj d#|d$ tHtHjKd%j|}jLr|jMjNr||rjO|d& nj'pt+ }j&pt* }fd'd}|jMr\|jMjPr\tj|jMjNt	jQj&jRjSjTj3d(j'}ntj|jMjNf||}tj|d| njFj6= |j<}|rtjU|| nֈj's|jMr*|jMjPr*j'pi }j&rt	jQj&jRjSjTj3d(|}n"t	jQf jRjSjTj3d(|}tj;|| nRj&rptVj&d)kr\t	jQj& }tj;|| ntj;|j&d  ntj;|d ntd*jj6nttjW	rj6jXkrtd+jj6qjYjZkrtd,jjYqjZjY j[}jGpjGd}jrjs6d-}jj | tHtHjI|}ny4t!j"jj#j$}
jj%d|
\}_&_'W nF t(k
r } z(jj d.|d! tHtHjJd/j|}W Y dd}~X n2X |krjj d0|d$ tHtHjKd1j|}|	r
j\tjWj]j6|}jj| n|j)dk		r |j)f}nt* }j&	r<|t*j& }j'	rJj'nt+ }|j,	rj^	rrfd2d3}nd}t	j_|j`jajbjd4||j,< tj|j4f||}fd5d}fd6d}tcj6|jXj6< tj||| n$ttjd
rDj6jXk
r(jjed7j6d8 njXj6 } tjf| j< nttjg
r҈j6jhk
rjhj8j6}jYjZk
rtijY|jG|j[jZjY< ntd9jjYtj;|j< ntd:jj6nJttjjrj6dkr<yjZjY }!W n& tkk
r"   td;jjYY nX jjld<|!jGjYd= n`j6jmkrjmj8j6}|jnjZkr~djZ|jn _DjZ|jn= tj;|j< ntd>jj6n|ttjord}jptjqj]krj6jFkrjFj8j6j<}njptjrj]krj6j7krj7j8j6j<}njptjsj]krBj6j>krBj>j8j6j<}njptjtj]krrj6jBkrrjBj8j6j<}n^jptjuj]krj6jhkrjhj8j6j<}n.jptjvj]krЈj6jmkrЈjmj8j6j<}|rtjw|s
tjU|jx ntd?jjpj6ntd@jjdS )AzY
        Implements :func:`autobahn.wamp.interfaces.ITransportHandler.onMessage`
        Nc                sD  | d k	r6j jd tjddj| }jj| d S jrDj_j	_
j_j_j_j_j_tjj
jjjjjjjjtjdrjjnd jjjd jd }tj |d fdd tj | fd	dd  tj |d fd
d tj |fddd  tj |d fdd d S )NzSession denied by onWelcomezwamp.error.cannot_authenticatez{0}peer_transport)rB   sessionrD   rE   rF   rG   r   
serializerr   resumedr   r   r,   c                s    j | dS )NzWhile notifying 'join')r   )ru   )r@   r(   r)   r   B  s    z?ApplicationSession.onMessage.<locals>.success.<locals>.<lambda>c                s   t jj S )N)r1   r   onJoin)r   )detailsr@   r(   r)   r   G  s    c                s    j | dS )NzWhile firing onJoin)r   )ru   )r@   r(   r)   r   M  s    c                s    j d S )Nr.   )r   )r   )r@   r(   r)   r   R  s    c                s    j | dS )NzWhile notifying 'ready')r   )ru   )r@   r(   r)   r   X  s    )!r2   infor	   Abortro   r   r   rB   r8   r   r9   rD   r:   rE   r;   rF   r<   rG   r=   r   _router_rolesr   r   Z_serializerZSERIALIZER_IDrI   r   r   r   r   r   r1   r   )resreplyr   )rb   r@   )r   r)   success  sZ    

z-ApplicationSession.onMessage.<locals>.successc                s$   t jdd} jj|  j| dS )Nzwamp.error.cannot_authenticatezError calling onWelcome handlerzWhile firing onWelcome)r	   r   r   r   r   )ru   r   )r@   r(   r)   rL   [  s    z+ApplicationSession.onMessage.<locals>.errorc                s8   j d} fdd}fdd}tj||| |S )Nr-   c                s    S )Nr(   )r   )argr(   r)   
return_argl  s    zAApplicationSession.onMessage.<locals>.success.<locals>.return_argc                s    j | dS )NzWhile firing 'leave' event)r   )ru   )r@   r(   r)   _erroro  s    z=ApplicationSession.onMessage.<locals>.success.<locals>._error)r   r1   r   )r   r   r   r   )r   r@   )r   r)   r   h  s
    c                s    j | dS )NzWhile firing onLeave)r   )ru   )r@   r(   r)   r   t  s    z,ApplicationSession.onMessage.<locals>._errorc                s^   | d krt dt| tkr&| jd} t| tkrDt djt| tj| } jj	| d S )Nz4onChallenge user callback did not return a signatureutf8z"signature must be unicode (was {}))
rm   rW   bytesrl   rX   ro   r	   ZAuthenticater   r   )	signaturer   )r@   r(   r)   r   }  s    

c                sv   j | d tjddj| j}jj| tj|j	|j t
jj } fdd}fdd}t
j||| |S )NzAuthentication failedzwamp.error.cannot_authenticatez{0}c                s   j d  | S )Nr-   )r   )r   )r   r@   r(   r)   r     s    z<ApplicationSession.onMessage.<locals>.error.<locals>.successc                s    j | dS )NzWhile firing onLeave)r   )ru   )r@   r(   r)   r     s    z;ApplicationSession.onMessage.<locals>.error.<locals>._error)rq   r	   r   ro   r   r   r   r
   r   reasonr1   r   onLeaver   )rd   r   r   r   r   )r@   )r   r)   rL     s    z8Received {0} message, and session is not yet establishedc                s   j d  | S )Nr-   )r   )r   )r   r@   r(   r)   r     s    c                s   dj  j j}j| |S )Nz7While firing onLeave for reason "{0}" and message "{1}")ro   r   r	   r   )ru   errmsg)rb   r@   r(   r)   r     s    zjreceived encoded payload with enc_algo={enc_algo}, but no payload codec active - ignoring encoded payload!)rR   FzNfailed to decode application payload encoded with enc_algo={enc_algo}: {error})rL   rR   z-envelope topic URI does not match encoded one)	publisherpublisher_authidpublisher_authroletopicretainedrR   ri   c                sB    j r>jd jr>jr2tj j}jj| njj	d d S )NZbrokerz}successfully processed event with acknowledged delivery, but could not send ACK, since the transport was lost in the meantime)
Zx_acknowledged_deliveryr   Zx_acknowledged_event_deliveryr   r	   ZEventReceivedpublicationr   r2   rj   )r   r   )rb   r@   r(   r)   _success  s
    z.ApplicationSession.onMessage.<locals>._successc                s   dj  jj}j| |S )Nz&While firing {0} subscribed under {1}.)ro   fnsubscriptionr   )ru   r   )handlerrb   r@   r(   r)   r     s    z5EVENT received for non-subscribed subscription ID {0})was_encryptedz1PUBLISHED received for non-pending request ID {0}z2SUBSCRIBED received for non-pending request ID {0}r   z4UNSUBSCRIBED received for non-pending request ID {0}z5received encoded payload, but no payload codec activeTz.failed to decrypt application payload 1: {err})rd   z+failed to decrypt application payload 1: {}zXURI within encrypted payload ('{decrypted_proc}') does not match the envelope ('{proc}'))decrypted_procproczFURI within encrypted payload ('{}') does not match the envelope ('{}')zLcould not deliver progressive call result, because payload decryption failedc                s    j | d d S )NzWhile firing on_progress)rq   )r   )r@   r(   r)   r   X  s    )rf   rg   rh   ri      z.RESULT received for non-pending request ID {0}z6INVOCATION received for request ID {0} already invokedz:INVOCATION received for non-registered registration ID {0}z<received encrypted INVOCATION payload, but no keyring activez+failed to decrypt INVOCATION payload: {err}z(failed to decrypt INVOCATION payload: {}zcURI within encrypted INVOCATION payload ('{decrypted_proc}') does not match the envelope ('{proc}')zQURI within encrypted INVOCATION payload ('{}') does not match the envelope ('{}')c                 s   | d kst | ttfkst|d ks4t |tks4td } jr^jsLtdjjd| |}|rt	j
 j|jd|j|j|jd}nt	j
 j| |dd}jj| d S )Nz7trying to send encrypted payload, but no keyring activeFT)rQ   progressrR   rS   rT   )rN   rO   r   )rW   rU   tuplerJ   r   rR   r>   rm   r[   r	   Yieldr^   rQ   rS   rT   r   r   )rN   rO   ra   Zprogress_msg)rb   r   r@   r(   r)   r     s&    z.ApplicationSession.onMessage.<locals>.progress)r   callercaller_authidcaller_authrole	procedurerR   c          !      s*  j  j= d } jrjs,d}jj| nny:t| tjrRjj	d| j
| j}njj	d| g}W n2 tk
r } zjjd|d W Y d d }~X nX |rt| tjrtj j|j|j|j|j| j| j| j| jd	}ntj j|j|j|j|jd}nHt| tjr0tj j| j
| j| j| j| j| jd}ntj j| gd}jd krjjjd	jj j d S yjj| W n tk
r } z8tjtjj jtj d
jj|gd}jj| W Y d d }~X nV t!k
r$ } z8tjtjj jtj"djj|gd}jj| W Y d d }~X nX d S )Nz7trying to send encrypted payload, but no keyring activeFz,failed to encrypt application payload: {err})rd   )rQ   rR   rS   rT   rf   rg   rh   ri   )rQ   rR   rS   rT   )rN   rO   rf   rg   rh   ri   )rN   zCSkipping result of "{}", request {} because transport disconnected.zNsuccess return value from invoked procedure "{0}" could not be serialized: {1}zSsuccess return value from invoked procedure "{0}" exceeds transport size limit: {1})#r   r^   rR   r>   r2   rj   rV   r
   
CallResultr[   resultsZ	kwresultsrm   r	   r   rQ   rS   rT   rf   rg   rh   ri   r   debugro   r   r   r   r\   
InvocationMESSAGE_TYPEr   r5   r   r6   )r   ra   rt   ru   r   )rb   r   registrationr@   r(   r)   r     sj    

c                s   j  j= tj| }yj| | W n   Y nX d }jrFtj| }jtj	j
 j| j| j}yjj| W n tk
r } z8tjtj	j
 jtjdjj|gd}jj| W Y d d }~X nV tk
r } z8tjtj	j
 jtjdjj|gd}jj| W Y d d }~X nX d S )NzLerror return value from invoked procedure "{0}" could not be serialized: {1})rN   zSsuccess return value from invoked procedure "{0}" exceeds transport size limit: {1})r   r^   r1   Zfailure_messagerq   r3   r   rc   r	   r   r   r   rR   r   r   r   r\   r   r5   ro   r   r   r6   )rd   r   Zformatted_tbr   ru   )rb   r   r@   r(   r)   rL   C  s4    


z7INTERRUPT received for non-pending invocation {request})r^   z<REGISTERED received for already existing registration ID {0}z2REGISTERED received for non-pending request ID {0}z:UNREGISTERED received for non-existant registration ID {0}z3Router unregistered procedure '{proc}' with ID {id})r   idz4UNREGISTERED received for non-pending request ID {0}z^WampAppSession.onMessage(): ERROR received for non-pending request_type {0} and request ID {1}zUnexpected message {0})yr9   rV   r	   ZWelcomer1   r   	onWelcomer   r   r
   r   r   r   Z	ChallengemethodextraonChallenger   ro   rY   Goodbyer   r   r   Eventr   r   r   r   rR   r>   r2   rj   r   rQ   rT   rS   rl   rN   rO   rm   objr   r   details_argZEventDetailsr   r   r   r   r   ri   r   Z	Publishedr^   r   popr   r   resolveon_replyZ
Subscribedr   r   r   ZUnsubscribedr   Zsubscription_idactiveZResultr   r   r   rk   rn   rp   r   optionsZon_progressrq   r   r   rf   rg   rh   rejectlenr   r   r   r   endpointrc   r   Zreceive_progressZCallDetailsr   r   r   r!   Z	Interruptr   cancelZ
Registeredr   r   ZUnregisteredKeyErrorr   r   Zregistration_idr\   r]   CallPublish	SubscribeUnsubscribeRegister
Unregister	is_calledrv   )"r@   rb   r   r   rL   r   	challenger   r   r   ra   Zdecoded_topicru   Zinvoke_argsZinvoke_kwargsr   futureZpublish_requestr   r^   Zcall_requestrs   rt   r   kwrN   Zprog_dr   rO   r   r   r   Zinvokedregr(   )r   r   rb   r   r   r@   r)   	onMessage  s   C

0









D'
zApplicationSession.onMessagec                s   d_ jrbtjtjjdjjd tjj } fdd}fdd}tj	||| d_tjj
}fdd}fd	d}tj	||| dS )
zW
        Implements :func:`autobahn.wamp.interfaces.ITransportHandler.onClose`
        Nz=WAMP transport was lost without closing the session {} before)r   r	   c                s   j d  | S )Nr-   )r   )r   )r   r@   r(   r)   r     s    z+ApplicationSession.onClose.<locals>.successc                s    j | dS )NzWhile firing onLeave)r   )ru   )r@   r(   r)   r     s    z*ApplicationSession.onClose.<locals>._errorc                s    j d dS )Nr0   )Z	was_clean)r   )r   )r@   wasCleanr(   r)   r     s    c                s    j | dS )NzWhile firing onDisconnect)r   )ru   )r@   r(   r)   r     s    )r   r9   r
   r   ZREASON_TRANSPORT_LOSTro   r1   r   r   r   onDisconnect)r@   r  r   r   r   r(   )r   r@   r  r)   onClose  s    zApplicationSession.onClosec             C   s   t ddS )zR
        Implements :func:`autobahn.wamp.interfaces.ISession.onChallenge`
        zBreceived authentication challenge, but onChallenge not implementedN)rm   )r@   r   r(   r(   r)   r     s    zApplicationSession.onChallengec             C   s   dS )zM
        Implements :func:`autobahn.wamp.interfaces.ISession.onJoin`
        Nr(   )r@   r   r(   r(   r)   r     s    zApplicationSession.onJoinc             C   s   dS )zP
        Implements :func:`autobahn.wamp.interfaces.ISession.onWelcome`
        Nr(   )r@   rb   r(   r(   r)   r     s    zApplicationSession.onWelcomec                s   t jd}| j| j| j| j| j| jg}g }x"|D ]}|j|j	  |j
  q0W |rf| jjdt|d x`|D ]X | jjd j j jjd t j jst j j| t j| fdd fdd qlW |S )zB
        Errback any still outstanding requests with exc.
        Nz'Cancelling {count} outstanding requests)countzncleaning up outstanding {request_type} request {request_id}, firing errback on user handler {request_on_reply})Zrequest_on_reply
request_idr]   c                s    j S )N)r   )r   )r^   r(   r)   r   .  s    zBApplicationSession._errback_outstanding_requests.<locals>.<lambda>)r1   create_future_successr   r   r   r   r   r   extendvaluesclearr2   r   r   r   r   r  rY   rw   r   r   r   )r@   r_   r   Zall_requestsZoutstandingrequestsr(   )r^   r)   _errback_outstanding_requests  s2    


"z0ApplicationSession._errback_outstanding_requestsc                sX   |j tjkr" jjd|j |jd t|j |j} j|} fdd}tj	||| |S )zN
        Implements :func:`autobahn.wamp.interfaces.ISession.onLeave`
        z/session closed with reason {reason} [{message}])r   r	   c                s    j r j  d S )N)r   r0   )r   )r@   r(   r)   r0   =  s    z.ApplicationSession.onLeave.<locals>.disconnect)
r   r   ZREASON_DEFAULTr2   rj   r	   r   r  r1   r   )r@   r   r_   r   r0   r(   )r@   r)   r   1  s    
zApplicationSession.onLeavec             C   sb   | j std| js@|sd}tjj||d}| jj| d| _n| jj	d | jdkp\| jj
}|S )zL
        Implements :func:`autobahn.wamp.interfaces.ISession.leave`
        zsession hasn't joined a realmzwamp.close.normal)r   r	   TzBsession was already requested to leave - not sending GOODBYE againN)r9   r   r   r   r	   r   r   r   r2   rj   	is_closed)r@   r   r	   rb   r  r(   r(   r)   r-   C  s    zApplicationSession.leavec             C   s   t j }| j| dS )zS
        Implements :func:`autobahn.wamp.interfaces.ISession.onDisconnect`
        N)r   TransportLostr  )r@   r_   r(   r(   r)   r  X  s    zApplicationSession.onDisconnectc       
      O   s&  t |tkst|dks,t |ttfks,t|dksDt |tksDttj|dj| j	j
dddd |jdd}|rt|tj rtd| jstj | jj }d}| jr| jjd|||}|r|rtj||f|j|j|j|jd|j }ntj|||j|j|j|jd}n8|r8tj||f||d	|j }ntj||||d	}|r|jdk	rd|j|_|jdk	rx|j|_|jdk	r|j|_|j dk	r|j |_ |r|j!rt"j# }t$|||dk	d
| j%|< nd}y| jj&| W n< tk
r  }	 z|| j%kr| j%|= |	W Y dd}	~	X nX |S )zP
        Implements :func:`autobahn.wamp.interfaces.IPublisher.publish`
        Nz{}.publish()F)r	   strictallow_empty_components
allow_noner   z,options must be of type a.w.t.PublishOptionsT)rQ   rR   rS   rT   )rN   rO   )r   )'rW   rX   rJ   rU   r   r   r	   check_or_raise_uriro   rY   rw   r   rV   r
   ZPublishOptionsrm   r   r   r  r?   nextr>   r[   r   rQ   rR   rS   rT   message_attrcorrelation_idcorrelation_uricorrelation_is_anchorcorrelation_is_lastZacknowledger1   create_futurer   r   r   )
r@   r   rN   rO   r   r  ra   rb   r   ru   r(   r(   r)   publishc  s|    
	zApplicationSession.publishFc          	      s@  t |r|dk	s$t|dr | s$t|dks<t|tks<t|dksTt|tjsTt jsbt	j
  fdd}t |r|d||||S g }xtj|jtD ]}|d }d|jkrxx|jd D ]j}	|	j r|	j }
|	jp|}|dkr|	jtjjkrtjdd}ntjd	d}|j||||
||	j qW qW tj|d
dS dS )zS
        Implements :func:`autobahn.wamp.interfaces.ISubscriber.subscribe`
        NrY   c       	         s   t j|dj jjdddd  jj }tj }|r> j	|}t
|| |rN|jnd }t|||| j|< |rt j||f|j }nt j||}|r|jd k	r|j|_|jd k	r|j|_|jd k	r|j|_|jd k	r|j|_ jj| |S )Nz{}.subscribe()FT)r	   r  r  r  )r	   r  ro   rY   rw   r?   r  r1   r  r   r   r   r   r   r   r  r  r  r  r  r   r   )	r   r   r   r   check_typesr  r   Zhandler_objrb   )r@   r(   r)   
_subscribe  s2    





z0ApplicationSession.subscribe.<locals>._subscriber   rH   Zwildcard)matchexactT)consume_exceptions)callablerI   rJ   rW   rX   rV   r
   ZSubscribeOptionsr   r   r  r$   
getmembersrY   r*   __dict__Z
is_handlerr   r   Zuri_typerK   ZURI_TYPE_WILDCARDr   _check_typesr1   gather)r@   r   r   r   r  r  
on_replieskr   patrZ   Zsuboptsr(   )r@   r)   	subscribe  s,    $ 


 zApplicationSession.subscribec             C   s   t |tst|jst|j| jks(t|| j|j ks<t| jsJtj | j|j j	| d|_t
| j|j }|dkr| jj }tj }t|||j| j|< tj||j}| jj| |S tj|S dS )zU
        Called from :meth:`autobahn.wamp.protocol.Subscription.unsubscribe`
        Fr   N)rV   r   rJ   r   r   r   r   r   r  remover   r?   r  r1   r  r   r   r	   r   r   r  )r@   r   Zscountr  r   rb   r(   r(   r)   _unsubscribe  s"    

zApplicationSession._unsubscribec       	         s&  t |tkst|dks,t |ttfks,t|dksDt |tksDttj|djj	j
dddd |jdd}|rt|tj rtdjstj jj  d}jryjjd|||}W n   jj   Y nX |r2|rtj |f|j|j|j|jd|j }ntj ||j|j|j|jd}n8|rXtj |f||d	|j }ntj |||d	}|r|jdk	r|j|_|j dk	r|j |_ |j!dk	r|j!|_!|j"dk	r|j"|_" fd
d}t#j$|d}t% |||j& < yjj'| W n"    j&krj& =  Y nX |S )zJ
        Implements :func:`autobahn.wamp.interfaces.ICaller.call`
        Nz	{}.call()F)r	   r  r  r  r   z)options must be of type a.w.t.CallOptionsT)rQ   rR   rS   rT   )rN   rO   c                s   t j }jj| d S )N)r	   ZCancelr   r   )r   Z
cancel_msg)r  r@   r(   r)   	cancellerl  s    
z*ApplicationSession.call.<locals>.canceller)r,  )(rW   rX   rJ   rU   r   r   r	   r  ro   rY   rw   r   rV   r
   ZCallOptionsrm   r   r   r  r?   r  r>   r[   r2   Zfailurer   rQ   rR   rS   rT   r  r  r  r  r  r1   r  r    r   r   )	r@   r   rN   rO   r   ra   rb   r,  r   r(   )r  r@   r)   call%  s    

	zApplicationSession.callc          	      s$  t |r|dk	s$t|dr | s$t|dks<t|tks<t|dksTt|tjsTt dksjt tsjtjsxt	j
  fdd}t |r|d||||S g }xntj|jtD ]\}|d }	d|	jkrxD|	jd D ]6}
|
j r|
j }|
jp|}|j|||	|||
j qW qW tj|ddS dS )	zN
        Implements :func:`autobahn.wamp.interfaces.ICallee.register`
        NrY   c       	         s   t j|djjjdddd jj }tj }|r>j	|}t
|| |rN|jnd } d k	rhdj |}t||||j|< |rt j||f|j }nt j||}|r|jd k	r|j|_|jd k	r|j|_|jd k	r|j|_|jd k	r|j|_jj| |S )Nz{}.register()FT)r	   r  r  r  z{}{})r	   r  ro   rY   rw   r?   r  r1   r  r   r   r   r"   r   r   r  r  r  r  r  r   r   )	r   r   r   r   r  r  r   Zendpoint_objrb   )prefixr@   r(   r)   	_register  s6    





z.ApplicationSession.register.<locals>._registerr   rH   T)r   )r!  rI   rJ   rW   rX   rV   r
   ZRegisterOptionsr   r   r  r$   r"  rY   r*   r#  Zis_endpointr   r   r   r$  r1   r%  )r@   r   r   r   r.  r  r/  r&  r'  r   r(  rZ   Zregoptsr(   )r.  r@   r)   register  s&    $"

 zApplicationSession.registerc             C   sz   t |tst|jst|j| jks(t| js6tj | j	j
 }tj }t|||j| j|< tj||j}| jj| |S )zT
        Called from :meth:`autobahn.wamp.protocol.Registration.unregister`
        )rV   r   rJ   r   r   r   r   r   r  r?   r  r1   r  r#   r   r	   r   r   )r@   r   r  r   rb   r(   r(   r)   _unregister  s    

zApplicationSession._unregister)N)NNNNNNN)NN)NNF)NNNF) rw   rx   ry   rz   rA   r   r   r   r   r   r,   r0   r   r   rq   r   r   r  r  r   r   r   r  r   r-   r  r  r)  r+  r-  r0  r1  r(   r(   r(   r)   r|   7  sV   
"      #     S$&[D"bCr|   c               @   st   e Zd ZdZdZ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d Zdd Zdd Zdd ZdS )_SessionShima  
    shim that lets us present pep8 API for user-classes to override,
    but also backwards-compatible for existing code using
    ApplicationSession "directly".

    **NOTE:** this is not public or intended for use; you should import
    either :class:`autobahn.asyncio.wamp.Session` or
    :class:`autobahn.twisted.wamp.Session` depending on which async
    framework yo're using.
    Nc             C   s
   | j |S )N)on_join)r@   r   r(   r(   r)   r     s    z_SessionShim.onJoinc             C   sv   | j rjdd | j j D d }dd | j j D d	 }| j }| j| jjt| j j |pZd|p`d|d n| j  d S )
Nc             S   s   g | ]}|j jd dqS )rD   N)_argsget).0xr(   r(   r)   
<listcomp>  s    z*_SessionShim.onConnect.<locals>.<listcomp>r   c             S   s   g | ]}|j jd dqS )rE   N)r4  r5  )r6  r7  r(   r(   r)   r8    s    r   default)r   rD   rE   r   r:  )	_authenticatorsr
  _merged_authextrar,   r   rB   rU   keys
on_connect)r@   rD   rE   r   r(   r(   r)   r     s    
z_SessionShim.onConnectc             C   sB   y| j |j }W n$ tk
r4   tdj|jY nX |j| |S )Nz.Received challenge for unknown authmethod '{}')r;  r   r   RuntimeErrorro   Zon_challenge)r@   r   authenticatorr(   r(   r)   r     s    z_SessionShim.onChallengec             C   s\   |j d ks| jd krd S y| j|j  }W n$ tk
rL   tdj|j Y nX |j| |jS )Nz.Received onWelcome for unknown authmethod '{}')rF   r;  r   r?  ro   Z
on_welcomer   )r@   rb   r@  r(   r(   r)   r     s    z_SessionShim.onWelcomec             C   s
   | j |S )N)on_leave)r@   r   r(   r(   r)   r   !  s    z_SessionShim.onLeavec             C   s   | j  S )N)on_disconnect)r@   r(   r(   r)   r  $  s    z_SessionShim.onDisconnectc                s   t  tstjd kri _ fdd}|d |d  j}j }x>|j D ]2\}}||krT|| |krTtdj|||| qTW  j j	< d S )Nc                sL   t  fddtjj g D }t|dkrHtdj dj|d S )Nc                s    g | ]} |j kr|j   qS r(   )r4  )r6  a)r   r(   r)   r8  5  s   zG_SessionShim.add_authenticator.<locals>.at_most_one.<locals>.<listcomp>r   zInconsistent {}s: {} )setrU   r;  r
  r   
ValueErrorro   r,   )r   uni)r@  r@   )r   r)   at_most_one3  s    
z3_SessionShim.add_authenticator.<locals>.at_most_onerD   rE   z4Inconsistent authextra values for '{}': '{}' vs '{}')
rV   r   rJ   r;  r   r<  r   rF  ro   r   )r@   r@  rH  r   mergedr'  vr(   )r@  r@   r)   add_authenticator)  s    
z_SessionShim.add_authenticatorc                sH   dd | j j D  dd }t| t } fddfdd|D S )	a:  
        internal helper

        :returns: a single 'authextra' dict, consisting of all keys
            from any authenticator's authextra.

        Note that when the authenticator was added, we already checked
        that any keys it does contain has the same value as any
        existing authextra.
        c             S   s   g | ]
}|j qS r(   )r   )r6  rC  r(   r(   r)   r8  a  s    z2_SessionShim._merged_authextra.<locals>.<listcomp>c             S   s   | t |j B S )N)rE  r=  )r7  yr(   r(   r)   extract_keysc  s    z4_SessionShim._merged_authextra.<locals>.extract_keysc                s0   x D ]}| |kr||  S qW t dj| dS )z
            for anything already in self._authenticators, we checked
            that it has the same value for any keys in its authextra --
            so here we just extract the first one
            zNo values for '{}'N)rF  ro   )r'  r   )
authextrasr(   r)   first_value_forh  s
    
z7_SessionShim._merged_authextra.<locals>.first_value_forc                s   i | ]} ||qS r(   r(   )r6  r'  )rO  r(   r)   
<dictcomp>v  s   z2_SessionShim._merged_authextra.<locals>.<dictcomp>)r;  r
  r   rE  )r@   rM  Zunique_keysr(   )rN  rO  r)   r<  V  s    
z_SessionShim._merged_authextrac             C   s   d S )Nr(   )r@   r   r(   r(   r)   r3  ~  s    z_SessionShim.on_joinc             C   s   | j   d S )N)r0   )r@   r   r(   r(   r)   rA    s    z_SessionShim.on_leavec             C   s   | j | jj d S )N)r,   r   rB   )r@   r(   r(   r)   r>    s    z_SessionShim.on_connectc             C   s   d S )Nr(   )r@   r(   r(   r)   rB    s    z_SessionShim.on_disconnect)rw   rx   ry   rz   r;  r   r   r   r   r   r  rK  r<  r3  rA  r>  rB  r(   r(   r(   r)   r2    s   
-(r2  c               @   s&   e Zd ZdZeZdddZdd ZdS )ApplicationSessionFactoryz(
    WAMP endpoint session factory.
    Nc             C   s   |pt jdd| _dS )z

        :param config: The default component configuration.
        :type config: instance of :class:`autobahn.wamp.types.ComponentConfig`
        r}   )rB   N)r
   r~   r   )r@   r   r(   r(   r)   rA     s    z"ApplicationSessionFactory.__init__c             C   s   | j | j}| |_|S )z
        Creates a new WAMP application session.

        :returns: -- An instance of the WAMP application session class as
                     given by `self.session`.
        )r   r   factory)r@   r   r(   r(   r)   __call__  s    z"ApplicationSessionFactory.__call__)N)rw   rx   ry   rz   r|   r   rA   rS  r(   r(   r(   r)   rQ    s   
rQ  )4typingr   r1   r$   	functoolsr   Zautobahnr   Zautobahn.utilr   r   r   Zautobahn.wampr   r	   r
   r   r   Zautobahn.wamp.exceptionr   r   r   r   r   Zautobahn.wamp.interfacesr   r   Zautobahn.wamp.typesr   r   r   Zautobahn.exceptionr   Zautobahn.wamp.requestr   r   r   r   r   r   r   r   r    r!   r"   r#   r*   r+   r|   r2  objectrQ  r(   r(   r(   r)   <module>   sD   8 z           4 /