Exemplo n.º 1
0
        private async Task Names_R4(IOtpTransport socket)
        {
            try
            {
                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug("<- NAMES(r4) ");
                }

                OtpOutputStream obuf = new OtpOutputStream();
                obuf.Write4BE(EpmdPort);
                foreach (var node in portmap.Values)
                {
                    byte[] bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes($"name {node.Alive} at port {node.Port}\n");
                    obuf.WriteN(bytes);
                    Logger.Debug($"-> name {node.Alive} at port {node.Port}");
                }

                await obuf.WriteToAsync(socket.OutputStream);
            }
            catch (IOException e)
            {
                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug("<- (no response)");
                }
                throw new IOException("Request not responding", e);
            }
        }
Exemplo n.º 2
0
        internal async Task <OtpInputStream> ReadRequestAsync(IOtpTransport sock)
        {
            OtpInputStream ibuf = await sock.ReadAsync(2);

            ibuf = await sock.ReadAsync(ibuf.Read2BE());

            return(ibuf);
        }
Exemplo n.º 3
0
 /**
  * Make public the information needed by remote nodes that may wish to
  * connect to this one. This method establishes a connection to the Erlang
  * port mapper (Epmd) and registers the server node's name and port so that
  * remote nodes are able to connect.
  *
  * This method will fail if an Epmd process is not running on the localhost.
  * See the Erlang documentation for information about starting Epmd.
  *
  * Note that once this method has been called, the node is expected to be
  * available to accept incoming connections. For that reason you should make
  * sure that you call {@link #accept()} shortly after calling
  * {@link #publishPort()}. When you no longer intend to accept connections
  * you should call {@link #unPublishPort()}.
  */
 public bool PublishPort()
 {
     if (Epmd is null)
     {
         Epmd = OtpEpmd.PublishPort(this);
     }
     return(Epmd != null);
 }
Exemplo n.º 4
0
 public static void Close(this IOtpTransport s)
 {
     if (s is null)
     {
         return;
     }
     try { s.Close(); }
     catch (Exception) { }
 }
Exemplo n.º 5
0
        private async Task Port_R4(IOtpTransport socket, OtpInputStream ibuf)
        {
            try
            {
                int    len   = (int)(ibuf.Length - 1);
                byte[] alive = ibuf.ReadN(len);

                string name = OtpErlangString.FromEncoding(alive);
                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug($"<- PORT (r4) {name}");
                }

                if (!portmap.TryGetValue(name, out AbstractNode node))
                {
                    node = null;
                }

                OtpOutputStream obuf = new OtpOutputStream();
                if (node != null)
                {
                    obuf.Write1(port4resp);
                    obuf.Write1(0);
                    obuf.Write2BE(node.Port);
                    obuf.Write1(node.Type);
                    obuf.Write1(node.Proto);
                    obuf.Write2BE(node.DistHigh);
                    obuf.Write2BE(node.DistLow);
                    obuf.Write2BE(len);
                    obuf.WriteN(alive);
                    obuf.Write2BE(0);
                    if (traceLevel >= traceThreshold)
                    {
                        Logger.Debug("-> 0 (success)");
                    }
                }
                else
                {
                    obuf.Write1(port4resp);
                    obuf.Write1(1);
                    if (traceLevel >= traceThreshold)
                    {
                        Logger.Debug("-> 1 (failure)");
                    }
                }

                await obuf.WriteToAsync(socket.OutputStream);
            }
            catch (IOException e)
            {
                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug("<- (no response)");
                }
                throw new IOException("Request not responding", e);
            }
        }
Exemplo n.º 6
0
        private async void HandleConnectionAsync(IOtpTransport socket)
        {
            Logger.Info($"[OtpEpmd] connected {socket}");
            List <string> publishedNodes = new List <string>();

            try
            {
                while (true)
                {
                    var ibuf = await ReadRequestAsync(socket);

                    int request = ibuf.Read1();

                    // This request retains the connection
                    if (request == ALIVE2_REQ)
                    {
                        publishedNodes.Add(await Publish_R4(socket, ibuf));
                        continue;
                    }

                    // These requests terminate the connection
                    if (request == stopReq)
                    {
                    }
                    else if (request == port4req)
                    {
                        await Port_R4(socket, ibuf);
                    }
                    else if (request == names4req)
                    {
                        await Names_R4(socket);
                    }
                    else
                    {
                        Logger.Info($"[OtpEpmd] Unknown request (request={request}, length={ibuf.Length}) from {socket}");
                    }
                    break;
                }
            }
            catch (Exception e)
            {
                Logger.Error($"[OtpEpmd] socket {socket} error {e}");
            }

            Logger.Info($"[OtpEpmd] closing {socket}");
            OtpTransport.Close(socket);

            foreach (var name in publishedNodes)
            {
                portmap.TryRemove(name, out _);
            }
        }
Exemplo n.º 7
0
        /**
         * Accept an incoming connection from a remote node. Used by {@link
         * OtpSelf#accept() OtpSelf.accept()} to create a connection based on data
         * received when handshaking with the peer node, when the remote node is the
         * connection initiator.
         */
        protected AbstractConnection(OtpLocalNode self, IOtpTransport s)
            : base("accept", true)
        {
            TraceLevel = Logger.DefaultTraceLevel;
            Local      = self;
            socket     = s;

            if (TraceLevel >= TraceHandshake)
            {
                Logger.Debug($"<- ACCEPT FROM {s}");
            }

            Accept();
        }
Exemplo n.º 8
0
        /**
         * Unregister the server node's name and port number from the Erlang port
         * mapper, thus preventing any new connections from remote nodes.
         */
        public void UnPublishPort()
        {
            if (Epmd == null)
            {
                return;
            }

            // Unregister
            OtpEpmd.UnPublishPort(this);

            // Close and ignore errors
            OtpTransport.Close(Epmd);
            Epmd = null;
        }
Exemplo n.º 9
0
 /**
  * Close the connection to the remote node.
  */
 public virtual void Close()
 {
     Stop();
     Connected = false;
     lock (objRead)
     {
         if (socket != null)
         {
             if (TraceLevel >= TraceCTRL)
             {
                 Logger.Debug($"-> CLOSE {socket}");
             }
             OtpTransport.Close(socket);
             socket = null;
         }
     }
 }
Exemplo n.º 10
0
        /**
         * Accept an incoming connection from a remote node. A call to this method
         * will block until an incoming connection is at least attempted.
         */
        public OtpConnection Accept()
        {
            IOtpTransport newsock = null;

            while (true)
            {
                try
                {
                    newsock = listen.Accept();
                    return(new OtpConnection(this, newsock));
                }
                catch (SocketException e)
                {
                    newsock?.Dispose();
                    throw new IOException("Failed to accept connection", e);
                }
            }
        }
Exemplo n.º 11
0
        private async Task <string> Publish_R4(IOtpTransport socket, OtpInputStream ibuf)
        {
            try
            {
                int    port     = ibuf.Read2BE();
                int    type     = ibuf.Read1();
                int    proto    = ibuf.Read1();
                int    distHigh = ibuf.Read2BE();
                int    distLow  = ibuf.Read2BE();
                string name     = ibuf.ReadStringData();
                ibuf.ReadStringData(); // extra
                AbstractNode node = new AbstractNode()
                {
                    Node     = name,
                    Port     = port,
                    Type     = type,
                    DistHigh = distHigh,
                    DistLow  = distLow,
                    Proto    = proto
                };

                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug($"<- PUBLISH (r4) {name} port={node.Port}");
                }

                OtpOutputStream obuf = new OtpOutputStream();
                obuf.Write1(ALIVE2_RESP);
                obuf.Write1(0);
                obuf.Write2BE(NextCreation());
                await obuf.WriteToAsync(socket.OutputStream);

                portmap.TryAdd(name, node);
                return(name);
            }
            catch (IOException e)
            {
                if (traceLevel >= traceThreshold)
                {
                    Logger.Debug("<- (no response)");
                }
                throw new IOException("Request not responding", e);
            }
        }
Exemplo n.º 12
0
        protected void Connect()
        {
            try
            {
                socket = Peer.CreateTransport(Peer.Host, Peer.Port);

                if (TraceLevel >= TraceHandshake)
                {
                    Logger.Debug($"-> MD5 CONNECT TO {Peer.Host}:{Peer.Port}");
                }

                int nameTag = SendName(Peer.DistChoose, Local.CapFlags, Local.Creation);
                RecvStatus();
                int    peer_challenge = RecvChallenge();
                byte[] our_digest     = GenDigest(peer_challenge, Local.Cookie);
                int    our_challenge  = GenChallenge();
                SendComplement(nameTag);
                SendChallengeReply(our_challenge, our_digest);
                RecvChallengeAck(our_challenge);
                Connected  = true;
                cookieOk   = true;
                sendCookie = false;
                if (TraceLevel >= TraceHandshake)
                {
                    Logger.Debug($"-> CONNECTED TO {Peer.Host}:{Peer.Port}");
                }
            }
            catch (IOException)
            {
                Close();
                throw;
            }
            catch (OtpAuthException)
            {
                Close();
                throw;
            }
            catch (Exception e)
            {
                Close();
                throw new IOException("Cannot connect to peer node", e);
            }
        }
Exemplo n.º 13
0
 public static async Task <OtpInputStream> ReadAsync(this IOtpTransport s, int bytes)
 {
     if (s is null)
     {
         return(default);
Exemplo n.º 14
0
 /*
  * Accept an incoming connection from a remote node. Used by {@link
  * OtpSelf#accept() OtpSelf.accept()} to create a connection based on data
  * received when handshaking with the peer node, when the remote node is the
  * connection intitiator.
  */
 internal OtpConnection(OtpSelf self, IOtpTransport socket)
     : base(self, socket)
 {
     Self = self;
     Start();
 }
Exemplo n.º 15
0
 /*
  * Accept an incoming connection from a remote node. Used by {@link
  * OtpSelf#accept() OtpSelf.accept()} to create a connection based on data
  * received when handshaking with the peer node, when the remote node is the
  * connection intitiator.
  */
 internal OtpCookedConnection(OtpNode self, IOtpTransport s)
     : base(self, s)
 {
     this.self = self;
     Start();
 }