/// <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); }