public GuacamoleTunnel connect()

in extensions/guacamole-auth-json/src/main/java/org/apache/guacamole/auth/json/connection/ConnectionService.java [169:305]


    public GuacamoleTunnel connect(UserData.Connection connection,
            GuacamoleClientInformation info, Map<String, String> tokens) throws GuacamoleException {

        // Retrieve proxy configuration from environment
        GuacamoleProxyConfiguration proxyConfig = environment.getDefaultGuacamoleProxyConfiguration();

        // Get guacd connection parameters
        String hostname = proxyConfig.getHostname();
        int port = proxyConfig.getPort();

        // Generate and verify connection configuration
        GuacamoleConfiguration filteredConfig = getConfiguration(connection);
        if (filteredConfig == null) {
            logger.debug("Configuration for connection could not be "
                    + "generated. Perhaps the connection being joined is not "
                    + "active?");
            throw new GuacamoleResourceNotFoundException("No such connection");
        }

        // Apply tokens to config parameters
        new TokenFilter(tokens).filterValues(filteredConfig.getParameters());

        // Determine socket type based on required encryption method
        final ConfiguredGuacamoleSocket socket;
        switch (proxyConfig.getEncryptionMethod()) {

            // If guacd requires SSL, use it
            case SSL:
                socket = new ConfiguredGuacamoleSocket(
                    new SSLGuacamoleSocket(hostname, port),
                    filteredConfig, info
                );
                break;

            // Connect directly via TCP if encryption is not enabled
            case NONE:
                socket = new ConfiguredGuacamoleSocket(
                    new InetGuacamoleSocket(hostname, port),
                    filteredConfig, info
                );
                break;

            // Abort if encryption method is unknown
            default:
                throw new GuacamoleServerException("Unimplemented encryption method.");

        }

        final GuacamoleTunnel tunnel;

        // If the current connection is not being tracked (no ID) just use a
        // normal, non-tracking tunnel
        final String id = connection.getId();
        if (id == null)
            tunnel = new SimpleGuacamoleTunnel(socket);

        // Otherwise, create a tunnel with proper tracking which can be joined
        else {

            // Allow connection to be joined
            final String connectionID = socket.getConnectionID();
            final Collection<GuacamoleTunnel> existingTunnels = shadowers.putIfAbsent(connectionID,
                    Collections.synchronizedList(new ArrayList<>()));

            // Duplicate connection IDs cannot exist
            assert(existingTunnels == null);

            // If the current connection is intended to be tracked (an ID was
            // provided), but a connection is already in progress with that ID,
            // log a warning that the original connection will no longer be tracked
            String activeConnection = activeConnections.put(id, connectionID);
            if (activeConnection != null)
                logger.warn("A connection with ID \"{}\" is already in progress, "
                        + "but another attempt to use this ID has been made. The "
                        + "original connection will no longer be joinable.", id);

            // Return a tunnel which automatically tracks the active connection
            tunnel = new SimpleGuacamoleTunnel(new GuacamoleSocket() {

                @Override
                public GuacamoleReader getReader() {
                    return socket.getReader();
                }

                @Override
                public GuacamoleWriter getWriter() {
                    return socket.getWriter();
                }

                @Override
                public void close() throws GuacamoleException {

                    // Stop connection from being joined further
                    activeConnections.remove(id, connectionID);

                    // Close all connections sharing the closed connection
                    Collection<GuacamoleTunnel> tunnels = shadowers.remove(connectionID);
                    if (tunnels != null)
                        closeAll(tunnels);

                    socket.close();

                }

                @Override
                public boolean isOpen() {
                    return socket.isOpen();
                }

            });

        }

        // Track tunnels which join connections, such that they can be
        // automatically closed when the joined connection closes
        String joinedConnection = filteredConfig.getConnectionID();
        if (joinedConnection != null) {

            // Track shadower of joined connection if possible
            Collection<GuacamoleTunnel> tunnels = shadowers.get(joinedConnection);
            if (tunnels != null)
                tunnels.add(tunnel);

            // Close this tunnel in ALL CASES if the joined connection has
            // closed. Note that it is insufficient to simply check whether the
            // retrieved Collection is null here, as it may have been removed
            // after retrieval. We must ensure that the tunnel is closed in any
            // case where it will not automatically be closed due to the
            // closure of the shadowed connection.
            if (!shadowers.containsKey(joinedConnection))
                tunnel.close();

        }

        return tunnel;

    }