예제 #1
0
        public OtpErlangMap(OtpInputStream buf)
        {
            int arity = buf.ReadMapHead();

            if (arity == 0)
            {
                return;
            }
            for (int i = 0; i < arity; i++)
            {
                IOtpErlangObject key   = buf.ReadAny();
                IOtpErlangObject value = buf.ReadAny();
                Add(key, value);
            }
        }
예제 #2
0
        /**
         * Read a compressed term from the stream
         */
        public IOtpErlangObject ReadCompressed()
        {
            int tag = Read1SkipVersion();

            if (tag != OtpExternal.compressedTag)
            {
                throw new OtpDecodeException("Wrong tag encountered, expected " + OtpExternal.compressedTag + ", got " + tag);
            }

            int size = Read4BE();

            byte[]        buf = new byte[size];
            DeflateStream dos = new DeflateStream(this, CompressionMode.Decompress, true);

            try
            {
                int dsize = dos.Read(buf, 0, size);
                if (dsize != size)
                {
                    throw new OtpDecodeException("Decompression gave " + dsize + " bytes, not " + size);
                }
            }
            catch (OtpDecodeException)
            {
                throw;
            }
            catch (InvalidDataException e)
            {
                throw new OtpDecodeException("Failed to decode compressed", e);
            }

            OtpInputStream ois = new OtpInputStream(buf)
            {
                Flags = Flags
            };

            return(ois.ReadAny());
        }
예제 #3
0
        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();
            }
        }