U
    e»{jIÜ  ã                   @   s   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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mZ ddlmZmZmZ ddlmZmZ ddlmZ dd	lmZmZmZ dd
l m!Z!m"Z" ddgZ#ddgZ$G dd„ dƒZ%G dd„ dƒZ&dS )é    N)Ú
urlunparse)Úlogé   )ÚSAMP_STATUS_OKÚ__profile_version__)ÚSAMPHubErrorÚSAMPProxyErrorÚSAMPWarning)Úcreate_lock_fileÚread_lockfile)ÚThreadingXMLRPCServer)ÚServerProxyPoolÚ_HubAsClientÚinternet_on)ÚWebProfileXMLRPCServerÚweb_profile_text_dialogÚSAMPHubServerÚWebProfileDialogÚ.zSAMPHubServer.*c                   @   s  e Zd ZdZdˆd	d
„Zedd„ ƒZdd„ Zdd„ Zdd„ Z	dd„ Z
d‰dd„ZdŠdd„Zdd„ Zdd„ Zdd„ Zdd „ Zd‹d"d#„Zed$d%„ ƒZd&d'„ Zd(d)„ Zd*d+„ ZdŒd,d-„Zed.d/„ ƒZd0d1„ Zd2d3„ Zd4d5„ Zd6d7„ Zd8d9„ Zd:d;„ Zd<d=„ Zd>d?„ Zd@dA„ Z dBdC„ Z!dDdE„ Z"dFdG„ Z#dHdI„ Z$dJdK„ Z%dLdM„ Z&dNdO„ Z'dPdQ„ Z(dRdS„ Z)dTdU„ Z*dVdW„ Z+e,dXdY„ ƒZ-dZd[„ Z.d\d]„ Z/d^d_„ Z0d`da„ Z1dbdc„ Z2ddde„ Z3dfdg„ Z4dhdi„ Z5djdk„ Z6dldm„ Z7dndo„ Z8dpdq„ Z9drds„ Z:dtdu„ Z;dvdw„ Z<d�dxdy„Z=dzd{„ Z>d|d}„ Z?d~d„ Z@dŽd‚dƒ„ZAd„d…„ ZBd†d‡„ ZCdS )�r   aÇ
  
    SAMP Hub Server.

    Parameters
    ----------
    secret : str, optional
        The secret code to use for the SAMP lockfile. If none is is specified,
        the :func:`uuid.uuid1` function is used to generate one.

    addr : str, optional
        Listening address (or IP). This defaults to 127.0.0.1 if the internet
        is not reachable, otherwise it defaults to the host name.

    port : int, optional
        Listening XML-RPC server socket port. If left set to 0 (the default),
        the operating system will select a free port.

    lockfile : str, optional
        Custom lockfile name.

    timeout : int, optional
        Hub inactivity timeout. If ``timeout > 0`` then the Hub automatically
        stops after an inactivity period longer than ``timeout`` seconds. By
        default ``timeout`` is set to 0 (Hub never expires).

    client_timeout : int, optional
        Client inactivity timeout. If ``client_timeout > 0`` then the Hub
        automatically unregisters the clients which result inactive for a
        period longer than ``client_timeout`` seconds. By default
        ``client_timeout`` is set to 0 (clients never expire).

    mode : str, optional
        Defines the Hub running mode. If ``mode`` is ``'single'`` then the Hub
        runs using the standard ``.samp`` lock-file, having a single instance
        for user desktop session. Otherwise, if ``mode`` is ``'multiple'``,
        then the Hub runs using a non-standard lock-file, placed in
        ``.samp-1`` directory, of the form ``samp-hub-<UUID>``, where
        ``<UUID>`` is a unique UUID assigned to the hub.

    label : str, optional
        A string used to label the Hub with a human readable name. This string
        is written in the lock-file assigned to the ``hub.label`` token.

    web_profile : bool, optional
        Enables or disables the Web Profile support.

    web_profile_dialog : class, optional
        Allows a class instance to be specified using ``web_profile_dialog``
        to replace the terminal-based message with e.g. a GUI pop-up. Two
        `queue.Queue` instances will be added to the instance as attributes
        ``queue_request`` and ``queue_result``. When a request is received via
        the ``queue_request`` queue, the pop-up should be displayed, and a
        value of `True` or `False` should be added to ``queue_result``
        depending on whether the user accepted or refused the connection.

    web_port : int, optional
        The port to use for web SAMP. This should not be changed except for
        testing purposes, since web SAMP should always use port 21012.

    pool_size : int, optional
        The number of socket connections opened to communicate with the
        clients.
    Nr   ÚsingleÚ TéR  é   c                 C   sB  t t ¡ ƒ| _d| _|| _d | _|| _|| _|| _	|| _
|| _|| _|| _|	| _|
| _|| _d | _i | _d | _d | _d | _d| _tƒ rÊz(t ¡ | _t | jp | j| jp¨d¡ W n tk
rÈ   d| _Y nX t ¡ | _d | _d | _ d | _!g | _"d | _#i | _$d| _%|| _&|  '¡ | _(d| _)i | _*i | _+i | _,i | _-i | _.i | _/d| _0d S )NFú	127.0.0.1r   r   éÿÿÿÿ)1ÚstrÚuuidÚuuid1Ú_idÚ_is_runningÚ_customlockfilenameÚ	_lockfileÚ_addrÚ_portÚ_modeÚ_labelÚ_timeoutÚ_client_timeoutÚ
_pool_sizeÚ_web_profileÚ_web_profile_dialogÚ	_web_portÚ_web_profile_serverÚ_web_profile_callbacksÚ_web_profile_requests_queueÚ_web_profile_requests_resultÚ_web_profile_requests_semaphoreÚ
_host_namer   ÚsocketÚgetfqdnÚgetaddrinfoÚOSErrorÚ	threadingÚLockÚ_thread_lockÚ_thread_runÚ_thread_hub_timeoutÚ_thread_client_timeoutÚ_launched_threadsÚ_last_activity_timeÚ_client_activity_timeÚ_hub_msg_id_counterÚ_hub_secret_code_customizedÚ_create_secret_codeÚ_hub_secretÚ_hub_public_idÚ_private_keysÚ	_metadataÚ
_mtype2idsÚ
_id2mtypesÚ_xmlrpc_endpointsÚ_sync_msg_ids_heapÚ_client_id_counter)ÚselfÚsecretÚaddrÚportZlockfileÚtimeoutZclient_timeoutÚmodeÚlabelÚweb_profileZweb_profile_dialogZweb_portZ	pool_size© rS   úO/var/www/html/bwave/python/venv/lib/python3.8/site-packages/astropy/samp/hub.pyÚ__init___   sX    


zSAMPHubServer.__init__c                 C   s   | j S )z$
        The unique hub ID.
        )r   ©rK   rS   rS   rT   ÚidÀ   s    zSAMPHubServer.idc                 C   sä   |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | j	d	¡ |  | j
d
¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ d S )Nzsamp.hub.pingzsamp.hub.setXmlrpcCallbackzsamp.hub.registerzsamp.hub.unregisterzsamp.hub.declareMetadatazsamp.hub.getMetadatazsamp.hub.declareSubscriptionszsamp.hub.getSubscriptionszsamp.hub.getRegisteredClientszsamp.hub.getSubscribedClientszsamp.hub.notifyzsamp.hub.notifyAllzsamp.hub.callzsamp.hub.callAllzsamp.hub.callAndWaitzsamp.hub.reply)Úregister_functionÚ_pingÚ_set_xmlrpc_callbackÚ	_registerÚ_unregisterÚ_declare_metadataÚ_get_metadataÚ_declare_subscriptionsÚ_get_subscriptionsÚ_get_registered_clientsÚ_get_subscribed_clientsÚ_notifyÚ_notify_allÚ_callÚ	_call_allÚ_call_and_waitÚ_reply©rK   ÚserverrS   rS   rT   Ú_register_standard_apiÇ   s8     ÿ ÿ ÿ ÿz$SAMPHubServer._register_standard_apic                 C   sò   |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | j	d	¡ |  | j
d
¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ |  | jd¡ d S )Nzsamp.webhub.pingzsamp.webhub.unregisterzsamp.webhub.declareMetadatazsamp.webhub.getMetadataz samp.webhub.declareSubscriptionszsamp.webhub.getSubscriptionsz samp.webhub.getRegisteredClientsz samp.webhub.getSubscribedClientszsamp.webhub.notifyzsamp.webhub.notifyAllzsamp.webhub.callzsamp.webhub.callAllzsamp.webhub.callAndWaitzsamp.webhub.replyzsamp.webhub.registerz!samp.webhub.allowReverseCallbackszsamp.webhub.pullCallbacks)rX   rY   r\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   Ú_web_profile_registerÚ"_web_profile_allowReverseCallbacksÚ_web_profile_pullCallbacksri   rS   rS   rT   Ú_register_web_profile_apiä   sF     ÿ ÿ ÿ ÿ ÿ ÿz'SAMPHubServer._register_web_profile_apic                 C   s‚   t | jp| j| jpdftddd�| _d}| jj ¡ d | _| jpD| j› d| j› �}t||ddddfƒ| _	| j 
¡  |  | j¡ d S )	Nr   FT©ZlogRequestsÚ
allow_noneÚhttpr   ú:r   )r   r"   r1   r#   r   Ú_serverr2   Úgetsocknamer   Ú_urlÚ register_introspection_functionsrk   )rK   ZprotrM   rS   rS   rT   Ú_start_standard_server  s    ü
z$SAMPHubServer._start_standard_serverc                 C   sÖ   t  d¡| _t  d¡| _t  d¡| _| jd k	rB| j| j_| j| j_zNtd| j	ft
ddd�| _| jj ¡ d | _	| j ¡  |  | j¡ t
 d¡ W n@ tk
rÐ   t
 d | j	¡t¡ d| _d | _d | _d | _Y nX d S )Nr   Ú	localhostFTrp   z0Hub set to run with Web Profile support enabled.zKPort {} already in use. Impossible to run the Hub with Web Profile support.)ÚqueueÚQueuer.   r/   r0   r*   Úqueue_requestÚqueue_resultr   r+   r   r,   r2   ru   rw   ro   Úinfor5   ÚwarningÚformatr	   r)   rV   rS   rS   rT   Ú_start_web_profile_server  s8    


   ÿ
ÿýz'SAMPHubServer._start_web_profile_serverc                 C   sb   g }| j D ]}| ¡ s
| |¡ q
|D ]}| j  |¡ q&tj||||d�}| ¡  | j  |¡ d S )N)ÚgroupÚtargetÚnameÚargs)r<   Úis_aliveÚappendÚremover6   ÚThreadÚstart)rK   r‚   rƒ   r„   r…   rˆ   ÚtrS   rS   rT   Ú_launch_thread3  s    
zSAMPHubServer._launch_threadc                 C   s   | j D ]}|j|d� qd S ©N©rO   )r<   Újoin)rK   rO   r‹   rS   rS   rT   Ú_join_launched_threadsC  s    
z$SAMPHubServer._join_launched_threadsc              	   C   s’   | j dkrd S t ¡ }| jrŽt d¡ t ¡ }|| dkr| j�B | jd k	r~|| j | j kr~t dt¡ |  	¡  W 5 Q R £ d S W 5 Q R X |}qd S )Nr   çš™™™™™©?ç      ð?z&Timeout expired, Hub is shutting down!)
r&   Útimer   Úsleepr8   r=   ÚwarningsÚwarnr	   Ústop)rK   ÚlastÚnowrS   rS   rT   Ú_timeout_test_hubG  s"    


 ÿzSAMPHubServer._timeout_test_hubc                 C   sš   | j dkrd S t ¡ }| jr–t d¡ t ¡ }|| dkr| j ¡ D ]J}|| j|  | j krD|| jkrDt d|› d�t	¡ |  
|¡ |  |¡ qD|}qd S )Nr   r‘   r’   zClient z timeout expired!)r'   r“   r   r”   r>   ÚkeysÚ_hub_private_keyr•   r–   r	   Ú_notify_disconnectionr\   )rK   r˜   r™   Úprivate_keyrS   rS   rT   Ú_timeout_test_clientZ  s*    

ÿÿý
 ÿ
z"SAMPHubServer._timeout_test_clientc                 C   sL   |dkr| j |Ž S |dkr$| j|Ž S |dkr6| j|Ž S |dkrH| j|Ž S d S )Nzsamp.client.receiveCallzsamp.client.receiveNotificationzsamp.client.receiveResponseúsamp.app.ping)Ú_receive_callÚ_receive_notificationÚ_receive_responserY   )rK   Úmethodr…   rS   rS   rT   Ú_hub_as_client_request_handlerp  s    


z,SAMPHubServer._hub_as_client_request_handlerc                 C   sn   d| j dd| jd dœ}|  | j¡}|d | _|d | _|  | j| j¡ |  | j|¡ |  | ji i dœ¡ d S )	NzAstropy SAMP HubzThe Astropy Collaborationz'https://docs.astropy.org/en/stable/sampz
/samp/icon)ú	samp.namezsamp.description.textzauthor.namezsamp.documentation.urlzsamp.icon.urlúsamp.self-idúsamp.private-key)r    úx-samp.query.by-meta)	r%   rv   r[   rB   rC   rœ   rZ   r]   r_   )rK   Zhub_metadataÚresultrS   rS   rT   Ú_setup_hub_as_clientz  s    û

 ÿz"SAMPHubServer._setup_hub_as_clientFc                 C   s�   | j rtdƒ‚| jdk	r tdƒ‚| jr.|  ¡  |  ¡  t| j| j| j	| j
d�| _|  ¡  |  ¡  |  ¡  t d¡ |rŒ| j rŒ| j ¡  d| _dS )a<  
        Start the current SAMP Hub instance and create the lock file. Hub
        start-up can be blocking or non blocking depending on the ``wait``
        parameter.

        Parameters
        ----------
        wait : bool
            If `True` then the Hub process is joined with the caller, blocking
            the code flow. Usually `True` option is used to run a stand-alone
            Hub in an executable script. If `False` (default), then the Hub
            process runs in a separated thread. `False` is usually used in a
            Python shell.
        zHub is already runningNz&Hub is not running but lockfile is set)ZlockfilenamerP   Zhub_idZ
hub_paramszHub started)r   r   r!   r)   r�   rx   r
   r    r$   rW   ÚparamsÚ_update_last_activity_timer«   Ú_start_threadsr   r~   r9   r�   )rK   ÚwaitrS   rS   rT   rŠ   Œ  s(    
ü


zSAMPHubServer.startc                 C   sD   i }| j |d< | j|d< t|d< | j|d< | jp:d| j› �|d< |S )zG
        The hub parameters (which are written to the logfile)
        úsamp.secretzsamp.hub.xmlrpc.urlzsamp.profile.versionzhub.idzHub z	hub.label)rB   rv   r   rW   r%   )rK   r¬   rS   rS   rT   r¬   ¹  s    


zSAMPHubServer.paramsc                 C   s¬   t j| jd�| _d| j_| jdkr>t j| jdd�| _d| j_nd | _| jdkrjt j| j	dd�| _
d| j
_nd | _
d| _| j ¡  | jd k	r”| j ¡  | j
d k	r¨| j
 ¡  d S )N)rƒ   Tr   zHub timeout test)rƒ   r„   zClient timeout test)r6   r‰   Ú_serve_foreverr9   Údaemonr&   rš   r:   r'   rŸ   r;   r   rŠ   rV   rS   rS   rT   r®   Î  s,    
 ÿ

 ÿ




zSAMPHubServer._start_threadsc                 C   s    | j d k	r| j S tt ¡ ƒS d S ©N)r@   r   r   r   rV   rS   rS   rT   rA   ê  s    
z!SAMPHubServer._create_secret_codec                 C   s´   | j s
dS t d¡ |  ¡  d| _ | jrZtj | j¡rZt| jƒ}|d | j	krZt 
| j¡ d| _| jdd� d| _|  ¡ | _	d| _i | _i | _i | _i | _i | _d| _t d	¡ dS )
zN
        Stop the current SAMP Hub instance and delete the lock file.
        NzHub is stopping...Fr°   g      $@rŽ   r   r   zHub stopped.)r   r   r~   Ú_notify_shutdownr!   ÚosÚpathÚisfiler   rB   rˆ   Ú_join_all_threadsr?   rA   rC   rE   rD   rF   rG   rH   r=   )rK   ZlockfiledictrS   rS   rT   r—   ð  s*    


zSAMPHubServer.stopc                 C   s¤   t  ¡ }| j|k	r0| jj|d� | j ¡ s0d | _| jd k	rb| j|k	rb| jj|d� | j ¡ sbd | _| jd k	r”| j|k	r”| jj|d� | j ¡ s”d | _| j|d� d S r�   )r6   Úcurrent_threadr9   r�   r†   r:   r;   r�   )rK   rO   r¹   rS   rS   rT   r¸     s(    

ÿþ
ÿþ
zSAMPHubServer._join_all_threadsc                 C   s   | j S )z™Return an information concerning the Hub running status.

        Returns
        -------
        running : bool
            Is the hub running?
        )r   rV   rS   rS   rT   Ú
is_running.  s    	zSAMPHubServer.is_runningc              
   C   s6  | j �rzt | jjgg g d¡d }W n4 tk
rZ } zt d|› �t¡ W 5 d }~X Y nX |rj| j ¡  | j	r | j
d kr¬z| j ¡ }W n tjk
rž   Y nX t|| jƒ zt | jjgg g d¡d }W n6 tk
�r  } zt d|› �t¡ W 5 d }~X Y q X |r | j ¡  q | j ¡  | jd k	�r2| j ¡  d S )Nç{®Gáz„?r   z*Call to select() in SAMPHubServer failed: )r   Úselectrt   r2   r5   r•   r–   r	   Úhandle_requestr)   r*   r.   Ú
get_nowaitrz   ÚEmptyr   r/   r,   Úserver_close)rK   Z
read_readyÚexcÚrequestrS   rS   rT   r±   9  sN     ÿ

 ÿ   ÿþ ÿ
zSAMPHubServer._serve_foreverc              	   C   sR   t  d¡}|D ]>}|| jkr| j| D ]$}|  | j| j| d di dœ¡ q&qd S )Nzsamp.hub.event.shutdownr   ©ú
samp.mtypeúsamp.params)r   Úget_mtype_subtypesrF   Ú_notify_rœ   rD   )rK   ÚmsubsÚmtypeÚkeyrS   rS   rT   r´   d  s    

ýzSAMPHubServer._notify_shutdownc              	   C   sd   t  d¡}|D ]P}|| jkr| j| d }| j| D ](}|  | j| j| d dd|idœ¡ q4qd S )Nzsamp.hub.event.registerr   rW   rÃ   ©r   rÆ   rF   rD   rc   rœ   ©rK   rž   rÈ   rÉ   Ú	public_idrÊ   rS   rS   rT   Ú_notify_registero  s    

þýzSAMPHubServer._notify_registerc              	   C   sl   t  d¡}|D ]X}|| jkr| j| d }| j| D ]0}||kr4|  | j| j| d dd|idœ¡ q4qd S )Nzsamp.hub.event.unregisterr   rW   rÃ   rË   rÌ   rS   rS   rT   Ú_notify_unregister  s    

þýz SAMPHubServer._notify_unregisterc              
   C   sl   t  d¡}|D ]X}|| jkr| j| d }| j| D ]0}|  | j| j| d d|| j| dœdœ¡ q4qd S )Nzsamp.hub.event.metadatar   )rW   ÚmetadatarÃ   )r   rÆ   rF   rD   rc   rœ   rE   rÌ   rS   rS   rT   Ú_notify_metadata�  s    

þþýzSAMPHubServer._notify_metadatac              
   C   sl   t  d¡}|D ]X}|| jkr| j| d }| j| D ]0}|  | j| j| d d|| j| dœdœ¡ q4qd S )Nzsamp.hub.event.subscriptionsr   )rW   ZsubscriptionsrÃ   )r   rÆ   rF   rD   rc   rœ   rG   rÌ   rS   rS   rT   Ú_notify_subscriptions¢  s    

þþýz#SAMPHubServer._notify_subscriptionsc              	   C   s†   dd„ }t  d¡}| j| d }| j| d }|D ]N}|| jkr2|| j| kr2t d|› �¡ | j|||| jdddid	œfd
� q2d S )Nc                 S   s   | j j |||¡ d S r³   )ÚsampÚclientÚreceiveNotification)Úendpointrž   Úhub_public_idÚmessagerS   rS   rT   Ú_xmlrpc_call_disconnectµ  s
      ÿzDSAMPHubServer._notify_disconnection.<locals>._xmlrpc_call_disconnectzsamp.hub.disconnectr   r   znotify disconnection to ÚreasonúTimeout expired!rÃ   ©rƒ   r…   )	r   rÆ   rD   rH   rF   r   ÚdebugrŒ   rC   )rK   rž   rÙ   rÈ   rÍ   rÖ   rÉ   rS   rS   rT   r�   ´  s"    
þüþz#SAMPHubServer._notify_disconnectionc                 C   s   |   ¡  t d¡ dS )NZpingÚ1)r­   r   rÝ   rV   rS   rS   rT   rY   Î  s    
zSAMPHubServer._pingc                 C   sH   g }| j D ]8}|| j | kr
| j | | |kr
| | j| d ¡ q
|S ©Nr   )rE   r‡   rD   )rK   rÊ   ÚvalueZpublic_id_listZ
private_idrS   rS   rT   Ú_query_by_metadataÓ  s    
z SAMPHubServer._query_by_metadatac                 C   s¦   |   |¡ || jkr�|| jkrD| j| d }|t| jƒf| j|< dS t d|› d|› �¡ d }t| j	t
j|dd�}| j| d }||f| j|< ntdd|› d	�ƒ‚dS )
Nr   r   zset_xmlrpc_callback: ú r   )rq   é   úPrivate-key ú expired or invalid.)r­   rD   rœ   r   r¥   rH   r   rÝ   r   r(   ÚxmlrpcÚServerProxyr   )rK   rž   Zxmlrpc_addrrÍ   Zserver_proxy_poolrS   rS   rT   rZ   Ü  s(    


þ
   ÿz"SAMPHubServer._set_xmlrpc_callbackc              	   C   sh   | j � |  ¡ \}}W 5 Q R X |t ¡ f| j|< |  |¡ |  |¡ t d|› d|› �¡ ||| jdœS )Nzregister: private-key = z and self-id = )r§   r¨   zsamp.hub-id)	r8   Ú_get_new_idsr“   rD   r­   rÎ   r   rÝ   rC   ©rK   rž   rÍ   rS   rS   rT   Ú_perform_standard_registerø  s    

ýz(SAMPHubServer._perform_standard_registerc                 C   s(   |   ¡  || jkr|  ¡ S tddƒ‚d S )Né   zBad secret code)r­   rB   rê   r   )rK   rL   rS   rS   rT   r[     s    
zSAMPHubServer._registerc                 C   s<   t t ¡ ƒ}|  jd7  _d}| jdkr4d| j› �}||fS )Nr   zcli#hubr   zcli#)r   r   r   rJ   ré   rS   rS   rT   rè     s    
zSAMPHubServer._get_new_idsc              	   C   s  |   ¡  d}|  |¡ | j�Ð || jkr@| j| d }| j|= nW 5 Q R £ dS || jkr`| j|= || jkrr| j|= | j ¡ D ]"}|| j| kr|| j|  |¡ q||| j	kr²| j	|= || j
krÄ| j
|= | jrè|| jkrÜ| j|= | j |¡ W 5 Q R X t d|› d|› d�¡ dS )Nr   r   zunregister z (ú))r­   rÏ   r8   rD   rE   rG   rF   r›   rˆ   rH   r>   r)   r-   r,   Zremove_clientr   rÝ   )rK   rž   Z
public_keyrÉ   rS   rS   rT   r\     s2    







zSAMPHubServer._unregisterc                 C   sV   |   |¡ || jkr@t d |t|ƒ¡¡ || j|< |  |¡ ntdd|› d�ƒ‚dS )Nz0declare_metadata: private-key = {} metadata = {}rã   rä   rå   r   )	r­   rD   r   rÝ   r€   r   rE   rÑ   r   )rK   rž   rÐ   rS   rS   rT   r]   =  s    

 ÿÿ
zSAMPHubServer._declare_metadatac                 C   sŠ   |   |¡ || jkrt|  |¡}t d ||¡¡ |d k	rh|| jkrbt d| j| › �¡ | j| S i S q†tddƒ‚ntdd|› d�ƒ‚d S )Nz-get_metadata: private-key = {} client-id = {}z--> metadata = é   úInvalid client IDrã   rä   rå   )r­   rD   Ú_public_id_to_private_keyr   rÝ   r€   rE   r   ©rK   rž   Z	client_idZclient_private_keyrS   rS   rT   r^   K  s     


 ÿÿ

zSAMPHubServer._get_metadatac              	   C   sP  |   |¡ || jk�r:t d |t|ƒ¡¡ || jkrt| j| }|D ].}z| j|  |¡ W qD t	k
rp   Y qDX qDt
 |¡| j|< t
 |¡}|D ]@}| d¡r’|D ],}| |d d… ¡r¤||kr¤||kr¤||= q¤q’t d |t|ƒ¡¡ |D ]>}|| jk�r || j| k�r,| j|  |¡ qî|g| j|< qî|  |¡ ntdd|› d�ƒ‚dS )	Nz3declare_subscriptions: private-key = {} mtypes = {}Ú*r   z;declare_subscriptions: subscriptions accepted from {} => {}rã   rä   rå   r   )r­   rD   r   rÝ   r€   r   rG   rF   rˆ   Ú
ValueErrorÚcopyÚdeepcopyÚendswithÚ
startswithr‡   rÒ   r   )rK   rž   ZmtypesZprev_mtypesrÉ   Zoriginal_mtypesZmtype2rS   rS   rT   r_   _  sJ    
 ÿÿ




 ÿÿz$SAMPHubServer._declare_subscriptionsc                 C   sŽ   |   |¡ || jkrx|  |¡}|d k	rl|| jkrVt d |t| j| ƒ¡¡ | j| S t d |¡¡ i S qŠtddƒ‚ntdd|› d�ƒ‚d S )Nz-get_subscriptions: client-id = {} mtypes = {}z2get_subscriptions: client-id = {} mtypes = missingrí   rî   rã   rä   rå   )	r­   rD   rï   rG   r   rÝ   r€   r   r   rð   rS   rS   rT   r`   “  s(    



 ÿÿ
ÿÿz SAMPHubServer._get_subscriptionsc                 C   sp   |   |¡ || jkrZg }| j ¡ D ] }||kr"| | j| d ¡ q"t d ||¡¡ |S tdd|› d�ƒ‚d S )Nr   z5get_registered_clients: private_key = {} clients = {}rã   rä   rå   )r­   rD   r›   r‡   r   rÝ   r€   r   )rK   rž   Zreg_clientsÚpkeyrS   rS   rT   ra   ¬  s    

 ÿÿz%SAMPHubServer._get_registered_clientsc                 C   s|   |   |¡ || jkrfi }| j ¡ D ]*}||kr"|  ||¡r"i || j| d < q"t d |||¡¡ |S tdd|› d�ƒ‚d S )Nr   z@get_subscribed_clients: private_key = {} mtype = {} clients = {}rã   rä   rå   )r­   rD   r›   Ú_is_subscribedr   rÝ   r€   r   )rK   rž   rÉ   Zsub_clientsr÷   rS   rS   rT   rb   ½  s    

  ÿÿz%SAMPHubServer._get_subscribed_clientsc                 C   s|   g }|   d¡}ttt|ƒƒƒ}| ¡  | d¡ |D ]B}d |d|d … ¡}|| krl|dkrh|d }nd}| |¡ q4|S )aÒ  
        Return a list containing all the possible wildcarded subtypes of MType.

        Parameters
        ----------
        mtype : str
            MType to be parsed.

        Returns
        -------
        types : list
            List of subtypes

        Examples
        --------
        >>> from astropy.samp import SAMPHubServer
        >>> SAMPHubServer.get_mtype_subtypes("samp.app.ping")
        ['samp.app.ping', 'samp.app.*', 'samp.*', '*']
        r   r   Nr   r   z.*rñ   )ÚsplitÚlistÚrangeÚlenÚreverser‡   r�   )rÉ   ÚsubtypesrÈ   ZindexesÚiZ	tmp_mtyperS   rS   rT   rÆ   Ï  s    


z SAMPHubServer.get_mtype_subtypesc                 C   s8   d}t  |¡}|D ] }|| jkr|| j| krd}q|S )NFT)r   rÆ   rF   )rK   rž   rÉ   Z
subscribedrÈ   ZmsubrS   rS   rT   rø   ÷  s    

zSAMPHubServer._is_subscribedc                 C   sp   |   |¡ || jkrZ|  |  |¡|d ¡s@tdd ||d ¡ƒ‚| j| j|||fd� i S tdd|› d�ƒ‚d S )NrÄ   é   ú$Client {} not subscribed to MType {}rÜ   rã   rä   rå   )r­   rD   rø   rï   r   r€   rŒ   rÇ   )rK   rž   Úrecipient_idrØ   rS   rS   rT   rc     s(    

 ÿÿ ÿþ ÿzSAMPHubServer._notifyc           	      C   s¢   || j krd S | j | d }zBt d |d ||¡¡ |  |¡}||f}d}|  ||||¡ W n> tk
rœ } z t d |d |||¡t	¡ W 5 d }~X Y nX d S )Nr   znotify {} from {} to {}rÄ   rÕ   z7{} notification from client {} to client {} failed [{}])
rD   r   rÝ   r€   rï   Ú_retry_methodÚ	Exceptionr•   r–   r	   )	rK   Úsender_private_keyÚrecipient_public_idrØ   Úsender_public_idÚrecipient_private_keyÚ
arg_paramsÚsamp_method_namerÁ   rS   rS   rT   rÇ     s<    
  ÿÿ
   ÿ   ÿüzSAMPHubServer._notify_c                 C   sL   |   |¡ || jkr6d|kr&tddƒ‚|  ||¡}|S tdd|› d�ƒ‚d S )NrÄ   é   zsamp.mtype keyword is missingrã   rä   rå   )r­   rD   r   Ú_notify_all_)rK   rž   rØ   Úrecipient_idsrS   rS   rT   rd   7  s    


zSAMPHubServer._notify_allc                 C   sp   g }t  |d ¡}|D ]T}|| jkr| j| D ]:}||kr.| j| d }| |¡ | j| j|||fd� q.q|S ©NrÄ   r   rÜ   )r   rÆ   rF   rD   r‡   rŒ   rc   )rK   r  rØ   r  rÈ   rÉ   rÊ   Z_recipient_idrS   rS   rT   r  B  s    

þ
zSAMPHubServer._notify_all_c                 C   sŽ   |   |¡ || jkrx|  |  |¡|d ¡s@tdd ||d ¡ƒ‚| j| d }|  ||¡}| j| j|||||fd� |S tdd|› d�ƒ‚d S )	NrÄ   r   r  r   rÜ   rã   rä   rå   )	r­   rD   rø   rï   r   r€   Ú_get_new_hub_msg_idrŒ   Ú_call_)rK   rž   r  Úmsg_tagrØ   rÍ   Úmsg_idrS   rS   rT   re   S  s,    

 ÿÿ ÿþþzSAMPHubServer._callc           
      C   s´   || j krd S zPt d | d¡d |||d ¡¡ |  |¡}|||f}d}|  ||||¡ W nP tk
r® }	 z2t 	d |d | d¡d ||t
|	ƒ|	¡t¡ W 5 d }	~	X Y nX d S )Nzcall {} from {} to {} ({})ú;;r   rÄ   ZreceiveCallz5{} call {} from client {} to client {} failed [{},{}])rD   r   rÝ   r€   rù   rï   r  r  r•   r–   Útyper	   )
rK   r  r  r  r  rØ   r  r	  Zsamp_methodNamerÁ   rS   rS   rT   r  l  s@    
üÿ	

   ÿú÷zSAMPHubServer._call_c                 C   sd   |   |¡ || jkrNd|kr,tdd |¡ƒ‚| j| d }|  ||||¡}|S tdd|› d�ƒ‚d S )NrÄ   r  z5samp.mtype keyword is missing in message tagged as {}r   rã   rä   rå   )r­   rD   r   r€   Ú
_call_all_)rK   rž   r  rØ   rÍ   r  rS   rS   rT   rf   ‘  s    

ÿþzSAMPHubServer._call_allc              	   C   s~   i }t  |d ¡}|D ]b}|| jkr| j| D ]H}||kr.|  ||¡}	| j| d }
|	||
< | j| j|||
|	|fd� q.q|S r  )r   rÆ   rF   r  rD   rŒ   r  )rK   r  r  r  rØ   r  rÈ   rÉ   rÊ   Z_msg_idZreceiver_public_idrS   rS   rT   r  £  s&    
ûþ

zSAMPHubServer._call_all_c                 C   sÈ   |   |¡ || jkr²t|ƒ}t ¡ }i }|  ||d|¡}d | j|< | jr®d|  k rdt ¡ | krzn n| j|= tddƒ‚| j| d k	r¢t 	| j| ¡}| j|= q®t 
d¡ qB|S tdd|› d�ƒ‚d S )	Núsamp::sync::callr   r   rÛ   r»   rã   rä   rå   )r­   rD   Úintr“   re   rI   r   r   ró   rô   r”   )rK   rž   r  rØ   rO   r™   Úresponser  rS   rS   rT   rg   º  s$    


 
zSAMPHubServer._call_and_waitc                 C   sB   |   |¡ || jkr,| j| j|||fd� ntdd|› d�ƒ‚i S )z�
        The main method that gets called for replying. This starts up an
        asynchronous reply thread and returns.
        rÜ   rã   rä   rå   )r­   rD   rŒ   Ú_reply_r   )rK   rž   r  r  rS   rS   rT   rh   Õ  s    

 ÿzSAMPHubServer._replyc                 C   sÖ   || j ks|sd S | j | d }| dd¡\}}}}zbt d |||¡¡ |dkrl|| j ¡ kr”|| j|< n(|  |¡}	|||f}
d}|  |	|||
¡ W n: t	k
rÐ } zt
 d ||||¡t¡ W 5 d }~X Y nX d S )Nr   r  r  zreply {} from {} to {}r  ZreceiveResponsez0{} reply from client {} to client {} failed [{}])rD   rù   r   rÝ   r€   rI   r›   rï   r  r  r•   r–   r	   )rK   Zresponder_private_keyr  r  Zresponder_public_idÚcounterr×   r  Zrecipient_msg_tagr  r	  r
  rÁ   rS   rS   rT   r  ä  sN     ÿ  ÿÿÿ
ü   ÿüzSAMPHubServer._reply_c                 C   s  |dkrt dƒ‚ddlm} t|jƒD ]¼}| js<t d¡ q&zV| jrj|| j	krj||dœ}| j	|  
|¡ n&| j| d }t|jj|ƒ|f|žŽ  W nH tjk
rÚ }	 z(t d ||d |	j¡¡ t d¡ W 5 d}	~	X Y q&X  dS q&|d t|jƒ d	 }
t |
ƒ‚dS )
aÉ  
        This method is used to retry a SAMP call several times.

        Parameters
        ----------
        recipient_private_key
            The private key of the receiver of the call
        recipient_public_key
            The public key of the receiver of the call
        samp_method_name : str
            The name of the SAMP method to call
        arg_params : tuple
            Any additional arguments to be passed to the SAMP method
        Nrî   r   )Úconfr»   )zsamp.methodNamerÅ   z*{} XML-RPC endpoint error (attempt {}): {}z failed after z	 attempts)r   r   r  rû   Z	n_retriesr   r“   r”   r)   r-   ÚputrH   ÚgetattrrÓ   rÔ   ræ   ÚFaultr   rÝ   r€   ÚfaultStringr   )rK   r  r  r
  r	  r  ÚattemptÚcallbackZhubrÁ   Úerror_messagerS   rS   rT   r    sF    
ÿþþÿÿ
  ÿÿÿzSAMPHubServer._retry_methodc                 C   s.   | j  ¡ D ]}| j | d |kr
|  S q
d S rß   )rD   r›   )rK   rÍ   rž   rS   rS   rT   rï   M  s    
z'SAMPHubServer._public_id_to_private_keyc              	   C   s4   | j � |  jd7  _W 5 Q R X d | j| j||¡S )Nr   zmsg#{};;{};;{};;{})r8   r?   r€   rC   )rK   r  Zsender_msg_idrS   rS   rT   r  S  s    üz!SAMPHubServer._get_new_hub_msg_idc              	   C   s6   | j �& t ¡ | _|d k	r(t ¡ | j|< W 5 Q R X d S r³   )r8   r“   r=   r>   )rK   rž   rS   rS   rT   r­   ]  s    
z(SAMPHubServer._update_last_activity_timec                 C   s   dS ©Nr   rS   )rK   rž   Ú	sender_idrØ   rS   rS   rT   r¢   c  s    z#SAMPHubServer._receive_notificationc                 C   s˜   || j kr�d|kr6|d dkr6|  | j |ti dœ¡ nVd|krŒ|d dksV|d dkrŒ|  |d d |d d ¡}|  | j |td	|idœ¡ d
S d
S d S )NrÄ   r    )zsamp.statuszsamp.resultr©   zsamp.query.by-metarÅ   rÊ   rà   Zidsr   )rœ   rh   r   rá   )rK   rž   r$  r  rØ   Zids_listrS   rS   rT   r¡   f  s.    
ý
ÿ
þ
 
ÿýzSAMPHubServer._receive_callc                 C   s   dS r#  rS   )rK   rž   Zresponder_idr  r  rS   rS   rT   r£   €  s    zSAMPHubServer._receive_response©Úunknownr   r&  c                 C   s¼   |   ¡  |d dkrtddƒ‚|s&d}t|tƒrBd|krBtddƒ‚| j d¡ | j |||f¡ | j ¡ }| j ¡  |r®|  	¡ }d	 
| j|d
 ¡}||d< | j |d
 ¡ |S tddƒ‚d S )Nr   )ry   r   i“  z,Request of registration rejected by the Hub.r&  r¦   zLRequest of registration rejected by the Hub (application name not provided).r¯   z&http://localhost:{}/translator/{}?ref=r¨   zsamp.url-translatorz-Request of registration rejected by the user.)r­   r   Ú
isinstanceÚdictr0   r  r.   r/   Úgetrê   r€   r+   r,   Z
add_client)rK   Zidentity_infoÚclient_addressÚoriginr  Zregister_mapZtranslator_urlrS   rS   rT   rl   ƒ  s2    

þ

 ÿz#SAMPHubServer._web_profile_registerc                 C   sT   |   ¡  || jkr>|dkr.|| jkr<| j|= qPt ¡ | j|< ntdd|› d�ƒ‚dS )NÚ0rã   rä   rå   r   )r­   rD   r-   rz   r{   r   )rK   rž   ZallowrS   rS   rT   rm   ¬  s    


z0SAMPHubServer._web_profile_allowReverseCallbacksc                 C   sp   |   ¡  || jkrZg }| j| }z| jr<| ¡ }| |¡ q"W n tjk
rT   Y nX |S tdd|› d�ƒ‚d S )Nrã   rä   rå   )	r­   rD   r-   r   r¾   r‡   rz   r¿   r   )rK   rž   Ztimeout_secsr!  Zcallback_queueZitem_queuedrS   rS   rT   rn   ¸  s    

z(SAMPHubServer._web_profile_pullCallbacks)NNr   Nr   r   r   r   TNr   r   )NNNN)N)F)N)N)r%  r&  )DÚ__name__Ú
__module__Ú__qualname__Ú__doc__rU   ÚpropertyrW   rk   ro   rx   r�   rŒ   r�   rš   rŸ   r¥   r«   rŠ   r¬   r®   rA   r—   r¸   rº   r±   r´   rÎ   rÏ   rÑ   rÒ   r�   rY   rá   rZ   rê   r[   rè   r\   r]   r^   r_   r`   ra   rb   ÚstaticmethodrÆ   rø   rc   rÇ   rd   r  re   r  rf   r  rg   rh   r  r  rï   r  r­   r¢   r¡   r£   rl   rm   rn   rS   rS   rS   rT   r      s¢   B            ó
a
"



-
$


+		'4
'%*?

   ÿ
)c                   @   s(   e Zd ZdZdd„ Zdd„ Zdd„ ZdS )	r   aU  
    A base class to make writing Web Profile GUI consent dialogs
    easier.

    The concrete class must:

        1) Poll ``handle_queue`` periodically, using the timer services
           of the GUI's event loop.  This function will call
           ``self.show_dialog`` when a request requires authorization.
           ``self.show_dialog`` will be given the arguments:

              - ``samp_name``: The name of the application making the request.

              - ``details``: A dictionary of details about the client
                making the request.

              - ``client``: A hostname, port pair containing the client
                address.

              - ``origin``: A string containing the origin of the
                request.

        2) Call ``consent`` or ``reject`` based on the user's response to
           the dialog.
    c                 C   s|   z| j  ¡ }W n( tjk
r$   Y nT tk
r6   Y nBX t|d tƒrP|d }n|d d }|  ||d |d |d ¡ d S )Nr   r¦   r   r   )r|   r¾   rz   r¿   ÚAttributeErrorr'  r   Zshow_dialog)rK   rÂ   Z	samp_namerS   rS   rT   Úhandle_queueã  s    
zWebProfileDialog.handle_queuec                 C   s   | j  d¡ d S )NT©r}   r  rV   rS   rS   rT   Úconsentò  s    zWebProfileDialog.consentc                 C   s   | j  d¡ d S )NFr5  rV   rS   rS   rT   Úrejectõ  s    zWebProfileDialog.rejectN)r-  r.  r/  r0  r4  r6  r7  rS   rS   rS   rT   r   È  s   )'ró   rµ   rz   r¼   r2   r6   r“   r   r•   Úxmlrpc.clientrÔ   ræ   Úurllib.parser   Zastropyr   Ú	constantsr   r   Úerrorsr   r   r	   Zlockfile_helpersr
   r   Zstandard_profiler   Úutilsr   r   r   rR   r   r   Ú__all__Z__doctest_skip__r   r   rS   rS   rS   rT   Ú<module>   s@              5