/// <summary>Extracts the nodes.</summary> /// <param name="nodes">The nodes.</param> /// <param name="nodesList">The nodes list.</param> private void ExtractNodes(IList <Node> nodes, OtpErlangList nodesList) { foreach (var erlangNodeName in nodesList) { var nodeName = erlangNodeName.ToString(); nodes.Add(new Node(nodeName)); } }
/// <summary>Extracts the applications.</summary> /// <param name="applications">The applications.</param> /// <param name="appList">The app list.</param> private void ExtractApplications(IList <Application> applications, OtpErlangList appList) { foreach (var appDescription in appList) { var appDescriptionTuple = (OtpErlangTuple)appDescription; var name = appDescriptionTuple.elementAt(0).ToString(); var description = appDescriptionTuple.elementAt(1).ToString(); var version = appDescriptionTuple.elementAt(2).ToString(); applications.Add(new Application(name, description, version)); } }
/// <summary>Executes the erlang RPC.</summary> /// <param name="module">The module.</param> /// <param name="function">The function.</param> /// <param name="args">The args.</param> /// <returns>The OtpErlangObject.</returns> public OtpErlangObject ExecuteErlangRpc(string module, string function, OtpErlangList args) { return(this.Execute( delegate(IConnection connection) { Logger.Debug("Sending RPC for module [" + module + "] function [" + function + "] args [" + args); connection.SendRPC(module, function, args); var response = connection.ReceiveRPC(); Logger.Debug("Response received = " + response); this.HandleResponseError(module, function, response); return response; })); }
/** * Create an Erlang string from a list of integers. * * @return an Erlang string with Unicode code units. * * @throws OtpErlangException * for non-proper and non-integer lists. * @throws OtpErlangRangeException * if an integer in the list is not * a valid Unicode code point according to Erlang. */ public OtpErlangString(OtpErlangList list) { String s = list.stringValue(); int[] offset = System.Globalization.StringInfo.ParseCombiningCharacters(s); int n = offset.Length; for (int i = 0; i < n; i++) { int cp = (int)codePointAt(s, offset[i]); if (!isValidCodePoint(cp)) { throw new OtpErlangRangeException("Invalid CodePoint: " + cp); } } str = s; }
/* * 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()); }
/** * 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)); }
/// <summary>Sends the RPC.</summary> /// <param name="mod">The mod.</param> /// <param name="fun">The fun.</param> /// <param name="args">The args.</param> public void SendRPC(string mod, string fun, OtpErlangList args) { this.otpConnection.sendRPC(mod, fun, args); }
/// <summary> /// Executes a MFA over TCP stream and synchronously retrieves the data /// </summary> /// <param name="stream">TCP stream</param> /// <param name="module">Erlang Module atom</param> /// <param name="function">Erlang function atom</param> /// <param name="args">Function arguments (maybe empty/null)</param> /// <returns></returns> public static OtpErlangObject CallMFASync(ErlStream stream, string module, string function, OtpErlangObject[] args) { OtpErlangObject[] mfaArray = null; OtpOutputStream eouts = new OtpOutputStream(); mfaArray = new OtpErlangObject[4]; // mod and fun and args as list // ['mod', 'fun', arg1, arg2, ...] mfaArray[0] = new OtpErlangAtom("c#ref"); mfaArray[1] = new OtpErlangAtom(module); mfaArray[2] = new OtpErlangAtom(function); if (null != args) mfaArray[3] = new OtpErlangList(args); else mfaArray[3] = new OtpErlangList(); OtpErlangTuple mfaTouple = new OtpErlangTuple(mfaArray); eouts = new OtpOutputStream(); mfaTouple.encode(eouts); uint payloadLen = (uint)(eouts.Length + 1); byte[] buf = new byte[eouts.Length + 5]; // added payload size (including protocol id byte) // and the missing protocol id byte after it buf[0] = (byte)((payloadLen & 0xFF000000) >> 24); buf[1] = (byte)((payloadLen & 0x00FF0000) >> 16); buf[2] = (byte)((payloadLen & 0x0000FF00) >> 8); buf[3] = (byte)((payloadLen & 0x000000FF)); buf[4] = 131; Array.Copy(eouts.GetBuffer(), 0, buf, 5, eouts.Length); // rest of the buffer copied stream.Write(buf, 0, buf.Length); // wait for data DateTime startToWaitForData = DateTime.Now; while (!stream.DataAvailable) { if ((DateTime.Now - startToWaitForData).Seconds > Properties.Settings.Default.StreamResponseTimeout) throw new ErlnetException("Response timeout in call to " + module + ":" + function); else Thread.Sleep(0); } // read till empty int readCount = 0; payloadLen = 0; // read payload length (4 byte header) byte[] payloadbuf = new byte[4]; do { readCount += stream.Read(payloadbuf, readCount, payloadbuf.Length - readCount); if (readCount != 4) continue; else payloadLen = ((uint)payloadbuf[3] & 0x000000FF) + (((uint)payloadbuf[2] << 8) & 0x0000FF00) + (((uint)payloadbuf[1] << 16) & 0x00FF0000) + (((uint)payloadbuf[0] << 24) & 0xFF000000); break; } while(true); //Console.WriteLine("RX " + payloadLen + " bytes"); // read the payload of length 'payloadLen' readCount = 0; buf = new byte[payloadLen]; MemoryStream resp = new MemoryStream(); do { readCount += stream.Read(buf, readCount, buf.Length - readCount); if (readCount != payloadLen) continue; else break; } while (true); // rebuild term resp.Write(buf, 0, buf.Length); OtpErlangTuple res = (OtpErlangTuple)OtpErlangObject.decode(new OtpInputStream(resp.GetBuffer())); //Console.WriteLine("RX " + res.elementAt(0).ToString()); return res.elementAt(1); }