@Override
    public void close(VirtualConnection inVC, Exception e) {
        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
            Tr.debug(tc, "close(vc, e) called H2InboundLink: " + this + " " + inVC);
        }

        //At this point our side should be in the close state, as we have sent out our data
        //Should probably check if the connection is closed, if so issue the destroy up the chain
        //Then call the close on the underlying muxLink so we can close the connection if everything has been closed
        //Additionally, don't close the underlying link if this is a push stream
        if (streamID == 0 || streamID % 2 == 1) {
            // if this isn't an http/2 exception, don't pass it down, since that will cause a GOAWAY to be sent immediately
            if (e == null || e instanceof Http2Exception) {
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                    Tr.debug(tc, "close: closing with exception: " + e);
                }
                if (httpInboundServiceContextImpl != null) {
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                        Tr.debug(tc, "close: (1)httpInboundServiceContextImpl.clear()");
                    }
                    httpInboundServiceContextImpl.clear();
                    httpInboundServiceContextImpl = null;
                }
                this.muxLink.close(inVC, e);
            } else {
                H2StreamProcessor h2sp = muxLink.getStreamProcessor(streamID);
                if (h2sp != null && !h2sp.isStreamClosed()) {
                    try {
                        if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                            Tr.debug(tc, "close: attempting to reset stream: " + streamID);
                        }
                        int PROTOCOL_ERROR = 0x1;
                        Frame reset = new FrameRstStream(streamID, PROTOCOL_ERROR, false);
                        h2sp.processNextFrame(reset, Constants.Direction.WRITING_OUT);
                    } catch (Http2Exception h2e) {
                        // if we can't write out RST frame, throw the original exception
                        if (httpInboundServiceContextImpl != null) {
                            if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                                Tr.debug(tc, "close: (2)httpInboundServiceContextImpl.clear()");
                            }
                            httpInboundServiceContextImpl.clear();
                            httpInboundServiceContextImpl = null;
                        }
                        this.muxLink.close(inVC, e);
                    }
                }
                if (httpInboundServiceContextImpl != null) {
                    if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                        Tr.debug(tc, "close: (3)httpInboundServiceContextImpl.clear()");
                    }
                    httpInboundServiceContextImpl.clear();
                    httpInboundServiceContextImpl = null;
                }
                this.muxLink.close(inVC, null);
            }
        } else { // try to send an RST_STREAM to let the client know the push promise has been canceled
            H2StreamProcessor h2sp = muxLink.getStreamProcessor(streamID);
            if (h2sp != null && !h2sp.isStreamClosed() && !h2sp.isHalfClosed()) {
                if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                    Tr.debug(tc, "close: attempting to reset stream: " + streamID);
                }
                int PROTOCOL_ERROR = 0x1;
                Frame reset = new FrameRstStream(streamID, PROTOCOL_ERROR, false);
                try {
                    h2sp.processNextFrame(reset, Constants.Direction.WRITING_OUT);
                } catch (Http2Exception h2e) {
                    // don't close
                }
            }
        }
    }
@ Override public void close ( VirtualConnection inVC , Exception e ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close(vc, e) called H2InboundLink: " + this + " " + inVC ) ; } if ( streamID == 0 || streamID % 2 == 1 ) { if ( e == null || e instanceof Http2Exception ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: closing with exception: " + e ) ; } if ( httpInboundServiceContextImpl != null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: (1)httpInboundServiceContextImpl.clear()" ) ; } httpInboundServiceContextImpl . clear ( ) ; httpInboundServiceContextImpl = null ; } this . muxLink . close ( inVC , e ) ; } else { H2StreamProcessor h2sp = muxLink . getStreamProcessor ( streamID ) ; if ( h2sp != null && ! h2sp . isStreamClosed ( ) ) { try { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: attempting to reset stream: " + streamID ) ; } int PROTOCOL_ERROR = 0x1 ; Frame reset = new FrameRstStream ( streamID , PROTOCOL_ERROR , false ) ; h2sp . processNextFrame ( reset , Constants . Direction . WRITING_OUT ) ; } catch ( Http2Exception h2e ) { if ( httpInboundServiceContextImpl != null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: (2)httpInboundServiceContextImpl.clear()" ) ; } httpInboundServiceContextImpl . clear ( ) ; httpInboundServiceContextImpl = null ; } this . muxLink . close ( inVC , e ) ; } } if ( httpInboundServiceContextImpl != null ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: (3)httpInboundServiceContextImpl.clear()" ) ; } httpInboundServiceContextImpl . clear ( ) ; httpInboundServiceContextImpl = null ; } this . muxLink . close ( inVC , null ) ; } } else { H2StreamProcessor h2sp = muxLink . getStreamProcessor ( streamID ) ; if ( h2sp != null && ! h2sp . isStreamClosed ( ) && ! h2sp . isHalfClosed ( ) ) { if ( TraceComponent . isAnyTracingEnabled ( ) && tc . isDebugEnabled ( ) ) { Tr . debug ( tc , "close: attempting to reset stream: " + streamID ) ; } int PROTOCOL_ERROR = 0x1 ; Frame reset = new FrameRstStream ( streamID , PROTOCOL_ERROR , false ) ; try { h2sp . processNextFrame ( reset , Constants . Direction . WRITING_OUT ) ; } catch ( Http2Exception h2e ) { } } } }
/*
(non-Javadoc)

@see com.ibm.ws.http.channel.internal.inbound.HttpInboundLink#close(com.ibm.wsspi.channelfw.VirtualConnection, java.lang.Exception)