/* * <p> Deserialize and return a new copy of the message contained in * this OtpMsg. </p> * * <p> The first time this method is called the actual payload is * deserialized and the Erlang term is created. Calling this method * subsequent times will not cuase the message to be deserialized * additional times, instead the same Erlang term object will be * returned. </p> * * @return an Erlang term. * * @exception DecodeException if the byte stream could not be deserialized. * **/ public Erlang.Object getMsg() { if (payload == null) { payload = paybuf.read_any(); } return(payload); }
public virtual void Start() { if (!connected) { deliver(new System.IO.IOException("Not connected")); return ; } byte[] lbuf = new byte[4]; OtpInputStream ibuf; Erlang.Object traceobj; int len; byte[] tock = new byte[]{0, 0, 0, 0}; try { while (!done) { // 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! do { // read 4 bytes - get length of incoming packet // socket.getInputStream().read(lbuf); int n; if ((n = readSock(socket, lbuf)) < lbuf.Length) throw new System.Exception("Read " + n + " out of " + lbuf.Length + " bytes!"); ibuf = new OtpInputStream(lbuf); len = ibuf.read4BE(); // received tick? send tock! if (len == 0) lock(this) { System.Byte[] temp_bytearray; temp_bytearray = tock; if (socket != null) ((System.IO.Stream) socket.GetStream()).Write(temp_bytearray, 0, temp_bytearray.Length); } } while (len == 0); // tick_loop // got a real message (maybe) - read len bytes byte[] tmpbuf = new byte[len]; // i = socket.getInputStream().read(tmpbuf); int m = readSock(socket, tmpbuf); if (m < len) throw new System.Exception("Read " + m + " out of " + len + " bytes!"); ibuf = new OtpInputStream(tmpbuf); if (ibuf.read1() != passThrough) { goto receive_loop_brk; } // got a real message (really) Erlang.Atom reason = null; Erlang.Atom cookie = null; Erlang.Object tmp = null; Erlang.Tuple head = null; Erlang.Atom toName; Erlang.Pid to; Erlang.Pid from; Erlang.Ref eref; // decode the header tmp = ibuf.read_any(); if (!(tmp is Erlang.Tuple)) { goto receive_loop_brk; } head = (Erlang.Tuple) tmp; if (!(head.elementAt(0) is Erlang.Long)) { goto receive_loop_brk; } // lets see what kind of message this is OtpMsg.Tag tag = (OtpMsg.Tag)((Erlang.Long)(head.elementAt(0))).longValue(); switch (tag) { case OtpMsg.Tag.sendTag: case OtpMsg.Tag.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 Erlang.Atom)) { goto receive_loop_brk; } cookie = (Erlang.Atom) head.elementAt(1); if (sendCookie) { if (!cookie.atomValue().Equals(auth_cookie)) { cookieError(self, cookie); } } else { if (!cookie.atomValue().Equals("")) { cookieError(self, cookie); } } cookieOk = true; } if (traceLevel >= OtpTrace.Type.sendThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); /*show received payload too */ long mark = ibuf.Position; traceobj = ibuf.read_any(); if (traceobj != null) OtpTrace.TraceEvent(" " + traceobj.ToString()); else OtpTrace.TraceEvent(" (null)"); ibuf.Seek(mark, System.IO.SeekOrigin.Begin); } to = (Erlang.Pid) (head.elementAt(2)); deliver(new OtpMsg(to, ibuf)); break; case OtpMsg.Tag.regSendTag: case OtpMsg.Tag.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 Erlang.Atom)) { goto receive_loop_brk; } cookie = (Erlang.Atom) head.elementAt(2); if (sendCookie) { if (!cookie.atomValue().Equals(auth_cookie)) { cookieError(self, cookie); } } else { if (!cookie.atomValue().Equals("")) { cookieError(self, cookie); } } cookieOk = true; } if (traceLevel >= OtpTrace.Type.sendThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); /*show received payload too */ long mark = ibuf.Position; traceobj = ibuf.read_any(); if (traceobj != null) OtpTrace.TraceEvent(" " + traceobj.ToString()); else OtpTrace.TraceEvent(" (null)"); ibuf.Seek(mark, System.IO.SeekOrigin.Begin); } from = (Erlang.Pid) (head.elementAt(1)); toName = (Erlang.Atom) (head.elementAt(3)); deliver(new OtpMsg(from, toName.atomValue(), ibuf)); break; case OtpMsg.Tag.exitTag: case OtpMsg.Tag.exit2Tag: // { EXIT2, FromPid, ToPid, Reason } if (!(head.elementAt(3) is Erlang.Atom)) { goto receive_loop_brk; } if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } from = (Erlang.Pid) (head.elementAt(1)); to = (Erlang.Pid) (head.elementAt(2)); reason = (Erlang.Atom) head.elementAt(3); deliver(new OtpMsg(tag, from, to, reason)); break; case OtpMsg.Tag.exitTTTag: case OtpMsg.Tag.exit2TTTag: // { EXIT2, FromPid, ToPid, TraceToken, Reason } // as above, but bifferent element number if (!(head.elementAt(4) is Erlang.Atom)) { goto receive_loop_brk; } if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } from = (Erlang.Pid) (head.elementAt(1)); to = (Erlang.Pid) (head.elementAt(2)); reason = (Erlang.Atom) head.elementAt(4); deliver(new OtpMsg(tag, from, to, reason)); break; case OtpMsg.Tag.linkTag: case OtpMsg.Tag.unlinkTag: // { UNLINK, FromPid, ToPid} if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } from = (Erlang.Pid) (head.elementAt(1)); to = (Erlang.Pid) (head.elementAt(2)); deliver(new OtpMsg(tag, from, to)); break; // absolutely no idea what to do with these, so we ignore them... case OtpMsg.Tag.groupLeaderTag: case OtpMsg.Tag.nodeLinkTag: // { NODELINK } // (just show trace) if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } break; case OtpMsg.Tag.monitorPTag: // {MONITOR_P, FromPid, ToProc, Ref} case OtpMsg.Tag.demonitorPTag: // {DEMONITOR_P, FromPid, ToProc, Ref} if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } from = (Erlang.Pid)(head.elementAt(1)); to = (Erlang.Pid)(head.elementAt(2)); eref = (Erlang.Ref)(head.elementAt(3)); deliver(new OtpMsg(tag, from, to, eref)); break; case OtpMsg.Tag.monitorPexitTag: // {MONITOR_P_EXIT, FromPid, ToProc, Ref, Reason} if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- " + headerType(head) + " " + head.ToString()); } from = (Erlang.Pid)(head.elementAt(1)); to = (Erlang.Pid)(head.elementAt(2)); eref = (Erlang.Ref)(head.elementAt(3)); deliver(new OtpMsg(tag, from, to, eref, reason)); break; default: // garbage? if (traceLevel >= OtpTrace.Type.ctrlThreshold) { OtpTrace.TraceEvent("<- Unknown tag " + headerType(head) + " " + head.ToString()); } goto receive_loop_brk; } } receive_loop_brk: ; // end receive_loop // this section reachable only with break // we have received garbage from peer deliver(new Erlang.Exit("Remote is sending garbage")); } catch (OtpAuthException e) { deliver(e); } catch (Erlang.Exception e) { OtpTrace.TraceEvent(e.ToString()); deliver(new Erlang.Exit("Remote is sending garbage: " + e.ToString())); } catch (System.Exception e) { deliver(new Erlang.Exit("Remote has closed connection: " + e.ToString())); } finally { close(); OtpTrace.TraceEvent("exit connection "+System.Threading.Thread.CurrentThread.Name); } }