Exemplo n.º 1
0
        /// <summary>
        /// Accept an incoming connection from a remote node. Used by ErlLocalNode.Accept
        /// to create a connection
        /// based on data received when handshaking with the peer node, when
        /// the remote node is the connection intitiator.
        /// </summary>
        protected ErlAbstractConnection(ErlLocalNode home, IErlTransport s)
            : this(home, new ErlRemoteNode(home), s, home.Cookie)
        {
            setSockOpts();
            //this.socket.ReceiveTimeout = 5000;

            home.OnTrace(ErlTraceLevel.Handshake, Direction.Inbound, () =>
                         StringConsts.ERL_CONN_ACCEPT_FROM.Args(
                             IPAddress.Parse(s.RemoteEndPoint.ToString()).ToString(),
                             (s.RemoteEndPoint as IPEndPoint).Port.ToString()));

            // get his info
            recvName(m_Peer);

            // now find highest common dist value
            if ((m_Peer.Proto != home.Proto) || (home.DistHigh < m_Peer.DistLow) || (home.DistLow > m_Peer.DistHigh))
            {
                Close();
                throw new ErlException(StringConsts.ERL_CONN_NO_COMMON_PROTO_ERROR);
            }

            // highest common protocol version
            m_Peer.DistChoose = Math.Min(m_Peer.DistHigh, home.DistHigh);

            doAccept();
        }
Exemplo n.º 2
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.º 3
0
 private void closeSock(IErlTransport s)
 {
     try { if (s != null)
           {
               s.Close();
           }
     }
     catch { }
 }
Exemplo n.º 4
0
 public void AppendSSHParamsToTransport(IErlTransport transport)
 {
     //set SSH params
     transport.SSHAuthenticationType = SSHAuthenticationType;
     transport.SSHPrivateKeyFilePath = SSHPrivateKeyFilePath;
     transport.SSHServerPort         = SSHServerPort;
     transport.ConnectTimeout        = ConnectTimeout;
     transport.SSHUserName           = SSHUserName;
 }
Exemplo n.º 5
0
 private ErlAbstractConnection(ErlLocalNode home, ErlRemoteNode peer, IErlTransport s, ErlAtom? cookie = null)
 {
   m_Peer = peer;
   m_Home = home;
   m_Transport = s;
   m_Cookie = !cookie.HasValue || cookie.Value == ErlAtom.Null
       ? (peer.Cookie == ErlAtom.Null ? home.Cookie : peer.Cookie) : cookie.Value;
   m_SentBytes = 0;
   m_ReceivedBytes = 0;
   m_MaxPayloadLength = DEFAULT_MAX_PAYLOAD_LENGTH;
   if (m_Transport != null)
     m_Transport.Trace += (o, t, d, msg) => home.OnTrace(t, d, msg);
 }
Exemplo n.º 6
0
 private ErlAbstractConnection(ErlLocalNode home, ErlRemoteNode peer, IErlTransport s, ErlAtom?cookie = null)
 {
     m_Peer      = peer;
     m_Home      = home;
     m_Transport = s;
     m_Cookie    = !cookie.HasValue || cookie.Value == ErlAtom.Null
   ? (peer.Cookie == ErlAtom.Null ? home.Cookie : peer.Cookie) : cookie.Value;
     m_SentBytes        = 0;
     m_ReceivedBytes    = 0;
     m_MaxPayloadLength = DEFAULT_MAX_PAYLOAD_LENGTH;
     if (m_Transport != null)
     {
         m_Transport.Trace += (o, t, d, msg) => home.OnTrace(t, d, msg);
     }
 }
Exemplo n.º 7
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; }
             }
         }
     }
 }
Exemplo n.º 8
0
        private void doConnect(int port)
        {
            try
            {
                m_Transport = ErlTransportFactory.Create(RemoteNode.TransportClassName, RemoteNode.NodeName.Value);

                m_Transport.Trace += (o, t, d, msg) => m_Home.OnTrace(t, d, msg);

                setSockOpts();

                m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                               "MD5 CONNECT TO {0}:{1}".Args(m_Peer.Host, port));

                //m_TcpClient.ReceiveTimeout = 5000;
                m_Transport.Connect(m_Peer.Host, port, ConnectTimeout);

                m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                               "MD5 CONNECTED TO {0}:{1}".Args(m_Peer.Host, port));

                sendName(m_Peer.DistChoose, ErlAbstractNode.NodeCompatibility.Flags);
                recvStatus();
                int    herChallenge = recvChallenge();
                byte[] our_digest   = genDigest(herChallenge, m_Cookie);
                int    ourChallenge = genChallenge();
                sendChallengeReply(ourChallenge, our_digest);
                recvChallengeAck(ourChallenge);
                m_CookieOk         = true;
                m_ShouldSendCookie = false;
            }
            catch (ErlAuthException ae)
            {
                Close();
                throw ae;
            }
            catch (Exception e)
            {
                Close();
                throw new ErlConnectionException(Name,
                                                 StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(
                                                     "{0}:{1}{2}: {3}".Args(m_Peer.Host, port,
                                                                            m_Peer.NodeName == ErlAtom.Null ? "" : " [{0}]".Args(m_Peer.NodeName.Value),
                                                                            e.Message)));
            }
        }
Exemplo n.º 9
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; }
       }
     }
 }
Exemplo n.º 10
0
 private void closeSock(IErlTransport s)
 {
     try { if (s != null) s.Close(); }
       catch { }
 }
Exemplo n.º 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);
                }

                // 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.º 12
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);
        }
Exemplo n.º 13
0
 public void AppendSSHParamsToTransport(IErlTransport transport)
 {
     //set SSH params
     transport.SSHAuthenticationType = SSHAuthenticationType;
     transport.SSHPrivateKeyFilePath = SSHPrivateKeyFilePath;
     transport.SSHServerPort         = SSHServerPort;
     transport.ConnectTimeout        = ConnectTimeout;
     transport.SSHUserName           = SSHUserName;
 }
Exemplo n.º 14
0
    private void doConnect(int port)
    {
      try
      {
        m_Transport = ErlTransportFactory.Create(RemoteNode.TransportClassName, RemoteNode.NodeName.Value);

        m_Transport.Trace += (o, t, d, msg) => m_Home.OnTrace(t, d, msg);

        setSockOpts();
        //m_TcpClient.ReceiveTimeout = 5000;
        var connected = false;
        Thread thr = new Thread(
            () =>
            {
              try
              {
                m_Transport.Connect(m_Peer.Host, port);
                connected = true;
              }
              catch (Exception) { }
            }
        )
        { IsBackground = true, Name = "ErlSockConnectThread" };

        thr.Start();

        m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                "MD5 CONNECT TO {0}:{1}".Args(m_Peer.Host, port));

        var untilTime = DateTime.Now.AddMilliseconds(ConnectTimeout);

        while (!connected && DateTime.Now < untilTime)
          Thread.Sleep(10);

        if (!connected) // Timeout
          throw new ErlException(StringConsts.ERL_CONN_TIMEOUT_ERROR.Args(m_Peer.Host, port));

        m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                "MD5 CONNECTED TO {0}:{1}".Args(m_Peer.Host, port));

        sendName(m_Peer.DistChoose, ErlAbstractNode.NodeCompatibility.Flags);
        recvStatus();
        int herChallenge = recvChallenge();
        byte[] our_digest = genDigest(herChallenge, m_Cookie);
        int ourChallenge = genChallenge();
        sendChallengeReply(ourChallenge, our_digest);
        recvChallengeAck(ourChallenge);
        m_CookieOk = true;
        m_ShouldSendCookie = false;
      }
      catch (ErlAuthException ae)
      {
        Close();
        throw ae;
      }
      catch (Exception e)
      {
        Close();
        throw new ErlConnectionException(Name,
            StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(
                "{0}:{1}{2}: {3}".Args(m_Peer.Host, port,
                    m_Peer.NodeName == ErlAtom.Null ? "" : " [{0}]".Args(m_Peer.NodeName.Value),
                    e.Message)));
      }
    }
Exemplo n.º 15
0
        private void doConnect(int port)
        {
            try
              {
            m_Transport = ErlTransportFactory.Create(RemoteNode.TransportClassName, RemoteNode.NodeName.Value);

            m_Transport.Trace += (o, t, d, msg) => m_Home.OnTrace(t, d, msg);

            setSockOpts();

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                "MD5 CONNECT TO {0}:{1}".Args(m_Peer.Host, port));

            //m_TcpClient.ReceiveTimeout = 5000;
            m_Transport.Connect(m_Peer.Host, port, ConnectTimeout);

            m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                "MD5 CONNECTED TO {0}:{1}".Args(m_Peer.Host, port));

            sendName(m_Peer.DistChoose, ErlAbstractNode.NodeCompatibility.Flags);
            recvStatus();
            int herChallenge = recvChallenge();
            byte[] our_digest = genDigest(herChallenge, m_Cookie);
            int ourChallenge = genChallenge();
            sendChallengeReply(ourChallenge, our_digest);
            recvChallengeAck(ourChallenge);
            m_CookieOk = true;
            m_ShouldSendCookie = false;
              }
              catch (ErlAuthException ae)
              {
            Close();
            throw ae;
              }
              catch (Exception e)
              {
            Close();
            throw new ErlConnectionException(Name,
            StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(
                "{0}:{1}{2}: {3}".Args(m_Peer.Host, port,
                    m_Peer.NodeName == ErlAtom.Null ? "" : " [{0}]".Args(m_Peer.NodeName.Value),
                    e.Message)));
              }
        }
Exemplo n.º 16
0
        private long m_SentMsgs; // Total number of messages sent

        #endregion Fields

        #region Constructors

        /// <summary>
        /// Accept an incoming connection from a remote node. Used by ErlLocalNode.Accept
        /// to create a connection
        /// based on data received when handshaking with the peer node, when
        /// the remote node is the connection intitiator.
        /// </summary>
        protected ErlAbstractConnection(ErlLocalNode home, IErlTransport s)
            : this(home, new ErlRemoteNode(home), s, home.Cookie)
        {
            setSockOpts();
              //this.socket.ReceiveTimeout = 5000;

              home.OnTrace(ErlTraceLevel.Handshake, Direction.Inbound, () =>
              StringConsts.ERL_CONN_ACCEPT_FROM.Args(
                  IPAddress.Parse(s.RemoteEndPoint.ToString()).ToString(),
                  (s.RemoteEndPoint as IPEndPoint).Port.ToString()));

              // get his info
              recvName(m_Peer);

              // now find highest common dist value
              if ((m_Peer.Proto != home.Proto) || (home.DistHigh < m_Peer.DistLow) || (home.DistLow > m_Peer.DistHigh))
              {
            Close();
            throw new ErlException(StringConsts.ERL_CONN_NO_COMMON_PROTO_ERROR);
              }

              // highest common protocol version
              m_Peer.DistChoose = Math.Min(m_Peer.DistHigh, home.DistHigh);

              doAccept();
        }
Exemplo n.º 17
0
        private void doConnect(int port)
        {
            try
            {
                m_Transport = ErlTransportFactory.Create(RemoteNode.TransportClassName, RemoteNode.NodeName.Value);

                m_Transport.Trace += (o, t, d, msg) => m_Home.OnTrace(t, d, msg);

                setSockOpts();
                //m_TcpClient.ReceiveTimeout = 5000;
                var    connected = false;
                Thread thr       = new Thread(
                    () =>
                {
                    try
                    {
                        m_Transport.Connect(m_Peer.Host, port);
                        connected = true;
                    }
                    catch (Exception) { }
                }
                    )
                {
                    IsBackground = true, Name = "ErlSockConnectThread"
                };

                thr.Start();

                m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                               "MD5 CONNECT TO {0}:{1}".Args(m_Peer.Host, port));

                var untilTime = DateTime.Now.AddMilliseconds(ConnectTimeout);

                while (!connected && DateTime.Now < untilTime)
                {
                    Thread.Sleep(10);
                }

                if (!connected) // Timeout
                {
                    throw new ErlException(StringConsts.ERL_CONN_TIMEOUT_ERROR.Args(m_Peer.Host, port));
                }

                m_Home.OnTrace(ErlTraceLevel.Handshake, Direction.Outbound, () =>
                               "MD5 CONNECTED TO {0}:{1}".Args(m_Peer.Host, port));

                sendName(m_Peer.DistChoose, ErlAbstractNode.NodeCompatibility.Flags);
                recvStatus();
                int    herChallenge = recvChallenge();
                byte[] our_digest   = genDigest(herChallenge, m_Cookie);
                int    ourChallenge = genChallenge();
                sendChallengeReply(ourChallenge, our_digest);
                recvChallengeAck(ourChallenge);
                m_CookieOk         = true;
                m_ShouldSendCookie = false;
            }
            catch (ErlAuthException ae)
            {
                Close();
                throw ae;
            }
            catch (Exception e)
            {
                Close();
                throw new ErlConnectionException(Name,
                                                 StringConsts.ERL_CONN_CANT_CONNECT_TO_NODE_ERROR.Args(
                                                     "{0}:{1}{2}: {3}".Args(m_Peer.Host, port,
                                                                            m_Peer.NodeName == ErlAtom.Null ? "" : " [{0}]".Args(m_Peer.NodeName.Value),
                                                                            e.Message)));
            }
        }