o b#@svddlZddlmZddlmZmZddlmZmZddl m Z ddl m Z GdddZ eejGd d d ZdS) N) implementer)error interfaces)clientdns) DNSNameError) nativeStringc@s4eZdZddZddZddZddZd d Zd S) "_SRVConnector_ClientFactoryWrappercCs||_||_dSN)-_SRVConnector_ClientFactoryWrapper__connector2_SRVConnector_ClientFactoryWrapper__wrappedFactory)self connectorwrappedFactoryr:/usr/lib/python3/dist-packages/twisted/names/srvconnect.py__init__s z+_SRVConnector_ClientFactoryWrapper.__init__cCs|j|jdSr )r startedConnectingr )r rrrrrsz4_SRVConnector_ClientFactoryWrapper.startedConnectingcC|j|dSr )r connectionFailedr rreasonrrrclientConnectionFailedz9_SRVConnector_ClientFactoryWrapper.clientConnectionFailedcCrr )r connectionLostrrrrclientConnectionLostrz7_SRVConnector_ClientFactoryWrapper.clientConnectionLostcCs t|j|Sr )getattrr )r keyrrr __getattr__s z._SRVConnector_ClientFactoryWrapper.__getattr__N)__name__ __module__ __qualname__rrrrrrrrrr s  r c@seZdZdZdZdddidfddZd d Zd d Zd dZddZ ddZ ddZ ddZ ddZ ddZddZddZdS) SRVConnectoraD A connector that looks up DNS SRV records. RFC 2782 details how SRV records should be interpreted and selected for subsequent connection attempts. The algorithm for using the records' priority and weight is implemented in L{pickServer}. @ivar servers: List of candidate server records for future connection attempts. @type servers: L{list} of L{dns.Record_SRV} @ivar orderedServers: List of server records that have already been tried in this round of connection attempts. @type orderedServers: L{list} of L{dns.Record_SRV} rtcp connectTCPrNc Cs^||_||_|dur dnt||_||_||_||_||_||_ | |_ d|_ d|_ d|_ dS)a @param domain: The domain to connect to. If passed as a text string, it will be encoded using C{idna} encoding. @type domain: L{bytes} or L{str} @param defaultPort: Optional default port number to be used when SRV lookup fails and the service name is unknown. This should be the port number associated with the service name as defined by the IANA registry. @type defaultPort: L{int} N)reactorservicer domainStringdomainfactoryprotocolconnectFuncNameconnectFuncArgsconnectFuncKwArgs _defaultPortrserversorderedServers) r r%r&r(r)r*r+r,r- defaultPortrrrr6s zSRVConnector.__init__cCs|j|j||jsR|jdur|tddSt dt |j t |j t |jf}| |j|j||fdd|jrJ||j||jdS|jdur]|dS|jdS)z"Start connection to remote server.NzDomain is not defined.z _%s._%s.%scSs|Sr )_reallyConnect)xr rrrqsz&SRVConnector.connect..)r)doStartrr/r(rrDNSLookupErrorr lookupServicerr&r* addCallbacks _cbGotServers _ebGotServers addCallbackr. addErrback_ebServiceUnknownrr2connect)r drrrr>]s0      zSRVConnector.connectcCs|tg|_g|_dSr )traprr/r0r failurerrrr:zs  zSRVConnector._ebGotServerscCs|\}}}t|dkr2|djtjkr2|djr2|djjtdkr2tdt |j t |j fg|_ g|_ |D]}|jtjksE|jsFq:|j |jq:dS)Nr.z'Service %s not available for domain %s.)lentyperSRVpayloadtargetNamerr6reprr&r(r/r0append)r resultanswersauthaddarrrr9s$  zSRVConnector._cbGotServerscCs6|tjtdd|j|jg|_g|_| dS)a. Connect to the default port when the service name is unknown. If no SRV records were found, the service name will be passed as the port. If resolving the name fails with L{error.ServiceNameUnknownError}, a final attempt is done using the default port. rN) r@rServiceNameUnknownErrorr Record_SRVr.r(r/r0r>rArrrr=s  zSRVConnector._ebServiceUnknownc Cs$|jdusJ|jdusJ|js|jst|j|jfS|js)|jr)|j|_g|_|js.J|jjddd|jdj}d}d}g}|jD]}|j|kr]||j7}|||f|d7}qFt d|}|D]!\}}||kr|j|}|j|=|j|t |j |j fSqftd|jjd) a; Pick the next server. This selects the next server from the list of SRV records according to their priority and weight values, as set out by the default algorithm specified in RFC 2782. At the beginning of a round, L{servers} is populated with L{orderedServers}, and the latter is made empty. L{servers} is the list of candidates, and L{orderedServers} is the list of servers that have already been tried. First, all records are ordered by priority and weight in ascending order. Then for each priority level, a running sum is calculated over the sorted list of records for that priority. Then a random value between 0 and the final sum is compared to each record in order. The first record that is greater than or equal to that random value is chosen and removed from the list of candidates for this round. @return: A tuple of target hostname and port from the chosen DNS SRV record. @rtype: L{tuple} of native L{str} and L{int} NcSs |j|jfSr )priorityweight)recordrrrr4s z)SRVConnector.pickServer..)rrrCz Impossible z pickServer result.)r/r0rr(r&sortrTrUrLrandomrandintstrrIport RuntimeError __class__r) r minPriorityindex weightSum weightIndexr3randrUchosenrrr pickServers8           zSRVConnector.pickServercCs|jrd|_dS|\|_|_|jdusJd|jdus"Jdt|j|j}||j|jt||jg|j Ri|j |_ dS)NrzMust have a host to connect to.zMust have a port to connect to.) stopAfterDNSrdhostr[rr%r+r r)r,r-r)r connectFuncrrrr2s   zSRVConnector._reallyConnectcCs|jr |jdSd|_dS)zStop attempting to connect.rCN)rstopConnectingrer rrrrhs zSRVConnector.stopConnectingcCs$|jdur |jdS|dS)z%Disconnect whatever our are state is.N)r disconnectrhrirrrrjs  zSRVConnector.disconnectcCs|jsJ|jSr )rgetDestinationrirrrrks  zSRVConnector.getDestinationcC|j|||jdSr )r)rdoStopr rrrrr zSRVConnector.connectionFailedcCrlr )r)rrmrnrrrr rozSRVConnector.connectionLost)rr r!__doc__rerr>r:r9r=rdr2rhrjrkrrrrrrr""s( ' = r")rXzope.interfacertwisted.internetrr twisted.namesrrtwisted.names.errorrtwisted.python.compatrr IConnectorr"rrrrs