'Discovery task. Uses scapy.traceroute function in order to determine
the distance between http and https ports for the target.
Intended to be executed once during the infrastructure process.'

@runonce(exc_class=RunOnce)
def discover(self, fuzzable_request):

    if (not self._has_permission()):
        om.out.error(PERM_ERROR_MSG)
        return
    def set_info(name, desc):
        i = Info(name, desc, 1, self.get_name())
        kb.kb.append(self, 'http_vs_https_dist', i)
    target_url = fuzzable_request.get_url()
    domain = target_url.get_domain()
    http_port = self._http_port
    https_port = self._https_port
    netloc = target_url.get_net_location()
    try:
        port = int(netloc.split(':')[(-1)])
    except ValueError:
        pass
    else:
        protocol = target_url.get_protocol()
        if (protocol == 'https'):
            https_port = port
        else:
            http_port = port
    try:
        from scapy.all import traceroute
    except ImportError as ie:
        om.out.debug(('There    was    an    error    importing    scapy.all:    "%s"' % ie))
        return
    try:
        https_troute = traceroute(domain, dport=https_port)[0].get_trace()
        http_troute = traceroute(domain, dport=http_port)[0].get_trace()
    except Exception as e:
        om.out.debug(('There    was    an    error    running    scapy\'s    traceroute:    "%s"' % e))
        return
    if (not (https_troute and http_troute)):
        return
    https_ip_tuples = https_troute.values()[0].values()
    last_https_ip = https_ip_tuples[(-1)]
    http_ip_tuples = http_troute.values()[0].values()
    last_http_ip = http_ip_tuples[(-1)]
    if (not (last_https_ip[1] and last_http_ip[1])):
        desc = _("The    port    '%s'    is    not    open    on    target    %s")
        if (not last_https_ip[1]):
            om.out.error((desc % (https_port, domain)))
        if (not last_http_ip[1]):
            om.out.error((desc % (http_port, domain)))
    else:
        trace_str = (lambda iptuples: '\n'.join((('                %s    %s' % (t[0], t[1][0])) for t in enumerate(iptuples))))
        if (http_ip_tuples != https_ip_tuples):
            header = '        TCP    trace    to    %s:%s\n%s'
            trc1 = (header % (domain, http_port, trace_str(http_ip_tuples)))
            trc2 = (header % (domain, https_port, trace_str(https_ip_tuples)))
            desc = 'Routes    to    target    "%s"    using    ports    %s    and    %s    are    different:\n%s\n%s'
            desc %= (domain, http_port, https_port, trc1, trc2)
            set_info('HTTP    and    HTTPs    hop    distance', desc)
            om.out.information(desc)
        else:
            desc = ("The    routes    to    the    target's    HTTP    and    HTTPS    ports    are    the    same:\n%s" % trace_str(http_ip_tuples))
            set_info('HTTP    traceroute', desc)
