Ejemplo n.º 1
0
        /*
         * <p> Determine if another node is alive. This method has the side
         * effect of setting up a connection to the remote node (if
         * possible). Only a single outgoing message is sent; the timeout is
         * how long to wait for a response. </p>
         *
         * <p> Only a single attempt is made to connect to the remote node,
         * so for example it is not possible to specify an extremely long
         * timeout and expect to be notified when the node eventually comes
         * up. If you wish to wait for a remote node to be started, the
         * following construction may be useful: </p>
         *
         * <pre>
         * // ping every 2 seconds until positive response
         * while (!me.ping(him,2000));
         * </pre>
         *
         * @param node the name of the node to ping.
         *
         * @param timeout the time, in milliseconds, to wait for response
         * before returning false.
         *
         * @return true if the node was alive and the correct ping response
         * was returned. false if the correct response was not returned on
         * time.
         **/
        /*internal info about the message formats...
         *
         * the request:
         *  -> REG_SEND {6,#Pid<[email protected]>,'',net_kernel}
         *  {'$gen_call',{#Pid<[email protected]>,#Ref<[email protected]>},{is_auth,bingo@aule}}
         *
         * the reply:
         *  <- SEND {2,'',#Pid<[email protected]>}
         *  {#Ref<[email protected]>,yes}
         */
        public virtual bool ping(System.String node, long timeout)
        {
            if (node.Equals(this._node))
            {
                return(true);
            }

            OtpMbox mbox = null;

            try
            {
                mbox = createMbox();
                mbox.send("net_kernel", node, getPingTuple(mbox));
                Erlang.Object reply = mbox.receive(timeout);

                Erlang.Tuple t = (Erlang.Tuple)reply;
                Erlang.Atom  a = (Erlang.Atom)(t.elementAt(1));
                return("yes".Equals(a.atomValue()));
            }
            catch (System.Exception)
            {
            }
            finally
            {
                closeMbox(mbox);
            }
            return(false);
        }
Ejemplo n.º 2
0
        /*
         * this method simulates net_kernel only for
         * the purpose of replying to pings.
         */
        private bool netKernel(OtpMsg m)
        {
            OtpMbox mbox = null;

            try
            {
                Erlang.Tuple t   = (Erlang.Tuple)(m.getMsg());
                Erlang.Tuple req = (Erlang.Tuple)t.elementAt(1);                // actual request

                Erlang.Pid pid = (Erlang.Pid)req.elementAt(0);                  // originating pid

                Erlang.Object[] pong = new Erlang.Object[2];
                pong[0] = req.elementAt(1);                 // his #Ref
                pong[1] = new Erlang.Atom("yes");

                mbox = createMbox();
                mbox.send(pid, new Erlang.Tuple(pong));
                return(true);
            }
            catch (System.Exception)
            {
            }
            finally
            {
                closeMbox(mbox);
            }
            return(false);
        }
Ejemplo n.º 3
0
 public virtual void remove(OtpMbox mbox)
 {
     byPid.Remove(mbox._self);
     if (mbox.name != null)
     {
         byName.Remove(mbox.name);
     }
 }
Ejemplo n.º 4
0
            public virtual OtpMbox create()
            {
                Erlang.Pid pid = enclosingInstance.createPid();
                OtpMbox    m   = new OtpMbox(enclosingInstance, pid);

                byPid[pid] = new WeakReference(m);
                return(m);
            }
Ejemplo n.º 5
0
 /*
  * Close the specified mailbox.
  *
  * @param the mailbox to close.
  *
  * <p> After this operation, the mailbox will no longer be able to
  * receive messages. Any delivered but as yet unretrieved messages
  * can still be retrieved however. </p>
  *
  * <p> If there are links from the mailbox to other {@link
  * OtpErlangPid pids}, they will be broken when this method is
  * called and exit signals will be sent. </p>
  *
  **/
 public virtual void  closeMbox(OtpMbox mbox)
 {
     if (mbox != null)
     {
         mboxes.remove(mbox);
         mbox.name = null;
         mbox.breakLinks("normal");
     }
 }
Ejemplo n.º 6
0
        /*
         * Determine the {@link Pid pid} corresponding to a
         * registered name on this node.
         *
         * @return the {@link Pid pid} corresponding to the
         * registered name, or null if the name is not known on this node.
         **/
        public virtual Erlang.Pid whereis(System.String name)
        {
            OtpMbox m = mboxes.get(name);

            if (m != null)
            {
                return(m.self());
            }
            return(null);
        }
Ejemplo n.º 7
0
        /*
         * Determine if two mailboxes are equal.
         *
         * @return true if both Objects are mailboxes with the same
         * identifying {@link Pid pids}.
         **/
        public override bool Equals(System.Object o)
        {
            if (!(o is OtpMbox))
            {
                return(false);
            }

            OtpMbox m = (OtpMbox)o;

            return(m._self.Equals(this._self));
        }
Ejemplo n.º 8
0
            /*look up a mailbox based on its pid. If the mailbox has gone out
             * of scope we also remove the reference from the hashtable so we
             * don't find it again.
             */
            public virtual OtpMbox get(Erlang.Pid pid)
            {
                WeakReference wr = (WeakReference)byPid[pid];

                if (wr != null)
                {
                    OtpMbox m = (OtpMbox)wr.Target;

                    if (m != null)
                    {
                        return(m);
                    }
                    byPid.Remove(pid);
                }
                return(null);
            }
Ejemplo n.º 9
0
            /*look up a mailbox based on its name. If the mailbox has gone out
             * of scope we also remove the reference from the hashtable so we
             * don't find it again.
             */
            public virtual OtpMbox get(System.String name)
            {
                WeakReference wr = (WeakReference)byName[name];

                if (wr != null)
                {
                    OtpMbox m = (OtpMbox)wr.Target;

                    if (m != null)
                    {
                        return(m);
                    }
                    byName.Remove(name);
                }
                return(null);
            }
Ejemplo n.º 10
0
            public virtual OtpMbox create(System.String name)
            {
                OtpMbox m = null;

                lock (byName)
                {
                    if (get(name) != null)
                    {
                        return(null);
                    }
                    Erlang.Pid pid = enclosingInstance.createPid();
                    m            = new OtpMbox(enclosingInstance, pid, name);
                    byPid[pid]   = new WeakReference(m);
                    byName[name] = new WeakReference(m);
                }
                return(m);
            }
Ejemplo n.º 11
0
        /*create the outgoing ping message */
        private Erlang.Tuple getPingTuple(OtpMbox mbox)
        {
            Erlang.Object[] ping  = new Erlang.Object[3];
            Erlang.Object[] pid   = new Erlang.Object[2];
            Erlang.Object[] _node = new Erlang.Object[2];

            pid[0] = mbox.self();
            pid[1] = createRef();

            _node[0] = new Erlang.Atom("is_auth");
            _node[1] = new Erlang.Atom(node());

            ping[0] = new Erlang.Atom("$gen_call");
            ping[1] = new Erlang.Tuple(pid);
            ping[2] = new Erlang.Tuple(_node);

            return(new Erlang.Tuple(ping));
        }
Ejemplo n.º 12
0
        /*
         * OtpCookedConnection delivers messages here
         * return true if message was delivered successfully, or false otherwise.
         */
        internal virtual bool deliver(OtpMsg m)
        {
            OtpMbox mbox = null;

            try
            {
                OtpMsg.Tag t = m.type();

                if (t == OtpMsg.Tag.regSendTag)
                {
                    System.String name = m.getRecipientName();
                    /*special case for netKernel requests */
                    if (name.Equals("net_kernel"))
                    {
                        return(netKernel(m));
                    }
                    else
                    {
                        mbox = mboxes.get(name);
                    }
                }
                else
                {
                    mbox = mboxes.get(m.getRecipientPid());
                }
                if (mbox == null)
                {
                    return(false);
                }
                mbox.deliver(m);
            }
            catch (System.Exception)
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 13
0
 public virtual bool register(System.String name, OtpMbox mbox)
 {
     if (name == null)
     {
         if (mbox.name != null)
         {
             byName.Remove(mbox.name);
             mbox.name = null;
         }
     }
     else
     {
         lock (byName)
         {
             if (get(name) != null)
             {
                 return(false);
             }
             byName[name] = new WeakReference(mbox);
             mbox.name    = name;
         }
     }
     return(true);
 }
Ejemplo n.º 14
0
 private void SendDo(OtpMbox mbox, Erlang.Object code)
 {
     Otp.Erlang.Object reply = mbox.rpcCall(
         remote, "servant", "process_confirmation",
         new Otp.Erlang.List(code));
     WriteLine("Do reply: {0}", reply);
 }
Ejemplo n.º 15
0
		/*
		* Close the specified mailbox.
		*
		* @param the mailbox to close.
		*
		* <p> After this operation, the mailbox will no longer be able to
		* receive messages. Any delivered but as yet unretrieved messages
		* can still be retrieved however. </p>
		*
		* <p> If there are links from the mailbox to other {@link
		* OtpErlangPid pids}, they will be broken when this method is
		* called and exit signals will be sent. </p>
		*
		**/
		public virtual void  closeMbox(OtpMbox mbox)
		{
			if (mbox != null)
			{
				mboxes.remove(mbox);
				mbox.name = null;
				mbox.breakLinks("normal");
			}
		}
Ejemplo n.º 16
0
			public virtual void remove(OtpMbox mbox)
			{
				byPid.Remove(mbox._self);
				if (mbox.name != null)
					byName.Remove(mbox.name);
			}
Ejemplo n.º 17
0
		/*create the outgoing ping message */
		private Erlang.Tuple getPingTuple(OtpMbox mbox)
		{
			Erlang.Object[] ping = new Erlang.Object[3];
			Erlang.Object[] pid = new Erlang.Object[2];
			Erlang.Object[] _node = new Erlang.Object[2];
			
			pid[0] = mbox.self();
			pid[1] = createRef();
			
			_node[0] = new Erlang.Atom("is_auth");
			_node[1] = new Erlang.Atom(node());
			
			ping[0] = new Erlang.Atom("$gen_call");
			ping[1] = new Erlang.Tuple(pid);
			ping[2] = new Erlang.Tuple(_node);
			
			return new Erlang.Tuple(ping);
		}
Ejemplo n.º 18
0
 /*
  * <p> Register or remove a name for the given mailbox. Registering
  * a name for a mailbox enables others to send messages without
  * knowing the {@link OtpErlangPid pid} of the mailbox. A mailbox
  * can have at most one name; if the mailbox already had a name,
  * calling this method will supercede that name. </p>
  *
  * @param name the name to register for the mailbox. Specify null to
  * unregister the existing name from this mailbox.
  *
  * @param mbox the mailbox to associate with the name.
  *
  * @return true if the name was available, or false otherwise.
  **/
 public virtual bool registerName(System.String name, OtpMbox mbox)
 {
     return(mboxes.register(name, mbox));
 }
Ejemplo n.º 19
0
        private void GetList(OtpMbox mbox, Action<IEnumerable<Tuple<String, object>>> handler)
        {
            Otp.Erlang.Object reply = mbox.rpcCall(
                remote, "servant", "get_confirmations",
                new Otp.Erlang.List());

            Erlang.Object okPat = Erlang.Object.Format("{ok, List}");
            Erlang.Object itemPat = Erlang.Object.Format("{Text,Code}");
            Erlang.VarBind binding;
            if (okPat.match(reply, (binding = new Otp.Erlang.VarBind())))
            {
                Erlang.List list = binding.find("List") as Erlang.List;
                handler(ListToMenuItems(list));
            }
            else
            {
                WriteLine("Bad reply on getList {0}", reply.ToString());
            }
        }
Ejemplo n.º 20
0
			public virtual OtpMbox create(System.String name)
			{
				OtpMbox m = null;
				
				lock(byName)
				{
					if (get(name) != null)
						return null;
					Erlang.Pid pid = enclosingInstance.createPid();
					m = new OtpMbox(enclosingInstance, pid, name);
					byPid[pid] = new WeakReference(m);
					byName[name] = new WeakReference(m);
				}
				return m;
			}
Ejemplo n.º 21
0
			public virtual OtpMbox create()
			{
				Erlang.Pid pid = enclosingInstance.createPid();
				OtpMbox m = new OtpMbox(enclosingInstance, pid);
				byPid[pid] = new WeakReference(m);
				return m;
			}
Ejemplo n.º 22
0
        static public void Main(String[] args)
        {
            OtpTrace.TraceEvent("Otp test...");

            if (args.Length < 1)
            {
                OtpTrace.TraceEvent("Usage: Otp sname\n  where sname is" +
                                    "the short name of the Erlang node");
                return;
            }

            String host   = System.Net.Dns.GetHostName();
            String remote = args[0] + "@" + host;

            OtpNode node = new OtpNode("q@" + host);

            OtpTrace.TraceEvent("This node is called {0} and is using cookie='{1}'.",
                                node.node(), node.cookie());
            bool ok = false;

            ok = node.ping(remote, 1000);
            if (ok)
            {
                OtpTrace.TraceEvent("   successfully pinged node " + remote + "\n");
            }
            else
            {
                OtpTrace.TraceEvent("   could not ping node " + remote + "\n");
            }

            OtpMbox mbox = null;

            try
            {
                mbox = node.createMbox();

                Erlang.Object[] rpc  = new Erlang.Object[2];
                Erlang.Object[] call = new Erlang.Object[5];

                call[0] = new Erlang.Atom("call");
                call[1] = new Erlang.Atom("lists");
                call[2] = new Erlang.Atom("reverse");
                call[3] = new Erlang.List(new Erlang.List("Hello Erlang world!"));
                call[4] = mbox.self();

                rpc[0] = mbox.self();
                rpc[1] = new Erlang.Tuple(call);

                Erlang.Tuple rpcTuple = new Erlang.Tuple(rpc);
                OtpTrace.TraceEvent("=> " + rpcTuple.ToString());

                mbox.send("rex", remote, rpcTuple);
                Erlang.Object reply = mbox.receive(1000);

                OtpTrace.TraceEvent("<= " + reply.ToString());
            }
            catch (System.Exception)
            {
            }
            finally
            {
                node.closeMbox(mbox);
            }

            node.close();
        }
Ejemplo n.º 23
0
		/*
		* <p> Register or remove a name for the given mailbox. Registering
		* a name for a mailbox enables others to send messages without
		* knowing the {@link OtpErlangPid pid} of the mailbox. A mailbox
		* can have at most one name; if the mailbox already had a name,
		* calling this method will supercede that name. </p>
		*
		* @param name the name to register for the mailbox. Specify null to
		* unregister the existing name from this mailbox.
		*
		* @param mbox the mailbox to associate with the name.
		*
		* @return true if the name was available, or false otherwise.
		**/
		public virtual bool registerName(System.String name, OtpMbox mbox)
		{
			return mboxes.register(name, mbox);
		}
Ejemplo n.º 24
0
        static public void Main(String[] args)
        {
            System.Console.Out.WriteLine("Otp test...");

            string cookie   = OtpNode.defaultCookie;
            string host     = System.Net.Dns.GetHostName();
            string remote   = (args[0].IndexOf('@') < 0) ? args[0] + "@" + host : args[0];
            string nodename = Environment.UserName + "123@" + host;

            AbstractConnection.traceLevel = OtpTrace.Type.sendThreshold;

            if (args.Length < 1)
            {
                System.Console.Out.WriteLine(
                    "Usage: {0} remotenode [cookie] [-notrace]\n" +
                    "    nodename  - is the name of the remote Erlang node\n" +
                    "    cookie    - is the optional cookie string to use\n" +
                    "    -name     - this node name\n" +
                    "    -wire     - wire-level tracing\n" +
                    "    -notrace  - disable debug trace\n",
                    Environment.GetCommandLineArgs()[0]);
                return;
            }
            else if (args.Length > 1 && args[1][0] != '-')
            {
                cookie = args[1].ToString();
            }

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].Equals("-wire"))
                {
                    AbstractConnection.traceLevel = OtpTrace.Type.wireThreshold;
                }
                else if (args[i].Equals("-notrace"))
                {
                    AbstractConnection.traceLevel = OtpTrace.Type.defaultLevel;
                }
                else if (args[i].Equals("-name") && i + 1 < args.Length)
                {
                    nodename = args[i++ + 1];
                    if (nodename.IndexOf('@') < 0)
                    {
                        nodename += '@' + host;
                    }
                }
            }

            OtpNode node = new OtpNode(false, nodename, cookie, true);

            System.Console.Out.WriteLine("This node is called {0} and is using cookie='{1}'.",
                                         node.node(), node.cookie());

            OtpCookedConnection.ConnectTimeout = 2000;
            OtpCookedConnection conn = node.connection(remote);

            conn.OnReadWrite += OnReadWrite;

            if (conn == null)
            {
                Console.WriteLine("Can't connect to node " + remote);
                return;
            }

            // If using short names or IP address as the host part of the node name,
            // get the short name of the peer.
            remote = conn.peer.node();

            System.Console.Out.WriteLine("   successfully connected to node " + remote + "\n");

            OtpMbox mbox = null;

            try
            {
                mbox = node.createMbox();

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "lists", "reverse", new Otp.Erlang.List("Abcdef!"));
                    System.Console.Out.WriteLine("<= [REPLY1]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "global", "register_name",
                        new Otp.Erlang.List(new Otp.Erlang.Atom("me"), mbox.self()));

                    System.Console.Out.WriteLine("<= [REPLY2]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(remote, "global", "register_name", new Otp.Erlang.List(new Otp.Erlang.Atom("me"), mbox.self()), 5000);
                    System.Console.Out.WriteLine("<= [REPLY3]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "io", "format",
                        new Otp.Erlang.List(
                            "Test: ~w -> ~w\n",
                            new Otp.Erlang.List(mbox.self(), new Otp.Erlang.Atom("ok"))
                            ));

                    System.Console.Out.WriteLine("<= [REPLY4]:" + (reply == null ? "null" : reply.ToString()));
                }

                while (true)
                {
                    Otp.Erlang.Object msg = mbox.receive();
                    if (msg is Otp.Erlang.Tuple)
                    {
                        Otp.Erlang.Tuple m = msg as Otp.Erlang.Tuple;
                        if (m.arity() == 2 && m.elementAt(0) is Otp.Erlang.Pid)
                        {
                            mbox.send(m.elementAt(0) as Otp.Erlang.Pid, m.elementAt(1));
                        }
                    }
                    System.Console.Out.WriteLine("IN msg: " + msg.ToString() + "\n");
                }
            }
            catch (System.Exception e)
            {
                System.Console.Out.WriteLine("Error: " + e.ToString());
            }
            finally
            {
                node.closeMbox(mbox);
            }

            node.close();
        }
Ejemplo n.º 25
0
			public virtual bool register(System.String name, OtpMbox mbox)
			{
				if (name == null)
				{
					if (mbox.name != null)
					{
						byName.Remove(mbox.name);
						mbox.name = null;
					}
				}
				else
				{
					lock(byName)
					{
						if (get(name) != null)
							return false;
						byName[name] = new WeakReference(mbox);
						mbox.name = name;
					}
				}
				return true;
			}
Ejemplo n.º 26
0
        static public void Main(String[] args)
        {
            System.Console.Out.WriteLine("Otp test...");

            if (args.Length < 1)
            {
                System.Console.Out.WriteLine("Usage: Otp sname\n  where sname is" +
                                             "the short name of the Erlang node");
                return;
            }

            OtpNode.useShortNames = true;

            String  host   = System.Net.Dns.GetHostName();
            String  user   = Environment.UserName;
            OtpNode node   = new OtpNode(user + "@" + host);
            String  remote = (args[0].Contains("@")) ? args[0] : remote = args[0] + "@" + host;
            OtpMbox mbox   = null;

            System.Console.Out.WriteLine("This node is: {0} (cookie='{1}'). Remote: {2}",
                                         node.node(), node.cookie(), remote);

            //bool ok = node.ping(remote, 1000*300);

            OtpCookedConnection conn = node.getConnection(remote);

            try
            {
                if (conn != null)
                {
                    System.Console.Out.WriteLine("   successfully pinged node " + remote + "\n");
                }
                else
                {
                    throw new System.Exception("Could not ping node: " + remote);
                }

                conn.traceLevel = 1;

                mbox = node.createMbox();
                mbox.registerName("server");

                mbox.sendRPC(conn.peer.node(), "lists", "reverse", new Erlang.List(new Erlang.String("Hello world!")));
                Erlang.Object reply = mbox.receiveRPC(5000);
                System.Console.Out.WriteLine("<= " + reply.ToString());

                {
                    Erlang.List rpcArgs = new Erlang.List(
                        new Erlang.Object[] {
                        mbox.self(),
                        new Erlang.Tuple(
                            new Erlang.Object[] {
                            new Erlang.Atom("table"), new Erlang.Atom("test"), new Erlang.Atom("simple")
                        }
                            )
                    }
                        );

                    mbox.sendRPC(conn.peer.node(), "mnesia_subscr", "subscribe", rpcArgs);
                    reply = mbox.receiveRPC(5000);
                    System.Console.Out.WriteLine("<= " + reply.ToString());
                }

                while (true)
                {
                    Erlang.Object msg = mbox.receive();
                    System.Console.Out.WriteLine("IN msg: " + msg.ToString() + "\n");
                }
            }
            catch (System.Exception e)
            {
                System.Console.Out.WriteLine("Error: " + e.ToString());
            }
            finally
            {
                node.closeMbox(mbox);
            }

            node.close();
        }
Ejemplo n.º 27
0
        static public void Main(String[] args)
        {
            {
                Erlang.Object obj1 = Erlang.Object.Format("{a, b, 10, 2.0}");
                Erlang.Object obj2 = Erlang.Object.Format("{a, [b, 1, 2.0, \"abc\"], {1, 2}}");
            }

            System.Console.Out.WriteLine("Otp test...");

            string cookie = OtpNode.defaultCookie;

            AbstractConnection.traceLevel = OtpTrace.Type.sendThreshold;

            if (args.Length < 1)
            {
                System.Console.Out.WriteLine(
                    "Usage: {0} nodename [cookie] [-notrace]\n" +
                    "    nodename  - is the name of the remote Erlang node\n" +
                    "    cookie    - is the optional cookie string to use\n" +
                    "    -notrace  - disable debug trace\n",
                    Environment.GetCommandLineArgs()[0]);
                return;
            }
            else if (args.Length > 1)
            {
                cookie = args[1].ToString();
            }

            for (int i = 0; i < args.Length; i++)
            {
                if (args[i].Equals("-notrace"))
                {
                    AbstractConnection.traceLevel = OtpTrace.Type.defaultLevel;
                    break;
                }
            }


            String host   = System.Net.Dns.GetHostName();
            String remote = (args[0].IndexOf('@') < 0) ? args[0] + "@" + host : args[0];

            OtpNode node = new OtpNode(false, Environment.UserName + "123@" + host, cookie, true);

            System.Console.Out.WriteLine("This node is called {0} and is using cookie='{1}'.",
                                         node.node(), node.cookie());

            bool ok = node.ping(remote, 1000);

            if (!ok)
            {
                Console.WriteLine("Can't connect to node " + remote);
                return;
            }

            // If using short names, get the short name of the peer.
            remote = node.connection(remote).peer.node();

            if (remote != null)
            {
                System.Console.Out.WriteLine("   successfully pinged node " + remote + "\n");
            }
            else
            {
                System.Console.Out.WriteLine("   could not ping node " + remote + "\n");
            }

            OtpMbox mbox = null;

            try
            {
                mbox = node.createMbox();

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "lists", "reverse", new Otp.Erlang.List("Abcdef!"));
                    System.Console.Out.WriteLine("<= [REPLY1]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "global", "register_name",
                        new Otp.Erlang.List(new Otp.Erlang.Atom("me"), mbox.self()));

                    System.Console.Out.WriteLine("<= [REPLY2]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(remote, "global", "register_name", new Otp.Erlang.List(new Otp.Erlang.Atom("me"), mbox.self()), 5000);
                    System.Console.Out.WriteLine("<= [REPLY3]:" + (reply == null ? "null" : reply.ToString()));
                }

                {
                    Otp.Erlang.Object reply = mbox.rpcCall(
                        remote, "io", "format",
                        new Otp.Erlang.List(
                            "Test: ~w -> ~w\n",
                            new Otp.Erlang.List(mbox.self(), new Otp.Erlang.Atom("ok"))
                            ));

                    System.Console.Out.WriteLine("<= [REPLY4]:" + (reply == null ? "null" : reply.ToString()));
                }

                while (true)
                {
                    Otp.Erlang.Object msg = mbox.receive();
                    if (msg is Otp.Erlang.Tuple)
                    {
                        Otp.Erlang.Tuple m = msg as Otp.Erlang.Tuple;
                        if (m.arity() == 2 && m.elementAt(0) is Otp.Erlang.Pid)
                        {
                            mbox.send(m.elementAt(0) as Otp.Erlang.Pid, m.elementAt(1));
                        }
                    }
                    System.Console.Out.WriteLine("IN msg: " + msg.ToString() + "\n");
                }
            }
            catch (System.Exception e)
            {
                System.Console.Out.WriteLine("Error: " + e.ToString());
            }
            finally
            {
                node.closeMbox(mbox);
            }

            node.close();
        }