improve elapsed time calculation logic using async threads

also bump version
This commit is contained in:
Babak Farrokhi 2016-05-02 17:02:09 +04:30
parent bd643fddae
commit 97a97d53cc
Signed by: farrokhi
GPG Key ID: 6B267AD85D632E9A
2 changed files with 57 additions and 39 deletions

View File

@ -25,6 +25,7 @@
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import concurrent.futures
import getopt
import ipaddress
import os
@ -36,6 +37,10 @@ import time
import dns.rdatatype
import dns.resolver
__author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD'
__version__ = 1.3
# http://pythonhosted.org/cymruwhois/
try:
import cymruwhois
@ -45,7 +50,6 @@ except ImportError:
has_whois = False
# Constants
__VERSION__ = 1.2
__PROGNAME__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache'
@ -102,7 +106,7 @@ if has_whois:
def usage():
print('%s version %1.1f\n' % (__PROGNAME__, __VERSION__))
print('%s version %1.1f\n' % (__PROGNAME__, __version__))
print('usage: %s [-h] [-q] [-a] [-s server] [-p port] [-c count] [-t type] [-w wait] hostname' % __PROGNAME__)
print(' -h --help Show this help')
print(' -q --quiet Quiet')
@ -157,7 +161,40 @@ def expert_report(trace_path, color_mode):
print(" %s[*]%s No expert hint available for this trace" % (color.G, color.N))
def ping(resolver, hostname, dnsrecord, ttl):
reached = False
try:
resolver.query(hostname, dnsrecord, ipttl=ttl)
except dns.resolver.NoNameservers as e:
if not quiet:
print("no or bad response:", e)
exit(1)
except dns.resolver.NXDOMAIN as e:
if not quiet:
print("Invalid hostname:", e)
exit(1)
except dns.resolver.Timeout:
pass
except dns.resolver.NoAnswer:
if not quiet:
print("invalid answer")
pass
except SystemExit:
pass
except:
print("unxpected error: ", sys.exc_info()[0])
exit(1)
else:
reached = True
return reached
def main():
global quiet
try:
signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore CTRL+Z
signal.signal(signal.SIGINT, signal_handler) # custom CTRL+C handler
@ -257,51 +294,32 @@ def main():
icmp_socket.bind(("", dest_port))
icmp_socket.settimeout(timeout)
try: # send DNS request
stime = time.time()
resolver.query(hostname, dnsrecord, ipttl=ttl)
except dns.resolver.NoNameservers as e:
if not quiet:
print("no or bad response:", e)
exit(1)
except dns.resolver.NXDOMAIN as e:
if not quiet:
print("Invalid hostname:", e)
exit(1)
except dns.resolver.Timeout:
pass
except dns.resolver.NoAnswer:
if not quiet:
print("invalid answer")
pass
except SystemExit:
pass
except:
print("unxpected error: ", sys.exc_info()[0])
exit(1)
else:
reached = True
curr_addr = None
curr_host = None
try: # expect ICMP response
_, curr_addr = icmp_socket.recvfrom(512)
curr_addr = curr_addr[0]
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: # dispatch dns lookup to another thread
stime = time.time()
thr = pool.submit(ping, resolver, hostname, dnsrecord, ttl)
except socket.error:
pass
try: # expect ICMP response
_, curr_addr = icmp_socket.recvfrom(512)
curr_addr = curr_addr[0]
except socket.error:
etime = time.time()
pass
finally:
etime = time.time()
icmp_socket.close()
finally:
icmp_socket.close()
etime = time.time()
elapsed = abs(etime - stime) * 1000 # convert to milliseconds
reached = thr.result()
if reached:
curr_addr = dnsserver
stime = time.time() # need to recalculate elapsed time for last hop without waiting for an icmp error reply
ping(resolver, hostname, dnsrecord, ttl)
etime = time.time()
elapsed -= timeout * 1000
elapsed = abs(etime - stime) * 1000 # convert to milliseconds
if should_resolve:
try:

View File

@ -1,7 +1,7 @@
from setuptools import setup, find_packages
setup(
name = "dnsdiag",
version = "1.2.6",
version = "1.3.0",
packages = find_packages(),
install_requires = ['cymruwhois==1.5'],
dependency_links = [