def discover_connectors(
        domain: str,
        loop=None,
        logger=logger):
    """
    Discover all connection options for a domain, in descending order of
    preference.

    This coroutine returns options discovered from SRV records, or if none are
    found, the generic option using the domain name and the default XMPP client
    port.

    Each option is represented by a triple ``(host, port, connector)``.
    `connector` is a :class:`aioxmpp.connector.BaseConnector` instance which is
    suitable to connect to the given host and port.

    `logger` is the logger used by the function.

    The following sources are supported:

    * :rfc:`6120` SRV records. One option is returned per SRV record.

      If one of the SRV records points to the root name (``.``),
      :class:`ValueError` is raised (the domain specifically said that XMPP is
      not supported here).

    * :xep:`368` SRV records. One option is returned per SRV record.

    * :rfc:`6120` fallback process (only if no SRV records are found). One
      option is returned for the host name with the default XMPP client port.

    The options discovered from SRV records are mixed together, ordered by
    priority and then within priorities are shuffled according to their weight.
    Thus, if there are multiple records of equal priority, the result of the
    function is not deterministic.

    .. versionadded:: 0.6
    """

    domain_encoded = domain.encode("idna") + b"."
    starttls_srv_failed = False
    tls_srv_failed = False

    try:
        starttls_srv_records = yield from network.lookup_srv(
            domain_encoded,
            "xmpp-client",
        )
        starttls_srv_disabled = False
    except dns.resolver.NoNameservers as exc:
        starttls_srv_records = []
        starttls_srv_disabled = False
        starttls_srv_failed = True
        starttls_srv_exc = exc
        logger.debug("xmpp-client SRV lookup for domain %s failed "
                     "(may not be fatal)",
                     domain_encoded,
                     exc_info=True)
    except ValueError:
        starttls_srv_records = []
        starttls_srv_disabled = True

    try:
        tls_srv_records = yield from network.lookup_srv(
            domain_encoded,
            "xmpps-client",
        )
        tls_srv_disabled = False
    except dns.resolver.NoNameservers:
        tls_srv_records = []
        tls_srv_disabled = False
        tls_srv_failed = True
        logger.debug("xmpps-client SRV lookup for domain %s failed "
                     "(may not be fatal)",
                     domain_encoded,
                     exc_info=True)
    except ValueError:
        tls_srv_records = []
        tls_srv_disabled = True

    if starttls_srv_failed and (tls_srv_failed or tls_srv_records is None):
        # the failure is probably more useful as a diagnostic
        # if we find a good reason to allow this scenario, we might change it
        # later.
        raise starttls_srv_exc

    if starttls_srv_disabled and (tls_srv_disabled or tls_srv_records is None):
        raise ValueError(
            "XMPP not enabled on domain {!r}".format(domain),
        )

    if starttls_srv_records is None and tls_srv_records is None:
        # no SRV records published, fall back
        logger.debug(
            "no SRV records found for %s, falling back",
            domain,
        )
        return [
            (domain, 5222, connector.STARTTLSConnector()),
        ]

    starttls_srv_records = starttls_srv_records or []
    tls_srv_records = tls_srv_records or []

    srv_records = [
        (prio, weight, (host.decode("ascii"), port,
                        connector.STARTTLSConnector()))
        for prio, weight, (host, port) in starttls_srv_records
    ]

    srv_records.extend(
        (prio, weight, (host.decode("ascii"), port,
                        connector.XMPPOverTLSConnector()))
        for prio, weight, (host, port) in tls_srv_records
    )

    options = list(
        network.group_and_order_srv_records(srv_records)
    )

    logger.debug(
        "options for %s: %r",
        domain,
        options,
    )

    return options
Discover all connection options for a domain, in descending order of
    preference.

    This coroutine returns options discovered from SRV records, or if none are
    found, the generic option using the domain name and the default XMPP client
    port.

    Each option is represented by a triple ``(host, port, connector)``.
    `connector` is a :class:`aioxmpp.connector.BaseConnector` instance which is
    suitable to connect to the given host and port.

    `logger` is the logger used by the function.

    The following sources are supported:

    * :rfc:`6120` SRV records. One option is returned per SRV record.

      If one of the SRV records points to the root name (``.``),
      :class:`ValueError` is raised (the domain specifically said that XMPP is
      not supported here).

    * :xep:`368` SRV records. One option is returned per SRV record.

    * :rfc:`6120` fallback process (only if no SRV records are found). One
      option is returned for the host name with the default XMPP client port.

    The options discovered from SRV records are mixed together, ordered by
    priority and then within priorities are shuffled according to their weight.
    Thus, if there are multiple records of equal priority, the result of the
    function is not deterministic.

    .. versionadded:: 0.6