<div dir="ltr"><div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:arial,sans-serif;font-size:13px">Fixed failing documentation formatting error, added test cases. Please refetch:</span></div>
<div class="gmail_default" style="font-family:arial,helvetica,sans-serif"><span style="font-family:arial,sans-serif;font-size:13px"><br></span></div><div class="gmail_default" style="font-family:arial,helvetica,sans-serif">
<span style="font-family:arial,sans-serif;font-size:13px">git fetch git://</span><a href="http://github.com/saleyn/otp.git" target="_blank" style="font-family:arial,sans-serif;font-size:13px">github.com/saleyn/otp.git</a><span style="font-family:arial,sans-serif;font-size:13px"> proto_dist</span><br style="font-family:arial,sans-serif;font-size:13px">
<br style="font-family:arial,sans-serif;font-size:13px"><a href="https://github.com/saleyn/otp/compare/erlang:master...proto_dist" target="_blank" style="font-family:arial,sans-serif;font-size:13px">https://github.com/saleyn/otp/compare/<span class="">erlang</span>:master...proto_dist</a><br style="font-family:arial,sans-serif;font-size:13px">
<a href="https://github.com/saleyn/otp/compare/erlang:maint...proto_dist.patch" target="_blank" style="font-family:arial,sans-serif;font-size:13px">https://github.com/saleyn/otp/compare/<span class="">erlang</span>:maint...proto_dist.patch</a><br>
</div></div><div class="gmail_extra"><br><br><div class="gmail_quote">On Fri, Nov 1, 2013 at 12:58 AM, Serge Aleynikov <span dir="ltr"><<a href="mailto:serge@aleynikov.org" target="_blank">serge@aleynikov.org</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
<br>
[Note: this patch is submitted by email as as a pull request #121]<br>
<br>
Short problem description<br>
=========================<br>
I want an Erlang node to listen on incoming connections using<br>
TCPv4, TCPv6, UDS, and TLS transports on different ports.<br>
<br>
I'd like other nodes to connect to this node using TLS if nodes<br>
are in external networks, use TCPv4 or TCPv6 if nodes are<br>
in the same subnet, and use UDS if nodes are on the same machine.<br>
<br>
Present implementation requires that all nodes in the network<br>
use the same transport, which is a huge limitation<br>
<br>
git fetch git://<a href="http://github.com/saleyn/otp.git" target="_blank">github.com/saleyn/otp.git</a> proto_dist<br>
<br>
<a href="https://github.com/saleyn/otp/compare/erlang:master...proto_dist" target="_blank">https://github.com/saleyn/otp/compare/erlang:master...proto_dist</a><br>
<a href="https://github.com/saleyn/otp/compare/erlang:maint...proto_dist.patch" target="_blank">https://github.com/saleyn/otp/compare/erlang:maint...proto_dist.patch</a><br>
<br>
Long solution description<br>
=========================<br>
<br>
This patch addresses the limitation of registering only one Erlang<br>
distributed transport with Erlang Port Mapping Daemon, and therefore<br>
enabling a node to listen for distributed node connections on multiple<br>
port using different protocols, and selectively choose the protocol<br>
to use when connecting to a node from different secure and unsecure<br>
networks.<br>
<br>
The legacy implementation of Erlang distributed transport allows to<br>
start a node with more than one transport via the<br>
"-proto_dist mod1 mod2 ..." command-line option. But epmd didn't support<br>
registration of multiple protocols. And net_kernel doesn't implement a<br>
way of figuring out which transports are supported on a remote node and<br>
doesn't allow to select a desired transport protocol of choice to use it<br>
for connecting to the node.<br>
<br>
The current patch extends epmd by having it store the name of the<br>
protocol handling module passed to the -proto_dist startup option during<br>
node registration. Multiple registrations are allowed, and they can be<br>
registered to different ports. This way a node can start distributed<br>
transport listeners (e.g. TCP, SSL, UDS), and register them with epmd.<br>
<br>
When another node does epmd "PORT_PLEASE" lookup in order to connect to<br>
node X, it now gives to epmd a list of transport names it supports (i.e.<br>
the ones that were passed to it via -proto_dist option at startup)<br>
together with the node name it queries. The epmd filters out only the<br>
transports supported by the calling client node, and gives back only<br>
those along with the corresponding port numbers.<br>
<br>
net_kernel now supports a new command-line option<br>
"-proto_dist_mf Mod Fun" which is a user-define callback function that<br>
can be used to resolve which transport protocol to use to connect to<br>
a node. This function is called after the epmd query returned a list<br>
of protocols supported by the target node. By default the first<br>
transport in the list is used. An example implementation of this<br>
function is included in<br>
`lib/kernel/examples/uds_dist/src/dist_selector.erl`.<br>
<br>
In order to support backward compatibility the EPMD protocol was<br>
extended with new commands documented in erl_dist_rotocol.xml. Old<br>
nodes can query the new EPMD version, but new nodes (using this patch)<br>
require new version of EPMD.<br>
<br>
Here's an illustration:<br>
<br>
# Node 's' is started with TCP and TLS support<br>
# see <a href="http://www.erlang.org/doc/apps/ssl/ssl_distribution.html#id61752" target="_blank">http://www.erlang.org/doc/apps/ssl/ssl_distribution.html#id61752</a><br>
# note that lib/kernel/examples/uds_dist/src/dist_selector.erl<br>
# module is used to do custom transport selection<br>
<br>
$ erl -boot start_ssl -proto_dist inet_tcp inet_tls -ssl_difile<br>
"/home/serge/tmp/key.pem" -ssl_dist_opt server_certfile<br>
"/home/serge/tmp/certificate.pem" -ssl_dist_opt<br>
server_secure_renegotiate true client_secure_renegotiate true<br>
-proto_dist_mf dist_selector select -pa<br>
"lib/kernel/examples/uds_dist/ebin" -sname s@f16<br>
<br>
(s@f16)1> erl_epmd:names().<br>
[{ok,{"s",[{49645,"inet_tcp"},{41477,"inet_tls"}]}}]<br>
(s@f16)2><br>
<br>
As we see the node registered itself with epmd and has TCP listener on<br>
port 49645, and TLS listener on port 41477.<br>
<br>
We now start another node with just TCP transport:<br>
<br>
$ install/bin/erl -sname k@f16<br>
Erlang R17A (erts-5.11) [source-7e9f18c] [64-bit] [smp:4:4]<br>
[async-threads:10] [hipe] [kernel-poll:false]<br>
<br>
Eshell V5.11 (abort with ^G)<br>
(k@localhost)1> erl_epmd:names().<br>
[{ok,{"k",[{38558,"inet_tcp"}]}},<br>
{ok,{"s",[{49645,"inet_tcp"},{41477,"inet_tls"}]}}]<br>
(k@f16)2><br>
<br>
Connect it to node 's':<br>
<br>
(k@f16)2> net_kernel:connect_node(s@f16).<br>
true<br>
(k@f16)4> nodes().<br>
[s@f16]<br>
<br>
Start the 3rd node 'm' with TCP and SSL, and connect it to node 's':<br>
<br>
$ erl -boot start_ssl -proto_dist inet_tcp inet_tls -ssl_difile<br>
"/home/serge/tmp/key.pem" -ssl_dist_opt server_certfile<br>
"/home/serge/tmp/certificate.pem" -ssl_dist_opt<br>
server_secure_renegotiate true client_secure_renegotiate true<br>
-proto_dist_mf dist_selector select -pa<br>
"/home/serge/tmp/otp/lib/kernel/examples/uds_dist/ebin" -sname m@f16<br>
<br>
% Let's query the EPMD to see which transports/ports are available<br>
% to connect<br>
(m@f16)1><br>
erl_epmd:port_please(s,"localhost",net_kernel:dist_protos(),infinity).<br>
{ports,[{49645,"inet_tcp"},{41477,"inet_tls"}],<br>
5,<br>
[{epmd,{{127,0,0,1},4369}}]}<br>
<br>
% Let the magic begin (since this is a node in the same subnet,<br>
% dist_selector will select the TCP protocol<br>
<br>
(m@f16)2> net_kernel:connect_node(s@f16).<br>
true<br>
<br>
This is a long email, and a sizable patch. I hope others find it useful<br>
and it can be included in the distribution.<br>
<br>
Regards,<br>
<br>
Serge<br>
</blockquote></div><br></div>