protected byte[] read2BytePackage() { byte[] lbuf = new byte[2]; byte[] tmpbuf; readSock(socket, lbuf); OtpInputStream ibuf = new OtpInputStream(lbuf, 0); int len = ibuf.read2BE(); tmpbuf = new byte[len]; readSock(socket, tmpbuf); return tmpbuf; }
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; }
/* * this function will get an exception if it tries to talk to an r3 epmd, or * if something else happens that it cannot forsee. In both cases we return * an exception (and the caller should try again, using the r3 protocol). If * we manage to successfully communicate with an r4 epmd, we return either * the socket, or null, depending on the result. */ private static TcpClient r4_publish(OtpLocalNode node) { TcpClient s = null; try { OtpOutputStream obuf = new OtpOutputStream(); s = new TcpClient(node.Host, EpmdPort.get()); obuf.write2BE(node.Alive.Length + 13); obuf.write1(publish4req); obuf.write2BE(node.Port); obuf.write1(node.Type); obuf.write1(node.Proto); obuf.write2BE(node.DistHigh); obuf.write2BE(node.DistLow); obuf.write2BE(node.Alive.Length); obuf.writeN(Encoding.GetEncoding("iso-8859-1").GetBytes(node.Alive)); obuf.write2BE(0); // No extra // send request obuf.WriteTo(s.GetStream()); if (traceLevel >= traceThreshold) { log.Debug("-> PUBLISH (r4) " + node + " port=" + node.Port); } // get reply byte[] tmpbuf = new byte[100]; int n = s.GetStream().Read(tmpbuf, 0, tmpbuf.Length); if (n < 0) { // this was an r3 node => not a failure (yet) if (s != null) { s.Close(); } throw new IOException("Nameserver not responding on " + node.Host + " when publishing " + node.Alive); } OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); int response = ibuf.read1(); if (response == publish4resp) { int result = ibuf.read1(); if (result == 0) { node.Creation = ibuf.read2BE(); if (traceLevel >= traceThreshold) { log.Debug("<- OK"); } return s; // success } } } catch (SocketException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host); } catch (IOException) { // epmd closed the connection = fail if (s != null) { s.Close(); } if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when publishing " + node.Alive); } catch (OtpErlangDecodeException) { if (s != null) { s.Close(); } if (traceLevel >= traceThreshold) { log.Debug("<- (invalid response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when publishing " + node.Alive); } if (s != null) { s.Close(); } return null; }
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); } }
private static int r4_lookupPort(AbstractNode node) { int port = 0; try { OtpOutputStream obuf = new OtpOutputStream(); using (TcpClient s = new TcpClient(node.Host, EpmdPort.get())) { // build and send epmd request // length[2], tag[1], alivename[n] (length = n+1) obuf.write2BE(node.Alive.Length + 1); obuf.write1(port4req); obuf.writeN(Encoding.GetEncoding("iso-8859-1").GetBytes(node.Alive)); // send request obuf.WriteTo(s.GetStream()); if (traceLevel >= traceThreshold) { log.Debug("-> LOOKUP (r4) " + node); } // receive and decode reply // resptag[1], result[1], port[2], ntype[1], proto[1], // disthigh[2], distlow[2], nlen[2], alivename[n], // elen[2], edata[m] byte[] tmpbuf = new byte[100]; int n = s.GetStream().Read(tmpbuf, 0, tmpbuf.Length); if (n < 0) { // this was an r3 node => not a failure (yet) throw new IOException("Nameserver not responding on " + node.Host + " when looking up " + node.Alive); } OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); int response = ibuf.read1(); if (response == port4resp) { int result = ibuf.read1(); if (result == 0) { port = ibuf.read2BE(); node.Type = ibuf.read1(); node.Proto = ibuf.read1(); node.DistHigh = ibuf.read2BE(); node.DistLow = ibuf.read2BE(); // ignore rest of fields } } } } catch (SocketException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host); } catch (IOException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when looking up " + node.Alive); } catch (OtpErlangDecodeException) { if (traceLevel >= traceThreshold) { log.Debug("<- (invalid response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when looking up " + node.Alive); } if (traceLevel >= traceThreshold) { if (port == 0) { log.Debug("<- NOT FOUND"); } else { log.Debug("<- PORT " + port); } } return port; }
private static TcpClient r3_publish(OtpLocalNode node) { TcpClient s; try { OtpOutputStream obuf = new OtpOutputStream(); s = new TcpClient(node.Host, EpmdPort.get()); obuf.write2BE(node.Alive.Length + 3); obuf.write1(publish3req); obuf.write2BE(node.Port); obuf.writeN(Encoding.GetEncoding("iso-8859-1").GetBytes(node.Alive)); // send request obuf.WriteTo(s.GetStream()); if (traceLevel >= traceThreshold) { log.Debug("-> PUBLISH (r3) " + node + " port=" + node.Port); } byte[] tmpbuf = new byte[100]; int n = s.GetStream().Read(tmpbuf, 0, tmpbuf.Length); if (n < 0) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } return null; } OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); if (ibuf.read1() == publish3ok) { node.Creation = ibuf.read2BE(); if (traceLevel >= traceThreshold) { log.Debug("<- OK"); } return s; // success - don't close socket } } catch (SocketException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host); } catch (IOException) { // epmd closed the connection = fail if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when publishing " + node.Alive); } catch (OtpErlangDecodeException) { if (traceLevel >= traceThreshold) { log.Debug("<- (invalid response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when publishing " + node.Alive); } return null; // failure }
private static int r3_lookupPort(AbstractNode node) { int port = 0; try { OtpOutputStream obuf = new OtpOutputStream(); using (TcpClient s = new TcpClient(node.Host, EpmdPort.get())) { // build and send epmd request // length[2], tag[1], alivename[n] (length = n+1) obuf.write2BE(node.Alive.Length + 1); obuf.write1(port3req); obuf.writeN(Encoding.GetEncoding("iso-8859-1").GetBytes(node.Alive)); // send request obuf.WriteTo(s.GetStream()); if (traceLevel >= traceThreshold) { log.Debug("-> LOOKUP (r3) " + node); } // receive and decode reply byte[] tmpbuf = new byte[100]; s.GetStream().Read(tmpbuf, 0, tmpbuf.Length); OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0); port = ibuf.read2BE(); } } catch (SocketException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host); } catch (IOException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when looking up " + node.Alive); } catch (OtpErlangDecodeException) { if (traceLevel >= traceThreshold) { log.Debug("<- (invalid response)"); } throw new IOException("Nameserver not responding on " + node.Host + " when looking up " + node.Alive); } if (traceLevel >= traceThreshold) { if (port == 0) { log.Debug("<- NOT FOUND"); } else { log.Debug("<- PORT " + port); } } return port; }
private void r4_publish(TcpClient s, OtpInputStream ibuf) { try { int port = ibuf.read2BE(); int type = ibuf.read1(); int proto = ibuf.read1(); int distHigh = ibuf.read2BE(); int distLow = ibuf.read2BE(); int len = ibuf.read2BE(); byte[] alive = new byte[len]; ibuf.readN(alive); int elen = ibuf.read2BE(); byte[] extra = new byte[elen]; ibuf.readN(extra); String name = OtpErlangString.newString(alive); OtpPublishedNode node = new OtpPublishedNode(name); node.Type = type; node.DistHigh = distHigh; node.DistLow = distLow; node.Proto = proto; node.Port = port; if (traceLevel >= traceThreshold) { log.Debug("<- PUBLISH (r4) " + name + " port=" + node.Port); } OtpOutputStream obuf = new OtpOutputStream(); obuf.write1(publish4resp); obuf.write1(0); obuf.write2BE(epmd.Creation); obuf.WriteTo(s.GetStream()); lock (portmap) { portmap.Add(name, node); } publishedPort.Add(name); } catch (IOException) { if (traceLevel >= traceThreshold) { log.Debug("<- (no response)"); } throw new IOException("Request not responding"); } return; }
public override void run() { byte[] lbuf = new byte[2]; OtpInputStream ibuf; int len; try { while (!done) { readSock(sock, lbuf); ibuf = new OtpInputStream(lbuf, 0); len = ibuf.read2BE(); byte[] tmpbuf = new byte[len]; readSock(sock, tmpbuf); ibuf = new OtpInputStream(tmpbuf, 0); int request = ibuf.read1(); switch (request) { case publish4req: r4_publish(sock, ibuf); break; case port4req: r4_port(sock, ibuf); done = true; break; case names4req: r4_names(sock, ibuf); done = true; break; case stopReq: break; default: log.InfoFormat("[OtpEpmd] Unknown request (request={0}, length={1}) from {2}", request, len, sock.Client.RemoteEndPoint); break; } } } catch (IOException) { } finally { quit(); } }