Commit 6494f304 authored by Carlos Galindo's avatar Carlos Galindo
Browse files

jinterface 1.13

parent 00db4abf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ Available versions:

| JInterface | Erlang versions supported |
|------------|---------------------------|
| 1.13       | >=25, <25.1               |
| 1.12.2     | >=24.3, <25               |
| 1.12.1     | >=24.1, <24.3             |
| 1.12       | >=24, <24.1               |
+74 −131
Original line number Diff line number Diff line
/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2000-2021. All Rights Reserved.
 * Copyright Ericsson AB 2000-2022. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -79,7 +79,7 @@ public abstract class AbstractConnection extends Thread {
    protected static final int unlinkIdTag = 35;
    protected static final int unlinkIdAckTag = 36;

    // MD5 challenge messsage tags
    // MD5 challenge message tags
    protected static final int ChallengeReply = 'r';
    protected static final int ChallengeAck = 'a';
    protected static final int ChallengeStatus = 's';
@@ -166,18 +166,12 @@ public abstract class AbstractConnection extends Thread {
            throws IOException, OtpAuthException {
        peer = other;
        localNode = self;
        socket = null;
        int port;

        traceLevel = defaultLevel;
        setDaemon(true);

        // now get a connection between the two...
        port = OtpEpmd.lookupPort(peer);
        if (port == 0)
            throw new IOException("No remote node found - cannot connect");

        // now find highest common dist value
        // Find highest common dist value
        if (peer.proto != self.proto || self.distHigh < peer.distLow
                || self.distLow > peer.distHigh) {
            throw new IOException("No common protocol found - cannot connect");
@@ -187,7 +181,21 @@ public abstract class AbstractConnection extends Thread {
        peer.distChoose = peer.distHigh > self.distHigh ? self.distHigh
                : peer.distHigh;

        doConnect(port);
        // Now get a connection between the two nodes
        if (self.transportFactory instanceof OtpGenericTransportFactory) {
            // For alternative distribution protocols using a transport factory
            // extending the OtpGenericTransportFactory class, the notion of
            // socket port is not used so the remote node is not registered
            // with Epmd.
            doGenericConnect();

        } else {
            // Get the listening port of the remote node registered with Epmd
            port = OtpEpmd.lookupPort(peer);
            if (port == 0)
                throw new IOException("No remote node found - cannot connect");
            doPortConnect(port);
        }

        name = peer.node();
        connected = true;
@@ -1025,7 +1033,6 @@ public abstract class AbstractConnection extends Thread {
            sendStatus("ok");
            final int our_challenge = genChallenge();
            sendChallenge(peer.flags, localNode.flags, our_challenge);
            recvComplement(send_name_tag);
            final int her_challenge = recvChallengeReply(our_challenge);
            final byte[] our_digest = genDigest(her_challenge,
                    localNode.cookie());
@@ -1052,27 +1059,51 @@ public abstract class AbstractConnection extends Thread {
        }
    }

    protected void doConnect(final int port) throws IOException,
    protected void doPortConnect(final int port) throws IOException,
            OtpAuthException {
        try {
            socket = peer.createTransport(peer.host(), port);

            if (traceLevel >= handshakeThreshold) {
                System.out.println("-> MD5 CONNECT TO " + peer.host() + ":"
                        + port);
            }
            doConnect();

        } catch (final OtpAuthException ae) {
            close();
            throw ae;
        } catch (final Exception e) {
            close();
            final IOException ioe = new IOException(
                    "Cannot connect to peer node");
            ioe.initCause(e);
            throw ioe;
        }
    }

    protected void doConnect() throws IOException, OtpAuthException {
            final int send_name_tag = sendName(peer.distChoose, localNode.flags,
                                               localNode.creation);
                                               localNode.creation());
            recvStatus();
            final int her_challenge = recvChallenge();
            final byte[] our_digest = genDigest(her_challenge,
                    localNode.cookie());
            final int our_challenge = genChallenge();
            sendComplement(send_name_tag);
            sendChallengeReply(our_challenge, our_digest);
            recvChallengeAck(our_challenge);
            cookieOk = true;
            sendCookie = false;
    }

    protected void doGenericConnect() throws IOException,
            OtpAuthException {
        try {
            socket = peer.createTransport(peer);
            if (traceLevel >= handshakeThreshold) {
                System.out.println("-> MD5 CONNECT TO " + peer.node());
            }
            doConnect();

        } catch (final OtpAuthException ae) {
            close();
            throw ae;
@@ -1149,15 +1180,6 @@ public abstract class AbstractConnection extends Thread {
        final OtpOutputStream obuf = new OtpOutputStream();
        final String str = localNode.node();
        int send_name_tag;
        if (dist == 5) {
            obuf.write2BE(1+2+4 + str.length());
            send_name_tag = 'n';
            obuf.write1(send_name_tag);
            obuf.write2BE(dist);
            obuf.write4BE(aflags);
            obuf.write(str.getBytes());
        }
        else {
        obuf.write2BE(1+8+4+2 + str.length());
        send_name_tag = 'N';
        obuf.write1(send_name_tag);
@@ -1165,63 +1187,29 @@ public abstract class AbstractConnection extends Thread {
        obuf.write4BE(creation);
        obuf.write2BE(str.length());
        obuf.write(str.getBytes());
        }

        obuf.writeToAndFlush(socket.getOutputStream());

        if (traceLevel >= handshakeThreshold) {
            System.out.println("-> " + "HANDSHAKE sendName" + " flags="
                    + aflags + " dist=" + dist + " local=" + localNode);
                    + aflags + " local=" + localNode);
        }
        return send_name_tag;
    }

    protected void sendComplement(final int send_name_tag)
            throws IOException {

        if (send_name_tag == 'n' &&
            (peer.flags & AbstractNode.dFlagHandshake23) != 0) {
            @SuppressWarnings("resource")
            final OtpOutputStream obuf = new OtpOutputStream();
            obuf.write2BE(1+4+4);
            obuf.write1('c');
            final int flagsHigh = (int)(localNode.flags >> 32);
            obuf.write4BE(flagsHigh);
            obuf.write4BE(localNode.creation);

            obuf.writeToAndFlush(socket.getOutputStream());

            if (traceLevel >= handshakeThreshold) {
                System.out.println("-> " + "HANDSHAKE sendComplement" +
                                   " flagsHigh=" + flagsHigh +
                                   " creation=" + localNode.creation);
            }
        }
    }

    protected void sendChallenge(final long her_flags, final long our_flags,
                                 final int challenge) throws IOException {

        @SuppressWarnings("resource")
        final OtpOutputStream obuf = new OtpOutputStream();
        final String str = localNode.node();
        if ((her_flags & AbstractNode.dFlagHandshake23) == 0) {
            obuf.write2BE(1+2+4+4 + str.length());
            obuf.write1('n');
            obuf.write2BE(5);
            obuf.write4BE(our_flags & 0xffffffff);
            obuf.write4BE(challenge);
            obuf.write(str.getBytes());
        }
        else {
        obuf.write2BE(1+8+4+4+2 + str.length());
        obuf.write1('N');
        obuf.write8BE(our_flags);
        obuf.write4BE(challenge);
            obuf.write4BE(localNode.creation);
        obuf.write4BE(localNode.creation());
        obuf.write2BE(str.length());
        obuf.write(str.getBytes());
        }

        obuf.writeToAndFlush(socket.getOutputStream());

@@ -1259,21 +1247,15 @@ public abstract class AbstractConnection extends Thread {
            final int len = tmpbuf.length;
            send_name_tag = ibuf.read1();
            switch (send_name_tag) {
            case 'n':
                apeer.distLow = apeer.distHigh = ibuf.read2BE();
                if (apeer.distLow != 5)
                    throw new IOException("Invalid handshake version");
                apeer.flags = ibuf.read4BE();
                tmpname = new byte[len - 7];
                ibuf.readN(tmpname);
                hisname = OtpErlangString.newString(tmpname);
                break;
            case 'N':
                apeer.distLow = apeer.distHigh = 6;
                apeer.flags = ibuf.read8BE();
                if ((apeer.flags & AbstractNode.dFlagMandatory25Digest) != 0) {
                    apeer.flags |= AbstractNode.mandatoryFlags25;
                }
                if ((apeer.flags & AbstractNode.dFlagHandshake23) == 0)
                    throw new IOException("Missing DFLAG_HANDSHAKE_23");
                apeer.creation = ibuf.read4BE();
                apeer.setCreation(ibuf.read4BE());
                int namelen = ibuf.read2BE();
                tmpname = new byte[namelen];
                ibuf.readN(tmpname);
@@ -1283,21 +1265,16 @@ public abstract class AbstractConnection extends Thread {
                throw new IOException("Unknown remote node type");
            }

            if ((apeer.flags & AbstractNode.dFlagExtendedReferences) == 0) {
                throw new IOException(
                        "Handshake failed - peer cannot handle extended references");
            }

            if ((apeer.flags & AbstractNode.dFlagExtendedPidsPorts) == 0) {
            if ((apeer.flags & AbstractNode.mandatoryFlags) != AbstractNode.mandatoryFlags) {
                throw new IOException(
                        "Handshake failed - peer cannot handle extended pids and ports");
                        "Handshake failed - peer cannot handle all mandatory capabilities");
            }

        } catch (final OtpErlangDecodeException e) {
            throw new IOException("Handshake failed - not enough data");
        }

        final int i = hisname.indexOf('@', 0);
        final int i = hisname.indexOf('@');
        apeer.node = hisname;
        apeer.alive = hisname.substring(0, i);
        apeer.host = hisname.substring(i + 1, hisname.length());
@@ -1319,23 +1296,16 @@ public abstract class AbstractConnection extends Thread {
            final OtpInputStream ibuf = new OtpInputStream(buf, 0);
            int namelen;
            switch (ibuf.read1()) {
            case 'n':
                if (peer.distChoose != 5)
                    throw new IOException("Old challenge wrong version");
                peer.distLow = peer.distHigh = ibuf.read2BE();
                peer.flags = ibuf.read4BE();
                if ((peer.flags & AbstractNode.dFlagHandshake23) != 0)
                    throw new IOException("Old challenge unexpected DFLAG_HANDHAKE_23");
                challenge = ibuf.read4BE();
                namelen = buf.length - (1+2+4+4);
                break;
            case 'N':
                peer.distLow = peer.distHigh = peer.distChoose = 6;
                peer.flags = ibuf.read8BE();
                if ((peer.flags & AbstractNode.dFlagMandatory25Digest) != 0) {
                    peer.flags |= AbstractNode.mandatoryFlags25;
                }
                if ((peer.flags & AbstractNode.dFlagHandshake23) == 0)
                    throw new IOException("New challenge missing DFLAG_HANDHAKE_23");
                challenge = ibuf.read4BE();
                peer.creation = ibuf.read4BE();
                peer.setCreation(ibuf.read4BE());
                namelen = ibuf.read2BE();
                break;
            default:
@@ -1348,15 +1318,9 @@ public abstract class AbstractConnection extends Thread {
                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) {
            if ((peer.flags & AbstractNode.mandatoryFlags) != AbstractNode.mandatoryFlags) {
                throw new IOException(
                        "Handshake failed - peer cannot handle extended pids and ports");
                        "Handshake failed - peer cannot handle all mandatory capabilities");
            }

        } catch (final OtpErlangDecodeException e) {
@@ -1372,27 +1336,6 @@ public abstract class AbstractConnection extends Thread {
        return challenge;
    }

    protected void recvComplement(int send_name_tag) throws IOException {

        if (send_name_tag == 'n' &&
            (peer.flags & AbstractNode.dFlagHandshake23) != 0) {
            try {
                final byte[] tmpbuf = read2BytePackage();
                @SuppressWarnings("resource")
                final OtpInputStream ibuf = new OtpInputStream(tmpbuf, 0);
                if (ibuf.read1() != 'c')
                    throw new IOException("Not a complement tag");

                final long flagsHigh = ibuf.read4BE();
                peer.flags |= flagsHigh << 32;
                peer.creation = ibuf.read4BE();

            } catch (final OtpErlangDecodeException e) {
                throw new IOException("Handshake failed - not enough data");
            }
        }
    }

    protected void sendChallengeReply(final int challenge, final byte[] digest)
            throws IOException {

+73 −12
Original line number Diff line number Diff line
/*
 * %CopyrightBegin%
 *
 * Copyright Ericsson AB 2000-2021. All Rights Reserved.
 * Copyright Ericsson AB 2000-2022. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
@@ -95,21 +95,35 @@ public class AbstractNode implements OtpTransportFactory {
    static final int dFlagBigCreation = 0x40000;
    static final int dFlagHandshake23 = 0x1000000;
    static final int dFlagUnlinkId = 0x2000000;
    static final int dFlagMandatory25Digest = 0x4000000;
    static final long dFlagV4PidsRefs = 0x4L << 32;

    /* Mandatory flags in OTP 25. */
    static final long mandatoryFlags25 = dFlagExtendedReferences
        | dFlagFunTags
        | dFlagExtendedPidsPorts
        | dFlagUtf8Atoms
        | dflagNewFunTags
        | dFlagBigCreation
        | dFlagNewFloats
        | dFlagMapTag
        | dFlagExportPtrTag
        | dFlagBitBinaries
        | dFlagHandshake23;

    /* Mandatory flags for distribution. Keep them in sync with
       DFLAG_DIST_MANDATORY in erts/emulator/beam/dist.h. */
    static final long mandatoryFlags = mandatoryFlags25;

    int ntype = NTYPE_R6;
    int proto = 0; // tcp/ip
    int distHigh = 6;
    int distLow = 5; // Cannot talk to nodes before R6
    int creation = 0;
    long flags = dFlagExtendedReferences | dFlagExtendedPidsPorts
            | dFlagBitBinaries | dFlagNewFloats | dFlagFunTags
            | dflagNewFunTags | dFlagUtf8Atoms | dFlagMapTag
            | dFlagExportPtrTag
	    | dFlagBigCreation
            | dFlagHandshake23
    int distLow = 6; // Cannot talk to nodes before OTP 23
    private int creation = 0x710000;
    long flags = mandatoryFlags
        | dFlagUnlinkId
            | dFlagV4PidsRefs;
        | dFlagV4PidsRefs
        | dFlagMandatory25Digest;

    /* initialize hostname and default cookie */
    static {
@@ -190,7 +204,7 @@ public class AbstractNode implements OtpTransportFactory {
        this.cookie = cookie;
        this.transportFactory = transportFactory;

        final int i = name.indexOf('@', 0);
        final int i = name.indexOf('@');
        if (i < 0) {
            alive = name;
            host = localHost;
@@ -271,6 +285,13 @@ public class AbstractNode implements OtpTransportFactory {
        return creation;
    }

    void setCreation(int cr) throws OtpErlangDecodeException {
        if (cr == 0) {
            throw new OtpErlangDecodeException("Node creation 0 not allowed");
        }
        this.creation = cr;
    }

    /**
     * Set the authorization cookie used by this node.
     *
@@ -311,4 +332,44 @@ public class AbstractNode implements OtpTransportFactory {
            throws IOException {
        return transportFactory.createServerTransport(port);
    }

    /**
     * Create a client-side transport for alternative distribution protocols
     * using a transport factory extending the OtpGenericTransportFactory
     * abstract class. Connect it to the specified server.
     *
     * @param peer
     *            the peer identifying the server to connect to
     *
     */
    public OtpTransport createTransport(final OtpPeer peer)
            throws IOException {
        if (transportFactory instanceof OtpGenericTransportFactory) {
            return ((OtpGenericTransportFactory) transportFactory)
                .createTransport(peer);
        }
        throw new IOException("Method createTransport(OtpPeer) " +
                              "applicable only for Nodes with a transport " +
                              "factory instance of OtpGenericTransportFactory");
    }

    /**
     * Create a server-side transport for alternative distribution protocols
     * using a transport factory extending the OtpGenericTransportFactory
     * abstract class.
     *
     * @param node
     *            the local node identifying the transport to create server-side
     *
     */
    public OtpServerTransport createServerTransport(final OtpLocalNode node)
            throws IOException {
        if (transportFactory instanceof OtpGenericTransportFactory) {
            return ((OtpGenericTransportFactory) transportFactory)
                .createServerTransport(node);
        }
        throw new IOException("Method createServerTransport(OtpLocalNode) " +
                              "applicable only for Nodes with a transport " +
                              "factory instance of OtpGenericTransportFactory");
    }
}
+3 −3
Original line number Diff line number Diff line
@@ -38,7 +38,7 @@ import java.io.IOException;
 *
 * <p>
 * If an exception occurs in any of the methods in this class, the connection
 * will be closed and must be explicitely reopened in order to resume
 * will be closed and must be explicitly reopened in order to resume
 * communication with the peer.
 *
 * <p>
@@ -317,7 +317,7 @@ public class OtpConnection extends AbstractConnection {
    }

    /**
     * Receive a messge complete with sender and recipient information.
     * Receive a message complete with sender and recipient information.
     *
     * @return an {@link OtpMsg OtpMsg} containing the header information about
     *         the sender and recipient, as well as the actual message contents.
@@ -352,7 +352,7 @@ public class OtpConnection extends AbstractConnection {
    }

    /**
     * Receive a messge complete with sender and recipient information. This
     * Receive a message complete with sender and recipient information. This
     * method blocks at most for the specified time.
     *
     * @param timeout
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ public class OtpCookedConnection extends AbstractConnection {
    }

    /*
     * this one called explicitely by user code => use exit2
     * this one called explicitly by user code => use exit2
     */
    void exit2(final OtpErlangPid from, final OtpErlangPid to,
            final OtpErlangObject reason) {
Loading