o
    US`cny                  	   @   s|  d dl mZ zd dlmZ W n ey   d dlmZ Y nw d dlmZmZm	Z	 d dl
Z
d dlmZ d dlZd dlZd dlmZ d dlZd dlZd dlZdZejdkrjejd	k rjzd dlZW n eyi   ed
w eeZd ZZd ZZd ZZeeedZ e!e"e # e $ Z%ej Z&Z'dd Z(G dd de)Z*G dd de*Z+G dd de*Z,G dd de*Z-G dd de*Z.G dd de*Z/G dd de*Z0dd d!d"Z1d#d$d%d&d'd(d)d*d+Z2ed,ed,ed-iZ3	.	d@d/d0Z4d1d2 Z5d3d4 Z6e6Z7d5d6 Z8e8Z9			.		dAd7d8Z:G d9d: d:ejZ;d;d< Z<d=D ]Ze=e;edZ>e?e>es2e;j@Ae eBe;ee<e qG d>d? d?e;ZCdS )B    )	b64encode)Callable)
EOPNOTSUPPEINVALEAGAINN)BytesIO)SEEK_CURz1.7.1nt)   r   z8To run PySocks on Windows you must install win_inet_pton      r
   )SOCKS4SOCKS5HTTPc                    s   t   fdd}|S )Nc               
      s|   | d }z.z |  }|dkr|d  | i |W W |dkr%|d S S  ty2 } z d }~ww |dkr=|d w w )Nr   TF)
gettimeoutsetblocking	Exception)argskwargsselfZ_is_blockingefunction 0/usr/local/lib/python3.10/dist-packages/socks.pywrapper(   s    
z"set_self_blocking.<locals>.wrapper)	functoolswraps)r   r   r   r   r   set_self_blocking&   s   r   c                   @   s"   e Zd ZdZdddZdd ZdS )
ProxyErrorz4Socket_err contains original socket.error exception.Nc                 C   s,   || _ || _|r|  j d|7  _ d S d S )Nz: {})msg
socket_errformat)r   r    r!   r   r   r   __init__;   s
   zProxyError.__init__c                 C      | j S N)r    r   r   r   r   __str__B      zProxyError.__str__r%   )__name__
__module____qualname____doc__r#   r'   r   r   r   r   r   9   s    
r   c                   @      e Zd ZdS )GeneralProxyErrorNr)   r*   r+   r   r   r   r   r.   F       r.   c                   @   r-   )ProxyConnectionErrorNr/   r   r   r   r   r1   J   r0   r1   c                   @   r-   )SOCKS5AuthErrorNr/   r   r   r   r   r2   N   r0   r2   c                   @   r-   )SOCKS5ErrorNr/   r   r   r   r   r3   R   r0   r3   c                   @   r-   )SOCKS4ErrorNr/   r   r   r   r   r4   V   r0   r4   c                   @   r-   )	HTTPErrorNr/   r   r   r   r   r5   Z   r0   r5   zRequest rejected or failedzLRequest rejected because SOCKS server cannot connect to identd on the clientzPRequest rejected because the client program and identd report different user-ids)[   \   ]   zGeneral SOCKS server failurez!Connection not allowed by rulesetzNetwork unreachablezHost unreachablezConnection refusedzTTL expiredz(Command not supported, or protocol errorzAddress type not supported)r   r   r
                  i8  i  Tc                 C   s.   | ||||r
|  nd|r|  ndft_dS )zSets a default proxy.

    All further socksocket objects will use the default unless explicitly
    changed. All parameters are as for socket.set_proxy().N)encode
socksocketdefault_proxy)
proxy_typeaddrportrdnsusernamepasswordr   r   r   set_default_proxys   s   
rG   c                  O   s$   d|v r| d|d< t| i |S NZ	proxytyperA   )poprG   )r   r   r   r   r   setdefaultproxy~   s   rJ   c                   C   s   t jS )z4Returns the default proxy, set by set_default_proxy.)r?   r@   r   r   r   r   get_default_proxy      rK   c                 C   s   t jr	t | j_dS td)a  Attempts to replace a module's socket library with a SOCKS socket.

    Must set a default proxy using set_default_proxy(...) first. This will
    only work on modules that import socket directly into the namespace;
    most of the Python Standard Library falls into this category.zNo default proxy specifiedN)r?   r@   socketr.   )moduler   r   r   wrap_module   s   rO   c
                 C   s,  | \}
}|
 dr|
d}
|r| dr|d}d}t||dtjD ]g}|\}}}}}d}z=t|||}|	rC|	D ]}|j|  q;t|tt	frO|
| |r[||||||| |rb|| ||
|f |W   S  tjtfy } z|}|r|  d}W Y d}~q%d}~ww |r|td)a  create_connection(dest_pair, *[, timeout], **proxy_args) -> socket object

    Like socket.create_connection(), but connects to proxy
    before returning the socket object.

    dest_pair - 2-tuple of (IP/hostname, port).
    **proxy_args - Same args passed to socksocket.set_proxy() if present.
    timeout - Optional socket timeout value, in seconds.
    source_address - tuple (host, port) for the socket to bind to as its source
    address before connecting (only for compatibility)
    [z[]Nr   zgai returned empty list.)
startswithstriprM   getaddrinfoSOCK_STREAMr?   
setsockopt
isinstanceintfloat
settimeout	set_proxybindconnecterrorr   close)	dest_pairtimeoutsource_addressrA   
proxy_addr
proxy_portZ
proxy_rdnsZproxy_usernameZproxy_passwordsocket_optionsZremote_hostZremote_porterrrfamilysocket_typeproto	canonnamesasockoptr   r   r   r   create_connection   sD   






rn   c                   @   s   e Zd ZdZdd Ze ZdS )_BaseSocketzBAllows Python 2 delegated methods such as send() to be overridden.c                 O   sJ   t j| g|R i | t | _| jD ]}t| || j|< t| | qd S r%   )_orig_socketr#   dict_savedmethods
_savenamesgetattrdelattr)r   poskwnamer   r   r   r#      s   
z_BaseSocket.__init__N)r)   r*   r+   r,   r#   listrs   r   r   r   r   ro      s    
ro   c                    s    fddS )Nc                    s   | j   |i |S r%   )rr   )r   rv   rw   rx   r   r   <lambda>   s    z_makemethod.<locals>.<lambda>r   rz   r   rz   r   _makemethod   s   r|   )sendtosendrecvfromrecvc                       s@  e Zd ZdZdZejejdf fdd	Zdd Z	 fdd	Z
d
d Zdd Z		d7ddZdd Z fddZ fddZd8 fdd	Zd8 fdd	Zdd Z fddZdd  ZeZd!d" ZeZd#d$ ZeZd%d& Z fd'd(Zd)d* Zd+d, Zd-d. Zd/d0 Z e!ee"ee#e iZ$e%d9 fd1d2	Z&e%d3d4 Z'd5d6 Z(  Z)S ):r?   a2  socksocket([family[, type[, proto]]]) -> socket object

    Open a SOCKS enabled socket. The parameters are the same as
    those of the standard socket init. In order for SOCKS to work,
    you must specify family=AF_INET and proto=0.
    The "type" argument must be either SOCK_STREAM or SOCK_DGRAM.
    Nr   c                    sv   |t jt jfvrd}t||tt| j|||g|R i | d | _| j	r-| j	| _
nd| _
d | _d | _d | _d S )Nz0Socket type must be stream or datagram, not {!r})NNNNNN)rM   rT   
SOCK_DGRAM
ValueErrorr"   superr?   r#   
_proxyconnr@   proxyproxy_socknameproxy_peername_timeout)r   rg   typeri   r   r   r    	__class__r   r   r#      s   "

zsocksocket.__init__c                 C   sF   d}t ||k r!||t | }|std||7 }t ||k s|S )zReceive EXACTLY the number of bytes requested from the file object.

        Blocks until the required number of bytes have been received.    Connection closed unexpectedly)lenreadr.   )r   filecountdatadr   r   r   _readall  s   zsocksocket._readallc                    s>   || _ z|  }tt| | j  W d S  tjy   Y d S w r%   )r   get_proxy_peernamer   r?   rY   rM   r]   )r   r`   Zpeerr   r   r   rY     s   zsocksocket.settimeoutc                 C   r$   r%   )r   r&   r   r   r   r   #  r(   zsocksocket.gettimeoutc                 C   s    |r	|  d  d S |  d d S )Ng        )rY   )r   vr   r   r   r   &  s   zsocksocket.setblockingTc                 C   s.   |||||r
|  nd|r|  ndf| _dS )a   Sets the proxy to be used.

        proxy_type -  The type of the proxy to be used. Three types
                        are supported: PROXY_TYPE_SOCKS4 (including socks4a),
                        PROXY_TYPE_SOCKS5 and PROXY_TYPE_HTTP
        addr -        The address of the server (IP or DNS).
        port -        The port of the server. Defaults to 1080 for SOCKS
                        servers and 8080 for HTTP proxy servers.
        rdns -        Should DNS queries be performed on the remote side
                       (rather than the local side). The default is True.
                       Note: This has no effect with SOCKS4 servers.
        username -    Username to authenticate with to the server.
                       The default is no authentication.
        password -    Password to authenticate with to the server.
                       Only relevant when username is also provided.N)r>   r   )r   rA   rB   rC   rD   rE   rF   r   r   r   rZ   ,  s   
zsocksocket.set_proxyc                 O   s&   d|v r| d|d< | j|i |S rH   )rI   rZ   )r   r   r   r   r   r   setproxyA  s   zsocksocket.setproxyc                    s  | j \}}}}}}|r| jtjkrtj| g|R i |S | jr&ttd|t	kr2d}	tt
|	tt| j|i | |  \}
}d|f}t | _|  }| j| d}| | j||\}
}|\}}
|\}
}tt| ||f tt| | j d| _dS )zVImplements proxy connection for UDP sockets.

        Happens during the bind() phase.z"Socket already bound to an addressz'UDP only supported by SOCKS5 proxy type0   )0.0.0.0r   N)r   r   rM   r   rp   r[   r   r]   r   r   r   r   r?   getsockname_proxy_addrr\   _SOCKS5_requestrY   r   r   )r   rv   rw   rA   rb   rc   rD   rE   rF   r    _rC   dstr   ZUDP_ASSOCIATEZrelayhostr   r   r   r[   F  s.   
zsocksocket.bindc           
         s   | j tjkrtt| j|g|R i |S | js| d |d }|d d }t }d}|	| d}|	| | 
|| tt| j| | g|R i |}	|	|  S )N r   s         )r   rM   r   r   r?   r}   r   r[   r   write_write_SOCKS5_addressr~   getvaluetell)
r   bytesr   r   addressflagsheaderZRSVZ
STANDALONEsentr   r   r   r}   k  s    


zsocksocket.sendtoc                    s>   | j tjkr| j||| jfi |S tt| j||fi |S r%   )r   rM   r   r}   r   r   r?   r~   )r   r   r   r   r   r   r   r~     s   zsocksocket.sendc           	         s   | j tjkrtt| ||S | js| d ttt| 	|d |}|
dt |d}t|r7td| |\}}| jrV| j\}}||ksP|d|fvrVttd||||ffS )Nr   i   r   r   zReceived UDP packet fragmentr   zPacket filtered)r   rM   r   r   r?   r   r   r[   r   r   seekr   r   ordNotImplementedError_read_SOCKS5_addressr   r]   r   )	r   bufsizer   buffragZfromhostZfromportZpeerhostZpeerportr   r   r   r     s   


zsocksocket.recvfromc                 O   s   | j |i |\}}|S r%   )r   )r   rv   rw   r   r   r   r   r   r     s   zsocksocket.recvc                    s   | j r| j   tt|  S r%   )r   r^   r   r?   r&   r   r   r   r^     s   
zsocksocket.closec                 C   r$   )z:Returns the bound IP address and port number at the proxy.)r   r&   r   r   r   get_proxy_sockname  rL   zsocksocket.get_proxy_socknamec                 C   s   |   S )z>
        Returns the IP and port number of the proxy.
        )getpeernamer&   r   r   r   r     s   zsocksocket.get_proxy_peernamec                 C   r$   )zwReturns the IP address and port number of the destination machine.

        Note: get_proxy_peername returns the proxy.)r   r&   r   r   r   get_peername  s   zsocksocket.get_peernamec                 G   s   d}|  | ||\| _| _dS )z7Negotiates a stream connection through a SOCKS5 server.   N)r   r   r   )r   	dest_addrZCONNECTr   r   r   _negotiate_SOCKS5  s   zsocksocket._negotiate_SOCKS5c                    s  | j \}}}}}}	|d}
|dd}z|r|	r|
d n|
d |
  | |d}|dd dkr:td	|dd d
kr|rF|	sJtd|
dtt|	  | tt|		  |	  |
  | |d}|dd dkrytd	|dd dkrtdn|dd dkr|dd dkrtdtd	|
d| d  | 
||
}|
  | |d}|dd dkrtd	t|dd }|dkrt|d}td||| |}tt| | j ||fW |  |
  S |  |
  w )z
        Send SOCKS5 request with given command (CMD field) and
        address (DST field). Returns resolved DST address that was used.
        wbrbr   s    s    r   r      %SOCKS5 proxy server sent invalid data   zPNo username/password supplied. Server requested username/password authenticationr   r   zSOCKS5 authentication failed   z7All offered SOCKS5 authentication methods were rejectedr
   Unknown error{:#04x}: {})r   makefiler   flushr   r.   r2   chrr   r>   r   r   SOCKS5_ERRORSgetr3   r"   r   r   r?   rY   r   r^   )r   conncmdr   rA   rB   rC   rD   rE   rF   writerreaderZchosen_authZauth_statusresolvedrespstatusr]   Zbndr   r   r   r     sv   




zsocksocket._SOCKS5_requestc              	   C   sD  |\}}| j \}}}}}}	tjdtjdi}
tjtjfD ]1}z%t||}||
| |  t||}|td| ||fW   S  tj	yL   Y qw |rd|
d}|dtt|
  |  n1t||tjtjtjtj}|d }|d }|d d }t||}||
| |  t||}|td| ||fS )z~
        Return the host and port packed for the SOCKS5 protocol,
        and the resolved address as a tuple object.
        r      >Hidnar   r   r9   )r   rM   AF_INETAF_INET6	inet_ptonr   	inet_ntopstructpackr]   r>   r   r   rS   	AF_UNSPECrT   IPPROTO_TCPAI_ADDRCONFIG)r   rB   r   r   rC   rA   r   rD   rE   rF   Zfamily_to_byterg   
addr_bytesZ
host_bytes	addressesZtarget_addrr   r   r   r      s:   
 z socksocket._write_SOCKS5_addressc                 C   s   |  |d}|dkrt|  |d}n'|dkr'|  |d}|  |t|}n|dkr7ttj|  |d}ntdtd|  |d	d
 }||fS )Nr   r   r9   r   r      r   r   r   r   )	r   rM   	inet_ntoar   r   r   r.   r   unpack)r   r   ZatyprB   lengthrC   r   r   r   r   M  s   zsocksocket._read_SOCKS5_addressc                 C   s  | j \}}}}}}| d}	| dd}
zd}zt|}W n tjy7   |r-d}d}ntt|}Y nw |	tddd	| |	| |rO|	| |	d
 |r`|	|	dd
  |	
  | |
d}|dd	 d
krvtdt|d	d }|dkrt|d}td||t|dd td|dd d f| _|rt||f| _n||f| _W |
  |	  dS W |
  |	  dS |
  |	  w )z0Negotiates a connection through a SOCKS4 server.r   r   r   Fs      Tz>BBHr9   r   r   r   r=   z%SOCKS4 proxy server sent invalid datar   Z   r   r   Nr   )r   r   rM   	inet_atonr]   gethostbynamer   r   r   r>   r   r   r.   r   SOCKS4_ERRORSr   r4   r"   r   r   r   r   r^   )r   r   	dest_portrA   rB   rC   rD   rE   rF   r   r   Zremote_resolver   r   r   r]   r   r   r   _negotiate_SOCKS4\  s\   





zsocksocket._negotiate_SOCKS4c                 C   sX  | j \}}}}}}|r|nt|}d|d d t|  d d|d g}	|r;|r;|	dt|d |   |	d | d|	 | 	 }
|

 }|
  |sZtdz|d	d
\}}}W n typ   tdw |dsztdzt|}W n ty   tdw |dkrd||}|dv r|d7 }t|d| _||f| _dS )zwNegotiates a connection through an HTTP server.

        NOTE: This currently only supports HTTP CONNECT-style proxies.s   CONNECT r      :s	    HTTP/1.1s   Host: s   Proxy-Authorization: basic s   
r    r   z'HTTP proxy server sent invalid responsezHTTP/z0Proxy server does not appear to be an HTTP proxyz4HTTP proxy server did not return a valid HTTP status   z{}: {})i  i  i  za
[*] Note: The HTTP proxy server may not be supported by PySocks (must be a CONNECT tunnel proxy))s   0.0.0.0r   N)r   rM   r   r>   strappendr   sendalljoinr   readliner^   r.   splitr   rQ   rW   r5   r"   r   r   )r   r   r   rA   rB   rC   rD   rE   rF   Zhttp_headersZfobjZstatus_lineri   status_codeZ
status_msgr]   r   r   r   _negotiate_HTTP  sV   


zsocksocket._negotiate_HTTPc              
      s  t |dks|d drtdt| |\}}| jtjkr?| js(| d t	|}|dkr8|s8d| _
dS ||f| _
dS | j\}}}}}	}
t|ttfr\t |dks\|r\t|ts`tdtt| | j |du r|| _
tt| | j tt| ||f dS |  }z
tt| | W n5 tjy } z(|   |s|\}}d	||}t| }d
||}td|| t|||d}~ww z| j| }|| || W dS  tjy } z|s|   td||d}~w ty   |    w )z
        Connects to the specified destination through a proxy.
        Uses the same API as socket's connect().
        To select the proxy server, use set_proxy().

        dest_pair - 2-tuple of (IP/hostname, port).
        r   r   rP   z PySocks doesn't support IPv6: %sr   r   Nz0Invalid destination-connection (host, port) pairz{}:{}zError connecting to {} proxy {}z%s due to: %szSocket error)r   rQ   rM   r]   r   r   r   r   r[   r   r   r   rV   ry   tuplerW   r.   r   r?   rY   r   r\   r   r^   r"   PRINTABLE_PROXY_TYPESlogdebugr1   _proxy_negotiatorsr   )r   r_   catch_errorsr   r   rA   rb   rc   rD   rE   rF   r]   Zproxy_serverZprintable_typer    Z	negotiater   r   r   r\     s~   	






zsocksocket.connectc              
   C   sH   z
| j |dd W dS  ty# } z|jr|jW  Y d}~S  d}~ww )a&   https://docs.python.org/3/library/socket.html#socket.socket.connect_ex
        Like connect(address), but return an error indicator instead of raising an exception for errors returned by the C-level connect() call (other problems, such as "host not found" can still raise exceptions).
        T)r   r   N)r\   OSErrorerrno)r   r_   r   r   r   r   
connect_ex6  s   zsocksocket.connect_exc                 C   s4   | j \}}}}}}|pt|}|std||fS )zD
        Return proxy address to connect to as tuple object
        zInvalid proxy type)r   DEFAULT_PORTSr   r.   )r   rA   rb   rc   rD   rE   rF   r   r   r   r   F  s   zsocksocket._proxy_addrNNNTNN)r   r%   )*r)   r*   r+   r,   r@   rM   r   rT   r#   r   rY   r   r   rZ   r   r[   r}   r~   r   r   r^   r   Zgetproxysocknamer   Zgetproxypeernamer   r   r   r   r   r   r   r   r   r   r   r   r   r\   r   r   __classcell__r   r   r   r   r?      sR    	
%b-<<\
r?   r   )	NNNNNTNNN)Dbase64r   collections.abcr   ImportErrorcollectionsr   r   r   r   r   ior   loggingosr   rM   r   sys__version__rx   version_infoZwin_inet_pton	getLoggerr)   r   ZPROXY_TYPE_SOCKS4r   ZPROXY_TYPE_SOCKS5r   ZPROXY_TYPE_HTTPr   ZPROXY_TYPESrq   zipvalueskeysr   Z
_orgsocketrp   r   IOErrorr   r.   r1   r2   r3   r4   r5   r   r   r   rG   rJ   rK   ZgetdefaultproxyrO   Z
wrapmodulern   ro   r|   rt   methodrV   rs   r   setattrr?   r   r   r   r   <module>   s    

	

=