示例#1
0
文件: ErlEpmd.cs 项目: itadapter/nfx
        /// <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;
        }
示例#2
0
        /// <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);
        }