/// <summary> /// Publish node's port at local EPMD, so that other nodes can connect to it. /// /// On failure to connect to EPMD the function may throw if the value of /// ErlApp.IgnoreLocalEpmdConnectErrors variable is true. /// /// On failed connection attempt the function calls /// node.OnEpmdFailedConnectAttempt delegate /// </summary> /// <remarks> /// This function will get an exception if it tries to talk to an r3 /// epmd, or if something else happens that it cannot forsee. In both /// cases we return an exception (and the caller should try again, using /// the r3 protocol). /// /// If we manage to successfully communicate with an r4 epmd, we return /// either the socket, or null, depending on the result /// </remarks> public static bool PublishPort(ErlLocalNode node) { Exception error = null; IErlTransport s = null; try { ErlOutputStream obuf = new ErlOutputStream(writeVersion: false, capacity: node.AliveName.Length + 20); s = node.Epmd ?? new ErlTcpTransport(ErlLocalNode.LocalHost, EPMD_PORT) { NodeName = node.NodeName.Value }; obuf.Write2BE(node.AliveName.Length + 13); obuf.Write1((byte)Indicator.Publish4req); obuf.Write2BE(node.Port); obuf.Write1((byte)node.Ntype); obuf.Write1((byte)node.Proto); obuf.Write2BE(node.DistHigh); obuf.Write2BE(node.DistLow); obuf.Write2BE(node.AliveName.Length); var buf = Encoding.ASCII.GetBytes(node.AliveName); //UPGRADE_NOTE: This code will be optimized in the future; obuf.Write(buf); obuf.Write2BE(0); // No extra // send request obuf.WriteTo(s.GetStream()); node.OnTrace(ErlTraceLevel.Epmd, Direction.Outbound, () => StringConsts.ERL_EPMD_PUBLISH.Args(node.AliveName, node.Port, "r4")); // get reply buf = new byte[100]; int n = s.GetStream().Read(buf, 0, buf.Length); if (n < 0) // this was an r3 node => not a failure (yet) throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName)); ErlInputStream ibuf = new ErlInputStream(buf, 0, n, checkVersion: false); if (Indicator.Publish4resp == (Indicator)ibuf.Read1()) { int result = ibuf.Read1(); if (result == 0) { node.Creation = (byte)ibuf.Read2BE(); node.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_OK); node.Epmd = s; return true; // success } } error = new ErlException("Cannot register node '{0}' (not unique?)".Args(node.AliveName)); } catch (Exception e) { error = e; } // epmd closed the connection = fail if (s != null) try { s.Close(); } catch { } node.Epmd = null; node.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_NO_RESPONSE); node.OnEpmdFailedConnectAttempt(node.NodeName, error.Message); node.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_FAILED_TO_CONNECT_ERROR); if (!ErlApp.IgnoreLocalEpmdConnectErrors) throw new ErlException(StringConsts.ERL_EPMD_FAILED_TO_CONNECT_ERROR + ": " + error.Message); node.Creation = 0; return false; }
/// <summary> /// Publish node's port at local EPMD, so that other nodes can connect to it. /// /// On failure to connect to EPMD the function may throw if the value of /// ErlApp.IgnoreLocalEpmdConnectErrors variable is true. /// /// On failed connection attempt the function calls /// node.OnEpmdFailedConnectAttempt delegate /// </summary> /// <remarks> /// This function will get an exception if it tries to talk to an r3 /// epmd, or if something else happens that it cannot forsee. In both /// cases we return an exception (and the caller should try again, using /// the r3 protocol). /// /// If we manage to successfully communicate with an r4 epmd, we return /// either the socket, or null, depending on the result /// </remarks> public static bool PublishPort(ErlLocalNode node) { Exception error = null; TcpClient s = null; try { ErlOutputStream obuf = new ErlOutputStream( writeVersion: false, capacity: node.AliveName.Length + 20); s = node.Epmd ?? new TcpClient(ErlLocalNode.LocalHost, EPMD_PORT); obuf.Write2BE(node.AliveName.Length + 13); obuf.Write1((byte)Indicator.Publish4req); obuf.Write2BE(node.Port); obuf.Write1((byte)node.Ntype); obuf.Write1((byte)node.Proto); obuf.Write2BE(node.DistHigh); obuf.Write2BE(node.DistLow); obuf.Write2BE(node.AliveName.Length); var buf = Encoding.ASCII.GetBytes(node.AliveName); //UPGRADE_NOTE: This code will be optimized in the future; obuf.Write(buf); obuf.Write2BE(0); // No extra // send request obuf.WriteTo(s.GetStream()); node.Trace(ErlTraceLevel.Epmd, Direction.Outbound, () => StringConsts.ERL_EPMD_PUBLISH.Args(node.AliveName, node.Port, "r4")); // get reply buf = new byte[100]; int n = s.GetStream().Read(buf, 0, buf.Length); if (n < 0) { // this was an r3 node => not a failure (yet) throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName)); } ErlInputStream ibuf = new ErlInputStream(buf, 0, n, checkVersion: false); if (Indicator.Publish4resp == (Indicator)ibuf.Read1()) { int result = ibuf.Read1(); if (result == 0) { node.Creation = (byte)ibuf.Read2BE(); node.Trace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_OK); node.Epmd = s; return(true); // success } } error = new ErlException("Cannot register node '{0}' (not unique?)".Args(node.AliveName)); } catch (Exception e) { error = e; } // epmd closed the connection = fail if (s != null) { try { s.Close(); } catch {} } node.Epmd = null; node.Trace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_NO_RESPONSE); node.OnEpmdFailedConnectAttempt(node.NodeName, error.Message); node.Trace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_FAILED_TO_CONNECT_ERROR); if (!ErlApp.IgnoreLocalEpmdConnectErrors) { throw new ErlException(error.Message); } node.Creation = 0; return(false); }