improve elapsed time calculation logic using async threads
also bump version
This commit is contained in:
parent
bd643fddae
commit
97a97d53cc
@ -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:
|
||||||
|
2
setup.py
2
setup.py
@ -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 = [
|
||||||
|
Loading…
x
Reference in New Issue
Block a user