
    =                     R   S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKrSSK	r	SSK
r
SSKJr  SSKrSSKJr  SSKJr  SSKJr  SSKJr  SSKJr  SrSrSr\R@                  RB                  \R@                  RD                  /r# " S	 S
\$5      r% " S S\$5      r& " S S\$5      r'g)zLightweight websocket for IAP.    )absolute_import)division)unicode_literalsN)	platforms   i  c                       \ rS rSrSrS rSrg)SockOpt.   zDClass that represents the options for the underlying socket library.c                 6    Uc  0 nS U l         / U l        Xl        g N)timeoutsockoptsslopt)selfr   s     Flib/googlecloudsdk/api_lib/compute/iap_tunnel_lightweight_websocket.py__init__SockOpt.__init__1   s!    ~f DLDLK    )r   r   r   N)__name__
__module____qualname____firstlineno____doc__r   __static_attributes__ r   r   r	   r	   .   s
    Lr   r	   c                   0    \ rS rSrSrS rS rS rS rSr	g)	_FrameBuffer;   zIClass that represents one single frame sent or received by the websocket.c                     Xl         g r   recv)r   recv_fns     r   r   _FrameBuffer.__init__>   s    Ir   c                 (   U R                  S5      nUS   n[        R                  (       a  [        U5      nUS-	  S-  nUS-	  S-  nUS-	  S-  nUS-	  S-  nUS-  nUS   n[        R                  (       a  [        U5      nUS-	  S-  n	US	-  n
X4XVXyU
4$ )
z"Parse the header from the message.   r                        )r!   sixPY2ord)r   headerb1finrsv1rsv2rsv3opcodeb2has_masklength_bitss              r   _recv_header_FrameBuffer._recv_headerA   s    YYq\F	B
wwr7b
'A+C7Q;D7Q;D7Q;D#XF	B
wwr7bQw{Ht)Kt6[AAr   c                     US-  nUS:X  a+  U R                  S5      n[        R                  " SU5      S   $ US:X  a+  U R                  S5      n[        R                  " SU5      S   $ U$ )z"Parse the length from the message.r,   ~   r%   !Hr      z!Q)r!   structunpack)r   bitsr9   vs       r   _recv_length_FrameBuffer._recv_lengthX   sg    +Kd
))A,a]]4#A&&		
))A,a]]4#A&&r   c           	          U R                  5       u  pp4pVnUS:X  a  [        S5      eU R                  U5      nU R                  U5      n	[        R
                  " XX4XVU	5      $ )zReceives the whole frame.r'   z#Server should not mask the response)r:   	ExceptionrD   r!   websocket_frame_utilsABNF)
r   r2   r3   r4   r5   r6   r8   r9   lengthpayloads
             r   
recv_frame_FrameBuffer.recv_framed   si     >B=N=N=P:SFk1};<<{+FiiG %%cV&-/ /r   r    N)
r   r   r   r   r   r   r:   rD   rL   r   r   r   r   r   r   ;   s    QB.
/r   r   c                       \ rS rSrSr SS jrS rS r\\	R                  " S5      4S jr\\	R                  " S5      4S	 jrS
 rS rS rS rS rS rS rS rS rSrg)IapLightWeightWebsockets   zoLightweight websocket created to send and receive data as fast as possible.

This websocket implements rfc6455
Nc                     Xl         X0l        X@l        XPl        Xpl        [        U R                  5      U l        SU l        S U l	        X`l
        X l        [        R                  " 5       U l        g )NF)urlon_dataon_closeon_errorsockr   _recv_bytesframe_buffer	connectedget_mask_keysubprotocolsr0   	threadingLocksend_write_lock)r   rR   r0   rS   rT   rU   r[   rV   s           r   r    IapLightWeightWebsocket.__init__y   s]     HLMMI$T%5%56DDN D$K
 %>>+Dr   c                     U R                   (       a  U R                  (       d  [        R                  " S5      eU R                  R                  5       $ )zReceives data from the server.'Connection closed while receiving data.)rY   rV   websocket_exceptions"WebSocketConnectionClosedExceptionrX   rL   )r   s    r   r!   IapLightWeightWebsocket.recv   s<    >> CC
35 5 ''))r   c           
         U[         ;  a  [        S5      e[        R                  " SSSSUSUS9nU R                  (       a  U R                  Ul        UR                  5       nU R                     [        S[        S-   5       H  n U R                  (       a  U R                  (       d  [        R                  " S5      eU R                  R                  U5      nU(       d  [        R                  " S5      e[        U5      U:w  a  [        S5      eUs  sSSS5        $    SSS5        g! [         a  nU R!                  XFS9   SnAM  SnAff = f! , (       d  f       g= f)	zSends data to the server.zInvalid opcoder'   r   )r2   r3   r4   r5   r6   maskdataz%Connection closed while sending data.z$Packet was not sent in it's entiretyNattempt	exception)VALID_OPCODES
ValueErrorrH   rI   rZ   formatr^   rangeWEBSOCKET_MAX_ATTEMPTSrY   rV   rb   rc   sendlenrG   _throw_or_wait_for_retry)r   rg   r6   
frame_datari   
bytes_sentes          r   rp   IapLightWeightWebsocket.send   s1   ]"'((
 '++AAAf14IJ  $ 1 1j""$J 
		14q89'	Ftyy&II79 9yy~~j1*&II79 9 _
*BCC
 
	9 
	   	F

'
'
'
E	F! 
	s=   .EBD(EE(
E2EEEE
E c                 P   U R                   (       aM  U R                  (       a;   U R                  X5        U R                  R                  5         SU l        SU l         ggg! [        R
                  [        R                  4 a!  nU R                  U5      (       d  e  SnAgSnAff = f)zCloses the connection.NF)	rY   rV   
send_closecloserb   rc   socketerror_is_closed_connection_exceptionr   
close_codeclose_messageru   s       r   rz   IapLightWeightWebsocket.close   s    ~~$))

2			 $~ #EEll  33A66
 7	s   9A   $B%B  B%c                    U R                   (       aj  [        R                  (       a  UR                  S5      n U R	                  [
        R                  " SU5      U-   [        R                  R                  5        gg! [        R                  [        [        R                  [        R                   4 a!  nU R#                  U5      (       d  e  SnAgSnAff = f)z4Sends a close message to the server but don't close.zlatin-1r>   N)rY   r-   r.   encoderp   r@   packrH   rI   OPCODE_CLOSErb   rc   OSErrorr{   r|   sslSSLErrorr}   r~   s       r   ry   "IapLightWeightWebsocket.send_close   s    ~~
 
%,,Y7		KKj)M9!&&33	5  #EEwllCLL*  33A66
 7	s   AA= =8C5CCc                     UR                  SU R                  05        UR                  SU R                  05        U R                  " U40 UD6  U R                  (       a  U R
                  R                  5       S:X  a  [        R                  " S5      eU R                  [        S9  U R                  5       nUR                  [        R                  R                  :X  a;  U R!                  UR"                  5      nU R%                  5         U R&                  " U6   O&U R)                  UR"                  UR                  5        U R                  (       a  M  gg! [*         a'  nU R%                  5         U R'                  SSS9  UeSnAf[,         ah  nU R%                  5         U R/                  U5        [0        R2                  " U5      n[0        R4                  " U5      nU R'                  Xg5         SnAgSnAff = f)z@Main method that will stay running while the connection is open.r0   r[   ra   )r   N)r   r   )updater0   r[   _connectrY   rV   filenorb   rc   _wait_for_socket_to_readyWEBSOCKET_RETRY_TIMEOUT_SECSr!   r6   rH   rI   r   _get_close_argsrg   rz   rT   rS   KeyboardInterruptrG   rU   websocket_utilsextract_error_codeextract_err_message)r   r   optionsframe
close_argsru   
error_codemessages           r   run_forever#IapLightWeightWebsocket.run_forever   su   )nnh,-nnnd&7&789
mmF&g&NN99#$GG79 9 	&&/K&L		<<055BBB++EJJ7*
**,
--
$
,,uzz5<<
0 NNN  
jjl
mmt4m8g )
jjl
mmA"55a8j33A6g
mmJ(()s%   EE 
G6"FG6AG11G6c                    [        [        U5      5      nSn[        S[        S-   5       Hp  n X1:  aW  U R                  R                  X#S X-
  5      nUS:X  a&  U R                  5         [        R                  " S5      eX5-  nX1:  a  MW  UR                  5       s  $    g! [         a  nU R                  XFS9   SnAM  SnAff = f)z5Internal implementation of recv called by recv_frame.r   r'   Nra   rh   )
memoryview	bytearrayrn   ro   rV   	recv_intorz   rb   rc   tobytesrG   rr   )r   
buffersizeviewtotal_bytes_readri   bytes_receivedru   s          r   rW   #IapLightWeightWebsocket._recv_bytes  s    i
+,D 2Q67D
 +99..t4E/F/9/LN.
 q JJL&II9; ;

,
 + ||~% 8&  D%%g%CDs   AB
B
C)B>>Cc                     Xl         g r   )rZ   )r   mask_keys     r   _set_mask_key%IapLightWeightWebsocket._set_mask_key"  s     r   c                 d   [         R                  " S0 UD6n[        U5      nU R                  (       a(  [         R                  " U R
                  5      u  pVpxXVU4n	ON[         R                  " U R
                  XCS5      u  U l        n	[        R                  " U R                  /U	Q70 UD6  SU l	        U	$ )z)Connect method, doesn't follow redirects.NTr   )
websocket_http_utils
proxy_infor	   rV   	parse_urlrR   connectwebsocket_handshake	handshakerY   )
r   ssl_optr   proxyr   hostnameportresource_addrss
             r   r    IapLightWeightWebsocket._connect%  s     ++6g6EgG yy$8$B$B488$L!hhx(e-55dhh6:<di##DIIAAADNLr   c                 |   U R                  U5      (       a  [        R                  " S5      eU[        R                  L a$  UR
                  S   [        R                  :w  a  UegU[        R                  L aF  [        R                  " U5      nUc  UeU[        R                  :w  d  U[        R                  :w  a  Uegg)zIDecides if we throw or if we ignore the exception because it's retriable.z*Connection closed while waiting for retry.r   N)r}   rb   rc   r   r   argsSSL_ERROR_WANT_WRITEr{   r|   r   r   errnoEAGAINEWOULDBLOCK)r   ru   r   s      r   !_throw_on_non_retriable_exception9IapLightWeightWebsocket._throw_on_non_retriable_exception5  s     ++A.. CC
68 8CLL 
c..	. 
/	
fll	"55a8j			u||	#zU5F5F'F (G 
r   c                     U R                  U5        U[        :  aE  U R                  (       a4  U R                  R                  5       S:w  a  U R	                  [
        5        gUe)zEWait for the websocket to be ready we don't retry too much too quick.r   N)r   ro   rV   r   r   r   )r   ri   rj   s      r   rr   0IapLightWeightWebsocket._throw_or_wait_for_retryH  sJ    **95 	((TYY		b 
$$%ABor   c                 p   U R                   R                  5       (       a  g [        R                  " U R                   /SSU5      ng! [         aM  n[        R
                  " U5      n[        U[        5      (       a  SU;   a  [        R                  " S5      ee SnAf[        [        R                  4 a  n[        R                  R                  5       (       d  e U[        L a  UR                  S:w  a  e U[        R                  L a$  UR                   [         R"                  :w  a  e  SnAg SnAgSnAff = f)z@Wait for socket to be ready and treat some special errors cases.Nr   zarguments 1-3 must be sequencesz4Connection closed while waiting for socket to ready.i6'  )rV   pendingselect	TypeErrorr   r   
isinstancestrrb   rc   r   r|   r   OperatingSystem	IsWindowswinerrorr   ENOTSOCK)r   r   r   ru   r   s        r   r   1IapLightWeightWebsocket._wait_for_socket_to_readyT  s     yy
--RW
5a 	33A6g 
G
 
>'I"EEBD 	DV\\"  &&0022	
g1::.	
fll	qww%..8  9	s%   $A 
D5ABD56A0D00D5c                 h   U[         R                  L a  gU[        L a  UR                  [        R                  :X  a  gU[
        R                  L a$  UR                  S   [
        R                  :X  a  g g[        R                  " U5      nU[        R                  :X  d  U[        R                  :X  a  gg)zAMethod to identify if the exception is of closed connection type.Tr   F)rb   rc   r   r   EBADFr   r   r   SSL_ERROR_EOFr   r   ENOTCONNEPIPE)r   rj   r   s      r   r}   7IapLightWeightWebsocket._is_closed_connection_exceptions  s    (KKK	g	)//U[["@ 	cll	" 
	c//	/ 
0  #55i@j 
u~~	%u{{)Br   c                     U(       a]  [        U5      S:  aM  S[        R                  " USS 5      -  [        R                  " USS 5      -   nUSS  R                  S5      nX#/$ g g )Nr%      r   r'   zutf-8)rq   r-   byte2intdecode)r   rg   codereasons       r   r   'IapLightWeightWebsocket._get_close_args  s_    D	Q3<<Qq	**S\\$q)-DDdABxw'f^ tr   )rY   rX   rZ   r0   rT   rS   rU   r^   rV   r[   rR   r   )r   r   r   r   r   r   r!   rp   CLOSE_STATUS_NORMALr-   brz   ry   r   rW   r   r   r   rr   r   r}   r   r   r   r   r   rO   rO   s   st     ,8*!FF 1b	  #6SUU2Y .)@D8! &
>,r   rO   )(r   
__future__r   r   r   r   r   r{   r   r@   r\   googlecloudsdk.core.utilr   r-   websocket._abnf_abnfrH   websocket._exceptions_exceptionsrb   websocket._handshake
_handshaker   websocket._http_httpr   websocket._utils_utilsr   r   ro   r   rI   r   OPCODE_BINARYrk   objectr	   r   rO   r   r   r   <module>r      s    % '  '    
   . 
 / 4 2 . *    ++,,
f 
5/6 5/pZf Zr   