public override Object Clone() { OtpErlangTuple newTuple = (OtpErlangTuple)base.Clone(); newTuple.elems = (OtpErlangObject[])elems.Clone(); return(newTuple); }
/** * Determine if two tuples are equal. Tuples are equal if they have the same * arity and all of the elements are equal. * * @param o * the tuple to compare to. * * @return true if the tuples have the same arity and all the elements are * equal. */ public override bool Equals(Object o) { if (!(o is OtpErlangTuple)) { return(false); } OtpErlangTuple t = (OtpErlangTuple)o; int a = arity(); if (a != t.arity()) { return(false); } for (int i = 0; i < a; i++) { if (!elems[i].Equals(t.elems[i])) { return(false); // early exit } } return(true); }
private void ListenActivity() { EndPoint remote = new IPEndPoint(IPAddress.Any, 0); for (;;) { byte[] message = new byte[BUF]; while (this.socket.Available == 0) { } int size = this.socket.ReceiveFrom(message, ref remote); if (size == 0) continue; Debug.Print("Received " + size + " bytes from " + ((IPEndPoint)remote).Address + " (" + ((IPEndPoint)remote).Port + ")"); string messageString = ""; for (int i = 0; i < size; ++i) { messageString += (int)message[i] + " "; } Debug.Print(messageString); OtpInputStream inStream = new OtpInputStream(message); OtpErlangObject msg = inStream.read_any(); Debug.Print(msg.ToString()); OtpErlangTuple t = new OtpErlangTuple(new OtpErlangObject[] { new OtpErlangAtom("ok"), msg }); OtpOutputStream outStream = new OtpOutputStream(t, false); byte[] answer = outStream.GetBuffer(); this.socket.SendTo(answer, remote); Debug.Print(t.ToString()); } }
/* * this method simulates net_kernel only for the purpose of replying to * pings. */ private bool netKernel(OtpMsg m) { OtpMbox mbox = null; try { OtpErlangTuple t = (OtpErlangTuple)m.getMsg(); OtpErlangTuple req = (OtpErlangTuple)t.elementAt(1); // actual // request OtpErlangPid pid = (OtpErlangPid)req.elementAt(0); // originating // pid OtpErlangObject[] pong = new OtpErlangObject[2]; pong[0] = req.elementAt(1); // his #Ref pong[1] = new OtpErlangAtom("yes"); mbox = createMbox(true); mbox.send(pid, new OtpErlangTuple(pong)); return(true); } catch (Exception) { } finally { closeMbox(mbox); } return(false); }
/** * <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 bool ping(String node, long timeout) { if (node.Equals(this.Node)) { return(true); } else if (node.IndexOf('@', 0) < 0 && node.Equals(this.Node.Substring(0, this.Node.IndexOf('@', 0)))) { return(true); } // other node OtpMbox mbox = null; try { mbox = createMbox(true); mbox.send("net_kernel", node, getPingTuple(mbox)); OtpErlangObject reply = mbox.receive(timeout); OtpErlangTuple t = (OtpErlangTuple)reply; OtpErlangAtom a = (OtpErlangAtom)t.elementAt(1); return("yes".Equals(a.atomValue())); } catch (Exception) { } finally { closeMbox(mbox); } return(false); }
/** * Send an auth error to peer because he sent a bad cookie. The auth error * uses his cookie (not revealing ours). This is just like send_reg * otherwise */ protected void CookieError(OtpLocalNode local, OtpErlangAtom cookie) { try { OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag + version header.Write4BE(0); // reserve space for length header.Write1(passThrough); header.Write1(version); header.WriteTupleHead(4); header.WriteLong(regSendTag); header.WriteAny(local.CreatePid()); // disposable pid header.WriteAtom(cookie.Value); // important: his cookie, // not mine... header.WriteAtom("auth"); // version for payload header.Write1(version); // the payload // the no_auth message (copied from Erlang) Don't change this // (Erlang will crash) // {$gen_cast, {print, "~n** Unauthorized cookie ~w **~n", // [foo@aule]}} IOtpErlangObject[] msg = new IOtpErlangObject[2]; IOtpErlangObject[] msgbody = new IOtpErlangObject[3]; msgbody[0] = new OtpErlangAtom("print"); msgbody[1] = new OtpErlangString("~n** Bad cookie sent to " + local + " **~n"); // Erlang will crash and burn if there is no third argument here... msgbody[2] = new OtpErlangList(); // empty list msg[0] = new OtpErlangAtom("$gen_cast"); msg[1] = new OtpErlangTuple(msgbody); OtpOutputStream payload = new OtpOutputStream(new OtpErlangTuple(msg)); // fix up length in preamble header.Poke4BE(0, header.Length + payload.Length - 4); try { DoSend(header, payload); } catch (IOException) { } // ignore } finally { Close(); } throw new OtpAuthException("Remote cookie not authorized: " + cookie.Value); }
/** * Receive an RPC reply from the remote Erlang node. This convenience * function receives a message from the remote node, and expects it to have * the following format: * * <pre> * { rex, Term } * </pre> * * @return the second element of the tuple if the received message is a * two-tuple, otherwise null. No further error checking is * performed. * * @exception java.io.IOException * if the connection is not active or a communication * error occurs. * * @exception OtpErlangExit * if an exit signal is received from a process on the * peer node. * * @exception OtpAuthException * if the remote node sends a message containing an * invalid cookie. */ public OtpErlangObject receiveRPC() { OtpErlangObject msg = receive(); if (msg is OtpErlangTuple) { OtpErlangTuple t = (OtpErlangTuple)msg; if (t.arity() == 2) { return(t.elementAt(1)); // obs: second element } } return(null); }
/* create the outgoing ping message */ private OtpErlangTuple getPingTuple(OtpMbox mbox) { OtpErlangObject[] ping = new OtpErlangObject[3]; OtpErlangObject[] pid = new OtpErlangObject[2]; OtpErlangObject[] node = new OtpErlangObject[2]; pid[0] = mbox.Self; pid[1] = createRef(); node[0] = new OtpErlangAtom("is_auth"); node[1] = new OtpErlangAtom(Node); ping[0] = new OtpErlangAtom("$gen_call"); ping[1] = new OtpErlangTuple(pid); ping[2] = new OtpErlangTuple(node); return(new OtpErlangTuple(ping)); }
/** * Send an RPC request to the remote Erlang node. This convenience function * creates the following message and sends it to 'rex' on the remote node: * * <pre> * { self, { call, Mod, Fun, Args, user } } * </pre> * * <p> * Note that this method has unpredicatble results if the remote node is not * an Erlang node. * </p> * * @param mod * the name of the Erlang module containing the function to * be called. * @param fun * the name of the function to call. * @param args * a list of Erlang terms, to be used as arguments to the * function. * * @exception java.io.IOException * if the connection is not active or a communication * error occurs. */ public void sendRPC(String mod, String fun, OtpErlangList args) { OtpErlangObject[] rpc = new OtpErlangObject[2]; OtpErlangObject[] call = new OtpErlangObject[5]; /* {self, { call, Mod, Fun, Args, user}} */ call[0] = new OtpErlangAtom("call"); call[1] = new OtpErlangAtom(mod); call[2] = new OtpErlangAtom(fun); call[3] = args; call[4] = new OtpErlangAtom("user"); rpc[0] = self.Pid; rpc[1] = new OtpErlangTuple(call); send("rex", new OtpErlangTuple(rpc)); }
public override void Run() { if (!Connected) { Deliver(new IOException("Not connected")); return; } byte[] lbuf = new byte[4]; int len; try { while (!Stopping) { // don't return until we get a real message // or a failure of some kind (e.g. EXIT) // read length and read buffer must be atomic! // read 4 bytes - get length of incoming packet ReadSock(lbuf); OtpInputStream ibuf = new OtpInputStream(lbuf) { Flags = Local.Flags }; len = ibuf.Read4BE(); // received tick? send tock! if (len == 0) { lock (objWrite) { socket.OutputStream.Write(TOCK, 0, TOCK.Length); socket.OutputStream.Flush(); } continue; } // got a real message (maybe) - read len bytes byte[] tmpbuf = new byte[len]; ReadSock(tmpbuf); ibuf = new OtpInputStream(tmpbuf) { Flags = Local.Flags }; if (ibuf.Read1() != passThrough) { continue; } // got a real message (really) IOtpErlangObject reason = null; OtpErlangAtom cookie = null; IOtpErlangObject tmp = null; OtpErlangTuple head = null; OtpErlangAtom toName; OtpErlangPid to; OtpErlangPid from; int tag; // decode the header tmp = ibuf.ReadAny(); if (!(tmp is OtpErlangTuple)) { continue; } head = (OtpErlangTuple)tmp; if (!(head.ElementAt(0) is OtpErlangLong)) { continue; } // lets see what kind of message this is tag = (int)((OtpErlangLong)head.ElementAt(0)).LongValue(); switch (tag) { case sendTag: // { SEND, Cookie, ToPid } case sendTTTag: // { SEND, Cookie, ToPid, TraceToken } if (!cookieOk) { // we only check this once, he can send us bad cookies later if he likes if (!(head.ElementAt(1) is OtpErlangAtom)) { continue; } cookie = (OtpErlangAtom)head.ElementAt(1); if (sendCookie) { if (cookie.Value != Local.Cookie) { CookieError(Local, cookie); } } else { if (cookie.Value != "") { CookieError(Local, cookie); } } cookieOk = true; } if (TraceLevel >= TraceSend) { Logger.Debug($"<- {HeaderType(head)} {head}"); /* show received payload too */ ibuf.Mark(); Logger.Debug($" {ibuf.ReadAny()}"); ibuf.Reset(); } to = (OtpErlangPid)head.ElementAt(2); Deliver(new OtpMsg(to, ibuf)); break; case regSendTag: // { REG_SEND, FromPid, Cookie, ToName } case regSendTTTag: // { REG_SEND, FromPid, Cookie, ToName, TraceToken } if (!cookieOk) { // we only check this once, he can send us bad cookies later if he likes if (!(head.ElementAt(2) is OtpErlangAtom)) { continue; } cookie = (OtpErlangAtom)head.ElementAt(2); if (sendCookie) { if (cookie.Value != Local.Cookie) { CookieError(Local, cookie); } } else { if (cookie.Value != "") { CookieError(Local, cookie); } } cookieOk = true; } if (TraceLevel >= TraceSend) { Logger.Debug($"<- {HeaderType(head)} {head}"); /* show received payload too */ ibuf.Mark(); Logger.Debug($" {ibuf.ReadAny()}"); ibuf.Reset(); } from = (OtpErlangPid)head.ElementAt(1); toName = (OtpErlangAtom)head.ElementAt(3); Deliver(new OtpMsg(from, toName.Value, ibuf)); break; case exitTag: // { EXIT, FromPid, ToPid, Reason } case exit2Tag: // { EXIT2, FromPid, ToPid, Reason } if (head.ElementAt(3) == null) { continue; } if (TraceLevel >= TraceCTRL) { Logger.Debug($"<- {HeaderType(head)} {head}"); } from = (OtpErlangPid)head.ElementAt(1); to = (OtpErlangPid)head.ElementAt(2); reason = head.ElementAt(3); Deliver(new OtpMsg(tag, from, to, reason)); break; case exitTTTag: // { EXIT, FromPid, ToPid, TraceToken, Reason } case exit2TTTag: // { EXIT2, FromPid, ToPid, TraceToken, Reason } // as above, but bifferent element number if (head.ElementAt(4) == null) { continue; } if (TraceLevel >= TraceCTRL) { Logger.Debug($"<- {HeaderType(head)} {head}"); } from = (OtpErlangPid)head.ElementAt(1); to = (OtpErlangPid)head.ElementAt(2); reason = head.ElementAt(4); Deliver(new OtpMsg(tag, from, to, reason)); break; case linkTag: // { LINK, FromPid, ToPid} case unlinkTag: // { UNLINK, FromPid, ToPid} if (TraceLevel >= TraceCTRL) { Logger.Debug($"<- {HeaderType(head)} {head}"); } from = (OtpErlangPid)head.ElementAt(1); to = (OtpErlangPid)head.ElementAt(2); Deliver(new OtpMsg(tag, from, to)); break; // absolutely no idea what to do with these, so we ignore them... case groupLeaderTag: // { GROUPLEADER, FromPid, ToPid} // (just show trace) if (TraceLevel >= TraceCTRL) { Logger.Debug("<- " + HeaderType(head) + " " + head); } break; default: // garbage? break; } } // this section reachable only with break // we have received garbage from peer Deliver(new OtpExit("Remote is sending garbage")); } catch (OtpAuthException e) { Deliver(e); } catch (OtpDecodeException) { Deliver(new OtpExit("Remote is sending garbage")); } catch (IOException) { Deliver(new OtpExit("Remote has closed connection")); } finally { Close(); } }
/* * Send an auth error to peer because he sent a bad cookie. The auth error * uses his cookie (not revealing ours). This is just like send_reg * otherwise */ private void cookieError(OtpLocalNode local, OtpErlangAtom cookie) { try { OtpOutputStream header = new OtpOutputStream(headerLen); // preamble: 4 byte length + "passthrough" tag + version header.write4BE(0); // reserve space for length header.write1(passThrough); header.write1(version); header.write_tuple_head(4); header.write_long(regSendTag); header.write_any(local.createPid()); // disposable pid header.write_atom(cookie.atomValue()); // important: his cookie, // not mine... header.write_atom("auth"); // version for payload header.write1(version); // the payload // the no_auth message (copied from Erlang) Don't change this // (Erlang will crash) // {$gen_cast, {print, "~n** Unauthorized cookie ~w **~n", // [foo@aule]}} OtpErlangObject[] msg = new OtpErlangObject[2]; OtpErlangObject[] msgbody = new OtpErlangObject[3]; msgbody[0] = new OtpErlangAtom("print"); msgbody[1] = new OtpErlangString("~n** Bad cookie sent to " + local + " **~n"); // Erlang will crash and burn if there is no third argument here... msgbody[2] = new OtpErlangList(); // empty list msg[0] = new OtpErlangAtom("$gen_cast"); msg[1] = new OtpErlangTuple(msgbody); OtpOutputStream payload = new OtpOutputStream(new OtpErlangTuple(msg)); // fix up length in preamble header.poke4BE(0, header.size() + payload.size() - 4); try { do_send(header, payload); } catch (IOException) { } // ignore } finally { close(); } throw new OtpAuthException("Remote cookie not authorized: " + cookie.atomValue()); }
public override IEnumerator<OtpActor.Continuation> GetEnumerator() { while (true) { OtpMsg msg = null; OtpErlangPid sender = null; OtpErlangTuple reply = null; yield return (delegate(OtpMsg received) { msg = received; }); try { OtpErlangTuple t = (OtpErlangTuple)msg.getMsg(); sender = (OtpErlangPid)t.elementAt(0); string instr = ((OtpErlangAtom)t.elementAt(1)).ToString(); if (instr == "echo") { OtpErlangObject[] v = new OtpErlangObject[3]; v[0] = sender; v[1] = new OtpErlangAtom("ok"); v[2] = t.elementAt(2); reply = new OtpErlangTuple(v); } else if (instr == "new") { OtpActorMbox newmbox = (OtpActorMbox)m_node.createMbox(false); PCVMActor newactor = new PCVMActor(m_scene, m_source, m_node, newmbox); m_node.react(newactor); OtpErlangObject[] v = new OtpErlangObject[3]; v[0] = sender; v[1] = new OtpErlangAtom("ok"); v[2] = newmbox.Self; reply = new OtpErlangTuple(v); } } catch (Exception e) { m_log.Debug("[Distributed PC] Invalid message format: " + msg.getMsg()); OtpErlangObject[] v = new OtpErlangObject[3]; v[0] = sender; v[1] = new OtpErlangAtom("error"); v[2] = new OtpErlangString(e.Message); reply = new OtpErlangTuple(v); } finally { if (sender != null) { m_mbox.send(sender, reply); } } } }
/// <summary>Initializes a new instance of the <see cref="ErlangErrorRpcException"/> class.</summary> /// <param name="tuple">The tuple.</param> public ErlangErrorRpcException(OtpErlangTuple tuple) : base(tuple.ToString()) { this.reasonTuple = tuple; }
public static OtpErlangTuple Load(OtpMbox mbox, OtpErlangPid pid, string script) { OtpErlangObject body; OtpErlangBoolean debug = new OtpErlangBoolean(false); OtpErlangObject message; if (script.Length <= 65535) { body = new OtpErlangString(script); } else { body = new OtpErlangBinary(System.Text.Encoding.GetEncoding("iso-8859-1").GetBytes(script)); } message = new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("load"), body, debug }); mbox.send(pid, message); OtpErlangTuple reply = (OtpErlangTuple)mbox.receive(); Console.WriteLine("Load: {0}", reply); return reply; }
public static void Main(string[] args) { OtpNode node = new OtpNode("gen"); OtpMbox mbox = node.createMbox(true); OtpErlangObject message = new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("new") }); mbox.send("kernel", "pc@3di0050d", message); OtpErlangTuple reply = (OtpErlangTuple)mbox.receive(); OtpErlangPid self = (OtpErlangPid)reply.elementAt(0); OtpErlangAtom ok = (OtpErlangAtom)reply.elementAt(1); OtpErlangPid pid = (OtpErlangPid)reply.elementAt(2); Console.WriteLine("New: {0}", ok); if (ok.ToString() != "ok") { return; } mbox.link(pid); using (CUDA cuda = new CUDA(0, true)) { float deltaTime = 0.1f; int nextTickCount; using (NBody nbody = new NBody(cuda, deltaTime, 1.0f, 32)) { string script = String.Empty; nbody.Initialize(); script += String.Format("<128,128,50> translate\n"); script += String.Format("/C {{moveto createsphere dup <1,1,1> setsize dup show }} def\n"); for (int i = 0; i < nbody.HostOldPos.Length; i++) { Float4 pos = nbody.HostOldPos[i]; script += String.Format("<{0},{1},{2}> C /b{3} exch def\n", pos.x, pos.y, pos.z, i); } Load(mbox, pid, script); script = String.Empty; nextTickCount = System.Environment.TickCount; for (ulong frame = 0; frame < 300; frame++) { while (System.Environment.TickCount < nextTickCount); nextTickCount = nextTickCount + (int)(deltaTime * 1000); nbody.Update(0); nbody.Swap(); for (int i = 0; i < nbody.HostOldPos.Length; i++) { Float4 pos = nbody.HostOldPos[i]; script += String.Format("b{3} <{0},{1},{2}> setposition \n", pos.x, pos.y, pos.z, i); } Load(mbox, pid, script); script = String.Empty; } } } Console.WriteLine("Hit return key to continue"); Console.ReadLine(); mbox.send(pid, new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("exit") })); reply = (OtpErlangTuple)mbox.receive(); mbox.close(); node.close(); }
public static void Main(string[] args) { OtpNode node = new OtpNode("gen"); OtpMbox mbox = node.createMbox(true); OtpErlangObject message = new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("new") }); mbox.send("kernel", "pc@3di0050d", message); OtpErlangTuple reply = (OtpErlangTuple)mbox.receive(); OtpErlangPid self = (OtpErlangPid)reply.elementAt(0); OtpErlangAtom ok = (OtpErlangAtom)reply.elementAt(1); OtpErlangPid pid = (OtpErlangPid)reply.elementAt(2); Console.WriteLine("New: {0}", ok); if (ok.ToString() != "ok") { return; } mbox.link(pid); Maze m = new Maze(50, 50); m.Generate(); string script = String.Empty; double z = 25.0; double w = 5.0; double h = 5.0; double d = 0.5; script += String.Format("/L {{moveto createbox dup <{0},{1},{2}> setsize dup show}} def\n", d, (w + d), h); script += String.Format("/B {{moveto createbox dup <{0},{1},{2}> setsize dup show}} def\n", (w + d), d, h); foreach (Cell c in m.Cell) { double x = ((float)c.X) * w + 3.0; double y = ((float)c.Y) * w + 3.0; if (c.Left) { script += String.Format("<{0},{1},{2}> L\n", x, (y + w / 2.0), (z + h / 2.0)); } if (c.Bottom) { script += String.Format("<{0},{1},{2}> B\n", (x + w / 2.0), y, (z + h / 2.0)); } } Load(mbox, pid, script); Console.WriteLine("Hit return key to continue"); Console.ReadLine(); mbox.send(pid, new OtpErlangTuple(new OtpErlangObject[] { mbox.Self, new OtpErlangAtom("exit") })); reply = (OtpErlangTuple)mbox.receive(); mbox.close(); node.close(); }
/// <summary>Extracts the name value from tuple.</summary> /// <param name="value">The value.</param> /// <returns>The name value.</returns> private string ExtractNameValueFromTuple(OtpErlangTuple value) { object nameElement = value.elementAt(3); return new UTF8Encoding().GetString(((OtpErlangBinary)nameElement).binaryValue()); }
/* create the outgoing ping message */ private OtpErlangTuple getPingTuple(OtpMbox mbox) { OtpErlangObject[] ping = new OtpErlangObject[3]; OtpErlangObject[] pid = new OtpErlangObject[2]; OtpErlangObject[] node = new OtpErlangObject[2]; pid[0] = mbox.Self; pid[1] = createRef(); node[0] = new OtpErlangAtom("is_auth"); node[1] = new OtpErlangAtom(Node); ping[0] = new OtpErlangAtom("$gen_call"); ping[1] = new OtpErlangTuple(pid); ping[2] = new OtpErlangTuple(node); return new OtpErlangTuple(ping); }