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. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
import concurrent.futures
import getopt import getopt
import ipaddress import ipaddress
import os import os
@ -36,6 +37,10 @@ import time
import dns.rdatatype import dns.rdatatype
import dns.resolver import dns.resolver
__author__ = 'Babak Farrokhi (babak@farrokhi.net)'
__license__ = 'BSD'
__version__ = 1.3
# http://pythonhosted.org/cymruwhois/ # http://pythonhosted.org/cymruwhois/
try: try:
import cymruwhois import cymruwhois
@ -45,7 +50,6 @@ except ImportError:
has_whois = False has_whois = False
# Constants # Constants
__VERSION__ = 1.2
__PROGNAME__ = os.path.basename(sys.argv[0]) __PROGNAME__ = os.path.basename(sys.argv[0])
WHOIS_CACHE = 'whois.cache' WHOIS_CACHE = 'whois.cache'
@ -102,7 +106,7 @@ if has_whois:
def usage(): 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('usage: %s [-h] [-q] [-a] [-s server] [-p port] [-c count] [-t type] [-w wait] hostname' % __PROGNAME__)
print(' -h --help Show this help') print(' -h --help Show this help')
print(' -q --quiet Quiet') 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)) 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(): def main():
global quiet
try: try:
signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore CTRL+Z signal.signal(signal.SIGTSTP, signal.SIG_IGN) # ignore CTRL+Z
signal.signal(signal.SIGINT, signal_handler) # custom CTRL+C handler signal.signal(signal.SIGINT, signal_handler) # custom CTRL+C handler
@ -257,51 +294,32 @@ def main():
icmp_socket.bind(("", dest_port)) icmp_socket.bind(("", dest_port))
icmp_socket.settimeout(timeout) 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_addr = None
curr_host = None curr_host = None
try: # expect ICMP response with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool: # dispatch dns lookup to another thread
_, curr_addr = icmp_socket.recvfrom(512) stime = time.time()
curr_addr = curr_addr[0] thr = pool.submit(ping, resolver, hostname, dnsrecord, ttl)
except socket.error: try: # expect ICMP response
pass _, 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: reached = thr.result()
icmp_socket.close()
etime = time.time()
elapsed = abs(etime - stime) * 1000 # convert to milliseconds
if reached: if reached:
curr_addr = dnsserver 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: if should_resolve:
try: try:

View File

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