Пример #1
0
        /// <summary>
        /// Unregister from Epmd.
        /// Other nodes wishing to connect will no longer be able to
        /// </summary>
        public static void UnPublishPort(ErlLocalNode node)
        {
            TcpClient s = null;

            try
            {
                s = node.Epmd ?? new TcpClient(ErlLocalNode.LocalHost, EPMD_PORT);
                ErlOutputStream obuf = new ErlOutputStream(
                    writeVersion: false, capacity: node.AliveName.Length + 8);
                obuf.Write2BE(node.AliveName.Length + 1);
                obuf.Write1((byte)Indicator.StopReq);
                var buf = Encoding.ASCII.GetBytes(node.AliveName);
                obuf.Write(buf);
                obuf.WriteTo(s.GetStream());

                node.Trace(ErlTraceLevel.Epmd, Direction.Outbound, () =>
                           StringConsts.ERL_EPMD_UNPUBLISH.Args(node.NodeName.Value, node.Port));
            }
            catch
            {
                s = null;
            }
            finally
            {
                if (s != null)
                {
                    try { s.Close(); } catch {}
                }
                node.Epmd = null;
            }
        }
Пример #2
0
        private void sendName(int dist, ErlAbstractNode.NodeCompatibility flags)
        {
            string str  = m_Home.NodeName.Value;
            var    obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 7 + str.Length);

            obuf.Write2BE(str.Length + 7); // 7 bytes + nodename
            obuf.Write1((int)ErlAbstractNode.NodeType.Ntype_R6);
            obuf.Write2BE((short)dist);
            obuf.Write4BE((int)flags);
            obuf.Write(Encoding.ASCII.GetBytes(str));

            obuf.WriteTo(m_TcpClient.GetStream());

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                           "sendName(flags({0:X2})={1}, dist={2}, local={3}".Args(
                               (int)flags, flags, dist, m_Home.AliveName));
        }
Пример #3
0
        private void sendChallenge(int dist, ErlAbstractNode.NodeCompatibility flags, int challenge)
        {
            ErlAtom str  = m_Home.NodeName;
            var     obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 11 + str.Length);

            obuf.Write2BE((short)str.Length + 11); // 11 bytes + nodename
            obuf.Write1((byte)ErlAbstractNode.NodeType.Ntype_R6);
            obuf.Write2BE((short)dist);
            obuf.Write4BE((int)flags);
            obuf.Write4BE(challenge);
            obuf.Write(Encoding.ASCII.GetBytes(str.Value));

            obuf.WriteTo(m_Transport.GetStream());

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                           "sendChallenge(flags({0:X2})={1}, dist={2}, challenge={3}, local={4}".Args(
                               (int)flags, flags, dist, challenge, m_Home.AliveName));
        }
Пример #4
0
        private void sendStatus(string status)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 19);

            obuf.Write2BE(status.Length + 1);
            obuf.Write1(CHALLENGE_STATUS);
            obuf.Write(Encoding.ASCII.GetBytes(status));

            obuf.WriteTo(m_TcpClient.GetStream());

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                           "sendStatus(status={0}, local={1}".Args(status, m_Home.NodeName.Value));
        }
Пример #5
0
        private void sendChallengeAck(byte[] digest)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 19);

            obuf.Write2BE(17);
            obuf.Write1(CHALLENGE_ACK);
            obuf.Write(digest);

            obuf.WriteTo(m_TcpClient.GetStream());

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                           "sendChallengeAck(digest={1}, local={1}".Args(
                               hex(digest), m_Home.NodeName.Value));
        }
Пример #6
0
        private void sendChallengeReply(int challenge, byte[] digest)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 23);

            obuf.Write2BE(21);
            obuf.Write1(CHALLENGE_REPLY);
            obuf.Write4BE(challenge);
            obuf.Write(digest);
            obuf.WriteTo(m_TcpClient.GetStream());

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                           "sendChallengeReply(challenge={0}, digest={1}, local={2}".Args(
                               challenge, hex(digest), m_Home.NodeName.Value));
        }
Пример #7
0
        private void sendStatus(string status)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 19);
              obuf.Write2BE(status.Length + 1);
              obuf.Write1(CHALLENGE_STATUS);
              obuf.Write(Encoding.ASCII.GetBytes(status));

              obuf.WriteTo(m_Transport.GetStream());

              m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
              "sendStatus(status={0}, local={1}".Args(status, m_Home.NodeName.Value));
        }
Пример #8
0
        private void sendName(int dist, ErlAbstractNode.NodeCompatibility flags)
        {
            string str = m_Home.NodeName.Value;
              var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 7 + str.Length);
              obuf.Write2BE(str.Length + 7); // 7 bytes + nodename
              obuf.Write1((int)ErlAbstractNode.NodeType.Ntype_R6);
              obuf.Write2BE((short)dist);
              obuf.Write4BE((int)flags);
              obuf.Write(Encoding.ASCII.GetBytes(str));

              obuf.WriteTo(m_Transport.GetStream());

              m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
              "sendName(flags({0:X2})={1}, dist={2}, local={3}".Args(
              (int)flags, flags, dist, m_Home.AliveName));
        }
Пример #9
0
        private void sendChallengeReply(int challenge, byte[] digest)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 23);
              obuf.Write2BE(21);
              obuf.Write1(CHALLENGE_REPLY);
              obuf.Write4BE(challenge);
              obuf.Write(digest);
              obuf.WriteTo(m_Transport.GetStream());

              m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
              "sendChallengeReply(challenge={0}, digest={1}, local={2}".Args(
                  challenge, hex(digest), m_Home.NodeName.Value));
        }
Пример #10
0
        private void sendChallengeAck(byte[] digest)
        {
            var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 19);
              obuf.Write2BE(17);
              obuf.Write1(CHALLENGE_ACK);
              obuf.Write(digest);

              obuf.WriteTo(m_Transport.GetStream());

              m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
              "sendChallengeAck(digest={1}, local={1}".Args(
              hex(digest), m_Home.NodeName.Value));
        }
Пример #11
0
        /// <summary>
        /// Determine what port a node listens for incoming connections on
        /// </summary>
        /// <param name="home">Local node</param>
        /// <param name="node">Remote lode for which to look up the port number from remote EPMD</param>
        /// <param name="closeSocket">If true, close the connection to remote EPMD at return</param>
        /// <returns>the listen port for the specified node, or 0 if the node
        /// was not registered with Epmd</returns>
        public static int LookupPort(ErlLocalNode home, ErlRemoteNode node,
            bool closeSocket = false)
        {
            IErlTransport s = null;

              try
              {
            var obuf = new ErlOutputStream(writeVersion: false, capacity: 4 + 3 + node.AliveName.Length + 1);
            s = node.Epmd;

            if (s == null)
            {
              //create transport
              s = ErlTransportFactory.Create(node.TransportClassName, node.NodeName.Value);

              s.Trace += (o, t, d, msg) => home.OnTrace(t, d, msg);

              //append SSH params to transport
              node.AppendSSHParamsToTransport(s);

              //connect (I am not sure)
              s.Connect(node.Host, EPMD_PORT, node.ConnectTimeout);
            }

            // build and send epmd request
            // length[2], tag[1], alivename[n] (length = n+1)
            obuf.Write2BE(node.AliveName.Length + 1);
            obuf.Write1((byte)Indicator.Port4req);
            //UPGRADE_NOTE: This code will be optimized in the future;
            byte[] buf = Encoding.ASCII.GetBytes(node.AliveName);
            obuf.Write(buf);

            // send request
            obuf.WriteTo(s.GetStream());

            home.OnTrace(ErlTraceLevel.Epmd, Direction.Outbound,
                StringConsts.ERL_EPMD_LOOKUP_R4.Args(node.NodeName.Value));

            // receive and decode reply
            // resptag[1], result[1], port[2], ntype[1], proto[1],
            // disthigh[2], distlow[2], nlen[2], alivename[n],
            // elen[2], edata[m]
            buf = new byte[100];

            int n = s.GetStream().Read(buf, 0, buf.Length);

            if (n < 0)
              throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName));

            var ibuf = new ErlInputStream(buf, 0, n, checkVersion: false);

            if (Indicator.Port4resp == (Indicator)ibuf.Read1())
            {
              if (0 == ibuf.Read1())
              {
            node.Port = ibuf.Read2BE();

            node.Ntype = (ErlAbstractNode.NodeType)ibuf.Read1();
            node.Proto = ibuf.Read1();
            node.DistHigh = ibuf.Read2BE();
            node.DistLow = ibuf.Read2BE();
            // ignore rest of fields
              }
            }

            if (!closeSocket)
            {
              node.Epmd = s;
              s = null;
            }
              }
              catch (Exception e)
              {
            home.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_INVALID_RESPONSE_ERROR.Args(node.Host, node.AliveName, e.ToString()));
            throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName, e.ToString()));
              }
              finally
              {
            if (s != null)
              try { s.Close(); } catch { }
            s = null;
              }

              home.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, () =>
              node.Port == 0 ? StringConsts.ERL_EPMD_NOT_FOUND : StringConsts.ERL_EPMD_PORT.Args(node.Port));

              return node.Port;
        }
Пример #12
0
        /// <summary>
        /// Unregister from Epmd.
        /// Other nodes wishing to connect will no longer be able to
        /// </summary>
        public static void UnPublishPort(ErlLocalNode node)
        {
            IErlTransport s = null;

              try
              {
            s = node.Epmd ?? new ErlTcpTransport(ErlLocalNode.LocalHost, EPMD_PORT) { NodeName = node.NodeName.Value };
            ErlOutputStream obuf = new ErlOutputStream(
            writeVersion: false, capacity: node.AliveName.Length + 8);
            obuf.Write2BE(node.AliveName.Length + 1);
            obuf.Write1((byte)Indicator.StopReq);
            var buf = Encoding.ASCII.GetBytes(node.AliveName);
            obuf.Write(buf);
            obuf.WriteTo(s.GetStream());

            node.OnTrace(ErlTraceLevel.Epmd, Direction.Outbound, () =>
                StringConsts.ERL_EPMD_UNPUBLISH.Args(node.NodeName.Value, node.Port));
              }
              catch
              {
            s = null;
              }
              finally
              {
            if (s != null)
              try { s.Close(); } catch { }
            node.Epmd = null;
              }
        }
Пример #13
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;
              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;
        }
Пример #14
0
        /// <summary>
        /// Determine what port a node listens for incoming connections on
        /// </summary>
        /// <param name="home">Local node</param>
        /// <param name="node">Remote lode for which to look up the port number from remote EPMD</param>
        /// <param name="closeSocket">If true, close the connection to remote EPMD at return</param>
        /// <returns>the listen port for the specified node, or 0 if the node
        /// was not registered with Epmd</returns>
        public static int LookupPort(ErlLocalNode home, ErlRemoteNode node,
                                     bool closeSocket = false)
        {
            TcpClient s = null;

            try
            {
                var obuf = new ErlOutputStream(
                    writeVersion: false, capacity: 4 + 3 + node.AliveName.Length + 1);
                s = node.Epmd ?? new TcpClient(node.Host, EPMD_PORT);

                // build and send epmd request
                // length[2], tag[1], alivename[n] (length = n+1)
                obuf.Write2BE(node.AliveName.Length + 1);
                obuf.Write1((byte)Indicator.Port4req);
                //UPGRADE_NOTE: This code will be optimized in the future;
                byte[] buf = Encoding.ASCII.GetBytes(node.AliveName);
                obuf.Write(buf);

                // send request
                obuf.WriteTo(s.GetStream());

                home.Trace(ErlTraceLevel.Epmd, Direction.Outbound,
                           StringConsts.ERL_EPMD_LOOKUP_R4.Args(node.NodeName.Value));

                // receive and decode reply
                // resptag[1], result[1], port[2], ntype[1], proto[1],
                // disthigh[2], distlow[2], nlen[2], alivename[n],
                // elen[2], edata[m]
                buf = new byte[100];

                int n = s.GetStream().Read(buf, 0, buf.Length);

                if (n < 0)
                {
                    throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName));
                }

                var ibuf = new ErlInputStream(buf, 0, n, checkVersion: false);

                if (Indicator.Port4resp == (Indicator)ibuf.Read1())
                {
                    if (0 == ibuf.Read1())
                    {
                        node.Port = ibuf.Read2BE();

                        node.Ntype    = (ErlAbstractNode.NodeType)ibuf.Read1();
                        node.Proto    = ibuf.Read1();
                        node.DistHigh = ibuf.Read2BE();
                        node.DistLow  = ibuf.Read2BE();
                        // ignore rest of fields
                    }
                }

                if (!closeSocket)
                {
                    node.Epmd = s;
                    s         = null;
                }
            }
            catch (Exception)
            {
                home.Trace(ErlTraceLevel.Epmd, Direction.Inbound, StringConsts.ERL_EPMD_INVALID_RESPONSE_ERROR);
                throw new ErlException(StringConsts.ERL_EPMD_NOT_RESPONDING.Args(node.Host, node.AliveName));
            }
            finally
            {
                if (s != null)
                {
                    try { s.Close(); } catch {}
                }
                s = null;
            }

            home.Trace(ErlTraceLevel.Epmd, Direction.Inbound, () =>
                       node.Port == 0 ? StringConsts.ERL_EPMD_NOT_FOUND : StringConsts.ERL_EPMD_PORT.Args(node.Port));

            return(node.Port);
        }
Пример #15
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);
        }
Пример #16
0
    private void sendChallenge(int dist, ErlAbstractNode.NodeCompatibility flags, int challenge)
    {
      ErlAtom str = m_Home.NodeName;
      var obuf = new ErlOutputStream(writeVersion: false, writePktSize: false, capacity: 11 + str.Length);
      obuf.Write2BE((short)str.Length + 11); // 11 bytes + nodename
      obuf.Write1((byte)ErlAbstractNode.NodeType.Ntype_R6);
      obuf.Write2BE((short)dist);
      obuf.Write4BE((int)flags);
      obuf.Write4BE(challenge);
      obuf.Write(Encoding.ASCII.GetBytes(str.Value));

      obuf.WriteTo(m_TcpClient.GetStream());

      m_Home.Trace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
          "sendChallenge(flags({0:X2})={1}, dist={2}, challenge={3}, local={4}".Args(
              (int)flags, flags, dist, challenge, m_Home.AliveName));
    }