Merge branch 'jetty-9.3.x' into jetty-9.4.x
This commit is contained in:
commit
b4c958e68c
|
@ -27,7 +27,6 @@ Web Applications can be bundled into a single Web Archive (WAR file) or as a dir
|
||||||
|
|
||||||
`/WEB-INF/`::
|
`/WEB-INF/`::
|
||||||
Special Servlet API defined directory used to store anything related to the Web Application that are not part of the public access of the Web Application.
|
Special Servlet API defined directory used to store anything related to the Web Application that are not part of the public access of the Web Application.
|
||||||
|
|
||||||
If there is content that is accessed by a Web Application internally, but that should also never be accessed directly by a web browser, this is the directory it would placed in.
|
If there is content that is accessed by a Web Application internally, but that should also never be accessed directly by a web browser, this is the directory it would placed in.
|
||||||
|
|
||||||
`/WEB-INF/web.xml`::
|
`/WEB-INF/web.xml`::
|
||||||
|
|
|
@ -52,15 +52,15 @@ META-INF/web-fragment.xml
|
||||||
|
|
||||||
===== Anatomy of a Configuration Class
|
===== Anatomy of a Configuration Class
|
||||||
|
|
||||||
A Configuration class is called 5 times in different phases of the WebAppContext's lifecycle:
|
A Configuration class is called 5 times in different phases of the `WebAppContext's` lifecycle:
|
||||||
|
|
||||||
preConfigure::
|
preConfigure::
|
||||||
As the WebAppContext is starting up this phase is executed.
|
As the `WebAppContext` is starting up this phase is executed.
|
||||||
The Configuration should discover any of the resources it will need during the subsequent phases.
|
The `Configuration` should discover any of the resources it will need during the subsequent phases.
|
||||||
configure::
|
configure::
|
||||||
This phase is where the work of the class is done, usually using the resources discovered during the preConfigure phase.
|
This phase is where the work of the class is done, usually using the resources discovered during the `preConfigure` phase.
|
||||||
postConfigure::
|
postConfigure::
|
||||||
This phase allows the Configuration to clear down any resources that may have been created during the previous 2 phases that are not needed for the lifetime of the `WebAppContext`.
|
This phase allows the `Configuration` to clear down any resources that may have been created during the previous 2 phases that are not needed for the lifetime of the `WebAppContext`.
|
||||||
deconfigure::
|
deconfigure::
|
||||||
This phase occurs whenever a `WebAppContext` is being stopped and allows the Configuration to undo any resources/metadata that it created.
|
This phase occurs whenever a `WebAppContext` is being stopped and allows the Configuration to undo any resources/metadata that it created.
|
||||||
A `WebAppContext` should be able to be cleanly start/stopped multiple times without resources being held.
|
A `WebAppContext` should be able to be cleanly start/stopped multiple times without resources being held.
|
||||||
|
@ -68,8 +68,8 @@ destroy::
|
||||||
This phase is called when a `WebAppContext` is actually removed from service.
|
This phase is called when a `WebAppContext` is actually removed from service.
|
||||||
For example, the war file associated with it is deleted from the $JETTY_HOME/webapps directory.
|
For example, the war file associated with it is deleted from the $JETTY_HOME/webapps directory.
|
||||||
|
|
||||||
Each phase is called on each Configuration class in the order in which the `Configuration` class is listed.
|
Each phase is called on each `Configuration` class in the order in which the `Configuration` class is listed.
|
||||||
Using the default Configuration classes as an example, preConfigure() will be called on `WebInfConfiguration`, `WebXmlConfiguration`, `MetaInfConfiguration`, `FragmentConfiguration` and then `JettyWebXmlConfiguration`.
|
Using the default `Configuration` classes as an example, `preConfigure()` will be called on `WebInfConfiguration`, `WebXmlConfiguration`, `MetaInfConfiguration`, `FragmentConfiguration` and then `JettyWebXmlConfiguration`.
|
||||||
The cycle begins again for the `configure()` phase and again for the `postConfigure()` phases.
|
The cycle begins again for the `configure()` phase and again for the `postConfigure()` phases.
|
||||||
The cycle is repeated _in reverse order_ for the `deconfigure()` and eventually the `destroy()` phases.
|
The cycle is repeated _in reverse order_ for the `deconfigure()` and eventually the `destroy()` phases.
|
||||||
|
|
||||||
|
@ -96,10 +96,10 @@ To achieve that, we use 2 extra Configurations:
|
||||||
[cols=",",]
|
[cols=",",]
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|link:{JDURL}/org/eclipse/jetty/plus/webapp/EnvConfiguration.html[org.eclipse.jetty.plus.webapp.EnvConfiguration]
|
|link:{JDURL}/org/eclipse/jetty/plus/webapp/EnvConfiguration.html[org.eclipse.jetty.plus.webapp.EnvConfiguration]
|
||||||
|Creates java:comp/env for the webapp, applies a WEB-INF/jetty-env.xml file
|
|Creates `java:comp/env` for the webapp, applies a `WEB-INF/jetty-env.xml` file
|
||||||
|
|
||||||
|link:{JDURL}/org/eclipse/jetty/plus/webapp/PlusConfiguration.html[org.eclipse.jetty.plus.webapp.PlusConfiguration]
|
|link:{JDURL}/org/eclipse/jetty/plus/webapp/PlusConfiguration.html[org.eclipse.jetty.plus.webapp.PlusConfiguration]
|
||||||
|Processes JNDI related aspects of WEB-INF/web.xml and hooks up naming entries
|
|Processes JNDI related aspects of `WEB-INF/web.xml` and hooks up naming entries
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
These configurations must be added in _exactly_ the order shown above and should be inserted _immediately before_ the link:{JDURL}/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.html[org.eclipse.jetty.webapp.JettyWebXmlConfiguration] class in the list of configurations.
|
These configurations must be added in _exactly_ the order shown above and should be inserted _immediately before_ the link:{JDURL}/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.html[org.eclipse.jetty.webapp.JettyWebXmlConfiguration] class in the list of configurations.
|
||||||
|
@ -117,7 +117,7 @@ We need just one extra Configuration class to help provide servlet annotation sc
|
||||||
@WebListener etc
|
@WebListener etc
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|
|
||||||
The above configuration class must be _inserted immediately before_ the link:{JDURL}/org/eclipse/jetty/webapp/JettWebXmlConfiguration.html[org.eclipse.jetty.webapp.JettyWebXmlConfiguration] class in the list of configurations.
|
The above configuration class must be _inserted immediately before_ the link:{JDURL}/org/eclipse/jetty/webapp/JettyWebXmlConfiguration.html[org.eclipse.jetty.webapp.JettyWebXmlConfiguration] class in the list of configurations.
|
||||||
To fully support annotations, you need to do a couple of other things, details of which can be found below.
|
To fully support annotations, you need to do a couple of other things, details of which can be found below.
|
||||||
|
|
||||||
===== How to Set the List of Configurations
|
===== How to Set the List of Configurations
|
||||||
|
@ -204,7 +204,7 @@ They will then be applied to each `WebAppContext` deployed by the deployer:
|
||||||
|
|
||||||
Instead of having to enumerate the list in its entirety, you can simply nominate classes that you want to add, and indicate whereabouts in the list you want them inserted.
|
Instead of having to enumerate the list in its entirety, you can simply nominate classes that you want to add, and indicate whereabouts in the list you want them inserted.
|
||||||
Let's look at an example of using this method to add in Configuration support for JNDI - as usual you can either do this in an xml file, or via equivalent code.
|
Let's look at an example of using this method to add in Configuration support for JNDI - as usual you can either do this in an xml file, or via equivalent code.
|
||||||
This example uses an xml file, in fact it is the $JETTY_HOME/etc/jetty-plus.xml file from the Jetty distribution:
|
This example uses an xml file, in fact it is the `$JETTY_HOME/etc/jetty-plus.xml` file from the Jetty distribution:
|
||||||
|
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
|
@ -235,9 +235,9 @@ This example uses an xml file, in fact it is the $JETTY_HOME/etc/jetty-plus.xml
|
||||||
The link:{JDURL}/org/eclipse/jetty/webapp/Configuration.html[org.eclipse.jetty.webapp.Configuration.ClassList] class provides these methods for insertion:
|
The link:{JDURL}/org/eclipse/jetty/webapp/Configuration.html[org.eclipse.jetty.webapp.Configuration.ClassList] class provides these methods for insertion:
|
||||||
|
|
||||||
addAfter::
|
addAfter::
|
||||||
Inserts the supplied list of Configuration class names after the given Configuration class name.
|
Inserts the supplied list of `Configuration` class names after the given Configuration class name.
|
||||||
addBefore::
|
addBefore::
|
||||||
Inserts the supplied list of Configuration class names before the given Configuration class name.
|
Inserts the supplied list of `Configuration` class names before the given Configuration class name.
|
||||||
|
|
||||||
[[webapp-context-attributes]]
|
[[webapp-context-attributes]]
|
||||||
==== Other Configuration
|
==== Other Configuration
|
||||||
|
@ -280,7 +280,7 @@ Similarly to the previous link:#context_attributes[context attribute], this attr
|
||||||
However, this attribute controls which jars from the _webapp's_ classpath (usually `WEB-INF/lib`) are processed.
|
However, this attribute controls which jars from the _webapp's_ classpath (usually `WEB-INF/lib`) are processed.
|
||||||
This can be particularly useful when you have dozens of jars in `WEB-INF/lib`, but you know that only a few need to be scanned.
|
This can be particularly useful when you have dozens of jars in `WEB-INF/lib`, but you know that only a few need to be scanned.
|
||||||
|
|
||||||
Here's an example in a xml file of a pattern that matches any jar that starts with "spring-":
|
Here's an example in a xml file of a pattern that matches any jar that starts with `spring-`:
|
||||||
|
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
|
|
|
@ -187,8 +187,8 @@ If you need to configure something within a web application, often you do so by
|
||||||
However, both the servlet standard and some Jetty features allow for other configuration to be applied to a web
|
However, both the servlet standard and some Jetty features allow for other configuration to be applied to a web
|
||||||
application externally from the WAR:
|
application externally from the WAR:
|
||||||
|
|
||||||
* You configure datasources and security realms in the server and inject them into a web application either explicitly or by name matching.
|
* You configure data sources and security realms in the server and inject them into a web application either explicitly or by name matching.
|
||||||
* Jetty allows one or more override deployment descriptors, in `web.xml` format, to be set on a context (via code or IoC XML) to amend the configuration set by the default and standard ` web.xml`.
|
* Jetty allows one or more override deployment descriptors, in `web.xml` format, to be set on a context (via code or IoC XML) to amend the configuration set by the default and standard `web.xml`.
|
||||||
* The normal Jetty Java API may be called by code or IoC XML to amend the configuration of a web application.
|
* The normal Jetty Java API may be called by code or IoC XML to amend the configuration of a web application.
|
||||||
|
|
||||||
===== Setting the Context Path
|
===== Setting the Context Path
|
||||||
|
@ -232,7 +232,7 @@ An example of setting the context path is included with the Jetty distribution i
|
||||||
|
|
||||||
===== Setting an Authentication Realm
|
===== Setting an Authentication Realm
|
||||||
|
|
||||||
The authentication method and realm name for a standard web application may be set in the ` web.xml` deployment descriptor with elements like:
|
The authentication method and realm name for a standard web application may be set in the `web.xml` deployment descriptor with elements like:
|
||||||
|
|
||||||
[source,xml]
|
[source,xml]
|
||||||
----
|
----
|
||||||
|
|
|
@ -23,6 +23,9 @@ The following sections provide information about Jetty security issues.
|
||||||
[width="99%",cols="11%,19%,14%,9%,14%,14%,19%",options="header",]
|
[width="99%",cols="11%,19%,14%,9%,14%,14%,19%",options="header",]
|
||||||
|=======================================================================
|
|=======================================================================
|
||||||
|yyyy/mm/dd |ID |Exploitable |Severity |Affects |Fixed Version |Comment
|
|yyyy/mm/dd |ID |Exploitable |Severity |Affects |Fixed Version |Comment
|
||||||
|
|2016/05/31 |CVE-2016-4800 |high |high |>= 9.3.0, < = 9.3.8 |9.3.9
|
||||||
|
|http://www.ocert.org/advisories/ocert-2016-001.html[Alias vulnerability allowing access to protected resources within a webapp on Windows.]
|
||||||
|
|
||||||
|2015/02/24 |CVE-2015-2080 |high |high |>=9.2.3 <9.2.9 |9.2.9
|
|2015/02/24 |CVE-2015-2080 |high |high |>=9.2.3 <9.2.9 |9.2.9
|
||||||
|http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html[JetLeak exposure of past buffers during HttpParser error]
|
|http://blog.gdssecurity.com/labs/2015/2/25/jetleak-vulnerability-remote-leakage-of-shared-buffers-in-je.html[JetLeak exposure of past buffers during HttpParser error]
|
||||||
|
|
||||||
|
@ -34,7 +37,7 @@ https://bugs.eclipse.org/bugs/show_bug.cgi?id=418014[418014] |Alias checking dis
|
||||||
|https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684[413684] |low
|
|https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684[413684] |low
|
||||||
|medium |>=7.6.9 <9.0.5 |7.6.13,8.1.13,9.0.5
|
|medium |>=7.6.9 <9.0.5 |7.6.13,8.1.13,9.0.5
|
||||||
https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684[413684]
|
https://bugs.eclipse.org/bugs/show_bug.cgi?id=413684[413684]
|
||||||
|Constraints bypassed if unix symlink alias checker used on windows
|
|Constraints bypassed if Unix symlink alias checker used on Windows.
|
||||||
|
|
||||||
|2011/12/29
|
|2011/12/29
|
||||||
|http://www.ocert.org/advisories/ocert-2011-003.html[CERT2011-003] http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-4461[CVE-2011-4461]
|
|http://www.ocert.org/advisories/ocert-2011-003.html[CERT2011-003] http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2011-4461[CVE-2011-4461]
|
||||||
|
@ -49,11 +52,11 @@ around by turning off SSL renegotiation in Jetty. If using JVM > 1.6u19
|
||||||
setAllowRenegotiate(true) may be called on connectors.
|
setAllowRenegotiate(true) may be called on connectors.
|
||||||
|
|
||||||
|2009/06/18 |http://jira.codehaus.org/browse/JETTY-1042[Jetty-1042] |low
|
|2009/06/18 |http://jira.codehaus.org/browse/JETTY-1042[Jetty-1042] |low
|
||||||
|high |<=6.1.18, <=7.0.0.M4 |6.1.19, 7.0.0.Rc0 |Cookie leak between
|
|high |< = 6.1.18, < = 7.0.0.M4 |6.1.19, 7.0.0.Rc0 |Cookie leak between
|
||||||
requests sharing a connection.
|
requests sharing a connection.
|
||||||
|
|
||||||
|2009/04/30 |http://www.kb.cert.org/vuls/id/402580[CERT402580] |medium
|
|2009/04/30 |http://www.kb.cert.org/vuls/id/402580[CERT402580] |medium
|
||||||
|high |<=6.1.16, <=7.0.0.M2 a|
|
|high |< = 6.1.16, < = 7.0.0.M2 a|
|
||||||
5.1.15, 6.1.18, 7.0.0.M2
|
5.1.15, 6.1.18, 7.0.0.M2
|
||||||
|
|
||||||
http://jira.codehaus.org/browse/JETTY-1004[Jetty-1004]
|
http://jira.codehaus.org/browse/JETTY-1004[Jetty-1004]
|
||||||
|
|
|
@ -103,13 +103,13 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
/* This is assumed to always be a NORMAL closure, no reason phrase */
|
/* This is assumed to always be a NORMAL closure, no reason phrase */
|
||||||
connection.close(StatusCode.NORMAL, null);
|
close(StatusCode.NORMAL, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close(CloseStatus closeStatus)
|
public void close(CloseStatus closeStatus)
|
||||||
{
|
{
|
||||||
this.close(closeStatus.getCode(),closeStatus.getPhrase());
|
close(closeStatus.getCode(),closeStatus.getPhrase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -149,17 +149,13 @@ public class WebSocketSession extends ContainerLifeCycle implements Session, Web
|
||||||
{
|
{
|
||||||
if(LOG.isDebugEnabled())
|
if(LOG.isDebugEnabled())
|
||||||
LOG.debug("stopping - {}",this);
|
LOG.debug("stopping - {}",this);
|
||||||
|
try
|
||||||
if (getConnection() != null)
|
|
||||||
{
|
{
|
||||||
try
|
close(StatusCode.SHUTDOWN,"Shutdown");
|
||||||
{
|
}
|
||||||
getConnection().close(StatusCode.SHUTDOWN,"Shutdown");
|
catch (Throwable t)
|
||||||
}
|
{
|
||||||
catch (Throwable t)
|
LOG.debug("During Connection Shutdown",t);
|
||||||
{
|
|
||||||
LOG.debug("During Connection Shutdown",t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
super.doStop();
|
super.doStop();
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,8 @@ import org.eclipse.jetty.websocket.common.io.IOState.ConnectionStateListener;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection, Connection.UpgradeTo, ConnectionStateListener, Dumpable
|
public abstract class AbstractWebSocketConnection extends AbstractConnection implements LogicalConnection, Connection.UpgradeTo, ConnectionStateListener, Dumpable
|
||||||
{
|
{
|
||||||
|
private final AtomicBoolean closed = new AtomicBoolean();
|
||||||
|
|
||||||
private class Flusher extends FrameFlusher
|
private class Flusher extends FrameFlusher
|
||||||
{
|
{
|
||||||
private Flusher(ByteBufferPool bufferPool, Generator generator, EndPoint endpoint)
|
private Flusher(ByteBufferPool bufferPool, Generator generator, EndPoint endpoint)
|
||||||
|
@ -256,10 +258,9 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
@Override
|
@Override
|
||||||
public void close()
|
public void close()
|
||||||
{
|
{
|
||||||
if(LOG_CLOSE.isDebugEnabled())
|
if (LOG_CLOSE.isDebugEnabled())
|
||||||
LOG_CLOSE.debug(".close()");
|
LOG_CLOSE.debug("close()");
|
||||||
CloseInfo close = new CloseInfo();
|
close(new CloseInfo());
|
||||||
this.outgoingFrame(close.asFrame(),new OnCloseLocalCallback(close),BatchMode.OFF);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,9 +279,14 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
public void close(int statusCode, String reason)
|
public void close(int statusCode, String reason)
|
||||||
{
|
{
|
||||||
if (LOG_CLOSE.isDebugEnabled())
|
if (LOG_CLOSE.isDebugEnabled())
|
||||||
LOG_CLOSE.debug("close({},{})",statusCode,reason);
|
LOG_CLOSE.debug("close({},{})", statusCode, reason);
|
||||||
CloseInfo close = new CloseInfo(statusCode,reason);
|
close(new CloseInfo(statusCode, reason));
|
||||||
this.outgoingFrame(close.asFrame(),new OnCloseLocalCallback(close),BatchMode.OFF);
|
}
|
||||||
|
|
||||||
|
private void close(CloseInfo closeInfo)
|
||||||
|
{
|
||||||
|
if (closed.compareAndSet(false, true))
|
||||||
|
outgoingFrame(closeInfo.asFrame(), new OnCloseLocalCallback(closeInfo), BatchMode.OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -408,7 +414,7 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
@Override
|
@Override
|
||||||
public boolean isOpen()
|
public boolean isOpen()
|
||||||
{
|
{
|
||||||
return getIOState().isOpen() && getEndPoint().isOpen();
|
return !closed.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -524,8 +530,6 @@ public abstract class AbstractWebSocketConnection extends AbstractConnection imp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onFillInterestedFailed(Throwable cause)
|
protected void onFillInterestedFailed(Throwable cause)
|
||||||
{
|
{
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class IOState
|
||||||
/**
|
/**
|
||||||
* The source of a close handshake. (ie: who initiated it).
|
* The source of a close handshake. (ie: who initiated it).
|
||||||
*/
|
*/
|
||||||
private static enum CloseHandshakeSource
|
private enum CloseHandshakeSource
|
||||||
{
|
{
|
||||||
/** No close handshake initiated (yet) */
|
/** No close handshake initiated (yet) */
|
||||||
NONE,
|
NONE,
|
||||||
|
@ -53,7 +53,7 @@ public class IOState
|
||||||
/** Remote side initiated the close handshake */
|
/** Remote side initiated the close handshake */
|
||||||
REMOTE,
|
REMOTE,
|
||||||
/** An abnormal close situation (disconnect, timeout, etc...) */
|
/** An abnormal close situation (disconnect, timeout, etc...) */
|
||||||
ABNORMAL;
|
ABNORMAL
|
||||||
}
|
}
|
||||||
|
|
||||||
public static interface ConnectionStateListener
|
public static interface ConnectionStateListener
|
||||||
|
@ -150,7 +150,7 @@ public class IOState
|
||||||
|
|
||||||
public boolean isClosed()
|
public boolean isClosed()
|
||||||
{
|
{
|
||||||
synchronized (state)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
return (state == ConnectionState.CLOSED);
|
return (state == ConnectionState.CLOSED);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ public class IOState
|
||||||
|
|
||||||
public boolean isOpen()
|
public boolean isOpen()
|
||||||
{
|
{
|
||||||
return (getConnectionState() != ConnectionState.CLOSED);
|
return !isClosed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOutputAvailable()
|
public boolean isOutputAvailable()
|
||||||
|
@ -221,67 +221,87 @@ public class IOState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A close handshake has been issued from the local endpoint
|
* A close handshake has been issued from the local endpoint
|
||||||
* @param close the close information
|
* @param closeInfo the close information
|
||||||
*/
|
*/
|
||||||
public void onCloseLocal(CloseInfo close)
|
public void onCloseLocal(CloseInfo closeInfo)
|
||||||
|
{
|
||||||
|
boolean open = false;
|
||||||
|
synchronized (this)
|
||||||
|
{
|
||||||
|
ConnectionState initialState = this.state;
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("onCloseLocal({}) : {}", closeInfo, initialState);
|
||||||
|
if (initialState == ConnectionState.CLOSED)
|
||||||
|
{
|
||||||
|
// already closed
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("already closed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (initialState == ConnectionState.CONNECTED)
|
||||||
|
{
|
||||||
|
// fast close. a local close request from end-user onConnect/onOpen method
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("FastClose in CONNECTED detected");
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (open)
|
||||||
|
openAndCloseLocal(closeInfo);
|
||||||
|
else
|
||||||
|
closeLocal(closeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void openAndCloseLocal(CloseInfo closeInfo)
|
||||||
|
{
|
||||||
|
// Force the state open (to allow read/write to endpoint)
|
||||||
|
onOpened();
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("FastClose continuing with Closure");
|
||||||
|
closeLocal(closeInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void closeLocal(CloseInfo closeInfo)
|
||||||
{
|
{
|
||||||
ConnectionState event = null;
|
ConnectionState event = null;
|
||||||
ConnectionState abnormalEvent = null;
|
ConnectionState abnormalEvent = null;
|
||||||
ConnectionState initialState = this.state;
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
LOG.debug("onCloseLocal({}) : {}",close,initialState);
|
|
||||||
if (initialState == ConnectionState.CLOSED)
|
|
||||||
{
|
|
||||||
// already closed
|
|
||||||
LOG.debug("already closed");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (initialState == ConnectionState.CONNECTED)
|
|
||||||
{
|
|
||||||
// fast close. a local close request from end-user onConnect/onOpen method
|
|
||||||
LOG.debug("FastClose in CONNECTED detected");
|
|
||||||
// Force the state open (to allow read/write to endpoint)
|
|
||||||
onOpened();
|
|
||||||
if (LOG.isDebugEnabled())
|
|
||||||
LOG.debug("FastClose continuing with Closure");
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
closeInfo = close;
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("onCloseLocal(), input={}, output={}", inputAvailable, outputAvailable);
|
||||||
|
|
||||||
// Turn off further output
|
this.closeInfo = closeInfo;
|
||||||
|
|
||||||
|
// Turn off further output.
|
||||||
outputAvailable = false;
|
outputAvailable = false;
|
||||||
|
|
||||||
boolean in = inputAvailable;
|
|
||||||
boolean out = outputAvailable;
|
|
||||||
if (closeHandshakeSource == CloseHandshakeSource.NONE)
|
if (closeHandshakeSource == CloseHandshakeSource.NONE)
|
||||||
{
|
{
|
||||||
closeHandshakeSource = CloseHandshakeSource.LOCAL;
|
closeHandshakeSource = CloseHandshakeSource.LOCAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("onCloseLocal(), input={}, output={}",in,out);
|
if (!inputAvailable)
|
||||||
|
|
||||||
if (!in && !out)
|
|
||||||
{
|
{
|
||||||
LOG.debug("Close Handshake satisfied, disconnecting");
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("Close Handshake satisfied, disconnecting");
|
||||||
cleanClose = true;
|
cleanClose = true;
|
||||||
this.state = ConnectionState.CLOSED;
|
this.state = ConnectionState.CLOSED;
|
||||||
finalClose.compareAndSet(null,close);
|
finalClose.compareAndSet(null,closeInfo);
|
||||||
event = this.state;
|
event = this.state;
|
||||||
}
|
}
|
||||||
else if (this.state == ConnectionState.OPEN)
|
else if (this.state == ConnectionState.OPEN)
|
||||||
{
|
{
|
||||||
// We are now entering CLOSING (or half-closed)
|
// We are now entering CLOSING (or half-closed).
|
||||||
this.state = ConnectionState.CLOSING;
|
this.state = ConnectionState.CLOSING;
|
||||||
event = this.state;
|
event = this.state;
|
||||||
|
|
||||||
// if abnormal, we don't expect an answer.
|
// If abnormal, we don't expect an answer.
|
||||||
if (close.isAbnormal())
|
if (closeInfo.isAbnormal())
|
||||||
{
|
{
|
||||||
abnormalEvent = ConnectionState.CLOSED;
|
abnormalEvent = ConnectionState.CLOSED;
|
||||||
finalClose.compareAndSet(null,close);
|
finalClose.compareAndSet(null,closeInfo);
|
||||||
cleanClose = false;
|
cleanClose = false;
|
||||||
outputAvailable = false;
|
outputAvailable = false;
|
||||||
inputAvailable = false;
|
inputAvailable = false;
|
||||||
|
@ -294,8 +314,7 @@ public class IOState
|
||||||
if (event != null)
|
if (event != null)
|
||||||
{
|
{
|
||||||
notifyStateListeners(event);
|
notifyStateListeners(event);
|
||||||
|
if (abnormalEvent != null)
|
||||||
if(abnormalEvent != null)
|
|
||||||
{
|
{
|
||||||
notifyStateListeners(abnormalEvent);
|
notifyStateListeners(abnormalEvent);
|
||||||
}
|
}
|
||||||
|
@ -304,12 +323,12 @@ public class IOState
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A close handshake has been received from the remote endpoint
|
* A close handshake has been received from the remote endpoint
|
||||||
* @param close the close information
|
* @param closeInfo the close information
|
||||||
*/
|
*/
|
||||||
public void onCloseRemote(CloseInfo close)
|
public void onCloseRemote(CloseInfo closeInfo)
|
||||||
{
|
{
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
LOG.debug("onCloseRemote({})",close);
|
LOG.debug("onCloseRemote({})", closeInfo);
|
||||||
ConnectionState event = null;
|
ConnectionState event = null;
|
||||||
synchronized (this)
|
synchronized (this)
|
||||||
{
|
{
|
||||||
|
@ -319,27 +338,25 @@ public class IOState
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
closeInfo = close;
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("onCloseRemote(), input={}, output={}", inputAvailable, outputAvailable);
|
||||||
|
|
||||||
|
this.closeInfo = closeInfo;
|
||||||
|
|
||||||
// turn off further input
|
// turn off further input
|
||||||
inputAvailable = false;
|
inputAvailable = false;
|
||||||
|
|
||||||
boolean in = inputAvailable;
|
|
||||||
boolean out = outputAvailable;
|
|
||||||
if (closeHandshakeSource == CloseHandshakeSource.NONE)
|
if (closeHandshakeSource == CloseHandshakeSource.NONE)
|
||||||
{
|
{
|
||||||
closeHandshakeSource = CloseHandshakeSource.REMOTE;
|
closeHandshakeSource = CloseHandshakeSource.REMOTE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (LOG.isDebugEnabled())
|
if (!outputAvailable)
|
||||||
LOG.debug("onCloseRemote(), input={}, output={}",in,out);
|
|
||||||
|
|
||||||
if (!in && !out)
|
|
||||||
{
|
{
|
||||||
LOG.debug("Close Handshake satisfied, disconnecting");
|
LOG.debug("Close Handshake satisfied, disconnecting");
|
||||||
cleanClose = true;
|
cleanClose = true;
|
||||||
state = ConnectionState.CLOSED;
|
state = ConnectionState.CLOSED;
|
||||||
finalClose.compareAndSet(null,close);
|
finalClose.compareAndSet(null,closeInfo);
|
||||||
event = this.state;
|
event = this.state;
|
||||||
}
|
}
|
||||||
else if (this.state == ConnectionState.OPEN)
|
else if (this.state == ConnectionState.OPEN)
|
||||||
|
|
Loading…
Reference in New Issue