Search in sources :

Example 31 with SocketChannel

use of java.nio.channels.SocketChannel in project voltdb by VoltDB.

the class SocketJoiner method processSSC.

/*
     * Pull all ready to accept sockets
     */
private void processSSC(ServerSocketChannel ssc) throws Exception {
    SocketChannel sc = null;
    while ((sc = ssc.accept()) != null) {
        try {
            sc.socket().setTcpNoDelay(true);
            sc.socket().setPerformancePreferences(0, 2, 1);
            final String remoteAddress = sc.socket().getRemoteSocketAddress().toString();
            /*
                 * Send the current time over the new connection for a clock skew check
                 */
            ByteBuffer currentTimeBuf = ByteBuffer.allocate(8);
            currentTimeBuf.putLong(System.currentTimeMillis());
            currentTimeBuf.flip();
            while (currentTimeBuf.hasRemaining()) {
                sc.write(currentTimeBuf);
            }
            /*
                 * Read a length prefixed JSON message
                 */
            JSONObject jsObj = readJSONObjFromWire(sc, remoteAddress);
            LOG.info(jsObj.toString(2));
            // get the connecting node's version string
            String remoteBuildString = jsObj.getString(VERSION_STRING);
            VersionChecker versionChecker = m_acceptor.getVersionChecker();
            // send a response with version/build data of this node
            JSONObject returnJs = new JSONObject();
            returnJs.put(VERSION_STRING, versionChecker.getVersionString());
            returnJs.put(BUILD_STRING, versionChecker.getBuildString());
            returnJs.put(VERSION_COMPATIBLE, versionChecker.isCompatibleVersionString(remoteBuildString));
            // inject acceptor fields
            m_acceptor.decorate(returnJs, Optional.of(m_paused.get()));
            byte[] jsBytes = returnJs.toString(4).getBytes(StandardCharsets.UTF_8);
            ByteBuffer returnJsBuffer = ByteBuffer.allocate(4 + jsBytes.length);
            returnJsBuffer.putInt(jsBytes.length);
            returnJsBuffer.put(jsBytes).flip();
            while (returnJsBuffer.hasRemaining()) {
                sc.write(returnJsBuffer);
            }
            /*
                 * The type of connection, it can be a new request to join the cluster
                 * or a node that is connecting to the rest of the cluster and publishing its
                 * host id or a request to add a new connection to the request node.
                 */
            String type = jsObj.getString(TYPE);
            /*
                 * The new connection may specify the address it is listening on,
                 * or it can be derived from the connection itself
                 */
            InetSocketAddress listeningAddress;
            if (jsObj.has(ADDRESS)) {
                listeningAddress = new InetSocketAddress(InetAddress.getByName(jsObj.getString(ADDRESS)), jsObj.getInt(PORT));
            } else {
                listeningAddress = new InetSocketAddress(((InetSocketAddress) sc.socket().getRemoteSocketAddress()).getAddress().getHostAddress(), jsObj.getInt(PORT));
            }
            hostLog.info("Received request type " + type);
            if (type.equals(ConnectionType.REQUEST_HOSTID.name())) {
                m_joinHandler.requestJoin(sc, listeningAddress, jsObj);
            } else if (type.equals(ConnectionType.PUBLISH_HOSTID.name())) {
                m_joinHandler.notifyOfJoin(jsObj.getInt(HOST_ID), sc, listeningAddress, jsObj);
            } else if (type.equals(ConnectionType.REQUEST_CONNECTION.name())) {
                m_joinHandler.notifyOfConnection(jsObj.getInt(HOST_ID), sc, listeningAddress);
            } else {
                throw new RuntimeException("Unexpected message type " + type + " from " + remoteAddress);
            }
        } catch (Exception ex) {
            // do not leak sockets when exception happens
            try {
                sc.close();
            } catch (IOException ioex) {
            // ignore the close exception on purpose
            }
            // re-throw the exception, it will be handled by the caller
            throw ex;
        }
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) ServerSocketChannel(java.nio.channels.ServerSocketChannel) VersionChecker(org.voltcore.utils.VersionChecker) JSONObject(org.json_voltpatches.JSONObject) InetSocketAddress(java.net.InetSocketAddress) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) IOException(java.io.IOException) EOFException(java.io.EOFException) JSONException(org.json_voltpatches.JSONException) ClosedByInterruptException(java.nio.channels.ClosedByInterruptException) ClosedSelectorException(java.nio.channels.ClosedSelectorException)

Example 32 with SocketChannel

use of java.nio.channels.SocketChannel in project voltdb by VoltDB.

the class HostMessenger method createAuxiliaryConnections.

// Create connections to nodes within the same partition group
public void createAuxiliaryConnections(Set<Integer> peers, int secondaryConnections) {
    for (int hostId : peers) {
        for (int ii = 0; ii < secondaryConnections; ii++) {
            Iterator<ForeignHost> it = m_foreignHosts.get(hostId).iterator();
            if (it.hasNext()) {
                ForeignHost fh = it.next();
                try {
                    SocketChannel socket = m_joiner.requestForConnection(fh.m_listeningAddress);
                    // Auxiliary connection never time out
                    ForeignHost fhost = new ForeignHost(this, hostId, socket, Integer.MAX_VALUE, fh.m_listeningAddress, new PicoNetwork(socket));
                    putForeignHost(hostId, fhost);
                    fhost.enableRead(VERBOTEN_THREADS);
                } catch (IOException | JSONException e) {
                    m_hostLog.error("Failed to connect to peer nodes.", e);
                    throw new RuntimeException("Failed to establish socket connection with " + fh.m_listeningAddress.getAddress().getHostAddress(), e);
                }
            }
        }
    }
    m_hasAllSecondaryConnectionCreated = true;
}
Also used : SocketChannel(java.nio.channels.SocketChannel) PicoNetwork(org.voltcore.network.PicoNetwork) JSONException(org.json_voltpatches.JSONException) IOException(java.io.IOException)

Example 33 with SocketChannel

use of java.nio.channels.SocketChannel in project voltdb by VoltDB.

the class TestAdminMode method testBacklogAndPolling.

// Somewhat hacky test of the LIVECLIENTS @Statistics selector
public void testBacklogAndPolling() throws Exception {
    if (isValgrind()) {
        // also, this test isn't really about c++ code
        return;
    }
    ClientConfig config = new ClientConfig();
    config.setProcedureCallTimeout(600000);
    final Client adminclient = ClientFactory.createClient(config);
    if (((ClientImpl) adminclient).getSSLContext() != null) {
        return;
    }
    SocketChannel channel = getClientChannel();
    try {
        adminclient.createConnection("localhost", 32323);
        VoltTable[] results = adminclient.callProcedure("@Statistics", "LIVECLIENTS", 0).getResults();
        System.out.println(results[0].toString());
        results = adminclient.callProcedure("@Resume").getResults();
        System.out.println(results[0].toString());
        // queue up a bunch of invocations but don't read the responses
        for (int i = 0; i < 10000; i++) {
            ConnectionUtil.sendInvocation(channel, "InsertA", i, 1000 + i);
            ConnectionUtil.sendInvocation(channel, "SelectA");
        }
        results = adminclient.callProcedure("@Statistics", "LIVECLIENTS", 0).getResults();
        System.out.println(results[0].toString());
        assertEquals(2, results[0].getRowCount());
        results[0].advanceRow();
        // After queuing 10000 invocations and not reading any,
        // we should have some combination of outstanding work lingering around
        assertTrue((results[0].getLong("OUTSTANDING_RESPONSE_MESSAGES") + results[0].getLong("OUTSTANDING_TRANSACTIONS")) > 0);
        Thread.sleep(6000);
        // ENG-998 - get rid of the channel.close() here and force
        // Volt to kill the misbehaving connection itself.
        // make sure there's only one connection in the list
        // Check the proper results below
        results = adminclient.callProcedure("@Statistics", "LIVECLIENTS", 0).getResults();
        System.out.println(results[0].toString());
        assertEquals(1, results[0].getRowCount());
        results[0].advanceRow();
        assertEquals(1, results[0].getLong("ADMIN"));
    } finally {
        channel.close();
        adminclient.close();
    }
}
Also used : SocketChannel(java.nio.channels.SocketChannel) ClientConfig(org.voltdb.client.ClientConfig) Client(org.voltdb.client.Client) VoltTable(org.voltdb.VoltTable)

Example 34 with SocketChannel

use of java.nio.channels.SocketChannel in project voltdb by VoltDB.

the class GenerateCPPTestFiles method main.

/**
     * @param args
     */
public static void main(String[] args) throws Exception {
    boolean generateGeoMessages = true;
    String clientDataDirName = ".";
    long clusterStartTime = CLUSTER_START_TIME;
    int clusterRoundTripTime = CLUSTER_ROUND_TRIP_TIME;
    long clientData = CLIENT_DATA;
    int leaderIPAddr = LEADER_IP_ADDR;
    String buildString = BUILD_STRING;
    for (int idx = 0; idx < args.length; idx += 1) {
        if ("--client-dir".equals(args[idx])) {
            idx += 1;
            clientDataDirName = args[idx];
        } else if ("--clusterStartTime".equals(args[idx])) {
            idx += 1;
            clusterStartTime = Long.valueOf(args[idx]);
        } else if ("--clientData".equals(args[idx])) {
            idx += 1;
            clientData = Long.valueOf(args[idx]);
        } else if ("--leaderIPAddr".equals(args[idx])) {
            idx += 1;
            leaderIPAddr = Integer.valueOf(args[idx]);
        } else if ("--clusterRoundTripTime".equals(args[idx])) {
            idx += 1;
            clusterRoundTripTime = Integer.valueOf(args[idx]);
        } else if ("--no-geo-messages".equals(args[idx])) {
            generateGeoMessages = false;
        } else {
            abend("Unknown command line argument \"%s\"\n", args[idx]);
        }
    }
    // Make the client data directory if necessary.
    File clientDataDir = new File(clientDataDirName);
    if (clientDataDir.exists() && !clientDataDir.isDirectory()) {
        if (!clientDataDir.isDirectory()) {
            abend("Client data dir \"%s\" exists but is not a directory.\n", clientDataDirName);
        }
    } else {
        clientDataDir.mkdirs();
    }
    //
    // Capture a HASH_SHA256 style authentication message.  We do this by
    // creating a fake server, then, in a separate thread, creating an ordinary
    // client which connects to the fake server.  We read the authentication
    // request from the client, save it, send a faked authentication response,
    // close the server and join with the created thread.
    //
    ServerSocketChannel ssc = ServerSocketChannel.open();
    ssc.socket().bind(new InetSocketAddress("localhost", FAKE_SERVER_PORT));
    ClientConfig config = new ClientConfig("hello", "world", (ClientStatusListenerExt) null, ClientAuthScheme.HASH_SHA256);
    final org.voltdb.client.Client client = ClientFactory.createClient(config);
    Thread clientThread = new Thread() {

        @Override
        public void run() {
            try {
                client.createConnection("localhost", FAKE_SERVER_PORT);
                client.close();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    clientThread.setDaemon(true);
    clientThread.start();
    SocketChannel sc = ssc.accept();
    sc.socket().setTcpNoDelay(true);
    ByteBuffer authReqSHA256 = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    sc.configureBlocking(true);
    readMessage(authReqSHA256, sc);
    writeDataFile(clientDataDir, "authentication_request_sha256.msg", authReqSHA256);
    writeServerAuthenticationResponse(sc, true);
    ssc.close();
    clientThread.join(0);
    //
    // Now, create a fake server again, and login with the HASH_SHA1 scheme.
    // We save this authentication request as well.  The client in the
    // separate thread then sends some procedure invocation messages.  We
    // save all of these in files and then join with the client thread.
    //
    ssc = ServerSocketChannel.open();
    ssc.socket().bind(new InetSocketAddress("localhost", FAKE_SERVER_PORT));
    config = new ClientConfig("hello", "world", (ClientStatusListenerExt) null, ClientAuthScheme.HASH_SHA1);
    final org.voltdb.client.Client oclient = ClientFactory.createClient(config);
    Thread oclientThread = new Thread() {

        @Override
        public void run() {
            NullCallback ncb = new NullCallback();
            try {
                oclient.createConnection("localhost", FAKE_SERVER_PORT);
                oclient.callProcedure("Insert", "Hello", "World", "English");
                try {
                    oclient.callProcedure("Insert", "Hello", "World", "English");
                } catch (Exception e) {
                }
                oclient.callProcedure("Select", "English");
                //
                // Geo support.
                //
                // Insert a point and a polygon.
                oclient.callProcedure("InsertGeo", 200, GeographyValue.fromWKT(smallPolyTxt), GeographyPointValue.fromWKT(smallPointTxt));
                // Insert two nulls for points and polygons.
                oclient.callProcedure("InsertGeo", 201, null, null);
                // Select one row with a point and a polygon both.
                oclient.callProcedure("SelectGeo", 100);
                // Select another row with a different point and polygon.
                oclient.callProcedure("SelectGeo", 101);
                // Select one row with a null polygon and one non-null point.
                oclient.callProcedure("SelectGeo", 102);
                // Select one row with a non-null polygon and a null point.
                oclient.callProcedure("SelectGeo", 103);
                // Select one row with two nulls.
                oclient.callProcedure("SelectGeo", 104);
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };
    oclientThread.setDaemon(true);
    oclientThread.start();
    sc = ssc.accept();
    sc.socket().setTcpNoDelay(true);
    ByteBuffer authReqSHA1 = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    sc.configureBlocking(true);
    readMessage(authReqSHA1, sc);
    writeDataFile(clientDataDir, "authentication_request.msg", authReqSHA1);
    writeServerAuthenticationResponse(sc, true);
    //
    // Read some call procedure messages.
    //
    // The client engages us in some witty banter, which we don't
    // actually care about for the purposes of this program.  But
    // we need to read past it, and acknowledge it anyway.  We are
    // acting as a server here.  We don't need to change the client
    // data at all.
    //
    ByteBuffer subscription_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(subscription_request, sc);
    writeServerCallResponse(sc, getRequestClientData(subscription_request));
    ByteBuffer stats_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(stats_request, sc);
    writeServerCallResponse(sc, getRequestClientData(stats_request));
    ByteBuffer syscat_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(syscat_request, sc);
    writeServerCallResponse(sc, getRequestClientData(stats_request));
    //
    // Now, read the invocation requests from the client.  We can't
    // actually respond, so we fake up a response.  But this is good
    // enough for now, and we save the message.
    //
    String[] vanillaFileNames = new String[] { "invocation_request_success.msg", "invocation_request_fail_cv.msg", "invocation_request_select.msg" };
    Map<String, ByteBuffer> vanillaMessages = new HashMap<String, ByteBuffer>();
    for (String fileName : vanillaFileNames) {
        ByteBuffer responseMessage = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
        vanillaMessages.put(fileName, responseMessage);
        readMessage(responseMessage, sc);
        writeServerCallResponse(sc, getRequestClientData(responseMessage));
        // Set the client data.  The value here is not important, but it
        // needs to be shared between this and the client unit tests.
        setRequestClientData(responseMessage, clientData);
        writeDataFile(clientDataDir, fileName, responseMessage);
    }
    // Note that these names are somewhat stylized.  They name
    // the file which holds the request.  The response to this
    // request will be in a similarly named file, but with _request_
    // replaced by _response_.  So, make sure there is one _request_
    // substring in the file names.
    String[] geoFileNames = new String[] { "invocation_request_insert_geo.msg", "invocation_request_insert_geo_nulls.msg", "invocation_request_select_geo_both.msg", "invocation_request_select_geo_both_mid.msg", "invocation_request_select_geo_polynull.msg", "invocation_request_select_geo_ptnull.msg", "invocation_request_select_geo_bothnull.msg" };
    Map<String, ByteBuffer> geoMessages = new HashMap<String, ByteBuffer>();
    for (String filename : geoFileNames) {
        ByteBuffer requestMessage = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
        // We need to save these for later.
        geoMessages.put(filename, requestMessage);
        readMessage(requestMessage, sc);
        writeServerCallResponse(sc, getRequestClientData(requestMessage));
        setRequestClientData(requestMessage, clientData);
        if (generateGeoMessages) {
            writeDataFile(clientDataDir, filename, requestMessage);
        }
    }
    oclient.close();
    ssc.close();
    oclientThread.join();
    // Now, connect to a real server.  We are going to pretend to be a
    // client and write the messages we just read from the client, as we pretended to be
    // a server.  We will then capture the responses in files.
    SocketChannel voltsc = null;
    try {
        voltsc = SocketChannel.open(new InetSocketAddress("localhost", TRUE_SERVER_PORT));
        voltsc.socket().setTcpNoDelay(true);
        voltsc.configureBlocking(true);
        System.err.printf("Connected.\n");
    } catch (IOException ex) {
        abend("Can't connect to a server.  Is there a VoltDB server running?.\n");
    }
    // Write the authentication message and then
    // read the response.  We need the response.  The
    // Client will engage in witty repartee with the
    // server, but we neither see nor care about that.
    //
    // Note that for each of these responses we need to
    // set some parameters, so that they will not depend
    // on the particular context we executed.  This is the
    // cluster start time, the client data, the leader IP
    // address and the build string.  The client unit tests
    // will know these values.
    //
    ByteBuffer scratch = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    voltsc.write(authReqSHA1);
    readMessage(scratch, voltsc);
    setClusterStartTimestamp(scratch, clusterStartTime);
    setLeaderIPAddr(scratch, leaderIPAddr);
    setBuildString(scratch, buildString);
    writeDataFile(clientDataDir, "authentication_response.msg", scratch);
    for (String filename : vanillaFileNames) {
        // Write the three procedure messages.
        ByteBuffer requestMessage = vanillaMessages.get(filename);
        if (requestMessage == null) {
            abend("Cannot find request message for file name \"%s\"\n", filename);
        }
        voltsc.write(requestMessage);
        readMessage(scratch, voltsc);
        setResponseClientData(scratch, clientData);
        setClusterRoundTripTime(scratch, clusterRoundTripTime);
        String responseFileName = filename.replaceAll("_request_", "_response_");
        writeDataFile(clientDataDir, responseFileName, scratch);
    }
    if (generateGeoMessages) {
        for (String filename : geoFileNames) {
            // Write the three procedure messages.
            ByteBuffer requestMessage = geoMessages.get(filename);
            if (requestMessage == null) {
                abend("Cannot find request message for file name \"%s\"\n", filename);
            }
            voltsc.write(requestMessage);
            readMessage(scratch, voltsc);
            setResponseClientData(scratch, clientData);
            setClusterRoundTripTime(scratch, clusterRoundTripTime);
            String responseFileName = filename.replaceAll("_request_", "_response_");
            System.out.printf("Writing Response file \"%s\".\n", responseFileName);
            writeDataFile(clientDataDir, responseFileName, scratch);
        }
    }
    voltsc.close();
    clientThread.join();
    Thread.sleep(3000);
    ssc = ServerSocketChannel.open();
    ssc.socket().bind(new InetSocketAddress("localhost", FAKE_SERVER_PORT));
    clientThread = new Thread() {

        @Override
        public void run() {
            try {
                org.voltdb.client.Client newClient = ClientFactory.createClient();
                newClient.createConnection("localhost", FAKE_SERVER_PORT);
                String[] strings = new String[] { "oh", "noes" };
                byte[] bytes = new byte[] { 22, 33, 44 };
                short[] shorts = new short[] { 22, 33, 44 };
                int[] ints = new int[] { 22, 33, 44 };
                long[] longs = new long[] { 22, 33, 44 };
                double[] doubles = new double[] { 3, 3.1, 3.14, 3.1459 };
                TimestampType[] timestamps = new TimestampType[] { new TimestampType(33), new TimestampType(44) };
                BigDecimal[] bds = new BigDecimal[] { new BigDecimal("3"), new BigDecimal("3.14"), new BigDecimal("3.1459") };
                try {
                    newClient.callProcedure("foo", strings, bytes, shorts, ints, longs, doubles, timestamps, bds, null, "ohnoes!", (byte) 22, (short) 22, 22, (long) 22, 3.1459, new TimestampType(33), new BigDecimal("3.1459"));
                } catch (Exception e) {
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    };
    clientThread.setDaemon(true);
    clientThread.start();
    voltsc = ssc.accept();
    // Read the authentication message.  We don't need it.
    readMessage(scratch, voltsc);
    writeServerAuthenticationResponse(voltsc, true);
    //
    // The client engages us in some dialog.  We don't need this
    // either, but we need to read past it.
    //
    subscription_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(subscription_request, voltsc);
    writeServerCallResponse(voltsc, getRequestClientData(subscription_request));
    stats_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(stats_request, voltsc);
    writeServerCallResponse(voltsc, getRequestClientData(stats_request));
    syscat_request = ByteBuffer.allocate(DEFAULT_BUFFER_SIZE);
    readMessage(syscat_request, voltsc);
    writeServerCallResponse(voltsc, getRequestClientData(stats_request));
    // Read the all-types call procedure message.
    readMessage(scratch, voltsc);
    writeServerCallResponse(voltsc, getRequestClientData(scratch));
    setRequestClientData(scratch, clientData);
    writeDataFile(clientDataDir, "invocation_request_all_params.msg", scratch);
    voltsc.close();
    clientThread.join();
    //
    // Serialize a message and write it.
    //
    ColumnInfo[] columns = new ColumnInfo[] { new ColumnInfo("column1", VoltType.TINYINT), new ColumnInfo("column2", VoltType.STRING), new ColumnInfo("column3", VoltType.SMALLINT), new ColumnInfo("column4", VoltType.INTEGER), new ColumnInfo("column5", VoltType.BIGINT), new ColumnInfo("column6", VoltType.TIMESTAMP), new ColumnInfo("column7", VoltType.DECIMAL), new ColumnInfo("column8", VoltType.GEOGRAPHY), new ColumnInfo("column9", VoltType.GEOGRAPHY_POINT) };
    VoltTable vt = new VoltTable(columns);
    GeographyValue poly = GeographyValue.fromWKT(smallPolyTxt);
    GeographyPointValue pt = GeographyPointValue.fromWKT(smallPointTxt);
    vt.addRow(null, null, null, null, null, null, null, poly, pt);
    vt.addRow(0, "", 2, 4, 5, new TimestampType(44), new BigDecimal("3.1459"), poly, pt);
    vt.addRow(0, null, 2, 4, 5, null, null, poly, pt);
    vt.addRow(null, "woobie", null, null, null, new TimestampType(44), new BigDecimal("3.1459"), poly, pt);
    ByteBuffer bb = ByteBuffer.allocate(vt.getSerializedSize());
    vt.flattenToBuffer(bb);
    FastSerializer fs = new FastSerializer(vt.getSerializedSize());
    fs.write(bb);
    bb.flip();
    writeDataFile(clientDataDir, "serialized_table.bin", bb);
    clientThread.join();
}
Also used : ServerSocketChannel(java.nio.channels.ServerSocketChannel) SocketChannel(java.nio.channels.SocketChannel) HashMap(java.util.HashMap) InetSocketAddress(java.net.InetSocketAddress) FastSerializer(org.voltdb.messaging.FastSerializer) ColumnInfo(org.voltdb.VoltTable.ColumnInfo) TimestampType(org.voltdb.types.TimestampType) NullCallback(org.voltdb.client.NullCallback) ClientConfig(org.voltdb.client.ClientConfig) ServerSocketChannel(java.nio.channels.ServerSocketChannel) GeographyValue(org.voltdb.types.GeographyValue) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) IOException(java.io.IOException) BigDecimal(java.math.BigDecimal) ClientStatusListenerExt(org.voltdb.client.ClientStatusListenerExt) File(java.io.File) GeographyPointValue(org.voltdb.types.GeographyPointValue)

Example 35 with SocketChannel

use of java.nio.channels.SocketChannel in project voltdb by VoltDB.

the class ConnectionUtil method getAuthenticatedConnection.

private static Object[] getAuthenticatedConnection(String service, InetSocketAddress addr, String username, byte[] hashedPassword, final Subject subject, ClientAuthScheme scheme, SSLEngine sslEngine) throws IOException {
    Object[] returnArray = new Object[3];
    boolean success = false;
    if (addr.isUnresolved()) {
        throw new java.net.UnknownHostException(addr.getHostName());
    }
    SocketChannel aChannel = SocketChannel.open(addr);
    returnArray[0] = aChannel;
    assert (aChannel.isConnected());
    if (!aChannel.isConnected()) {
        // TODO Can open() be asynchronous if configureBlocking(true)?
        throw new IOException("Failed to open host " + ReverseDNSCache.hostnameOrAddress(addr.getAddress()));
    }
    synchronized (aChannel.blockingLock()) {
        aChannel.configureBlocking(false);
        aChannel.socket().setTcpNoDelay(true);
    }
    if (sslEngine != null) {
        TLSHandshaker handshaker = new TLSHandshaker(aChannel, sslEngine);
        boolean shookHands = false;
        try {
            shookHands = handshaker.handshake();
        } catch (IOException e) {
            aChannel.close();
            throw new IOException("SSL handshake failed", e);
        }
        if (!shookHands) {
            aChannel.close();
            throw new IOException("SSL handshake failed");
        }
    }
    final long[] retvals = new long[4];
    returnArray[1] = retvals;
    MessagingChannel messagingChannel = MessagingChannel.get(aChannel, sslEngine);
    try {
        /*
             * Send login info
             */
        synchronized (aChannel.blockingLock()) {
            aChannel.configureBlocking(true);
            aChannel.socket().setTcpNoDelay(true);
        }
        // encode strings
        byte[] serviceBytes = service == null ? null : service.getBytes(Constants.UTF8ENCODING);
        byte[] usernameBytes = username == null ? null : username.getBytes(Constants.UTF8ENCODING);
        // get the length of the data to serialize
        int requestSize = 4;
        //version and scheme
        requestSize += 2;
        requestSize += serviceBytes == null ? 4 : 4 + serviceBytes.length;
        requestSize += usernameBytes == null ? 4 : 4 + usernameBytes.length;
        requestSize += hashedPassword.length;
        ByteBuffer b = ByteBuffer.allocate(requestSize);
        // serialize it
        // length prefix
        b.putInt(requestSize - 4);
        // version
        b.put((byte) 1);
        b.put((byte) scheme.getValue());
        // data service (export|database)
        SerializationHelper.writeVarbinary(serviceBytes, b);
        SerializationHelper.writeVarbinary(usernameBytes, b);
        b.put(hashedPassword);
        b.flip();
        try {
            messagingChannel.writeMessage(b);
        } catch (IOException e) {
            throw new IOException("Failed to write authentication message to server.", e);
        }
        if (b.hasRemaining()) {
            throw new IOException("Failed to write authentication message to server.");
        }
        ByteBuffer loginResponse;
        try {
            loginResponse = messagingChannel.readMessage();
        } catch (IOException e) {
            throw new IOException("Authentication rejected", e);
        }
        byte version = loginResponse.get();
        byte loginResponseCode = loginResponse.get();
        if (version == Constants.AUTH_HANDSHAKE_VERSION) {
            byte tag = loginResponseCode;
            if (subject == null) {
                aChannel.close();
                throw new IOException("Server requires an authenticated JAAS principal");
            }
            if (tag != Constants.AUTH_SERVICE_NAME) {
                aChannel.close();
                throw new IOException("Wire protocol format violation error");
            }
            String servicePrincipal = SerializationHelper.getString(loginResponse);
            loginResponse = performAuthenticationHandShake(aChannel, subject, servicePrincipal);
            loginResponseCode = loginResponse.get();
        }
        if (loginResponseCode != 0) {
            aChannel.close();
            switch(loginResponseCode) {
                case Constants.MAX_CONNECTIONS_LIMIT_ERROR:
                    throw new IOException("Server has too many connections");
                case Constants.WIRE_PROTOCOL_TIMEOUT_ERROR:
                    throw new IOException("Connection timed out during authentication. " + "The VoltDB server may be overloaded.");
                case Constants.EXPORT_DISABLED_REJECTION:
                    throw new IOException("Export not enabled for server");
                case Constants.WIRE_PROTOCOL_FORMAT_ERROR:
                    throw new IOException("Wire protocol format violation error");
                case Constants.AUTHENTICATION_FAILURE_DUE_TO_REJOIN:
                    throw new IOException("Failed to authenticate to rejoining node");
                default:
                    throw new IOException("Authentication rejected");
            }
        }
        retvals[0] = loginResponse.getInt();
        retvals[1] = loginResponse.getLong();
        retvals[2] = loginResponse.getLong();
        retvals[3] = loginResponse.getInt();
        int buildStringLength = loginResponse.getInt();
        byte[] buildStringBytes = new byte[buildStringLength];
        loginResponse.get(buildStringBytes);
        returnArray[2] = new String(buildStringBytes, Constants.UTF8ENCODING);
        synchronized (aChannel.blockingLock()) {
            aChannel.configureBlocking(false);
            aChannel.socket().setKeepAlive(true);
        }
        success = true;
    } finally {
        messagingChannel.cleanUp();
        if (!success) {
            aChannel.close();
        }
    }
    return returnArray;
}
Also used : SocketChannel(java.nio.channels.SocketChannel) IOException(java.io.IOException) ByteBuffer(java.nio.ByteBuffer) MessagingChannel(org.voltcore.utils.ssl.MessagingChannel)

Aggregations

SocketChannel (java.nio.channels.SocketChannel)759 ServerSocketChannel (java.nio.channels.ServerSocketChannel)337 IOException (java.io.IOException)321 InetSocketAddress (java.net.InetSocketAddress)228 ByteBuffer (java.nio.ByteBuffer)188 SelectionKey (java.nio.channels.SelectionKey)126 Socket (java.net.Socket)101 Test (org.junit.Test)87 ClosedChannelException (java.nio.channels.ClosedChannelException)63 ServerSocket (java.net.ServerSocket)49 Selector (java.nio.channels.Selector)48 SocketAddress (java.net.SocketAddress)36 ClosedSelectorException (java.nio.channels.ClosedSelectorException)33 ConnectException (java.net.ConnectException)27 CancelledKeyException (java.nio.channels.CancelledKeyException)27 ArrayList (java.util.ArrayList)27 SocketTimeoutException (java.net.SocketTimeoutException)25 SelectableChannel (java.nio.channels.SelectableChannel)23 HashMap (java.util.HashMap)23 OutputStream (java.io.OutputStream)22