<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE chapter SYSTEM "chapter.dtd">

<chapter>
  <header>
    <copyright>
      <year>2018</year><year>2020</year>
      <holder>Ericsson AB. All Rights Reserved.</holder>
    </copyright>
    <legalnotice>
      Licensed under the Apache License, Version 2.0 (the "License");
      you may not use this file except in compliance with the License.
      You may obtain a copy of the License at

          http://www.apache.org/licenses/LICENSE-2.0

      Unless required by applicable law or agreed to in writing, software
      distributed under the License is distributed on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      See the License for the specific language governing permissions and
      limitations under the License.

    </legalnotice>

    <title>How to Implement an Alternative Node Discovery for Erlang Distribution
    </title>
    <prepared>Timmo Verlaan</prepared>
    <responsible></responsible>
    <docno></docno>
    <approved></approved>
    <checked></checked>
    <date>2018-04-25</date>
    <rev>PA1</rev>
    <file>alt_disco.xml</file>
  </header>
  <p>
    This section describes how to implement an alternative node discovery
    mechanism for Erlang distribution. Node discovery is normally done using DNS
    and the Erlang Port Mapper Daemon (EPMD) for port registration and lookup.
  </p>

  <note><p>
    Support for alternative node discovery mechanisms was added in Erlang/OTP
    21.
  </p></note>


  <section>
    <title>Introduction</title>
    <p>To implement your own node discovery module you have to write your own
    EPMD module. The <seeerl marker="kernel:erl_epmd">EPMD module</seeerl> is
    responsible for providing the location of another node. The distribution
    modules (<c>inet_tcp_dist</c>/<c>inet_tls_dist</c>) call the EPMD module to
    get the IP address and port of the other node. The EPMD module that is part
    of Erlang/OTP will resolve the hostname using DNS and uses the EPMD unix
    process to get the port of another node. The EPMD unix process does this by
    connecting to the other node on a well-known port, port 4369.</p>
  </section>

  <section>
    <title>Discovery module</title>
    <p>The discovery module needs to implement the same API as the regular
    <seeerl marker="kernel:erl_epmd">EPMD module</seeerl>. However, instead of
    communicating with EPMD you can connect to any service to find out
    connection details of other nodes. A discovery module is enabled
    by setting <seecom marker="erts:erl">-epmd_module</seecom>
    when starting erlang. The discovery module must implement the following
    callbacks:</p>

    <taglist>
      <tag><seemfa marker="kernel:erl_epmd#start_link/0">start_link/0</seemfa></tag>
      <item>Start any processes needed by the discovery module.</item>
      <tag><seemfa marker="kernel:erl_epmd#names/1">names/1</seemfa></tag>
      <item>Return node names held by the registrar for the given host.</item>
      <tag><seemfa marker="kernel:erl_epmd#register_node/2">register_node/2</seemfa></tag>
      <item>Register the given node name with the registrar.</item>
      <tag><seemfa marker="kernel:erl_epmd#port_please/3">port_please/3</seemfa></tag>
      <item>Return the distribution port used by the given node.</item>
    </taglist>

    <p>The discovery module may implement the following callback:</p>

    <taglist>
      <tag><seemfa marker="kernel:erl_epmd#address_please/3">address_please/3</seemfa></tag>
      <item><p>Return the address of the given node.
        If not implemented, <seemfa marker="kernel:erl_epmd#address_please/3">
        <c>erl_epmd:address_please/3</c></seemfa> will be used instead.</p>
        <p>This callback may also return the port of the given node. In that case
        <seemfa marker="kernel:erl_epmd#port_please/3">port_please/3</seemfa>
        may be omitted.</p></item>
      <tag><seemfa marker="kernel:erl_epmd#listen_port_please/2">listen_port_please/2</seemfa></tag>
      <item><p>Return the port the local node should listen to.
        If not implemented, <seemfa marker="kernel:erl_epmd#listen_port_please/2">
        <c>erl_epmd:listen_port_please/2</c></seemfa> will be used instead.</p>
      </item>
    </taglist>
  </section>
</chapter>
