
    gX                        d 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Zddlm	Z	 ddl
ZddlmZ d Z G d de      Z G d d	e      Z G d
 de      Z ed      fdZ ed      fdZd Z G d de      ZddZedk(  xr	  e        y y)z:
A simple library for managing the availability of ports.
    N)abc)timingc                     | dk(  ry| dv ry| S )z
    Return the host on which a client can connect to the given listener.

    >>> client_host('192.168.0.1')
    '192.168.0.1'
    >>> client_host('0.0.0.0')
    '127.0.0.1'
    >>> client_host('::')
    '::1'
    z0.0.0.0z	127.0.0.1)z::z::0z	::0.0.0.0z::1 )server_hosts    /opt/Tautulli/lib/portend.pyclient_hostr	      s#     i00     c                   "    e Zd ZddZddZd Zy)Checkerc                     || _         y Ntimeout)selfr   s     r   __init__zChecker.__init__)   s	    r
   Nc                 J   |"t        |t        j                        r|dd \  }}t        j                         dk(  rt        |      }t        j                  ||t        j                  t        j                        }t        t        j                  | j                  |             y)a  
        Assert that the given addr is free
        in that all attempts to connect fail within the timeout
        or raise a PortNotFree exception.

        >>> free_port = find_available_local_port()

        >>> Checker().assert_free('localhost', free_port)
        >>> Checker().assert_free('127.0.0.1', free_port)
        >>> Checker().assert_free('::1', free_port)

        Also accepts an addr tuple

        >>> addr = '::1', free_port, 0, 0
        >>> Checker().assert_free(addr)

        Host might refer to a server bind address like '::', which
        should use localhost to perform the check.

        >>> Checker().assert_free('::', free_port)
        N   Windows)
isinstancer   Sequenceplatformsystemr	   socketgetaddrinfo	AF_UNSPECSOCK_STREAMlist	itertoolsstarmap_connect)r   hostportinfos       r   assert_freezChecker.assert_free,   sy    , <JtS\\:bqJD$??	)t$D!!$f.>.>@R@RSYt}}d34r
   c                 |   t        j                   |||      }|j                  | j                         t        j                  |      5  	 |j                  |       	 d d d        |d d \  }}d}	t         |	j                  di t                     # t         j                  $ r Y d d d        y w xY w# 1 sw Y   WxY w)Nr   z Port {port} is in use on {host}.r   )
r   
settimeoutr   
contextlibclosingconnecterrorPortNotFreeformatlocals)
r   afsocktypeproto	canonnamesasr"   r#   tmpls
             r   r!   zChecker._connectI   s    MM"h.	T\\"" 			"	 V
d1+$++1122 << 		 		 	s*   B2
BB/$B2.B//B22B;)g      ?r   )__name__
__module____qualname__r   r%   r!   r   r
   r   r   r   (   s    5:3r
   r   c                       e Zd Zy)TimeoutNr6   r7   r8   r   r
   r   r:   r:   Z       r
   r:   c                       e Zd Zy)r,   Nr;   r   r
   r   r,   r,   ^   r<   r
   r,   Infc           	      4   | st        d      t        j                  |      }	 	 t        d      j	                  | |       y# t
        $ rK |j                         r#t         dj                  di t                     t        j                  d       Y nw xY wv)u  
    Wait for the specified port to become free (dropping or rejecting
    requests). Return when the port is free or raise a Timeout if timeout has
    elapsed.

    Timeout may be specified in seconds or as a timedelta.
    If timeout is None or ∞, the routine will run indefinitely.

    >>> free('localhost', find_available_local_port())

    >>> free(None, None)
    Traceback (most recent call last):
    ...
    ValueError: Host values of '' or None are not allowed.
    *Host values of '' or None are not allowed.皙?r   NzPort {port} not free on {host}.r   )
ValueErrorr   Timerr   r%   r,   expiredr:   r-   r.   timesleepr"   r#   r   timers       r   freerI   b   s      EFFLL!E
	C ,,T48 	}}F?FFRRSSJJsO		 s   A ABBc                 2   | st        d      t        j                  |      }	 	 t        d      j	                  | |       |j                         r#t         dj                  di t                     t        j                  d       f# t        $ r Y yw xY w)uE  
    Wait for the specified port to become occupied (accepting requests).
    Return when the port is occupied or raise a Timeout if timeout has
    elapsed.

    Timeout may be specified in seconds or as a timedelta.
    If timeout is None or ∞, the routine will run indefinitely.

    >>> occupied('localhost', find_available_local_port(), .1)
    Traceback (most recent call last):
    ...
    Timeout: Port ... not bound on localhost.

    >>> occupied(None, None)
    Traceback (most recent call last):
    ...
    ValueError: Host values of '' or None are not allowed.
    r@   g      ?r   z Port {port} not bound on {host}.rA   Nr   )rB   r   rC   r   r%   rD   r:   r-   r.   rE   rF   r,   rG   s       r   occupiedrK      s    & EFFLL!E
	C ,,T48}}G@GGS&(STTJJsO   		s   A$B
 
	BBc                  <   t        j                  ddt         j                  t         j                        } t	        t        |             \  }}}}}t        j                   ||      }|j                  |       |j                         dd \  }}|j                          |S )zb
    Find a free port on localhost.

    >>> 0 < find_available_local_port() < 65536
    True
    Nr   r   )	r   r   r   r   nextiterbindgetsocknameclose)infosfamilyr1   _addrsockr#   s          r   find_available_local_portrW      s     tQ(8(8&:L:LME $T%[ 1FE1a=='DIIdO!!#BQ'JD$JJLKr
   c                   @    e Zd ZdZed        Zed        Zed        Zy)HostPorta  
    A simple representation of a host/port pair as a string

    >>> hp = HostPort('localhost:32768')

    >>> hp.host
    'localhost'

    >>> hp.port
    32768

    >>> len(hp)
    15

    >>> hp = HostPort('[::1]:32768')

    >>> hp.host
    '::1'

    >>> hp.port
    32768
    c                 Z    t         j                  j                  d|        j                  S Nz//)urllibparseurlparsehostnamer   s    r   r"   zHostPort.host   s#    ||$$r$[1:::r
   c                 Z    t         j                  j                  d|        j                  S r[   )r\   r]   r^   r#   r`   s    r   r#   zHostPort.port   s#    ||$$r$[1666r
   c                     |d d \  }}t        |      }d|v rd| dn|} | dj                  |t        |      g            S )Nr   :[])r	   joinstr)clsrU   listen_hostr#   
plain_hostr"   s         r   	from_addrzHostPort.from_addr   sP     !HT -
$':$5:,a :388T3t9-.//r
   N)	r6   r7   r8   __doc__propertyr"   r#   classmethodrk   r   r
   r   rY   rY      sC    . ; ; 7 7 0 0r
   rY   c                    t        j                         }d }|j                  ddt               |j                  dd|       |j                  ddd t        	       |j                  |       } 	 | j                  | j                  j                  | j                  j                  | j                  
       y # t        $ r+}t        |t        j                         t        d      d }~ww xY w)Nc                     t               |    S r   )globals)keys    r   global_lookupz_main.<locals>.global_lookup   s    y~r
   targetz	host:port)metavartypefuncstatez-tz	--timeout)defaultrv   r   )file   )argparseArgumentParseradd_argumentrY   float
parse_argsrw   rt   r"   r#   r   r:   printsysstderr
SystemExit)argsparserrs   r   s       r   _mainr      s    $$&F +HE
mD
k4eDT"D		$++""DKK$4$4dll	K gCJJ'ms   /AB6 6	C*?&C%%C*__main__r   )rl   rE   r   r|   r   r   r(   r   collectionsr   urllib.parser\   temporar   r	   objectr   IOErrorr:   r,   r   rI   rK   rW   rg   rY   r   r6   r   r
   r   <module>r      s       
      ,/3f /3d	g 		' 	 #5\ B "'u !H %0s %0P" 	J  "57 "r
   