DRAFT

Introduction

There are currently two common ways to connect to an IRC network:

This requires users to make an informed decision as to which service to use. Clients traditionally default to an TLS-free connection on port 6667. If a user instructs a client to connect to a network without explicitly asking for TLS, they are likely to receive an unencrypted connection, even when the network provides for TLS connections.

Round-robin addresses such as irc.example.com may also make load balancing and failover difficult.

The use of SRV records as defined in RFC 2782 alleviates these issues by

  1. allowing the list of available service types to be determined automatically from a domain name, and

  2. by allowing administrators to express priority and weighting information to control server load and failover

The use of SRV records is likely to become more important if proposals for the use of SCTP and DTLS with IRC come to fruition. Such facilities significantly aggravate the need for an autonegotiation mechanism.

An additional advantage of SRV records is that they remove the need for the service name to be encoded into the domain name. For example, users could instruct an IRC client to connect to example.com instead of irc.example.com.

Readers of this document are assumed to be familiar with RFC 2782, and RFC 2782 is a normative reference for this specification.

The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.

Note on SCTP

This document makes reference to the use of SCTP with IRC. Such use is contingent on the currently anticipated publication of a specification for use of SCTP with IRC. Clients and servers MUST NOT attempt to implement SCTP in absence of such a specification.

SRV Service Names

The SRV service names to be used are, in order of preference:

Publication of SRV Records by Networks

All networks supporting TCP connections without TLS SHOULD publish SRV records for the _irc._tcp service.

All networks supporting TCP connections with TLS SHOULD publish SRV records for the _ircs._tcp service.

Networks supporting SCTP connections MUST publish SRV records for the _ircs._sctp service.

If a network publishes any SRV record for any IRC service name, it MUST publish SRV records for all IRC service names it supports.

Domain Name Recommendations

It is RECOMMENDED that IRC networks place all IRC SRV records on both their root domain name and any IRC-specific domain name (for example, example.com and irc.example.com). This allows the common irc. prefix to become unnecessary going forward, while still supporting it for users familiar with existing conventions.

Domain names that wish to indicate the explicit unavailability of a service via SRV can and as per RFC 2782 place a . record at the appropriate service name. Note that a . record at one service name will not prevent other service names from being attempted, but . records at any service name supported by the client (and therefore examined) will inhibit hostname fallback.

Domain name operators which wish to indicate the explicit unavailability of any IRC service at their domain MUST place a . SRV record at the _irc._tcp service name, and SHOULD place a . SRV record at the _ircs._tcp service name, to account for the possibility of future clients deprecating non-TLS connections. Operators MAY also place . SRV records at any other IRC service names.

Use of Geolocation

IRC network operators MAY wish to vary the priorities and weights of the SRV records returned by a query to give priority to servers which are likely to be closer to the user. More distant servers can be included with higher priorities.

Operators using such techniques SHOULD ensure that they make effective use of the EDNS Client Subnet extension, so that caching does not interfere with these efforts. See draft-vandergaast-edns-client-subnet-02.txt.

Example Records

Example records for the fictional Foonet IRC network are shown below. The Foonet IRC network has three IRC servers, one of which is intended for backup use only. The SRV priorities ensure that users are balanced equally between servers alpha and beta. If a connection cannot be achieved to either of these servers, a connection to backup will be attempted.

The network optionally supports TLS, and users can instruct a SRV-supporting client to connect to either irc.foonet.org or just foonet.org.

_irc._tcp.foonet.org.       IN SRV 10 10 6667 alpha.foonet.org.
_irc._tcp.foonet.org.       IN SRV 10 10 6667 beta.foonet.org.
_irc._tcp.foonet.org.       IN SRV 20 10 6667 backup.foonet.org.

_ircs._tcp.foonet.org.      IN SRV 10 10 6697 alpha.foonet.org.
_ircs._tcp.foonet.org.      IN SRV 10 10 6697 beta.foonet.org.
_ircs._tcp.foonet.org.      IN SRV 20 10 6697 backup.foonet.org.

_irc._tcp.irc.foonet.org.   IN SRV 10 10 6667 alpha.foonet.org.
_irc._tcp.irc.foonet.org.   IN SRV 10 10 6667 beta.foonet.org.
_irc._tcp.irc.foonet.org.   IN SRV 20 10 6667 backup.foonet.org.

_ircs._tcp.irc.foonet.org.  IN SRV 10 10 6697 alpha.foonet.org.
_ircs._tcp.irc.foonet.org.  IN SRV 10 10 6697 beta.foonet.org.
_ircs._tcp.irc.foonet.org.  IN SRV 20 10 6697 backup.foonet.org.

The owner of the unrelated domain foo.net is constantly receiving connection attempts on port 6667, due to users confusing their domain with the proper domain for the Foonet IRC network. They decide to set SRV records to indicate that no IRC service is available at the domain.

_irc._tcp.foo.net.           IN SRV 0 0 0 .
_ircs._tcp.foo.net.          IN SRV 0 0 0 .

Use of SRV Records by Clients

The following psuedocode expresses a set of coroutines which continually yield 'Endpoints'.

An Endpoint is a 3-tuple of (Transport Type, IP Address, Port). 'IP Address' is an IPv6 or IPv4 address. 'Transport Type' is "TCP", "TLS+TCP" or "DTLS+SCTP".

A client should use the following psuedocode and connect to each endpoint as it is yielded. For retrying operation, use the next_endpoint_loop coroutine, which never stops yielding. The connect_retry function suggests how to use the next_endpoint_loop coroutine.

The functions marked as 'PUBLIC' below are hereafter known as the Public Functions.


'Default Ports' = {
  "TCP":        6667,
  "TLS+TCP":    6697,
  "DTLS+SCTP":  6697
}

# A list of transports the client is willing to use, in the order of
# preference described in this document.
'Default Available Transports' = ["DTLS+SCTP", "TLS+TCP", "TCP"]

Endpoint('Address', 'Port', 'Transport'):
  if 'Transport' is None:
    'Transport' := "TCP"

  if 'Port' is None:
    'Port' := 'Default Ports'['Transport']

  return ('Address', 'Port', 'Transport')

dns_lookup('Hostname', 'Type'):
  # DNS Lookup Function.

resolve_ip('Hostname'):
  for ip in dns_lookup('Hostname', "AAAA"):
    yield ip
  for ip in dns_lookup('Hostname', "A"):
    yield ip

srv('Service', 'Hostname'):
  for r in dns_lookup('Service' ++ "." ++ 'Hostname', "SRV"):
    # Must be yielded in the weighted-random sorted order specified by RFC 2782.
    yield r

map_transport('Transport'):
  switch 'Transport':
    case "DTLS+SCTP": return "_ircs._sctp"
    case "TLS+TCP":   return "_ircs._tcp"
    case "TCP":       return "_irc._tcp"

# PUBLIC
next_endpoint('Address', 'Port'=None, 'Transport'=None,
    'Available Transports'='Default Available Transports'):
  if 'Address' is an IP address:
    yield Endpoint('Address', 'Port', 'Transport' or last item in 'Available Transports')

  else if 'Address' is a hostname:
    'No Fallback' := False

    if not 'Port' and not 'Transport':
      for sn in 'Available Transports':
        for s in srv(map_transport(sn), 'Address'):
          'No Fallback' := True
          # Essentially equivalent to an unusable SRV record for our
          # purposes.
          if s.'Hostname' == ".":
            continue
          for ip in resolve_ip(s.'Hostname'):
            yield Endpoint(ip, s.'Port', sn)

    if not 'No Fallback':
      for ip in resolve_ip('Address'):
        yield Endpoint(ip, 'Port', 'Transport' or last item in 'Available Transports')

  else:
    # Invalid address format, fail.

# PUBLIC
next_endpoint_loop('Address', 'Port'=None, 'Transport'=None,
    'Available Transports'='Default Available Transports'):
  while True:
    for e in next_endpoint('Address', 'Port', 'Transport'):
      yield e

retry_delay_by_tries('Tries')
  # Exponential backoff function.

# PUBLIC
connect_retry('Address', 'Port'=None, 'Transport'=None,
    'Available Transports'='Default Available Transports'):
  i := 0
  for e in next_endpoint_loop('Address', 'Port', 'Transport',
      'Available Transports'):
    sock = connect(e)
    if sock:
      return sock
    i := i + 1
    if i >= 'Max Retries':
      # fail
      return None
    sleep(retry_delay_by_tries(i))

Admission of IRC URLs

The following psuedocode describes how clients should follow irc or ircs URLs.


# PUBLIC
connect_to_url('URL',
    'Available Transports'='Default Available Transports'):
  # 'Port' is None if a port was not explicitly specified.
  #   e.g. irc[s]://example.com/
  # 'Port' is a port number if a port was explicitly specified.
  #   e.g. irc[s]://example.com:6667/
  'Scheme', 'Address', 'Port' := parse_url('URL')

  if 'Scheme' is 'ircs':
    'Available Transports' :=
      List of all transports in 'Available Transports' which use TLS

  # connect_retry may be substituted for any Public Function
  for e in connect_retry('Address', 'Port', None, 'Available Transports'):
    yield e

User Control of Connection Process

Clients MAY allow users to enable or disable any supported transports as a matter of general configuration. This modifies the 'Default Available Transports' list described above.

Clients MAY allow users to customize the 'Default Ports' dictionary described above as a matter of general configuration.

Clients MUST provide a means to explicitly specify a port when directing the client to connect and MUST NOT require such explicit specification. The 'Port' argument of any Public Function must be set if and only if a port was explicitly specified.

Clients MUST provide a means to explicitly specify a transport when directing the client to connect and MUST NOT require such explicit specification. When a command-line command is supported for such direction (e.g. via /SERVER or /CONNECT commands), the implementation of options with names -tcp, -ssl and -sctp are RECOMMENDED.

Clients SHOULD provide a means to preclude non-TLS-based connections. When a command-line command is supported for directing connections, the implementation of an option with name -reqssl is RECOMMENDED. When such an option is specified, any non-TLS-based transport is removed from the list passed to the 'Available Transports' argument for the purposes of that connection.