3
ò\ð]O&  ã               @   sP   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 G dd„ deƒZdS )é    Né   )Ú
exceptions)Úpacket)Úpayloadc               @   sh   e Zd ZdZdgZd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 )ÚSocketzAn Engine.IO socket.Ú	websocketc             C   sP   || _ || _| j jƒ | _tjƒ | _d| _d| _d| _g | _	d| _
d| _i | _d S )NF)ÚserverÚsidZcreate_queueÚqueueÚtimeÚ	last_pingÚ	connectedÚ	upgradingÚupgradedÚpacket_backlogÚclosingÚclosedÚsession)Úselfr   r	   © r   ú:/tmp/pip-build-mqc4i71p/python-engineio/engineio/socket.pyÚ__init__   s    
zSocket.__init__c             C   sœ   | j jƒ }y"| jj| j jd�g}| jjƒ  W n |k
rH   tjƒ ‚Y nX |dgkrXg S x>y"|j| jjdd�ƒ | jjƒ  W qZ |k
r’   P Y qZX qZW |S )z'Wait for packets to send to the client.)ÚtimeoutNF)Úblock)	r   Zget_queue_empty_exceptionr
   ÚgetÚping_timeoutÚ	task_doner   Ú
QueueEmptyÚappend)r   Zqueue_emptyÚpacketsr   r   r   Úpoll   s    

zSocket.pollc             C   sè   |j ttjƒk rtj|j  nd}| jjjd| j|t|j	t
ƒsB|j	ndƒ |j tjkrvtjƒ | _| jtjtj|j	ƒƒ nn|j tjkr | jjd| j|j	| jjd� nD|j tjkrÀ| jtjtjƒƒ n$|j tjkrÜ| jddd� ntjƒ ‚d	S )
zReceive packet from the client.ÚUNKNOWNz%s: Received packet %s data %sz<binary>Úmessage)Ú	run_asyncFT)ÚwaitÚabortN)Úpacket_typeÚlenr   Úpacket_namesr   ÚloggerÚinfor	   Ú
isinstanceÚdataÚbytesÚPINGr   r   ÚsendÚPacketÚPONGZMESSAGEÚ_trigger_eventZasync_handlersÚUPGRADEÚNOOPÚCLOSEÚcloser   ÚUnknownPacketError)r   ÚpktZpacket_namer   r   r   Úreceive-   s      

zSocket.receivec             C   sT   | j rtjƒ ‚tjƒ | j | jj| jj krP| jjj	d| j
ƒ | jddd� 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%   T)r   r   ÚSocketIsClosedErrorr   r   r   Zping_intervalZping_interval_grace_periodr)   r*   r	   r6   )r   r   r   r   Úcheck_ping_timeoutB   s    
zSocket.check_ping_timeoutc             C   s`   | j ƒ sdS | jr | jj|ƒ n| jj|ƒ | jjjd| j	t
j|j t|jtƒsV|jndƒ dS )zSend a packet to the client.Nz%s: Sending packet %s data %sz<binary>)r;   r   r   r   r
   Úputr   r)   r*   r	   r   r(   r&   r+   r,   r-   )r   r8   r   r   r   r/   T   s    
zSocket.sendc             C   s°   dd„ |j ddƒjƒ jdƒD ƒ}|j ddƒjƒ }d|krj|| jkrj| jjjd| j|ƒ t| d	| ƒ||ƒS y| j	ƒ }W n4 t
jk
rª   tjƒ }| jd
d� 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>d   s   z-Socket.handle_get_request.<locals>.<listcomp>ZHTTP_CONNECTIONÚ ú,ZHTTP_UPGRADEÚupgradez%%s: Received request to upgrade to %sZ	_upgrade_F)r$   )r   ÚlowerÚsplitÚupgrade_protocolsr   r)   r*   r	   Úgetattrr    r   r   ÚsysÚexc_infor6   ÚsixÚreraise)r   ÚenvironÚstart_responseÚconnectionsÚ	transportr   Úexcr   r   r   Úhandle_get_requesta   s    

zSocket.handle_get_requestc             C   s^   t |jddƒƒ}|| jjkr&tjƒ ‚n4|d j|ƒ}tj|d�}x|j	D ]}| j
|ƒ qHW dS )z3Handle a long-polling POST request from the client.ÚCONTENT_LENGTHÚ0z
wsgi.input)Zencoded_payloadN)Úintr   r   Zmax_http_buffer_sizer   ZContentTooLongErrorÚreadr   ZPayloadr   r9   )r   rL   ÚlengthÚbodyÚpr8   r   r   r   Úhandle_post_requestt   s    
zSocket.handle_post_requestTFc             C   sd   | j  r`| j r`d| _| jjd| jdd� |s@| jtjtjƒƒ d| _ | j	j
dƒ |r`| j	jƒ  dS )zClose the socket connection.TZ
disconnectF)r#   N)r   r   r   r2   r	   r/   r   r0   r5   r
   r<   Újoin)r   r$   r%   r   r   r   r6      s    zSocket.closec             C   sD   | j rtdƒ‚| jjd dkr(| jjƒ S | jjd | jƒ}|||ƒS )z1Upgrade the connection from polling to websocket.z Socket has been upgraded alreadyr   N)r   ÚIOErrorr   Z_asyncZ_bad_requestÚ_websocket_handler)r   rL   rM   Úwsr   r   r   Ú_upgrade_websocket‹   s    
zSocket._upgrade_websocketc       	         sŠ  x:dD ]2}t ˆ|ƒrt tˆ|ƒdƒrtˆ|ƒjˆ jjƒ qW ˆ j�r4dˆ _ˆjƒ }tj	|d�}|j
tjkst|jdkrŠˆ jjjdˆ jƒ g S ˆjtj	tjtjdƒd�jd	d
�ƒ ˆ jjtj	tjƒƒ ˆjƒ }tj	|d�}|j
tjk�rd	ˆ _ˆ jjjdˆ j|ƒ g S dˆ _xˆ jD ]}ˆ jj|ƒ �qW g ˆ _d	ˆ _ndˆ _dˆ _‡ ‡fdd„}ˆ jj|ƒ}ˆ jjjdˆ jƒ xöd}yˆjƒ }W nF tk
�rÄ } z(ˆ j�s²ˆ jjjdˆ jt|ƒƒ P W Y dd}~X nX |dk�rÒP t|tjƒ�rê|jdƒ}tj	|d�}yˆ j |ƒ W nX t!j"k
�r   Y nB t!j#k
�rB   ˆ jjjdƒ P Y n   ˆ jjj$dƒ P Y nX �qnW ˆ jjdƒ |j%ƒ  ˆ j&d	dd� g S )z*Engine.IO handler for websocket transport.Ú_sockÚsocketÚ
settimeoutT)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                 sn   xhd } yˆ j ƒ } W n tjk
r*   P Y nX | s2P y$x| D ]}ˆj|jdd�ƒ q:W W q   P Y qX qW d S )NF)rb   )r    r   r   r/   Úencode)r   r8   )r   r]   r   r   ÚwriterÁ   s    
z)Socket._websocket_handler.<locals>.writerz#%s: Upgrade to websocket successfulNz-%s: Unexpected error "%s", closing connectionzutf-8z!Receive error -- socket is closedzUnknown receive error)r$   r%   )r_   r`   )'ÚhasattrrG   ra   r   r   r   r   r$   r   r0   r&   r.   r,   r)   r*   r	   r/   r1   rJ   Ú	text_typerc   r
   r<   r4   r3   r   r   Zstart_background_taskÚ	Exceptionr   Ústrr+   r9   r   r7   r:   Ú	exceptionrZ   r6   )	r   r]   Úattrr8   Zdecoded_pktrd   Zwriter_taskrX   Úer   )r   r]   r   r\   •   s€    






zSocket._websocket_handlerN)TF)Ú__name__Ú
__module__Ú__qualname__Ú__doc__rF   r   r    r9   r;   r/   rQ   rY   r6   r^   r\   r   r   r   r   r   
   s   

r   )	rJ   rH   r   rA   r   r   r   Úobjectr   r   r   r   r   Ú<module>   s   