tira-web/src-java/de/webis/tira/client/web/HTTPTunnelServlet.java
@Override
    protected void doRead(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {

        HttpSession httpSession = request.getSession(false);
        GuacamoleSession session = new GuacamoleSession(httpSession);

        // Get tunnel, ensure tunnel exists
        GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
        if (tunnel == null)
            throw new GuacamoleResourceNotFoundException("No such tunnel.");

        // Ensure tunnel is open
        if (!tunnel.isOpen())
            throw new GuacamoleResourceNotFoundException("Tunnel is closed.");

        // Obtain exclusive read access
        GuacamoleReader reader = tunnel.acquireReader();

        try {

            // Note that although we are sending text, Webkit browsers will
            // buffer 1024 bytes before starting a normal stream if we use
            // anything but application/octet-stream.
            response.setContentType("application/octet-stream");
            response.setHeader("Cache-Control", "no-cache");

            // Get writer for response
            Writer out = new BufferedWriter(new OutputStreamWriter(
                    response.getOutputStream(), "UTF-8"));

            // Stream data to response, ensuring output stream is closed
            try {

                // Detach tunnel and throw error if EOF (and we haven't sent any
                // data yet.
                char[] message = reader.read();
                if (message == null)
                    throw new GuacamoleConnectionClosedException("Tunnel reached end of stream.");

                // For all messages, until another stream is ready (we send at least one message)
                do {

                    // Get message output bytes
                    out.write(message, 0, message.length);

                    // Flush if we expect to wait
                    if (!reader.available()) {
                        out.flush();
                        response.flushBuffer();
                    }

                    // No more messages another stream can take over
                    if (tunnel.hasQueuedReaderThreads())
                        break;

                } while (tunnel.isOpen() && (message = reader.read()) != null);

                // Close tunnel immediately upon EOF
                if (message == null) {
                    session.detachTunnel(tunnel);
                    tunnel.close();
                    handledisconnect(tunnelUUID);
                }

                // End-of-instructions marker
                out.write("0.;");
                out.flush();
                response.flushBuffer();
            }

            // Send end-of-stream marker and close tunnel if connection is closed
            catch (GuacamoleConnectionClosedException e) {

                // Detach and close
                session.detachTunnel(tunnel);
                tunnel.close();
                handledisconnect(tunnelUUID);

                // End-of-instructions marker
                out.write("0.;");
                out.flush();
                response.flushBuffer();
            }

            catch (GuacamoleException e) {

                // Detach and close
                session.detachTunnel(tunnel);
                tunnel.close();
                handledisconnect(tunnelUUID);

                throw e;
            }
            // Always close output stream
            finally {
                out.close();
            }
        }
        catch (IOException e) {
            // Log typically frequent I/O error if desired
            //logger.debug("Error writing to servlet output stream", e);

            // Detach and close
            session.detachTunnel(tunnel);
            tunnel.close();
            handledisconnect(tunnelUUID);
        }
        finally {
            tunnel.releaseReader();
        }
    }
// copied guacamole function with added tunnel detach callback
copied guacamole function with added tunnel detach callback
copied guacamole function with added tunnel detach callback
@Override
    protected void doRead(HttpServletRequest request, HttpServletResponse response, String tunnelUUID) throws GuacamoleException {
        HttpSession httpSession = request.getSession(false);
        GuacamoleSession session = new GuacamoleSession(httpSession);
        GuacamoleTunnel tunnel = session.getTunnel(tunnelUUID);
        if (tunnel == null)
            throw new GuacamoleResourceNotFoundException("No such tunnel.");
        if (!tunnel.isOpen())
            throw new GuacamoleResourceNotFoundException("Tunnel is closed.");
        GuacamoleReader reader = tunnel.acquireReader();
        try {
            response.setContentType("application/octet-stream");
            response.setHeader("Cache-Control", "no-cache");
            Writer out = new BufferedWriter(new OutputStreamWriter(
                    response.getOutputStream(), "UTF-8"));
            try {
                char[] message = reader.read();
                if (message == null)
                    throw new GuacamoleConnectionClosedException("Tunnel reached end of stream.");
                do {
                    out.write(message, 0, message.length);
                    if (!reader.available()) {
                        out.flush();
                        response.flushBuffer();
                    }
                    if (tunnel.hasQueuedReaderThreads())
                        break;
                } while (tunnel.isOpen() && (message = reader.read()) != null);
                if (message == null) {
                    session.detachTunnel(tunnel);
                    tunnel.close();
                    handledisconnect(tunnelUUID);
                }
                out.write("0.;");
                out.flush();
                response.flushBuffer();
            }
            catch (GuacamoleConnectionClosedException e) {
                session.detachTunnel(tunnel);
                tunnel.close();
                handledisconnect(tunnelUUID);
                out.write("0.;");
                out.flush();
                response.flushBuffer();
            }
            catch (GuacamoleException e) {
                session.detachTunnel(tunnel);
                tunnel.close();
                handledisconnect(tunnelUUID);
                throw e;
            }
            finally {
                out.close();
            }
        }
        catch (IOException e) {
            session.detachTunnel(tunnel);
            tunnel.close();
            handledisconnect(tunnelUUID);
        }
        finally {
            tunnel.releaseReader();
        }
    }
@ Override protected void doRead ( HttpServletRequest request , HttpServletResponse response , String tunnelUUID ) throws GuacamoleException { HttpSession httpSession = request . getSession ( false ) ; GuacamoleSession session = new GuacamoleSession ( httpSession ) ; GuacamoleTunnel tunnel = session . getTunnel ( tunnelUUID ) ; if ( tunnel == null ) throw new GuacamoleResourceNotFoundException ( "No such tunnel." ) ; if ( ! tunnel . isOpen ( ) ) throw new GuacamoleResourceNotFoundException ( "Tunnel is closed." ) ; GuacamoleReader reader = tunnel . acquireReader ( ) ; try { response . setContentType ( "application/octet-stream" ) ; response . setHeader ( "Cache-Control" , "no-cache" ) ; Writer out = new BufferedWriter ( new OutputStreamWriter ( response . getOutputStream ( ) , "UTF-8" ) ) ; try { char [ ] message = reader . read ( ) ; if ( message == null ) throw new GuacamoleConnectionClosedException ( "Tunnel reached end of stream." ) ; do { out . write ( message , 0 , message . length ) ; if ( ! reader . available ( ) ) { out . flush ( ) ; response . flushBuffer ( ) ; } if ( tunnel . hasQueuedReaderThreads ( ) ) break ; } while ( tunnel . isOpen ( ) && ( message = reader . read ( ) ) != null ) ; if ( message == null ) { session . detachTunnel ( tunnel ) ; tunnel . close ( ) ; handledisconnect ( tunnelUUID ) ; } out . write ( "0.;" ) ; out . flush ( ) ; response . flushBuffer ( ) ; } catch ( GuacamoleConnectionClosedException e ) { session . detachTunnel ( tunnel ) ; tunnel . close ( ) ; handledisconnect ( tunnelUUID ) ; out . write ( "0.;" ) ; out . flush ( ) ; response . flushBuffer ( ) ; } catch ( GuacamoleException e ) { session . detachTunnel ( tunnel ) ; tunnel . close ( ) ; handledisconnect ( tunnelUUID ) ; throw e ; } finally { out . close ( ) ; } } catch ( IOException e ) { session . detachTunnel ( tunnel ) ; tunnel . close ( ) ; handledisconnect ( tunnelUUID ) ; } finally { tunnel . releaseReader ( ) ; } }
copied guacamole function with added tunnel detach callback
copied guacamole function with added tunnel detach callback
// Get tunnel, ensure tunnel exists // Ensure tunnel is open // Obtain exclusive read access // Note that although we are sending text, Webkit browsers will // buffer 1024 bytes before starting a normal stream if we use // anything but application/octet-stream. // Get writer for response // Stream data to response, ensuring output stream is closed // Detach tunnel and throw error if EOF (and we haven't sent any // data yet. // For all messages, until another stream is ready (we send at least one message) // Get message output bytes // Flush if we expect to wait // No more messages another stream can take over // Close tunnel immediately upon EOF // End-of-instructions marker // Send end-of-stream marker and close tunnel if connection is closed // Detach and close // End-of-instructions marker // Detach and close // Always close output stream // Log typically frequent I/O error if desired //logger.debug("Error writing to servlet output stream", e); // Detach and close