
                            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rSSKrSSK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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SKJ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%J&r&  \"RN                  RQ                  5       (       d  SSK)r)OSSKJ*r*  Sr+ " S S\RX                  5      r- " S S\RX                  5      r.S r/S r0S5S jr1S r2S r3S  r4S! r5S" r6S# r7 " S$ S%\85      r9S6S& jr:S' r;S( r<S) r=S* r> " S+ S,\85      r? " S- S.\85      r@ " S/ S0\85      rA " S1 S25      rB " S3 S45      rCg)7z7Tunnel TCP traffic over Cloud IAP WebSocket connection.    )absolute_import)division)unicode_literalsN)iap_tunnel_websocket)iap_tunnel_websocket_utils)	sg_tunnel)sg_tunnel_utils)
exceptions)execution_utils)
http_proxy)log)
properties)	transport)creds)store)files)	platforms)queue)wintypes   c                       \ rS rSrSrg)LocalPortUnavailableError<    N__name__
__module____qualname____firstlineno____static_attributes__r       4lib/googlecloudsdk/command_lib/compute/iap_tunnel.pyr   r   <       r!   r   c                       \ rS rSrSrg)UnableToOpenPortError@   r   Nr   r   r!   r"   r%   r%   @   r#   r!   r%   c                 L    U R                  SSSS9  U R                  SSSSSS	9  g )
Nz--iap-tunnel-url-overrideTzFAllows for overriding the connection endpoint for integration testing.)hiddenhelp2--iap-tunnel-insecure-disable-websocket-cert-checkF
store_truez;Disables checking certificates on the WebSocket connection.)defaultactionr(   r)   add_argumentparsers    r"   _AddBaseArgsr2   D   sE    !  
 	:H  Jr!   c                 <    [        U 5        UR                  SSSS9  g )Nz--tunnel-through-iapr+   z      Tunnel the ssh connection through Cloud Identity-Aware Proxy for TCP
      forwarding.

      To learn more, see the
      [IAP for TCP forwarding documentation](https://cloud.google.com/iap/docs/tcp-forwarding-overview).
      )r-   r)   )r2   r/   )r1   tunnel_through_iap_scopes     r"   AddSshTunnelArgsr5   R   s(    v''
 ( 	r!   c                     U R                  5       nUR                  SSSSS9  U(       a7  UR                  SS9n[        UR                  SS95        UR                  5       n[        U5        g)z8Add the arguments for supporting host-based connections.z--regionNTzDConfigures the region to use when connecting via IP address or FQDN.r,   requiredr)   )mutex)r(   )add_argument_groupr/   AddSecurityGatewayTunnelArgsAddOnPremTunnelArgs)r1   support_security_gatewaygroupgroup_mutexs       r"   AddHostBasedTunnelArgsr@   `   sw     
#
#
%%	   ***6K !?!?t!?!LM**,Eer!   c                 L    U R                  SSSSS9  U R                  SSSSS9  g)	z7Add the arguments for supporting IP/FQDN-based tunnels.z	--networkNTzIConfigures the VPC network to use when connecting via IP address or FQDN.r7   z--dest-groupFOConfigures the destination group to use when connecting via IP address or FQDN.r.   r0   s    r"   r<   r<   r   sF       		  !r!   c                 N    U R                  SSSSS9  U R                  SSSSS	S
9  g)z,Add arguments for the Security Gateway path.z--security-gatewayNTz7Configure the security gateway resource for connecting.r7   z--use-dest-groupFr+   rB   )r,   r-   r8   r)   r.   r0   s    r"   r;   r;      sH    D	  F 	  !r!   c                     [        U 5        g N)r2   r0   s    r"   AddProxyServerHelperArgsrF      s
    vr!   c                    [        U S5      (       d  g[        U SS5      (       a  gU R                  S5      (       a  U R                  (       d  gO'U(       a  g[        R
                  R                  S5        [        5       nUR                  Ul	        UR                  Ul
        UR                  Ul        UR                  Ul        [        X5        U$ )a  Construct an SshTunnelArgs from command line args and values.

Args:
  args: The parsed commandline arguments. May or may not have had
    AddSshTunnelArgs called.
  track: ReleaseTrack, The currently running release track.
  instance_ref: The target instance reference object.
  external_interface: The external interface of target resource object, if
    available, otherwise None.
Returns:
  SshTunnelArgs or None if IAP Tunnel is disabled.
tunnel_through_iapNinternal_ipFzEExternal IP address was not found; defaulting to using IAP tunneling.)hasattrgetattrIsSpecifiedrH   r   statusPrintSshTunnelArgsprefixtrackprojectzoneinstance_AddPassThroughArgs)argsrQ   instance_refexternal_interfaceress        r"   CreateSshTunnelArgsrZ      s     
+	,	, T=%((	*++"" #
 JJ & ' 	#ll#)$$#+#(&&#,d 	*r!   c                    [        5       nUR                  Ul        [        R                  R
                  R                  R                  5       Ul        U R                  Ul        U R                  Ul	        X#l
        [        X5        U$ )a-  Construct an SshTunnelArgs from command line args and values for on-prem.

Args:
  args: The parsed commandline arguments. May or may not have had
    AddSshTunnelArgs called.
  track: ReleaseTrack, The currently running release track.
  host: The target IP address or FQDN.
Returns:
  SshTunnelArgs.
)rO   rP   rQ   r   VALUEScorerR   	GetOrFailregionnetworkrT   rU   )rV   rQ   hostrY   s       r"   CreateOnPremSshTunnelArgsrb      s`     	#ll#)!!&&..88:#+{{#*#+,d 	*r!   c                 V   U R                  S5      (       a(  UR                  R                  SU R                  -   5        U R                  (       a  UR                  R                  S5        U R                  S5      (       a)  UR                  R                  SU R                  -   5        gg)zAdds any passthrough args to the SshTunnelArgs.

Args:
  args: The parsed commandline arguments. May or may not have had
    AddSshTunnelArgs called.
  ssh_tunnel_args: SshTunnelArgs, The SSH tunnel args to update.
iap_tunnel_url_overridez--iap-tunnel-url-override=r*   
dest_groupz--dest-group=N)rL   pass_through_argsappendrd   0iap_tunnel_insecure_disable_websocket_cert_checkIsKnownAndSpecifiedre   )rV   ssh_tunnel_argss     r"   rU   rU      s     
/00%%,,$t'C'CCE	::%%,,<>	l++%%,,_t-NO ,r!   c                   6    \ rS rSrSrS rS rS rS rS r	Sr
g	)
rO      a  A class to hold some options for IAP Tunnel SSH/SCP.

Attributes:
  track: str/None, the prefix of the track for the inner gcloud.
  project: str, the project id (string with dashes).
  zone: str, the zone name.
  instance: str, the instance name (or IP or FQDN for on-prem).
  region: str, the region name (on-prem only).
  network: str, the network name (on-prem only).
  cloud_run_args: dict, The fields required to construct Cloud Run
    SshTunnelArgs. If present, this field should contain fields for
    'deployment_name', 'workload_type', and 'project_number'. Optionally can
    contain 'instance_id' and 'container_id'.
  pass_through_args: [str], additional args to be passed to the inner gcloud.
c                 t    S U l         SU l        SU l        SU l        SU l        SU l        S U l        / U l        g )N )rQ   rR   rS   rT   r_   r`   cloud_run_argsrf   selfs    r"   __init__SshTunnelArgs.__init__  s<    DJDLDIDMDKDLDDr!   c                     U R                   U R                  U R                  U R                  U R                  U R
                  U R                  U R                  4$ rE   )rQ   rR   rS   rT   r_   r`   rf   ro   rp   s    r"   _MembersSshTunnelArgs._Members  sH    

			 	r!   c                 D    U R                  5       UR                  5       :H  $ rE   ru   rq   others     r"   __eq__SshTunnelArgs.__eq__  s    ==?enn...r!   c                     X:X  + $ rE   r   ry   s     r"   __ne__SshTunnelArgs.__ne__  s    r!   c                 ,    SU R                  5       < S3$ )NzSshTunnelArgs<>rx   rp   s    r"   __repr__SshTunnelArgs.__repr__  s    "&--/33r!   )ro   rT   r`   rf   rR   r_   rQ   rS   N)r   r   r   r   __doc__rr   ru   r{   r~   r   r    r   r!   r"   rO   rO      s       
/4r!   rO   c                     U (       d  [         R                  " 5       n [         R                  " U 5      (       d  [        SU -  5      eU $ )Nz!Local port [%d] is not available.)
portpickerpick_unused_portis_port_freer   )port_args    r"   DetermineLocalPortr   "  sA    	**,H		 	 	*	*
#$G$,%- . .	/r!   c                     U (       a2   U R                  [        R                  5         U R	                  5         gg! [         a     Nf = f! [         a     gf = f)z8Callback function to close the local connection, if any.N)shutdownsocket	SHUT_RDWREnvironmentErrorclose)
local_conns    r"   _CloseLocalConnectionCallbackr   +  s_     
 &**+   
  
s    ; A 
AA
AAc                 F   U (       d  g[         R                  " S[        R                  " U 5      5        U   [        R
                  " U 5        [        R                  " U 5      (       a  U R                  sSSS5        $ U R                  sSSS5        $ ! , (       d  f       g= f)zACallback function to refresh credentials and return access token.Nz5credentials type for _GetAccessTokenCallback is [%s].)
r   debugsix	text_typer   RefreshIfAlmostExpirer   IsGoogleAuthCredentialstokenaccess_token)credentialslocks     r"   _GetAccessTokenCallbackr   =  sl    	))CMM+&( 	,$$[11	 t %% tts   =B=B
B c                 6    U (       a  U R                  U5        g g rE   )send)r   datas     r"   _SendLocalDataCallbackr   M  s    OOD r!   c                    / n[         R                  " X[         R                  [         R                  S[         R                  5       H  nUu  pEpgn [         R                   " XEU5      n	 [        R                  R                  5       (       d/  U	R                  [         R                  [         R                  S5        U	R                  U5        U	R                  S5        UR                  U	5        M     U(       a  U$ [#        SU-  5      e! [         R
                   a     M  f = f! [         a2     U	R!                  5          M  ! [         R
                   a      GM  f = ff = f)zGAttempt to open a local socket(s) listening on specified host and port.r         z#Unable to open socket on port [%d].)r   getaddrinfo	AF_UNSPECSOCK_STREAM
AI_PASSIVEerrorr   OperatingSystem	IsWindows
setsockopt
SOL_SOCKETSO_REUSEADDRbindlistenrg   r   r   r%   )

local_host
local_portopen_socketsrY   afsocktypeprotounused_canonname	sock_addrss
             r"   _OpenLocalTcpSocketsr   S  s'   ,f..0B0BAc 8;4B%9
--e
,a&&0022	V&&(;(;Q?ffYhhsm!, C() 	* *' <<   		\\ s=   D	)BD$	D! D!$
E /EEE EE c                       \ rS rSrSr " S S\5      r " S S\5      r " S S5      r	 " S	 S
5      r
 " S S5      rS rS rS rS rS rS rS rS rS rS rSrg)_StdinSocketis  zA wrapper around stdin/out that allows it to be treated like a socket.

Does not implement all socket functions. And of the ones implemented, not all
arguments/flags are supported. Once created, stdin should never be accessed by
anything else.
c                   *    \ rS rSrSrS rS rS rSrg) _StdinSocket._StdinSocketMessagei{  zHA class to wrap messages coming to the stdin socket for windows systems.c                     Xl         X l        g rE   )_type_data)rq   message_typer   s      r"   rr   )_StdinSocket._StdinSocketMessage.__init__~  s    jjr!   c                     U R                   $ rE   )r   rp   s    r"   GetData(_StdinSocket._StdinSocketMessage.GetData      ZZr!   c                     U R                   $ rE   )r   rp   s    r"   GetType(_StdinSocket._StdinSocketMessage.GetType  r   r!   )r   r   N)	r   r   r   r   r   rr   r   r   r    r   r!   r"   _StdinSocketMessager   {  s    Rr!   r   c                       \ rS rSrSrg)_StdinSocket._EOFErrori  r   Nr   r   r!   r"   	_EOFErrorr         r!   r   c                       \ rS rSrSrg)$_StdinSocket._StdinClosedMessageTypei  r   Nr   r   r!   r"   _StdinClosedMessageTyper     r   r!   r   c                       \ rS rSrSrg)"_StdinSocket._ExceptionMessageTypei  r   Nr   r   r!   r"   _ExceptionMessageTyper     r   r!   r   c                       \ rS rSrSrg)_StdinSocket._DataMessageTypei  r   Nr   r   r!   r"   _DataMessageTyper     r   r!   r   c                 b   SU l         [        R                  U l        [        R
                  R                  5       (       ai  [        R                  " 5       U l	        [        R                  " U R                  S9U l        SU R                  l        U R                  R                  5         g [         R                   " ["        R$                  [         R&                  5      U l        [         R                   " ["        R$                  [         R*                  U R(                  [,        R.                  -  5        g )NF)targetT)_stdin_closedutilsSUBPROTOCOL_MAX_DATA_FRAME_SIZE_bufsizer   r   r   r   Queue_message_queue	threadingThread&_ReadFromStdinAndEnqueueMessageWindows_reading_threaddaemonstartfcntlsysstdinF_GETFL
_old_flagsF_SETFLos
O_NONBLOCKrp   s    r"   rr   _StdinSocket.__init__  s    D99DM  **,, "KKMd&--<<>d$(d!
  "CIIu}}=dokk#))U]]DOObmm,KLr!   c                     [         R                  R                  5       (       d?  [        R                  " [        R
                  [        R                  U R                  5        g g rE   )r   r   r   r   r   r   r   r   rp   s    r"   __del___StdinSocket.__del__  s:     $$..00kk#))U]]DOO< 1r!   c                     [         R                  " [        R                  U5        [        R
                  (       d(  [        R                  R                  R                  5         [        U5      $ rE   )	r   WriteStreamBytesr   stdoutr   PY2bufferflushlen)rq   r   s     r"   r   _StdinSocket.send  s?    	3::t,77 
jjt9r!   c                     [         R                  R                  5       (       a  U R                  U5      $ U R	                  U5      $ )a  Receives data from stdin.

Blocks until at least 1 byte is available.
On Unix (but not Windows) this is unblocked by close() and shutdown(RD).
On all platforms a signal handler triggering an exception will unblock this.
This cannot be called by multiple threads at the same time.
This function performs cleanups before returning, so killing gcloud while
this is running should be avoided. Specifically RaisesKeyboardInterrupt
should be in effect so that ctrl-c causes a clean exit with an exception
instead of triggering gcloud's default os.kill().

Args:
  bufsize: The maximum number of bytes to receive. Must be positive.
Returns:
  The bytes received. EOF is indicated by b''.
Raises:
  IOError: On low level errors.
)r   r   r   _RecvWindows	_RecvUnix)rq   bufsizes     r"   recv_StdinSocket.recv  s9    (   **,,w''^^G$$r!   c                 B    U R                  [        R                  5        g rE   )r   r   SHUT_RDrp   s    r"   r   _StdinSocket.close  s     	MM&..!r!   c                    U[         R                  [         R                  4;   ac  SU l        [        R
                  R                  5       (       a8  U R                  U R                  S5      nU R                  R                  U5        g g g )NTr!   )r   r   r  r   r   r   r   r   r   r   put)rq   howmsgs      r"   r   _StdinSocket.shutdown  sn    
v00d 
	"	"	,	,	.	.&&t'C'CSI$ 
/	 1r!   c                 H    U R                   (       Gd7  [        R                  R                  R	                  S5      n[        R
                  " U R                  5      n[        R                  " 5       n[        R                  R                  R                  XU R                  [        R                  " U5      S5      nU(       d%  [        R                  " [        R                  S5      eUR                  SUR                    nU R"                  R%                  U R'                  U R(                  U5      5        U R                   (       d  GM6  gg! [*         aK    U R"                  R%                  U R'                  U R,                  [.        R0                  " 5       5      5         gf = f)zReads data from stdin on Windows.

This method will loop until stdin is closed. Should be executed in a
separate thread to avoid blocking the main thread.
iNzstdin ReadFile failed)r   ctypeswindllkernel32GetStdHandlecreate_string_bufferr   r   DWORDReadFilebyrefr   r   errnoEIOrawvaluer   r  r   r   	Exceptionr   r   exc_info)rq   hbufnumber_of_bytes_readokr  s         r"   r   3_StdinSocket._ReadFromStdinAndEnqueueMessageWindows  s/   4"""MM""//4))$--8'~~/]]##,,DMM6<<0D#EtMUYY(?@
@gg1+112 8 89N9N9<!> 	? """  4


"
"4#=#=#&<<>344s   EE AF! F!c                    U[         R                  :w  a  [        R                  " SU5        U R                  (       d   U R
                  R                  SS9nUR                  5       nUR                  5       nX0R                  L a!  [        R                  " US   US   US   5        X0R                  L a  SU l        U$ g! [        R                   a     M  f = f)zReads data from stdin on Windows.

Args:
  bufsize: The maximum number of bytes to receive. Must be positive.
Returns:
  The bytes received. EOF is indicated by b''.
Raises:
  socket.error: On low level errors.
'bufsize [%s] is not max_data_frame_sizer   )timeoutr      Tr!   )r   r   r   infor   r   getr   Emptyr   r   r   r   reraiser   )rq   r   r  msg_typemsg_datas        r"   r   _StdinSocket._RecvWindows  s     %777	hh8'B
   !!%%a%0
 hh	//	/HQK!hqk:	11	1!o ! [[ s   B> >CCc                    U[         R                  :w  a  [        R                  " SU5        U R                  (       a  g U R                  (       dS  [
        R
                  " [        R                  /SS[        5      nUS   (       d  MI  U R                  U R                  5      $  g! [        R                   a
    SU l         gf = f)a  Reads data from stdin on Unix.

Args:
  bufsize: The maximum number of bytes to receive. Must be positive.
Returns:
  The bytes received. EOF is indicated by b''. Once EOF has been indicated,
  will always indicate EOF.
Raises:
  IOError: On low level errors.
r  r!   r   r   T)r   r   r   r!  r   selectr   r   READ_FROM_STDIN_TIMEOUT_SECS_ReadUnixNonBlockingr   r   r   )rq   r   stdin_readys      r"   r   _StdinSocket._RecvUnix!  s     %777	hh8'B	 ""mmSYYKR$@B1~
((77 #  !!  d s   A#B% %CCc                     [         R                  (       a   [        R                  R	                  U5      nO*[        R                  R
                  R	                  U5      n US:X  a  [        R                  eUc  SnU$ ! [         aH  nUR                  [        R                  :X  d  [        U[        R                  5      (       a   SnAge SnAff = f)a  Reads from stdin on Unix in a nonblocking manner.

Args:
  bufsize: The maximum number of bytes to receive. Must be positive.
Returns:
  The bytes read. b'' means no data is available.
Raises:
  _StdinSocket._EOFError: to indicate EOF.
  IOError: On low level errors.
Nr!   )r   r   r   r   readr   IOErrorr  EAGAIN
isinstanceioBlockingIOErrorr   r   )rq   r   bes       r"   r+  !_StdinSocket._ReadUnixNonBlockingB  s    	IINN7#II!!'* 	Cx"""y aH%  		
ELL	 Jq"2D2D$E$E 	s"   4A> )A> >
C=C
CC)r   r   r   r   r   N)r   r   r   r   r   objectr   r  r   r   r   r   rr   r   r   r   r   r   r   r   r   r+  r    r   r!   r"   r   r   s  sr    F 	) 		 		 		 	M$=%2"	%42$LB%r!   r   c                   B    \ rS rSrSr S
S jrS rS r SS jrS r	Sr
g	)SecurityGatewayTunnelHelperij  z5Helper class for starting a Security Gateaway tunnel.c                    UR                   U l        UR                  U l        X l        X0l        X@l        XPl        X`l        Xpl	        SU l
        [        R                  " SS9U l        [        R                  " 5       U l        g NFT)use_google_auth)rd   _tunnel_url_overriderh   _ignore_certs_project_region_security_gateway_host_port_use_dest_group	_shutdownr   LoadIfEnabled_credentialr   Lock_credential_lock)rq   rV   rR   r_   security_gatewayra   portuse_dest_groups           r"   rr   $SecurityGatewayTunnelHelper.__init__m  si     !% < <DNNDML-JJ)DN**4@D%NN,Dr!   c           	          AU R                  5       n[        R                  " UU[        R                  " [
        U5      [        R                  " [        U5      U R                  5      nUR                  5         U$ rE   )	_GetTargetInfor   SecurityGatewayTunnel	functoolspartialr   r   r?  InitiateConnection)rq   r   get_access_token_callback
user_agentsg_tunnel_targetnew_sg_tunnels         r"   _InitiateConnection/SecurityGatewayTunnelHelper._InitiateConnection  si    **,33!0*=7DM $$&r!   c                    [         R                  " 5       n[        U5      (       a  U" SS9n[        R                  " U R
                  U R                  U R                  U R                  U R                  U R                  UU R                  S9$ )Nhttpsmethod)rR   r_   rK  ra   rL  url_override
proxy_inforM  )r   GetHttpProxyInfocallablesg_utilsSecurityGatewayTargetInfor@  rA  rB  rC  rD  r>  rE  rq   r`  s     r"   rP  *SecurityGatewayTunnelHelper._GetTargetInfo  sr    ,,.J
W-j--||//ZZZZ..++	 	r!   c                 2   ASn U R                  U[        R                  " [        U R                  U R
                  5      U5      nU R                  (       d  UR                  5       (       dw  UR                  [        R                  5      nU(       d  [        R                  " SU5        O9UR                  U5        U R                  (       d  UR                  5       (       d  Mw  [        R                   " SU5        U(       a/  UR#                  [        R$                  5        UR'                  5         U(       a(  UR)                  5         [        R*                  " SU5        gg! [        R                   a!  n[        R                  " SX'5         SnANSnAff = f! [        R                   " SU5        U(       a/  UR#                  [        R$                  5        UR'                  5         U(       a(  UR)                  5         [        R*                  " SU5        f f = f)aE  Receive data from provided local connection and send over HTTP CONNECT.

Args:
  local_conn: A socket or _StdinSocket representing the local connection.
  socket_address: A verbose loggable string describing where conn is
    connected to.
  user_agent: The user_agent of this connection
  conn_id: The id of the connection.
Nz!Local connection [%s] has closed.z3Error while transmitting local connection [%s]: %s z2Terminating connection from local connection: [%s]zConnection [%s] closed.)rY  rR  rS  r   rH  rJ  rF  
ShouldStopr   r   r   r   warningSendr   r   r!  r   r  r   Closer   )rq   r   socket_addressrV  conn_idsg_connr   r6  s           r"   RunReceiveLocalData/SecurityGatewayTunnelHelper.RunReceiveLocalData  s    	G=((



%t'7'79N9N g 7#5#5#7#7uDDE
++9>
J
T 7#5#5#7#7 
hhC	FNN+			+^< 
 << #	iiE# ## 
hhC	FNN+			+^< 
s7   B$E  )F *7E   F4FF FF A>Hc                     SU l         g NTrF  rp   s    r"   rk  !SecurityGatewayTunnelHelper.Close  s     DNr!   )rH  rJ  rC  r?  rD  r@  rA  rB  rF  r>  rE  NF)r   r   r   r   r   rr   rY  rP  ro  rk  r    r   r!   r"   r:  r:  j  s)    = $-&  #%&=Pr!   r:  c                   H    \ rS rSrSr  S
S jrS r SS jrS rSS jr	S	r
g)IAPWebsocketTunnelHelperi  z2Helper class for starting an IAP WebSocket tunnel.Nc                 (   X l         UR                  U l        UR                  U l        X0l        X@l        XPl        X`l        Xpl	        Xl
        Xl        Xl        SU l        [        R                  " SS9U l        ["        R$                  " 5       U l        g r<  )r@  rd   _iap_tunnel_url_overriderh   r?  _zone	_instance
_interfacerD  rA  _networkrC  _dest_grouprF  r   rG  rH  r   rI  rJ  )rq   rV   rR   rS   rT   	interfacerL  r_   r`   ra   re   s              r"   rr   !IAPWebsocketTunnelHelper.__init__  sw     M$($@$@D!NNDJNOJLMJ!DN**4@D%NN,Dr!   c                     SU l         g rr  rs  rp   s    r"   rk  IAPWebsocketTunnelHelper.Close  s	    DNr!   c           
          U R                  5       n[        R                  " XR[        R                  " [
        U5      [        R                  " [        U5      X0R                  US9nUR                  5         U$ )N)ignore_certsrm  )	_GetTunnelTargetInfor   IapTunnelWebSocketrR  rS  r   r   r?  rT  )rq   r   rU  rV  rm  tunnel_targetnew_websockets          r"   rY  ,IAPWebsocketTunnelHelper._InitiateConnection  se    --/M(;;0*=7D!3!3M $$&r!   c                 ^   [         R                  " 5       n[        U5      (       a  U" SS9n[        R                  " U R
                  U R                  U R                  U R                  U R                  U R                  UU R                  U R                  U R                  U R                  S S9$ )Nr\  r]  )rR   rS   rT   r  rL  r_  r`  r_   r`   ra   re   ro   )r   ra  rb  r   IapTunnelTargetInfor@  r|  r}  r~  rD  r{  rA  r  rC  r  re  s     r"   r  -IAPWebsocketTunnelHelper._GetTunnelTargetInfo  s    ,,.J
W-j$$ZZ//ZZ22||ZZ## r!   c                    Sn U R                  U[        R                  " [        U R                  U R
                  5      UUS9nU R                  (       d  UR                  [        R                  5      nU(       dT  UR                  5         [        R                  " SU5        UR                  5       (       d  [        R                  " SXB5        O$UR                  U5        U R                  (       d  M  U R                  (       a  [        R(                  " SXB5        O[        R(                  " SXB5         UR+                  5          U(       a  UR/                  5         gg! [         ["        R$                  4 a"  n[        R&                  " SUX'5         SnANSnAff = f! [,         a     Nef = f! [,        ["        R$                  4 a     gf = f! U R                  (       a  [        R(                  " SXB5        O[        R(                  " SXB5         UR+                  5         O! [,         a     Of = f U(       a  UR/                  5         f f ! [,        ["        R$                  4 a     f f = f= f)a8  Receive data from provided local connection and send over WebSocket.

Args:
  conn: A socket or _StdinSocket representing the local connection.
  socket_address: A verbose loggable string describing where conn is
    connected to.
  user_agent: The user_agent of this connection
  conn_id: Id of the connection.
Nrm  z+[%d] Received local EOF, closing connectionz'[%d] Failed to send all data from [%s].z.[%d] Error during local connection to [%s]: %sz$[%d] Terminating connection to [%s].z([%d] Client closed connection from [%s].)rY  rR  rS  r   rH  rJ  rF  r   r   r   LocalEOFr   r   WaitForAllSentri  rj  r  r
   Error	exceptionr!  r   r   rk  )rq   connrl  rV  rm  websocket_connr   r6  s           r"   ro  ,IAPWebsocketTunnelHelper.RunReceiveLocalData  s    N'//



%t'7'79N9N  0 n yy>>? 
!
!
#
))A7
K..00KKA1
D!   
7	* 	;	*





   z''( '	mmDg"' ''  
 
 0 01  
7	* 	;	*

 



  
 0 01 s   C
E G "E 4F F- F8FG FG 
F*)F*-G
	G
AI*H I* 
H-*I*,H--I*1I
I*
I'$I*&I''I*)rH  rJ  r  rC  r{  r?  r}  r~  r  rD  r@  rA  rF  r|  )NNNNNNNNrv  r   )r   r   r   r   r   rr   rk  rY  r  ro  r    r   r!   r"   ry  ry    s,    : ?C@D-* /1
&2r!   ry  c                   N    \ rS rSrSrS rS rS rS rS r	S r
S	 rS
 rS rSrg)IapTunnelProxyServerHelperi9  z@Proxy server helper listens on a port for new local connections.c                 ^    X@l         Xl        X l        X0l        / U l        / U l        SU l        g )Nr   )	_tunneler_local_host_local_port_should_test_connection_server_sockets_connections_total_connections)rq   r   r   should_test_connectiontunnelers        r"   rr   #IapTunnelProxyServerHelper.__init__<  s1    N!!#9 DDDr!   c                 $    U R                  5         g rE   )_CloseServerSocketsrp   s    r"   r   "IapTunnelProxyServerHelper.__del__F  s    r!   c                 n   U R                   (       a   U R                  5         [        U R                  U R                  5      U l	        [        R                  R                  SU R                  -  5         [        R                  " 5           U R                  R!                  U R#                  5       5        U R%                  5         M;  ! [        R                   a2  n[        R                  " S[        R
                  " U5      -  5      eSnAff = f! , (       d  f       O)= f! [&         a    [        R(                  " S5         Of = fU R+                  5         O! U R+                  5         f = fU R,                  R/                  5         U R1                  5         [        R2                  R                  S5        g)zStart accepting connections.z.While checking if a connection can be made: %sNzListening on port [%d].Keyboard interrupt received.zServer shutdown complete.)r  _TestConnectionr   ConnectionCreationErrorr   r   r   r  r  r  r   outrN   r   RaisesKeyboardInterruptr  rg   _AcceptNewConnection_CleanDeadClientConnectionsKeyboardInterruptr!  r  r  rk  _CloseClientConnectionsrM   )rq   r6  s     r"   RunIapTunnelProxyServerHelper.RunI  sN   ##Q 00@0@040@0@BDGGMM+d.>.>>?
!224



"
"4#<#<#>
? 
*
*
,	  "99 Q"::<s}}Q?OOQ 	QQ 54  /	hh-./  d NN  "JJ01sY   C 5D! 
=DD-DD
DD! E D! ! EE EE E*c           	      H   [         R                  R                  S5        [        R                  " 5       nU R
                  R                  S[        R                  " [        U R
                  R                  [        R                  " 5       5      U5      nUR                  5         g)z;Test if a connection can be made to the requested endpoint.z#Testing if tunnel connection works.N)r   rM   rN   r   MakeUserAgentStringr  rY  rR  rS  r   rH  r   rI  rk  )rq   rV  r  s      r"   r  *IapTunnelProxyServerHelper._TestConnectione  sr    JJ:;..0J>>--#NN&&NN	

 	D 	JJLr!   c                 b   S/nUS   (       d/  [         R                   " U R                  SSS5      nUS   (       d  M/  US   nUS   R                  5       u  p4[        R                  " U R
                  X4U R                  4S9nSUl        UR                  5         U =R                  S-  sl        XS4$ )z@Accept a new socket connection and start a new WebSocket tunnel.r   r   g?)r   rV   Tr   )	r)  r  acceptr   r   _HandleNewConnectionr  r   r   )rq   ready_socketsready_read_socketsr  rl  
new_threads         r"   r  /IapTunnelProxyServerHelper._AcceptNewConnectionv  s     DMAmmD$8$8"b#Fm A 'q)-a0779D!!)B)B(,(,(?(?(ABJ Jq r!   c                     [         R                  " S5         U R                   H  nUR                  5         M     g ! [         a     g f = f)NzStopping server.)r   r   r  r   r   )rq   server_sockets     r"   r  .IapTunnelProxyServerHelper._CloseServerSockets  sB    II !//- 0 
s   #< 
A	A	c                 &   U R                   (       ao  SnU R                    H2  u  p#UR                  5       (       d  M  US-  n UR                  5         M4     U(       a#  [        R
                  R                  SU-  5        ggg! [         a     Mo  f = f)z4Close client connections that seem to still be open.r   r   z Closed [%d] local connection(s).N)r  is_aliver   r   r   rM   rN   )rq   close_countclient_threadr  s       r"   r  2IapTunnelProxyServerHelper._CloseClientConnections  s    k!%!2!2
-!!##

+JJL	 "3 


;kIJ 
  " s   B
BBc                    / nU R                   (       a  SnU R                    HF  u  p4UR                  5       (       d  US-  n UR                  5         AAM4  UR	                  X4/5        MH     U(       a  [
        R                  " SU-  5        Xl         [        R                  " S5        [
        R                  " S[        U R                   5      -  5        gg! [         a     Nf = f)zEErase reference to dead connections so they can be garbage collected.r   r   z Cleaned [%d] dead connection(s).r   zconnections alive: [%d]N)
r  r  r   r   rg   r   r   gccollectr   )rq   conn_still_alivedead_connectionsr  r  s        r"   r  6IapTunnelProxyServerHelper._CleanDeadClientConnections  s    !%!2!2
-%%''
a

JJL 

!
!="7
8 "3 
		47GGH, 	jjm	ii)C0A0A,BBC)  " s   C
C#"C#c                 ,    [         R                  " 5       nU R                  R                  U[	        U5      XCS9  g ! [
         a5  n[        R                  " S[        R                  " U5      5         S nAg S nAf  [        R                  " S5         g = f)Nr  z.Socket error [%s] while receiving from client.z"Error while receiving from client.)r   r  r  ro  reprr   r   r!  r   r   r  )rq   r  rl  rm  rV  r6  s         r"   r  /IapTunnelProxyServerHelper._HandleNewConnection  sv    :002j
nn((tN/C)3 ) F !	hh?}}Q! !:	mm89s   9< 
B+A66B)r  r  r  r  r  r  r  N)r   r   r   r   r   rr   r   r  r  r  r  r  r  r  r    r   r!   r"   r  r  9  s4    H 28"*KD2	:r!   r  c                   $    \ rS rSrSrS rS rSrg)IapTunnelStdinHelperi  z9Facilitates a connection that gets local data from stdin.c                     Xl         g rE   r  )rq   r  s     r"   rr   IapTunnelStdinHelper.__init__  s    Nr!   c                 $    [         R                  " 5          [        R                  " 5       nU R                  R                  [        5       SU5        SSS5        g! , (       d  f       g= f! [         a    [        R                  " S5         gf = f)zExecutes the tunneling of data.r   Nr  )
r   r  r   r  r  ro  r   r  r   r!  )rq   rV  s     r"   r  IapTunnelStdinHelper.Run  sd    
/224
 224
**<>7JO 544  /	hh-./s.   A, ;AA, 
A)%A, )A, , BBr  N)r   r   r   r   r   rr   r  r    r   r!   r"   r  r    s    A/r!   r  ru  r  )Dr   
__future__r   r   r   r
  r  rR  r  r3  r   r)  r   r   r   googlecloudsdk.api_lib.computer   r   r   r   r	   rc  googlecloudsdk.corer
   r   r   r   r   r   googlecloudsdk.core.credentialsr   r   googlecloudsdk.core.utilr   r   r   r   	six.movesr   r   r   r   r   r*  r  r   r%   r2   r5   r@   r<   r;   rF   rZ   rb   rU   r8  rO   r   r   r   r   r   r   r:  ry  r  r  r   r!   r"   <module>r     sF    > &  '    	 	 	   
  ? N 4 F * / * # * ) 1 1 * .  
    **,,  
 0 0 J,, J$!$!"*Z0P$/4F /4d$& *@t6 tn]& ]@lv l^J: J:Z/ /r!   