3
ò\ð]  ã               @   sŒ   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ZeedƒZ	G dd„ dej
ƒZG dd	„ d	eƒZeejejee	r|endejd
œZdS )é    )Úabsolute_importN)Úqueue)ÚEventÚwebsocket_handshakec                   s.   e Zd ZdZg i f‡ fdd„	Zdd„ Z‡  ZS )ÚThreadz€
    This wrapper class provides gevent Greenlet interface that is compatible
    with the standard library's Thread class.
    c                s   t t| ƒj|f|ž|Ž d S )N)Úsuperr   Ú__init__)ÚselfÚtargetÚargsÚkwargs)Ú	__class__© úN/tmp/pip-build-mqc4i71p/python-engineio/engineio/async_drivers/gevent_uwsgi.pyr      s    zThread.__init__c             C   s   | j ƒ S )N)Úrun)r	   r   r   r   Ú_run   s    zThread._run)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r   r   Ú__classcell__r   r   )r   r   r      s   r   c               @   sH   e 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S )ÚuWSGIWebSocketzx
    This wrapper class provides a uWSGI WebSocket interface that is
    compatible with eventlet's implementation.
    c             C   s   || _ d | _d S )N)ÚappÚ_sock)r	   r   r   r   r   r      s    zuWSGIWebSocket.__init__c                s–   t jƒ | _|| _t jƒ  d | _tt dƒr4t jƒ | _nTddlm	} ddl
m} ddlm‰  |ƒ | _|ƒ | _‡ fdd„}tj|| j| jƒ| _| j| ƒ d S )NÚrequest_contextr   )r   )ÚQueue)Úselectc                s@   x:|j ƒ  yˆ | gg g ƒd  W q tk
r6   P Y qX qW dS )z5Sets event when data becomes available to read on fd.r   N)ÚsetÚ
ValueError)ÚfdÚevent)r   r   r   Úselect_greenlet_runner4   s    z7uWSGIWebSocket.__call__.<locals>.select_greenlet_runner)ÚuwsgiZconnection_fdr   Úenvironr   Ú_req_ctxÚhasattrr   Úgevent.eventr   Zgevent.queuer   Zgevent.selectr   Ú_eventÚ_send_queueÚgeventÚspawnÚ_select_greenletr   )r	   r#   Zstart_responser   r   r!   r   )r   r   Ú__call__!   s"    


zuWSGIWebSocket.__call__c             C   s*   t jƒ  | jdkr&| jjƒ  | jjƒ  dS )z"Disconnects uWSGI from the client.N)r"   Z
disconnectr$   r+   Úkillr'   r   )r	   r   r   r   ÚcloseC   s    

zuWSGIWebSocket.closec             C   s@   t |tjƒrtj}ntj}| jdk	r4||| jd� n||ƒ dS )zUTransmits message either in binary or UTF-8 text mode,
        depending on its type.N)r   )Ú
isinstanceÚsixÚbinary_typer"   Zwebsocket_send_binaryZwebsocket_sendr$   )r	   ÚmsgÚmethodr   r   r   Ú_sendK   s    
zuWSGIWebSocket._sendc             C   s8   t |tjƒs|S tj|dd… ƒ}|dkr4|jdƒS |S )z7Returns either bytes or str, depending on message type.r   é   é0   zutf-8)r/   r0   r1   Úbyte2intÚdecode)r	   r2   Útyper   r   r   Ú_decode_receivedW   s    
zuWSGIWebSocket._decode_receivedc             C   s0   | j dk	r| j|ƒ n| jj|ƒ | jjƒ  dS )z†Queues a message for sending. Real transmission is done in
        wait method.
        Sends directly if uWSGI version is new enough.N)r$   r4   r(   Úputr'   r   )r	   r2   r   r   r   Úsendc   s    
zuWSGIWebSocket.sendc             C   sò   xì| j dk	r>ytj| j d�}W n tk
r2   dS X | j|ƒS | jjdd�}|r°| jjƒ  g }x8y|j| j	j
dd�ƒ W q` tjjk
r’   P Y q`X q`W x|D ]}| j|ƒ qžW ytjƒ }W n tk
rÚ   | jjƒ  dS X |r| j|ƒS qW dS )aT  Waits and returns received messages.
        If running in compatibility mode for older uWSGI versions,
        it also sends messages that have been queued by send().
        A return value of None means that connection was closed.
        This must be called repeatedly. For uWSGI < 2.1.x it must
        be called from the main greenlet.N)r   é   )ÚtimeoutF)Úblock)r$   r"   Zwebsocket_recvÚIOErrorr:   r'   ÚwaitÚclearÚappendr(   Úgetr)   r   ÚEmptyr4   Zwebsocket_recv_nbr+   r-   )r	   r2   Z	event_setZmsgsr   r   r   rA   m   s2    




zuWSGIWebSocket.waitN)r   r   r   r   r   r,   r.   r4   r:   r<   rA   r   r   r   r   r      s   "
r   )Úthreadr   Zqueue_emptyr    Z	websocketÚsleep)Ú
__future__r   r0   r)   r   r&   r   r"   r%   Z_websocket_availableZGreenletr   Úobjectr   ZJoinableQueuerE   rG   Z_asyncr   r   r   r   Ú<module>   s   
~
