Example #1
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;
            }
        }
Example #2
0
 private void closeSock(IErlTransport s)
 {
     try { if (s != null)
           {
               s.Close();
           }
     }
     catch { }
 }
Example #3
0
 /// <summary>
 /// Close the connection to the remote node
 /// </summary>
 protected virtual void Close()
 {
     m_Connected = false;
     if (m_Transport != null)
     {
         lock (m_Transport)
         {
             if (m_Transport != null)
             {
                 m_Home.OnTrace(ErlTraceLevel.Ctrl, Direction.Inbound, "CLOSE");
                 try { m_Transport.Close(); }
                 catch { }
                 finally { m_Transport = null; }
             }
         }
     }
 }
Example #4
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);
                }

                // 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)
            {
                home.OnTrace(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.OnTrace(ErlTraceLevel.Epmd, Direction.Inbound, () =>
                         node.Port == 0 ? StringConsts.ERL_EPMD_NOT_FOUND : StringConsts.ERL_EPMD_PORT.Args(node.Port));

            return(node.Port);
        }
Example #5
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);
        }
Example #6
0
 private void closeSock(IErlTransport s)
 {
     try { if (s != null) s.Close(); }
       catch { }
 }