
    |<uj)                        S 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  \R                  R                  S5      r\R                  " S\R                   5      (       a  SO\r\" \R$                  R'                  S\5      5      r\S-  r\S	-  r\S
-  r\S-  r\S-  rSr\R6                  " S5      rS rS\4S jr " S S5      r g)u  
Axiom Zero — Remote Frontend TCP Bridge
=======================================
Runs inside the daemon (axiom_launcher.py) as a background thread.
Listens on TCP port 7443 with TLS, accepts connections from the
GTK frontend running on a DIFFERENT machine, and relays all IPC
events to it using the same length-prefixed JSON frame format
used by the UNIX socket.

If no TLS certificates are found, generates self-signed ones
automatically on first run and writes them to /var/lib/axiom-zero/.

Setup (automatic on first daemon start):
  Server cert → /var/lib/axiom-zero/server.pem + server.key
  CA cert      → /var/lib/axiom-zero/ca.pem
  Client cert  → generated and printed to console so operator can
                 copy ~/.axiom-zero/client.pem on their desktop

The frontend (gtk_ipc_listener.py) connects here automatically
if ~/.axiom-zero/connection.json specifies a remote server_host.
    N)Pathz~/.axiom-zeroz/var/libz/var/lib/axiom-zeroAXIOM_RUNTIME_DIRz
server.pemz
server.keyzca.pemz
client.pemz
client.keyi  zaxiom.tcp_bridgec                    ^^ [         R                  SSS9  [        R                  5       (       a  [        R                  5       (       a  g SSKJn   SSKJn  SSK	J
nJm  SSKJm  SSKnU4S	 jnU4S
 jnUR                  R                  5       nXcR                   " SS9-   nU" 5       nU R#                  U R%                  UR&                  S5      /5      n	U R)                  5       R+                  U	5      R-                  U	5      R/                  UR/                  5       5      R1                  U R3                  5       5      R5                  U5      R7                  U5      R9                  U R;                  SSS9SS9R=                  XR?                  5       5      n
[@        RB                  " 5       n[E        5       nU RG                  U5      U RG                  S5      /nU Vs/ s H'  oRI                  [J        RL                  " U5      5      PM)     nnXRI                  [J        RL                  " S5      5      /-  nU" 5       nU R)                  5       R+                  U R#                  U R%                  UR&                  U5      /5      5      R-                  U	5      R/                  UR/                  5       5      R1                  U R3                  5       5      R5                  U5      R7                  U5      R9                  U RO                  X-   5      SS9R=                  XR?                  5       5      nU" 5       nU R)                  5       R+                  U R#                  U R%                  UR&                  S5      /5      5      R-                  U	5      R/                  UR/                  5       5      R1                  U R3                  5       5      R5                  U5      R7                  U5      R9                  U RQ                  U RR                  RT                  /5      SS9R=                  XR?                  5       5      nU" [V        U
5        U" [        U5        U" [        U5        U" [X        U5        U" [Z        U5        [\        R_                  S5        [\        R_                  S5        [\        R_                  S[         35        [\        R_                  S[X         35        [\        R_                  S[Z         35        [\        R_                  S[V         35        [\        R_                  S5        [\        R_                  S5        [\        R_                  SU S[X         S35        [\        R_                  SU S[Z         S35        [\        R_                  SU S[V         S 35        [\        R_                  S5        [\        R_                  S!5        [\        R_                  S"5        [\        R_                  S#U(       a  US   OU S$35        [\        R_                  S5        gs  snf ! [`         a-    [\        Rc                  S%5        [\        Rc                  S&5         gf = f)'z?Generate self-signed CA + server + client certs if not present.T)parentsexist_okNr   )x509)NameOID)hashesserializationecc                  B   > T R                  T R                  5       5      $ N)generate_private_key	SECP384R1r   s   I/home/cade/axiom-zero-deploy/dev_control_center/remote_frontend_bridge.py	_make_key,generate_certs_if_missing.<locals>._make_key=   s    **2<<>::    c                 J  > [        US5      (       aJ  UR                  TR                  R                  TR                  R
                  TR                  5       5      nO%UR                  TR                  R                  5      nU R                  U5        U R                  S5        g )Nprivate_bytesi  )
hasattrr   EncodingPEMPrivateFormatTraditionalOpenSSLNoEncryptionpublic_byteswrite_byteschmod)pathobjdatar   s      r   
_write_pem-generate_certs_if_missing.<locals>._write_pem@   s    sO,,(()?)?)C)C)6)D)D)W)W)6)C)C)EG ''(>(>(B(BCT"JJur   iB  )dayszAxiom Zero CA)capath_length)critical	localhost	127.0.0.1Fzaxiom-operatorz<============================================================u)   AXIOM ZERO — TLS CERTIFICATES GENERATEDz  Server cert : z  Client cert : z  Client key  : z  CA cert     :  z1TO CONNECT FROM YOUR DESKTOP, COPY THESE 3 FILES:z  scp root@:z ~/.axiom-zero/client.pemz  ~/.axiom-zero/client.keyz     ~/.axiom-zero/ca.pemzTHEN RUN ON YOUR DESKTOP:z  axiom-zero-wizardz  (enter server IP: )uB   cryptography library not installed — TLS cert generation skippedz'Install with: pip3 install cryptography)2RUNTIME_DIRmkdirSERVER_CERTexists
SERVER_KEYcryptographyr   cryptography.x509.oidr	   cryptography.hazmat.primitivesr
   r   )cryptography.hazmat.primitives.asymmetricr   datetimeutcnow	timedeltaNameNameAttributeCOMMON_NAMECertificateBuildersubject_nameissuer_name
public_keyserial_numberrandom_serial_numbernot_valid_beforenot_valid_afteradd_extensionBasicConstraintssignSHA384socketgethostname_get_local_ipsDNSName	IPAddress	ipaddressIPv4AddressSubjectAlternativeNameExtendedKeyUsageExtendedKeyUsageOIDCLIENT_AUTHCA_CERTCLIENT_CERT
CLIENT_KEYloginfoImportErrorwarning)r   r	   r
   r8   r   r$   nowexpca_keyca_nameca_certhostname	local_ipssan_dnsipsan_ipssrv_keysrv_certcli_keycli_certr   r   s                       @@r   generate_certs_if_missingrj   0   s   dT2
 1 1 3 3V?%1H@	;	 &&(&&D11 +))T//0C0C_UVW**, L)++g*>Jv0023!M$";";"=>$$S)//#*>!M$"7"74T"7"R]aMbD1 	 '')#%	ll8,dll;.GHJST)BnnY%:%:2%>?)TnnY%:%:;%GHII[--/#|DIIt/A/A'BUBUW_/`.a$bc"{7+!z'"4"4"67$}T%>%>%@A'',__S-A$}T%@%@AR%S^c}dtFMMO4 	 ;++-!\$))T-?-?@S@SUe-f,g"hi [)Z 2 2 45"]4#<#<#>?%%c*??3+?"]4#8#8$:R:R:^:^9_#`kp]qT&--/2 	 	7(;):(;):(<=#K=12#K=12#J<01#G9-.DE;xj+6OPQ;xj*5OPQ;xj'2KLM,-&('		!x'PPQRSY U\  ?XY=>?s&   FX .XPX X 4YYreturnc                     / n  SS K nUR                  5        H{  nUR                  U5      R                  UR                  / 5      nU HG  nUR                  SS5      nU(       d  M  UR                  S5      (       a  M6  U R                  U5        MI     M}     U =(       d    S/$ ! [         a    [        R                  " [        R                  [        R                  5      n UR                  S5        U R                  UR                  5       S   5        O! [         a     Of = fUR                  5          N! UR                  5         f = ff = f)Nr   addrr,   z127.)z8.8.8.8P   r+   )	netifaces
interfacesifaddressesgetAF_INET
startswithappendrZ   rJ   
SOCK_DGRAMconnectgetsockname	Exceptionclose)ipsro   ifaceaddrsard   ss          r   rL   rL      s   
C))+E))%044Y5F5FKEUU62&2bmmF33JJrN  ,  ;-  	MM&..&*;*;<	IIo&JJq}}q)* 		 GGIAGGI	sN   AB# &B# >B# #=E!3DD7
D"D7!D""D7%E7E		Ec                       \ rS rSrSrSS\R                  4S jjrS rS\R                  S\R                  4S	 jrS
 rS\4S jr\S\S\4S j5       rSrg)RemoteFrontendBridge   zt
Asyncio TCP server. Accepts remote GTK frontend connections.
Event broadcasts are pushed to all connected clients.
Nevent_queuec                     [        5       U l        [        R                  " 5       U l        U=(       d    [        R
                  " 5       U l        S U l        g r   )set_clientsasyncioLock_lockQueuer   _server)selfr   s     r   __init__RemoteFrontendBridge.__init__   s2    5"<<>
&9'--/r   c                 j  #    [        5         [        R                  5       (       d  [        R	                  S5        g [
        R                  " [
        R                  5      nUR                  [        [        5      [        [        5      S9  [        R                  5       (       a3  UR                  [        [        5      5        [
        R                  Ul        [        R                   " U R"                  S[$        US9I S h  vN U l        [        R)                  S[$         S35        [        R*                  " U R-                  5       5        U R&                   IS h  vN   U R&                  R/                  5       I S h  vN   S S S 5      IS h  vN   g  N N9 N N! , IS h  vN  (       d  f       g = f7f)Nu5   No TLS cert found — remote frontend bridge disabled)certfilekeyfilez0.0.0.0)sslz)Remote frontend bridge listening on TCP :z (mTLS))rj   r1   r2   rX   r[   r   
SSLContextPROTOCOL_TLS_SERVERload_cert_chainstrr3   rU   load_verify_locationsCERT_REQUIREDverify_moder   start_server_handle_clientLISTEN_PORTr   rY   create_task_broadcast_loopserve_forever)r   ctxs     r   startRemoteFrontendBridge.start   s    !#!!##KKOPnnS445S%5s:O >>%%c'l3!//CO$11KS
 
 	<[MQR 	D0023<<<,,,,...  <<
  .  <<<sm   C<F3>F?AF3FF3F;F<F F3FF3F3FF3F0F" F0,F3readerwriterc           	      T  #    UR                  S5      n[        R                  SU 35        U R                   IS h  vN   U R                  R                  U5        S S S 5      IS h  vN     UR                  S5      I S h  vN nU(       d  OM#  U R                   IS h  vN   U R                  R                  U5        S S S 5      IS h  vN    UR                  5         UR                  5       I S h  vN   [        R                  SU 35        g  N N! , IS h  vN  (       d  f       N= f N! [         a     Nf = f N Nx! , IS h  vN  (       d  f       N= f Nk! [         a     Nuf = f! U R                   IS h  vN    U R                  R                  U5        S S S 5      IS h  vN    O! , IS h  vN  (       d  f       O= f UR                  5         UR                  5       I S h  vN    O! [         a     Of = f[        R                  SU 35        f = f7f)NpeernamezRemote frontend connected from i   zRemote frontend disconnected: )get_extra_inforX   rY   r   r   addreadry   discardrz   wait_closed)r   r   r   peerr#   s        r   r   #RemoteFrontendBridge._handle_client   s    $$Z024&9::::MMf% :	>#[[..  zzz%%f- "z((*** HH5dV<=% :::
 /  		 "zzz +  zzz%%f- "zzzzz((*** HH5dV<=s}  :H(DH( DH('D(H(-D3 D1D3 E3 D3 H(!E"H(%EH(EH(#E# 5E!6E# :H(H(D.D D.*H(1D3 3
E =E3 ?E  E3 H(H(EEEH(!E# #
E0-H(/E00H(3H%F
H%	F7%H%0F31H%7G=G >G
H%#G<5G86G<;H%<
H	H%H		H%%H(c                    #     U R                   R                  5       I Sh  vN nU R                  U5      nU R                   ISh  vN   [	        5       nU R
                   H-  n UR                  U5        UR                  5       I Sh  vN   M/     U =R
                  U-  sl        SSS5      ISh  vN   M   N Nt N3! [         a    UR                  U5         M|  f = f N.! , ISh  vN  (       d  f       NC= f7f)zEPicks events off the queue and sends to all connected remote clients.N)
r   rr   _encode_framer   r   r   writedrainry   r   )r   eventframedeadr   s        r   r   $RemoteFrontendBridge._broadcast_loop   s     **..00E&&u-Ezzzu"mmF)U+$lln,, , % "z 0!
 -$ )() "zzzs   C>B:%C>B<C>C$&$C 
B>C C$(C>3C"4C><C>>C  CC$CC$"C>$C;*C-+C;7C>r   c                 p     U R                   R                  U5        g! [        R                   a     gf = f)z3Thread-safe event push from the daemon's sync code.N)r   
put_nowaitr   	QueueFull)r   r   s     r   
push_eventRemoteFrontendBridge.push_event   s3    	''.   		s    55rk   c                     [         R                  " U 5      R                  S5      n[        R                  " S[        U5      5      nX!-   $ )Nzutf-8z>I)jsondumpsencodestructpacklen)r   payloadheaders      r   r   "RemoteFrontendBridge._encode_frame   s8    **U#**73++dCL1r   )r   r   r   r   r   )__name__
__module____qualname____firstlineno____doc__r   r   r   r   StreamReaderStreamWriterr   r   dictr   staticmethodbytesr   __static_attributes__ r   r   r   r      so    
 GMM  /4>7+?+? >&-&:&:>0&   T  e    r   r   )!r   r   r   r   r   osloggingrO   rJ   r8   pathlibr   r!   
expanduseruser_diraccessW_OKdefault_direnvironrr   r/   r1   r3   rU   rV   rW   r   	getLoggerrX   rj   listrL   r   r   r   r   <module>r      s   ,  
   	     77o.')yyRWW'E'E#82::>>"5{CD\)\)
X%\)\)
*+
\?~   2X  X r   