§
    ¬	Êj¡A  ã            
      ób  — d Z ddlmZ ddlZddlZddlZddlZddlZddlZddl	m
Z
mZmZ ddlmZ ej                             ej                             dd¦  «        d¦  «        Zd	Zd
dddddddddœ	Zd>d„Zd?d„Zd@dAd$„Zd@dBd%„ZdCdAd'„ZdDdEd*„ZdFdGd-„ZdHd1„ZdId2„Zdd3œdJd6„Zd7dd8œdKd;„Z dLd=„Z!dS )Muž  What this session's exit can REALLY do, measured before the launch.

â›” THIS IS PRODUCT, NOT MEASURING APPARATUS, and the difference shows in one
line: what this module answers DECIDES how the browser is configured. It was
born on the bench and lived there for a day; that file is now a pointer to this
one, because a fact computed in two places drifts.

**The rule the owner dictated on 2026-08-25, which simplifies everything:** what
is detected BEFORE the browser starts is the truth of the session, and it is
absolute for its lifetime. It is not re-checked, drift is not chased, and
whether the proxy stays sticky does not matter. Measure once, configure
accordingly.

â›” CAPABILITIES ARE A PROPERTY OF THE GATEWAY, NOT OF THE SESSION, and that is
what makes probing them practical. Measured 2026-08-25 over 500 sessions: 95 live
peers on one provider all answer `rep=7`, 100 out of 100 on another, and two
gateways of the same account share 71 addresses out of 71 while giving DIFFERENT
answers. Changing peer does not change the answer; changing gateway does. So it
is probed once per endpoint and reused, rather than paying seconds at every
launch. Measured cost: 4-19 seconds, once every 24 hours per gateway.

â›” AND ABSENCE OF PROOF ALWAYS FALLS ON THE CAUTIOUS SIDE. If the probe does not
answer, or answers ambiguously, the configuration is the usual one. A capability
is only exploited once it is DEMONSTRATED, because erring in that direction costs
the worst sentence a detector can write: measured by reading a real detector's
code, a browser that emits no candidates is given "Javascript is manipulated"
instead of "VPN detected".

No function here ever prints a credential.
é    )ÚannotationsN)ÚAnyÚDictÚOptional)ÚurlparseÚTEMPz/tmpzexit_capability.jsoni€Q Úokzgeneral failureznot allowedznetwork unreachablezhost unreachablezconnection refusedzttl expiredzcommand not supportedzaddress type not supported)	r   é   é   é   é   é   é   é   é   ÚuserÚstrÚsecretÚreturnúOptional[str]c                ó<  — |                       d¦  «         |                      d¦  «        }t          |¦  «        dk    s|d         dk    rdS |d         dk    r¶|                     ¦   «         |                     ¦   «         }}|                       dt	          t          |¦  «        g¦  «        z   |z   t	          t          |¦  «        g¦  «        z   |z   ¦  «         |                      d¦  «        }t          |¦  «        dk    s|d         dk    rdS n|d         d	k    rd
S d S )Ns   r   r   r   znot a SOCKS5 greetingr
   ó   zauthentication refusedéÿ   z#no acceptable authentication method)ÚsendallÚrecvÚlenÚencodeÚbytes)Úsr   r   ÚrÚuÚpÚas          úJC:\Projects\Muse2API\.venv\Lib\site-packages\invisible_core/_capability.pyÚ_greet_socks5r%   =   sù   € Ø‡I‚IˆoÑÔÐØ	�Šˆq‰	Œ	€AÝ
ˆ1�v„v�‚{€{�a˜”d˜a’i�iØ&Ð&Øˆ„tˆq‚y€yØ�{Š{‰}Œ}˜fŸmšm™oœoˆ1ˆØ	�	Š	�'�E¥3 q¡6¤6 (™OœOÑ+¨aÑ/µ%½¸Q¹¼¸±/´/ÑAÀAÑEÑFÔFÐFØ�FŠF�1‰IŒIˆÝˆq‰6Œ6�QŠ;ˆ;˜!˜Aœ$ !š)˜)Ø+Ð+ð $à	
ˆ1Œ�ŠˆØ4Ð4Øˆ4ó    ÚhostÚportÚintúOptional[int]c                ó>  — |                      ¦   «         }|                      dt          t          |¦  «        g¦  «        z   |z   t	          j        d|¦  «        z   ¦  «         |                      d¦  «        }t          |¦  «        dk    r|d         dk    r|d         nd S )Ns    ú!Hé
   r   r   r   r
   )r   r   r   r   ÚstructÚpackr   )r   r'   r(   Úhr    s        r$   Ú_connect_socks5r1   M   s‚   € Ø�Š‰Œ€AØ‡I‚IÐ!¥E­3¨q©6¬6¨(¡O¤OÑ3°aÑ7½&¼+ÀdÈDÑ:QÔ:QÑQÑRÔRÐRØ	�Šˆr‰
Œ
€AÝ�q‘6”6˜Q’;�; 1 Q¤4¨1¢9 9ˆ1ˆQŒ4ˆ4°$Ð6r&   é   ÚproxyúDict[str, str]ÚtimeoutÚfloatc                óR  — t          | d         ¦  «        }	 t          j        |j        |j        f|¬¦  «        }|                     |¦  «         |j        dk    r2ddl}|                     ¦   «          	                    ||j        ¬¦  «        }	 |j         
                    d¦  «        r’t          ||                      dd	¦  «        |                      d
d	¦  «        ¦  «        r	 |                     ¦   «          dS t          |dd¦  «        dk    r	 |                     ¦   «          dS |                     d¦  «         n”ddl}|                     |                      dd	¦  «        ›d|                      d
d	¦  «        ›�                     ¦   «         ¦  «                             ¦   «         }|                     d|z                       ¦   «         ¦  «         d}t)          |¦  «        dk     r0|                     d¦  «        }|sn||z  }t)          |¦  «        dk     °0t-          j        d|                     d¦  «        d         ¦  «        }	|	r'|	                     d¦  «                             ¦   «         nd	 |                     ¦   «          S # |                     ¦   «          w xY w# t4          $ r Y dS w xY w)zHThe address TCP leaves from, read in the clear over a single connection.Úserver©r5   Úhttpsr   N)Úserver_hostnameÚsocksÚusernameÚ Úpasswordzapi.ipify.orgéP   sN   GET / HTTP/1.1
Host: api.ipify.org
Connection: close
User-Agent: curl/8

ú:z�GET http://api.ipify.org/ HTTP/1.1
Host: api.ipify.org
Proxy-Authorization: Basic %s
Connection: close
User-Agent: curl/8

r&   é   s   \b(?:\d{1,3}\.){3}\d{1,3}\bó   

éÿÿÿÿ)r   ÚsocketÚcreate_connectionÚhostnamer(   Ú
settimeoutÚschemeÚsslÚcreate_default_contextÚwrap_socketÚ
startswithr%   ÚgetÚcloser1   r   Úbase64Ú	b64encoder   Údecoder   r   ÚreÚsearchÚsplitÚgroupÚOSError)
r3   r5   r!   r   rJ   rP   ÚcredÚdatar"   Úms
             r$   Útcp_exitr[   T   s»  € å��x”Ñ!Ô!€Að'ÝÔ$ a¤j°!´&Ð%9À7ÐKÑKÔKˆØ	�Š�WÑÔÐð Œ8�wÒÐØˆJˆJˆJØ×*Ò*Ñ,Ô,×8Ò8¸ÈAÌJÐ8ÑWÔWˆAð	ØŒx×"Ò" 7Ñ+Ô+ð _Ý   E§I¢I¨j¸"Ñ$=Ô$=¸u¿yºyÈÐUWÑ?XÔ?XÑYÔYð  Øð, �GŠG‰IŒIˆIˆIˆIõ+ # 1 o°rÑ:Ô:¸aÒ?Ð?Øð( �GŠG‰IŒIˆIˆIˆIð' —	’	ð Mñ Nô Nð Nð Nð ���Ø×'Ò'Ø %§	¢	¨*°bÑ 9Ô 9Ð 9Ð 9Ø %§	¢	¨*°bÑ 9Ô 9Ð 9ð;ß<BºF¹H¼HñFô FçFLÂfÁhÄhð ð —	’	ð MàOSñTçU[ÒU[ÑU]ÔU]ñ_ô _ð _ð ˆDÝ�d‘)”)˜dÒ"Ð"Ø—F’F˜4‘L”L�Øð ØØ˜‘	�õ	 �d‘)”)˜dÒ"Ð"õ
 ”	Ð9¸4¿:º:ÀkÑ;RÔ;RÐSUÔ;VÑWÔWˆAØ*+Ð5�1—7’7˜1‘:”:×$Ò$Ñ&Ô&Ð&°Ð5à�GŠG‰IŒIˆIˆIøˆA�GŠG‰IŒIˆIˆIøøøøÝð ð ð ØˆtˆtðøøøsD   —A4J ÂAI? Ã J Ã6I? ÄJ Ä"EI? É*J É?JÊJ Ê
J&Ê%J&c                ó¶  — t          | d         ¦  «        }|j                             d¦  «        sdd|j        z  fS 	 t          j        |j        |j        f|¬¦  «        }|                     |¦  «         	 t          ||  	                    dd¦  «        |  	                    dd¦  «        ¦  «        }|rd|f| 
                    ¦   «          S |                     d	¦  «         |                     d
¦  «        }|s	 | 
                    ¦   «          dS t          |¦  «        d
k     s|d         dk    r	 | 
                    ¦   «          dS |d         dk    rBdd|d         t           	                    |d         d¦  «        fz  f| 
                    ¦   «          S |d         }|dk    r't          j        |                     d
¦  «        ¦  «        nw|dk    r@|                     |                     d¦  «        d         ¦  «                             ¦   «         n1t          j        t          j        |                     d¦  «        ¦  «        }t'          j        d|                     d¦  «        ¦  «        d         }|dv r|j        }dd||fz  f| 
                    ¦   «          S # | 
                    ¦   «          w xY w# t*          $ r#}	ddt-          |	¦  «        j        z  fcY d}	~	S d}	~	ww xY w)zB`(supported, explanation)`. SOCKS5 only: HTTP has no such command.r8   r<   Fz=scheme %s: SOCKS UDP ASSOCIATE does not exist in the protocolr9   r=   r>   r?   ó
          r   )Fz$the gateway closed without answeringr   r   )Fzanswer could not be readr
   z	rep=%d %sú?r   é   r,   r   )z0.0.0.0z::Tz%s:%dzerror %sN)r   rI   rM   rE   rF   rG   r(   rH   r%   rN   rO   r   r   r   Ú_REPÚ	inet_ntoarR   Ú	inet_ntopÚAF_INET6r.   ÚunpackrW   ÚtypeÚ__name__)
r3   r5   r!   r   Úer    ÚatypÚaddrr(   Úexs
             r$   Úudp_associaterk   �   s¸  € å��x”Ñ!Ô!€AØŒ8×Ò˜wÑ'Ô'ð aØÐUÐXYÔX`Ñ`Ð`Ð`ð5ÝÔ$ a¤j°!´&Ð%9À7ÐKÑKÔKˆØ	�Š�WÑÔÐð	Ý˜a §¢¨:°rÑ!:Ô!:¸E¿IºIÀjÐRTÑ<UÔ<UÑVÔVˆAØð  Ø˜a�xð$ �GŠG‰IŒIˆIˆIð# �IŠIÐEÑFÔFÐFØ—’�q‘	”	ˆAØð EØDð �GŠG‰IŒIˆIˆIˆIõ �1‰vŒv˜Šzˆz˜Q˜qœT QšY˜YØ8ð �GŠG‰IŒIˆIˆIˆIð �Œt�qŠyˆyØ˜k¨Q¨q¬Tµ4·8²8¸A¸a¼DÀ#Ñ3FÔ3FÐ,GÑGÐGð �GŠG‰IŒIˆIˆIð �Q”4ˆDØ37¸1²9°9•FÔ$ Q§V¢V¨A¡Y¤YÑ/Ô/Ð/Ø59¸Q²Y°Y�A—F’F˜1Ÿ6š6 !™9œ9 Qœ<Ñ(Ô(×/Ò/Ñ1Ô1Ð1ÝÔ$¥V¤_°a·f²f¸R±j´jÑAÔAð õ ”=  q§v¢v¨a¡y¤yÑ1Ô1°!Ô4ˆDØÐ(Ð(Ð(Ø”z�Ø˜ D¨$ <Ñ/Ð/à�GŠG‰IŒIˆIˆIøˆA�GŠG‰IŒIˆIˆIøøøøÝð 5ð 5ð 5Ø�j¥4¨¡8¤8Ô#4Ñ4Ð4Ð4Ð4Ð4Ð4Ð4Ð4øøøøð5øøøsf   ½7J+ Á5>J Â3J+ Ã,J Ã5J+ ÄJ Ä+J+ Å9J Å:J+ ÆC.J É=J+ ÊJ(Ê(J+ Ê+
KÊ5KËKËKé   c                ón  — t          | ¦  «        \  }}|sdS |                     d¦  «        \  }}}t          | d         ¦  «        }	 t          j        |j        |j        f|¬¦  «        }|                     |¦  «         t          ||  	                    dd¦  «        |  	                    dd¦  «        ¦  «        r| 
                    ¦   «          dS |                     d¦  «         |                     d	¦  «         t          j        t          j        t          j        ¦  «        }	|	                     |¦  «         	 d
}
dt          t!          |
¦  «        g¦  «        z   |
z   t#          j        dd¦  «        z   }|	                     |dz   t)          j        d¦  «        z   |t-          |¦  «        f¦  «         |	                     d¦  «        \  }}t!          |¦  «        d	k     s|d         dk    r+	 |	 
                    ¦   «          | 
                    ¦   «          dS |d         d}}||dk    rdn|dk    rd|d         z   ndz  }||dz   d…         }t!          |¦  «        dk     s|dd…         dk    r+	 |	 
                    ¦   «          | 
                    ¦   «          dS ddt#          j        d|dd…         ¦  «        d         z   }}|dz   t3          |t!          |¦  «        ¦  «        k    ròt#          j        d|||dz   …         ¦  «        \  }}||dz   |dz   |z   …         }|dk    r~t!          |¦  «        dk    rkt          d„ t5          |dd…         d¦  «        D ¦   «         ¦  «        }t          j        |¦  «        |	 
                    ¦   «          | 
                    ¦   «          S |d|z   d|dz  z
  dz  z   z  }|dz   t3          |t!          |¦  «        ¦  «        k    °ò	 |	 
                    ¦   «          | 
                    ¦   «          dS # |	 
                    ¦   «          | 
                    ¦   «          w xY w# t8          $ r Y dS w xY w)a^  The address UDP leaves from, asked of STUN. `None` if UDP does not pass.

    This is the half almost nobody measures, and without it "the proxy carries
    UDP" is not enough: if this address is not the same as the TCP one, using it
    for WebRTC produces two addresses in one session, which is exactly the
    disagreement detectors look for.
    NrA   r8   r9   r=   r>   r?   r]   r-   s   stun.l.google.coms      r,   ifK  s      !¤Brl   i   r   r   r   r   r
   r_   é   s   z!HHé    r   c              3  ó&   K  — | ]\  }}||z  V — Œd S )N© )Ú.0r#   Úbs      r$   ú	<genexpr>zudp_exit.<locals>.<genexpr>Ì   s*   è è € ÐRÐR©¨¨A˜q 1™uÐRÐRÐRÐRÐRÐRr&   s   !¤B)rk   Ú
rpartitionr   rE   rF   rG   r(   rH   r%   rN   rO   r   r   ÚAF_INETÚ
SOCK_DGRAMr   r   r.   r/   ÚsendtoÚosÚurandomr)   Úrecvfromrd   ÚminÚzipra   rW   )r3   r5   r	   Úwherer'   Ú_r(   r!   Úctrlr   r0   ÚtestaÚdrh   ÚiÚcÚjÚfineÚtÚlnÚvÚips                         r$   Úudp_exitr‹   £   s  € õ ˜eÑ$Ô$�I€BˆØð ØˆtØ×$Ò$ SÑ)Ô)�M€Dˆ!ˆTÝ��x”Ñ!Ô!€Að$ÝÔ'¨¬°Q´VÐ(<ÀgÐNÑNÔNˆØ�Š˜Ñ Ô Ð Ý˜˜uŸyšy¨°RÑ8Ô8¸%¿)º)ÀJÐPRÑ:SÔ:SÑTÔTð 	Ø�JŠJ‰LŒLˆLØ�4Ø�ŠÐDÑEÔEÐEØ�	Š	�"‰ŒˆÝŒM�&œ.­&Ô*;Ñ<Ô<ˆØ	�Š�WÑÔÐð	Ø$ˆAØ'­%µ°Q±´°©/¬/Ñ9¸AÑ=ÅÄÈDÐRWÑ@XÔ@XÑXˆEØ�HŠH�UÐ@Ñ@Å2Ä:ÈbÁ>Ä>ÑQØ�C ™IœIÐ&ñ(ô (ð (à—:’:˜dÑ#Ô#‰DˆAˆqÝ�1‰vŒv˜Š{ˆ{˜a œd aši˜iØð  �GŠG‰IŒIˆIØ�JŠJ‰LŒLˆLˆLˆLð! ˜”d˜A�!ˆDØ�d˜a’i�i��°$¸!²)°) a¨!¨A¬$¡h hÀÑDˆAØ�!�a‘%�&�&”	ˆAÝ�1‰vŒv˜Š{ˆ{˜a  ! œf¨Ò3Ð3Øð �GŠG‰IŒIˆIØ�JŠJ‰LŒLˆLˆLˆLð ˜"�vœ}¨T°1°Q°q°S´6Ñ:Ô:¸1Ô=Ñ=ˆtˆAØ�a‘%�3˜t¥S¨¡V¤VÑ,Ô,Ò,Ð,Ýœ e¨Q¨q°°Q±¨w¬ZÑ8Ô8‘��2Ø�a˜!‘e˜A ™E B™JÐ&Ô'�Ø˜’;�;¥3 q¡6¤6¨Q¢; ;ÝÐRÐRµ°Q°q¸°s´VÐ=PÑ1QÔ1QÐRÑRÔRÑRÔR�BÝ!Ô+¨BÑ/Ô/ð �GŠG‰IŒIˆIØ�JŠJ‰LŒLˆLˆLð	 �Q˜‘V  B¨¡F¡
¨aÑ/Ñ0Ñ0�ð �a‘%�3˜t¥S¨¡V¤VÑ,Ô,Ò,Ð,ð à�GŠG‰IŒIˆIØ�JŠJ‰LŒLˆLˆLˆLøð �GŠG‰IŒIˆIØ�JŠJ‰LŒLˆLˆLøøøøÝð ð ð ØˆtˆtðøøøsY   ÁBP& ÃA(P& Ä5B/O9 Ç%(P& ÈAO9 É&(P& ÊCO9 Í-(P& Î8O9 Ï(P& Ï9*P#Ð#P& Ð&
P4Ð3P4rn   úOptional[bool]c                óˆ  — t          | d         ¦  «        }|j                             d¦  «        sdS 	 t          j        |j        |j        f|¬¦  «        }|                     |¦  «         	 t          ||  	                    dd¦  «        |  	                    dd¦  «        ¦  «        r	 | 
                    ¦   «          dS t          |dd	¦  «        d
k    r	 | 
                    ¦   «          dS |                     d¦  «         d}t          |¦  «        dk     r0|                     d¦  «        }|sn||z  }t          |¦  «        dk     °0|                     d¦  «        d         }d|v o$t          |                     ¦   «         ¦  «        dk    	 | 
                    ¦   «          S # | 
                    ¦   «          w xY w# t"          $ r Y dS w xY w)uê   `True`/`False`, or `None` when the question was not settled.

    â›” The `None` is NOT a `False`: a network failure and an exit without IPv6
    are different things, and flattening them would switch IPv6 off over a
    timeout.
    r8   r<   Nr9   r=   r>   r?   zapi6.ipify.orgr@   r   FsO   GET / HTTP/1.1
Host: api6.ipify.org
Connection: close
User-Agent: curl/8

r&   rB   rC   rD   ó   :r   )r   rI   rM   rE   rF   rG   r(   rH   r%   rN   rO   r1   r   r   r   rU   ÚstriprW   )r3   r5   r!   r   rY   r"   Úcorpos          r$   Úhas_ipv6r‘   ×   sÏ  € õ 	��x”Ñ!Ô!€AØŒ8×Ò˜wÑ'Ô'ð ØˆtðÝÔ$ a¤j°!´&Ð%9À7ÐKÑKÔKˆØ	�Š�WÑÔÐð	Ý˜Q §	¢	¨*°bÑ 9Ô 9¸5¿9º9ÀZÐQSÑ;TÔ;TÑUÔUð Øð �GŠG‰IŒIˆIˆIˆIõ ˜qÐ"2°BÑ7Ô7¸1Ò<Ð<Øð �GŠG‰IŒIˆIˆIˆIð �IŠIð Iñ Jô Jð JàˆDÝ�d‘)”)˜dÒ"Ð"Ø—F’F˜4‘L”L�Øð ØØ˜‘	�õ	 �d‘)”)˜dÒ"Ð"ð
 —J’J˜{Ñ+Ô+¨BÔ/ˆEØ˜5�=Ð;¥S¨¯ª©¬Ñ%7Ô%7¸!Ò%;Ð;à�GŠG‰IŒIˆIˆIøˆA�GŠG‰IŒIˆIˆIøøøøÝð ð ð ØˆtˆtðøøøsB   ³7F3 Á+9F Â%F3 Â;F ÃF3 Ã'BF ÆF3 ÆF0Æ0F3 Æ3
GÇ Gr   Úroundsc                óÀ   ‡ — ˆ fd„t          |¦  «        D ¦   «         }d„ |D ¦   «         }t          t          |¦  «        ¦  «        }|sdg fS t          |¦  «        dk    |fS )zö`(sticky, addresses)`. Six reads with the SAME credential.

    Six and not two: two identical draws in a row from an urn do not prove the
    urn holds a single ball, and that is a mistake this project has already made
    and written down.
    c                ó.   •— g | ]}t          ‰¦  «        ‘ŒS rq   )r[   )rr   r   r3   s     €r$   ú
<listcomp>zis_sticky.<locals>.<listcomp>   s   ø€ Ð4Ð4Ð4 �X�e‰_Œ_Ð4Ð4Ð4r&   c                ó   — g | ]}|¯|‘ŒS rq   rq   )rr   Úxs     r$   r•   zis_sticky.<locals>.<listcomp>  s   € Ð#Ð#Ð#�1 Ð#ˆQÐ#Ð#Ð#r&   Nr
   )ÚrangeÚsortedÚsetr   )r3   r’   ÚvistiÚbuoniÚdistintis   `    r$   Ú	is_stickyrž   ù   sq   ø€ ð 5Ð4Ð4Ð4¥e¨F¡m¤mÐ4Ñ4Ô4€EØ#Ð#˜Ð#Ñ#Ô#€EÝ•c˜%‘j”jÑ!Ô!€HØð Ø�RˆxˆÝˆx‰=Œ=˜AÒ˜xÐ'Ð'r&   Úudp_allowedÚudp_exit_ipÚtcp_exit_ipc                ó4   — | sdS t          |¦  «        o||k    S )a!  Is this gateway's UDP USABLE, rather than merely GRANTED? Three answers.

    Measured, and the whole reason the distinction exists: a gateway grants the
    UDP ASSOCIATE and hands back a relay, and through that relay STUN never
    answers. Granted is not usable, so the grant on its own must never be read
    as a capability - `_geo._srflx_suppressed` requires this AND the grant
    before it stops declaring a candidate, and getting that wrong costs the
    worst sentence a detector writes.

    The three answers are not two:

    * ``None``  - the question does not apply. The gateway did not grant UDP
      ASSOCIATE, so there is nothing that could have been usable. Flattening it
      to ``False`` erases the difference between a gateway that refused and one
      that granted and then failed to carry a packet, which are different facts
      about the provider and different things to do about them.
    * ``False`` - granted and not usable: no UDP exit came back at all, or the
      one that did is not the address TCP leaves from.
    * ``True``  - granted, and the two exits are the same address.

    A top-level function, and not the inline expression it was inside
    ``measure``, because ``measure`` does network and so cannot be called by
    anything that wants to check this rule. The workbench gate that exists to
    prove exactly this line had copied it instead, and the copy fell behind the
    day the core was translated and the field names moved. One place computes
    it now; a caller that cannot afford the network calls this.
    N)Úbool)rŸ   r    r¡   s      r$   Úudp_is_usabler¤     s)   € ð< ð ØˆtÝ�ÑÔÐ; °Ò!;Ð;r&   c                ó^   — t          | d         ¦  «        }|j        ›d|j        ›d|j        ›�S )Nr8   z://rA   )r   rI   rG   r(   )r3   r!   s     r$   Ú_keyr¦   /  s0   € Ý��x”Ñ!Ô!€AØœ8˜8˜8 Q¤Z Z Z°´°Ð8Ð8r&   ©Úknown_tcp_exitr¨   úDict[str, Any]c               óF  — |pt          | ¦  «        }t          | ¦  «        \  }}|rt          | ¦  «        nd}t          | ¦  «        t	          | d         ¦  «        j        ||||t          |||¬¦  «        t          | ¦  «        t          t          j	        ¦   «         ¦  «        dœ	S )uÿ  Everything that can be known about an exit without launching a browser.

    ``known_tcp_exit`` avoids measuring again what the caller already has.
    ``prepare_session_geo`` discovers the exit IP for the timezone and the
    locale, with one round trip through the proxy: doing it again here would be
    the same fact computed in two places, plus one more trip to an echo endpoint,
    which is non-browser traffic on the same exit.

    â›” STICKINESS IS NO LONGER HERE, and that is the owner's decision of
    2026-08-25: whether proxies are sticky is not interesting, because the truth
    is what is detected before the launch and it is absolute for the session.
    Removing it costs nothing and is worth it twice over:

    * it was **six network rounds out of eight** of this probe's cost;
    * and it **lied**. It reported `sticky = yes` for all four providers, while
      the same endpoint had been measured rotating **8 times in 25 minutes**. Six
      consecutive reads take a few seconds and rotation happens on a scale of
      minutes: that field could not see the phenomenon it was named after.

    ``is_sticky`` stays available for anyone who wants to MEASURE rotation over a
    suitable window, but it no longer enters any decision the product makes.
    Nr8   )r    r¡   )	ÚendpointÚschemar[   ÚudpÚ
udp_percher‹   Úudp_matches_tcpÚipv6Úmeasured_at)
r[   rk   r‹   r¦   r   rI   r¤   r‘   r)   Útime)r3   r¨   Úip_tcpÚok_udpÚwhyÚip_udps         r$   Úmeasurer·   4  s¤   € ð0 Ð.�x¨™œ€FÝ Ñ&Ô&�K€FˆCØ &Ð0�X�e‰_Œ_ˆ_¨D€Få˜‘K”KÝ˜5 œ?Ñ+Ô+Ô2ØØØØõ
 )¨¸VØ5;ð=ñ =ô =å˜‘”Ý�4œ9™;œ;Ñ'Ô'ðð ð r&   F)Ú	remeasurer¨   r¸   r£   c               ój  — t          | ¦  «        }i }	 t          t          d¬¦  «        5 }t          j        |¦  «        }ddd¦  «         n# 1 swxY w Y   n# t
          t          f$ r Y nw xY w|                     |¦  «        }|r<|s:t          j        ¦   «         |                     dd¦  «        z
  t          k     rd|d<   |S t          | |¬¦  «        }|||<   	 t          t          d	d¬¦  «        5 }t          j        ||d
¬¦  «         ddd¦  «         n# 1 swxY w Y   n# t
          $ r Y nw xY wd|d<   |S )zªThe measurement, from cache when it is recent.

    Capabilities belong to the gateway rather than to the session, which is what
    makes caching them sound at all.
    zutf-8)ÚencodingNr±   r   TÚ
from_cacher§   Úwr
   )ÚindentF)r¦   ÚopenÚCACHEÚjsonÚloadrW   Ú
ValueErrorrN   r²   ÚVALID_FOR_Sr·   Údump)r3   r¸   r¨   ÚkeyÚ
rememberedÚfÚentrys          r$   Ú
capabilityrÉ   a  sÒ  € õ ˆu‰+Œ+€CØ€JðÝ•% 'Ð*Ñ*Ô*ð 	&¨aÝœ 1™œˆJð	&ð 	&ð 	&ñ 	&ô 	&ð 	&ð 	&ð 	&ð 	&ð 	&ð 	&øøøð 	&ð 	&ð 	&ð 	&øøå•ZÐ ð ð ð Øˆðøøøà�NŠN˜3ÑÔ€EØð �Yð ¥D¤I¡K¤K°%·)²)¸MÈ1Ñ2MÔ2MÑ$MÕQ\Ò#\Ð#\Ø"ˆˆlÑØˆÝ�E¨.Ð9Ñ9Ô9€EØ€Jˆs�OðÝ•%˜ wÐ/Ñ/Ô/ð 	/°1ÝŒI�j !¨AÐ.Ñ.Ô.Ð.ð	/ð 	/ð 	/ñ 	/ô 	/ð 	/ð 	/ð 	/ð 	/ð 	/ð 	/øøøð 	/ð 	/ð 	/ð 	/øøåð ð ð Øˆðøøøà€Eˆ,ÑØ€Lsi   “A ©A
¾A Á
AÁA ÁAÁA ÁA*Á)A*ÃD Ã.DÄD ÄDÄD ÄDÄD Ä
D+Ä*D+r„   c           
     óŽ   — d„ }| d         d›d || d         ¦  «        d›d || d         ¦  «        d›d	 || d
         ¦  «        ›�S )Nc                ó   — | du rdn| du rdndS )NTÚsiFÚnoznon determinatorq   )r‰   s    r$   Ú_szsummarise.<locals>._s  s!   € Ø˜D�y�yˆtˆt¨q°E¨z¨z t tÐ?PÐQr&   r«   Ú46z udp=r­   Ú16z
 coerente=r¯   z ipv6=r°   rq   )r„   rÎ   s     r$   Ú	summariserÑ   ~  sn   € ðRð Rð Rð �Œ}ˆ}ˆ}ˆ}˜b˜b  5¤™lœl˜l˜l˜l¨B¨B¨qÐ1BÔ/CÑ,DÔ,DÐ,DÐ,DÐ,DÀbÀbÈÈ6ÌÁmÄmÀmðUð Vr&   )r   r   r   r   r   r   )r'   r   r(   r)   r   r*   )r2   )r3   r4   r5   r6   r   r   )r3   r4   r5   r6   )rl   )rn   )r3   r4   r5   r6   r   rŒ   )r   )r3   r4   r’   r)   )rŸ   rŒ   r    r   r¡   r   r   rŒ   )r3   r4   r   r   )r3   r4   r¨   r   r   r©   )r3   r4   r¸   r£   r¨   r   r   r©   )r„   r©   r   r   )"Ú__doc__Ú
__future__r   rÀ   ry   rS   rE   r.   r²   Útypingr   r   r   Úurllib.parser   ÚpathÚjoinÚenvironrN   r¿   rÃ   r`   r%   r1   r[   rk   r‹   r‘   rž   r¤   r¦   r·   rÉ   rÑ   rq   r&   r$   ú<module>rÙ      s"  ððð ð< #Ð "Ð "Ð "Ð "Ð "à €€€Ø 	€	€	€	Ø 	€	€	€	Ø €€€Ø €€€Ø €€€Ø &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ð &Ø !Ð !Ð !Ð !Ð !Ð !ð 	Œ�Š�R”Z—^’^ F¨FÑ3Ô3Ð5KÑLÔL€ð
 €ð Ð%¨-Ð<QØÐ"6¸=Ø"Ð'CðEð E€ðð ð ð ð 7ð 7ð 7ð 7ð*ð *ð *ð *ð *ðZ5ð 5ð 5ð 5ð 5ðD1ð 1ð 1ð 1ð 1ðhð ð ð ð ðD(ð (ð (ð (ð (ð& <ð  <ð  <ð  <ðF9ð 9ð 9ð 9ð /3ð*ð *ð *ð *ð *ð *ðZ <AØ-1ðð ð ð ð ð ð:Vð Vð Vð Vð Vð Vr&   