protected int recvChallenge() { int challenge; try { byte[] buf = read2BytePackage(); OtpInputStream ibuf = new OtpInputStream(buf, 0); peer.Type = ibuf.read1(); if (peer.Type != AbstractNode.NTYPE_R6) { throw new IOException("Unexpected peer type"); } peer.DistLow = peer.DistHigh = ibuf.read2BE(); peer.Flags = ibuf.read4BE(); challenge = ibuf.read4BE(); byte[] tmpname = new byte[buf.Length - 11]; ibuf.readN(tmpname); String hisname = OtpErlangString.newString(tmpname); if (!hisname.Equals(peer.Node)) { throw new IOException("Handshake failed - peer has wrong name: " + hisname); } if ((peer.Flags & AbstractNode.dFlagExtendedReferences) == 0) { throw new IOException("Handshake failed - peer cannot handle extended references"); } if ((peer.Flags & AbstractNode.dFlagExtendedPidsPorts) == 0) { throw new IOException("Handshake failed - peer cannot handle extended pids and ports"); } } catch (OtpErlangDecodeException) { throw new IOException("Handshake failed - not enough data"); } if (traceLevel >= handshakeThreshold) { log.Debug("<- " + "HANDSHAKE recvChallenge" + " from=" + peer.Node + " challenge=" + challenge + " local=" + self); } return challenge; }
public override void run() { if (!connected) { deliver(new IOException("Not connected")); return; } byte[] lbuf = new byte[4]; OtpInputStream ibuf; OtpErlangObject traceobj; int len; byte[] tock = { 0, 0, 0, 0 }; try { receive_loop: 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); readSock(socket, lbuf); ibuf = new OtpInputStream(lbuf, flags); len = ibuf.read4BE(); // received tick? send tock! if (len == 0) { lock (this) { socket.GetOutputStream().Write(tock, 0, tock.Length); socket.GetOutputStream().Flush(); } } } while (len == 0); // tick_loop // got a real message (maybe) - read len bytes byte[] tmpbuf = new byte[len]; // i = socket.getInputStream().read(tmpbuf); readSock(socket, tmpbuf); ibuf = new OtpInputStream(tmpbuf, flags); if (ibuf.read1() != passThrough) { goto receive_loop; } // got a real message (really) OtpErlangObject reason = null; OtpErlangAtom cookie = null; OtpErlangObject tmp = null; OtpErlangTuple head = null; OtpErlangAtom toName; OtpErlangPid to; OtpErlangPid from; int tag; // decode the header tmp = ibuf.read_any(); if (!(tmp is OtpErlangTuple)) { goto receive_loop; } head = (OtpErlangTuple)tmp; if (!(head.elementAt(0) is OtpErlangLong)) { goto receive_loop; } // 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)) { goto receive_loop; } cookie = (OtpErlangAtom)head.elementAt(1); if (sendCookie) { if (!cookie.atomValue().Equals(self.Cookie)) { cookieError(self, cookie); } } else { if (!cookie.atomValue().Equals("")) { cookieError(self, cookie); } } cookieOk = true; } if (traceLevel >= sendThreshold) { log.Debug("<- " + headerType(head) + " " + head); /* show received payload too */ ibuf.Mark(0); traceobj = ibuf.read_any(); if (traceobj != null) { log.Debug(" " + traceobj); } else { log.Debug(" (null)"); } 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)) { goto receive_loop; } cookie = (OtpErlangAtom)head.elementAt(2); if (sendCookie) { if (!cookie.atomValue().Equals(self.Cookie)) { cookieError(self, cookie); } } else { if (!cookie.atomValue().Equals("")) { cookieError(self, cookie); } } cookieOk = true; } if (traceLevel >= sendThreshold) { log.Debug("<- " + headerType(head) + " " + head); /* show received payload too */ ibuf.Mark(0); traceobj = ibuf.read_any(); if (traceobj != null) { log.Debug(" " + traceobj); } else { log.Debug(" (null)"); } ibuf.Reset(); } from = (OtpErlangPid)head.elementAt(1); toName = (OtpErlangAtom)head.elementAt(3); deliver(new OtpMsg(from, toName.atomValue(), ibuf)); break; case exitTag: // { EXIT, FromPid, ToPid, Reason } case exit2Tag: // { EXIT2, FromPid, ToPid, Reason } if (head.elementAt(3) == null) { goto receive_loop; } if (traceLevel >= ctrlThreshold) { log.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) { goto receive_loop; } if (traceLevel >= ctrlThreshold) { log.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 >= ctrlThreshold) { log.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} case nodeLinkTag: // { NODELINK } // (just show trace) if (traceLevel >= ctrlThreshold) { log.Debug("<- " + headerType(head) + " " + head); } break; default: // garbage? goto receive_loop; } } // end receive_loop // this section reachable only with break // we have received garbage from peer deliver(new OtpErlangExit("Remote is sending garbage")); } // try catch (OtpAuthException e) { deliver(e); } catch (OtpErlangDecodeException) { deliver(new OtpErlangExit("Remote is sending garbage")); } catch (IOException) { deliver(new OtpErlangExit("Remote has closed connection")); } finally { close(); } }
protected int recvChallengeReply(int our_challenge) { int challenge; byte[] her_digest = new byte[16]; try { byte[] buf = read2BytePackage(); OtpInputStream ibuf = new OtpInputStream(buf, 0); int tag = ibuf.read1(); if (tag != ChallengeReply) { throw new IOException("Handshake protocol error"); } challenge = ibuf.read4BE(); ibuf.readN(her_digest); byte[] our_digest = genDigest(our_challenge, self.Cookie); if (!digests_equals(her_digest, our_digest)) { throw new OtpAuthException("Peer authentication error."); } } catch (OtpErlangDecodeException) { throw new IOException("Handshake failed - not enough data"); } if (traceLevel >= handshakeThreshold) { log.Debug("<- " + "HANDSHAKE recvChallengeReply" + " from=" + peer.Node + " challenge=" + challenge + " digest=" + hex(her_digest) + " local=" + self); } return challenge; }
protected void recvName(OtpPeer peer) { String hisname = ""; try { byte[] tmpbuf = read2BytePackage(); OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); byte[] tmpname; int len = tmpbuf.Length; peer.Type = ibuf.read1(); if (peer.Type != AbstractNode.NTYPE_R6) { throw new IOException("Unknown remote node type"); } peer.DistLow = peer.DistHigh = ibuf.read2BE(); if (peer.DistLow < 5) { throw new IOException("Unknown remote node type"); } peer.Flags = ibuf.read4BE(); tmpname = new byte[len - 7]; ibuf.readN(tmpname); hisname = OtpErlangString.newString(tmpname); // Set the old nodetype parameter to indicate hidden/normal status // When the old handshake is removed, the ntype should also be. if ((peer.Flags & AbstractNode.dFlagPublished) != 0) { peer.Type = AbstractNode.NTYPE_R4_ERLANG; } else { peer.Type = AbstractNode.NTYPE_R4_HIDDEN; } if ((peer.Flags & AbstractNode.dFlagExtendedReferences) == 0) { throw new IOException("Handshake failed - peer cannot handle extended references"); } if ((peer.Flags & AbstractNode.dFlagExtendedPidsPorts) == 0) { throw new IOException("Handshake failed - peer cannot handle extended pids and ports"); } } catch (OtpErlangDecodeException) { throw new IOException("Handshake failed - not enough data"); } int i = hisname.IndexOf('@', 0); peer.Node = hisname; peer.Alive = hisname.Substring(0, i); peer.Host = hisname.Substring(i + 1, hisname.Length - (i + 1)); if (traceLevel >= handshakeThreshold) { log.Debug("<- " + "HANDSHAKE" + " ntype=" + peer.Type + " dist=" + peer.DistHigh + " remote=" + peer); } }
public static String[] lookupNames(IPAddress address) { try { OtpOutputStream obuf = new OtpOutputStream(); using (TcpClient s = new TcpClient(address.ToString(), EpmdPort.get())) { obuf.write2BE(1); obuf.write1(names4req); // send request obuf.WriteTo(s.GetStream()); if (traceLevel >= traceThreshold) { log.Debug("-> NAMES (r4) "); } // get reply byte[] buffer = new byte[256]; MemoryStream ms = new MemoryStream(256); while (true) { int bytesRead = s.GetStream().Read(buffer, 0, buffer.Length); if (bytesRead == -1) { break; } ms.Write(buffer, 0, bytesRead); } byte[] tmpbuf = ms.GetBuffer(); OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); ibuf.read4BE(); // read port int // int port = ibuf.read4BE(); // check if port = epmdPort int n = tmpbuf.Length; byte[] buf = new byte[n - 4]; Array.Copy(tmpbuf, 4, buf, 0, n - 4); String all = OtpErlangString.newString(buf); return all.Split(new char[] { '\n' }); } } catch (SocketException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + address); } catch (IOException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding when requesting names"); } catch (OtpErlangDecodeException) { if (traceLevel >= traceThreshold) { log.Debug("<- (invalid response)"); } throw new IOException("Nameserver not responding when requesting names"); } }