Exemplo n.º 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;
            }
        }
Exemplo n.º 2
0
        // used by Send and SendReg (message types with payload)
        protected void DoSend(ErlOutputStream header, ErlOutputStream payload = null)
        {
            bool tw = ErlApp.TraceEnabled(TraceLevel, ErlTraceLevel.Wire);
            bool ts = ErlApp.TraceEnabled(TraceLevel, ErlTraceLevel.Send);

            if (tw || ts)
            {
                var h = header.InputStream(5).Read(true);

                m_Home.OnTrace(ErlTraceLevel.Wire, Direction.Outbound, () =>
                {
                    var hb = header.ToBinary();
                    return("{0} {1} (header_sz={2}{3})\n   Header: {4}{5}"
                           .Args(HeaderType(h), h.ToString(), hb.Length,
                                 payload == null ? string.Empty : ", msg_sz={0}".Args(payload.Length),
                                 hb.ToBinaryString(),
                                 payload == null ? string.Empty : "\n   Msg:    {0}".Args(payload.ToBinaryString())));
                });

                m_Home.OnTrace(ErlTraceLevel.Send, Direction.Outbound, () =>
                {
                    var o = payload == null ? "" : payload.InputStream(0).Read(true).ToString();
                    return("{0} {1} {2}".Args(HeaderType(h), h.ToString(), o));
                });
            }

            var written = (int)header.Length;

            lock (m_Transport)
            {
                try
                {
                    header.WriteTo(m_Transport.GetStream());
                    if (payload != null)
                    {
                        written += (int)payload.Length;
                        payload.WriteTo(m_Transport.GetStream());
                    }

                    m_SentBytes += written;
                    m_SentMsgs++;
                }
                catch (Exception e)
                {
                    Close();
                    throw e;
                }
            }

            onReadWrite(Direction.Outbound, written, m_SentBytes, m_SentMsgs);
        }
Exemplo n.º 3
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);
        }
Exemplo n.º 4
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);
        }