3
ò\ð]³%  ã               @   sf   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 G dd„ dej	ƒZ
dS )	é    Né   )Ú
exceptions)Úpacket)Úpayload)Úsocketc               @   sV   e Zd Zdd„ Zdd„ Zdd„ Zdd„ Zd	d
„ Zdd„ Zddd„Z	dd„ Z
dd„ ZdS )ÚAsyncSocketc             Ã   sš   y,t j| jjƒ | jjƒI dH g}| jjƒ  W n$ t jt jfk
rP   t	j
ƒ ‚Y nX |dgkr`g S y|j| jjƒ ƒ | jjƒ  W n t j
k
r”   Y nX |S )z'Wait for packets to send to the client.N)ÚasyncioÚwait_forÚqueueÚgetÚserverÚping_timeoutÚ	task_doneÚTimeoutErrorÚCancelledErrorr   Ú
QueueEmptyÚappendÚ
get_nowait)ÚselfÚpackets© r   úB/tmp/pip-build-mqc4i71p/python-engineio/engineio/asyncio_socket.pyÚpoll   s    
zAsyncSocket.pollc             Ã   sè   | j jjd| jtj|j t|jt	ƒs*|jndƒ |jtj
krdtjƒ | _| jtjtj|jƒƒI dH  n€|jtjkr”| j jd| j|j| j jd�I dH  nP|jtjkrº| jtjtjƒƒI dH  n*|jtjkrÜ| jddd�I dH  ntjƒ ‚dS )	zReceive packet from the client.z%s: Received packet %s data %sz<binary>NÚmessage)Z	run_asyncFT)ÚwaitÚabort)r   ÚloggerÚinfoÚsidr   Úpacket_namesÚpacket_typeÚ
isinstanceÚdataÚbytesÚPINGÚtimeÚ	last_pingÚsendÚPacketÚPONGZMESSAGEÚ_trigger_eventZasync_handlersÚUPGRADEÚNOOPÚCLOSEÚcloser   ÚUnknownPacketError)r   Úpktr   r   r   Úreceive   s     


zAsyncSocket.receivec             Ã   sZ   | j rtjƒ ‚tjƒ | j | jj| jj krV| jjj	d| j
ƒ | jddd�I dH  dS dS )zyMake sure the client is still sending pings.

        This helps detect disconnections for long-polling clients.
        z"%s: Client is gone, closing socketF)r   r   NT)Úclosedr   ÚSocketIsClosedErrorr%   r&   r   Zping_intervalZping_interval_grace_periodr   r   r   r.   )r   r   r   r   Úcheck_ping_timeout2   s    
zAsyncSocket.check_ping_timeoutc             Ã   sl   | j ƒ I dH sdS | jr&| jj|ƒ n| jj|ƒI dH  | jjjd| j	t
j|j t|jtƒsb|jndƒ dS )zSend a packet to the client.Nz%s: Sending packet %s data %sz<binary>)r4   Ú	upgradingÚpacket_backlogr   r
   Úputr   r   r   r   r   r   r    r!   r"   r#   )r   r0   r   r   r   r'   D   s    
zAsyncSocket.sendc             Ã   sÀ   dd„ |j ddƒjƒ jdƒD ƒ}|j ddƒjƒ }d|krn|| jkrn| jjjd| j|ƒ t| d	| ƒ|ƒI d
H S y| j	ƒ I d
H }W n: t
jk
rº   tjƒ }| jdd�I d
H  tj|Ž  Y nX |S )z2Handle a long-polling GET request from the client.c             S   s   g | ]}|j ƒ ‘qS r   )Ústrip)Ú.0Úsr   r   r   ú
<listcomp>T   s   z2AsyncSocket.handle_get_request.<locals>.<listcomp>ZHTTP_CONNECTIONÚ ú,ZHTTP_UPGRADEÚupgradez%%s: Received request to upgrade to %sZ	_upgrade_NF)r   )r   ÚlowerÚsplitZupgrade_protocolsr   r   r   r   Úgetattrr   r   r   ÚsysÚexc_infor.   ÚsixÚreraise)r   ÚenvironÚconnectionsÚ	transportr   Úexcr   r   r   Úhandle_get_requestQ   s    

zAsyncSocket.handle_get_requestc             Ã   sj   t |jddƒƒ}|| jjkr&tjƒ ‚n@|d j|ƒI dH }tj|d�}x|j	D ]}| j
|ƒI dH  qNW dS )z3Handle a long-polling POST request from the client.ÚCONTENT_LENGTHÚ0z
wsgi.inputN)Zencoded_payload)Úintr   r   Zmax_http_buffer_sizer   ZContentTooLongErrorÚreadr   ZPayloadr   r1   )r   rF   ÚlengthÚbodyÚpr0   r   r   r   Úhandle_post_requestc   s    
zAsyncSocket.handle_post_requestTFc             Ã   sf   | j  rb| j rbd| _| jjd| jƒI dH  |sH| jtjtjƒƒI dH  d| _ |rb| j	j
ƒ I dH  dS )zClose the socket connection.TZ
disconnectN)r2   Úclosingr   r*   r   r'   r   r(   r-   r
   Újoin)r   r   r   r   r   r   r.   n   s    zAsyncSocket.closec             Ã   sH   | j rtdƒ‚| jjd dkr(| jjƒ S | jjd | jƒ}||ƒI dH S )z1Upgrade the connection from polling to websocket.z Socket has been upgraded alreadyZ	websocketN)ÚupgradedÚIOErrorr   Z_asyncZ_bad_requestÚ_websocket_handler)r   rF   Úwsr   r   r   Ú_upgrade_websockety   s    
zAsyncSocket._upgrade_websocketc          '   ƒ   sÔ  ˆ j �rJdˆ _yˆjƒ I dH }W n tk
r4   dS X tj|d�}|jtjksX|jdkrnˆ j	j
jdˆ jƒ dS ˆjtjtjtjdƒd�jdd�ƒI dH  ˆ jjtjtjƒƒI dH  yˆjƒ I dH }W n tk
rØ   dS X tj|d�}|jtjk�rdˆ _ˆ j	j
jd	ˆ j|ƒ dS dˆ _x"ˆ jD ]}ˆ jj|ƒI dH  �q W g ˆ _dˆ _ndˆ _ dˆ _‡ ‡fd
d„}tj|ƒ ƒ}ˆ j	j
jdˆ jƒ �xd}tjˆjƒ ƒ}ytj|ˆ j	jƒI dH }W n@ tjk
�ræ   y|jƒ  W n   Y nX P Y n   P Y nX |dk�r P t|tjƒ�r|jdƒ}tj|d�}yˆ j|ƒI dH  W nV t j!k
�rP   Y n@ t j"k
�rv   ˆ j	j
jdƒ P Y n   ˆ j	j
jdƒ Y nX �q†W ˆ jjdƒI dH  tj|dd�I dH  ˆ j#ddd�I dH  dS )z*Engine.IO handler for websocket transport.TN)Zencoded_packetZprobez,%s: Failed websocket upgrade, no PING packet)r"   F)Úalways_byteszK%s: Failed websocket upgrade, expected UPGRADE packet, received %s instead.c              “   sz   xtd } yˆ j ƒ I d H } W n tjk
r0   P Y nX | s8P y*x$| D ]}ˆj|jdd�ƒI d H  q@W W q   P Y qX qW d S )NF)rZ   )r   r   r   r'   Úencode)r   r0   )r   rX   r   r   Úwriter°   s    
 z.AsyncSocket._websocket_handler.<locals>.writerz#%s: Upgrade to websocket successfulzutf-8z!Receive error -- socket is closedzUnknown receive error)Útimeout)r   r   )$Ú	connectedr5   r   rV   r   r(   r    r$   r"   r   r   r   r   r'   r)   rD   Ú	text_typer[   r
   r7   r,   r+   rU   r6   r   Zensure_futurer	   r   r   Ú	exceptionr!   r1   r   r/   r3   r.   )r   rX   r0   Zdecoded_pktr\   Zwriter_taskrQ   Z	wait_taskr   )r   rX   r   rW   ƒ   sˆ    





zAsyncSocket._websocket_handlerN)TF)Ú__name__Ú
__module__Ú__qualname__r   r1   r4   r'   rJ   rR   r.   rY   rW   r   r   r   r   r      s   

r   )r   rD   rB   r%   r<   r   r   r   r   ZSocketr   r   r   r   r   Ú<module>   s   