Commit 5ad23d21 authored by Dave Cridland's avatar Dave Cridland

Merge pull request #223 from guusdk/OF-883

OF-883: Prevent sending data to known disconnected peers.
parents b5c572f7 0d75703d
...@@ -144,9 +144,29 @@ public interface Connection { ...@@ -144,9 +144,29 @@ public interface Connection {
* <li>Call notifyEvent all listeners that the channel is shutting down. * <li>Call notifyEvent all listeners that the channel is shutting down.
* <li>Close the socket. * <li>Close the socket.
* </ul> * </ul>
*
* An invocation of this method is equal to invoking {@link #close(boolean)} with a parameter
* that is false.
*/ */
public void close(); public void close();
/**
* Close this session including associated socket connection. The order of
* events for closing the session is:
* <ul>
* <li>Set closing flag to prevent redundant shutdowns.
* <li>Call notifyEvent all listeners that the channel is shutting down.
* <li>Close the socket.
* </ul>
*
* This method takes into account the connection state of the peer. Specifically,
* when the peer is known to be in a disconnected state, no data will be sent
* (otherwise, this method can trigger the delivery of an end-of-stream signal).
*
* @param peerIsKnownToBeDisconnected should be set to true when the peer is known to no longer be available.
*/
public void close( boolean peerIsKnownToBeDisconnected );
/** /**
* Notification message indicating that the server is being shutdown. Implementors * Notification message indicating that the server is being shutdown. Implementors
* should send a stream error whose condition is system-shutdown before closing * should send a stream error whose condition is system-shutdown before closing
......
...@@ -442,6 +442,10 @@ public class SocketConnection implements Connection { ...@@ -442,6 +442,10 @@ public class SocketConnection implements Connection {
} }
public void close() { public void close() {
close( false );
}
public void close( boolean peerIsKnownToBeDisconnected ) {
boolean wasClosed = false; boolean wasClosed = false;
synchronized (this) { synchronized (this) {
if (!isClosed()) { if (!isClosed()) {
...@@ -449,6 +453,8 @@ public class SocketConnection implements Connection { ...@@ -449,6 +453,8 @@ public class SocketConnection implements Connection {
if (session != null) { if (session != null) {
session.setStatus(Session.STATUS_CLOSED); session.setStatus(Session.STATUS_CLOSED);
} }
if ( !peerIsKnownToBeDisconnected ) {
boolean allowedToWrite = false; boolean allowedToWrite = false;
try { try {
requestWriting(); requestWriting();
...@@ -472,6 +478,7 @@ public class SocketConnection implements Connection { ...@@ -472,6 +478,7 @@ public class SocketConnection implements Connection {
} }
} }
} }
}
catch (Exception e) { catch (Exception e) {
Log.error(LocaleUtils.getLocalizedString("admin.error.close") Log.error(LocaleUtils.getLocalizedString("admin.error.close")
+ "\n" + this.toString(), e); + "\n" + this.toString(), e);
......
...@@ -169,6 +169,10 @@ public abstract class VirtualConnection implements Connection { ...@@ -169,6 +169,10 @@ public abstract class VirtualConnection implements Connection {
* has been closed. * has been closed.
*/ */
public void close() { public void close() {
close( false );
}
public void close(boolean peerIsKnownToBeDisconnected) {
boolean wasClosed = false; boolean wasClosed = false;
synchronized (this) { synchronized (this) {
if (!isClosed()) { if (!isClosed()) {
......
...@@ -111,7 +111,7 @@ public abstract class ConnectionHandler extends IoHandlerAdapter { ...@@ -111,7 +111,7 @@ public abstract class ConnectionHandler extends IoHandlerAdapter {
public void inputClosed( IoSession session ) throws Exception { public void inputClosed( IoSession session ) throws Exception {
final Connection connection = (Connection) session.getAttribute(CONNECTION); final Connection connection = (Connection) session.getAttribute(CONNECTION);
if ( connection != null ) { if ( connection != null ) {
connection.close(); connection.close( true );
} }
} }
......
...@@ -219,7 +219,11 @@ public class NIOConnection implements Connection { ...@@ -219,7 +219,11 @@ public class NIOConnection implements Connection {
return backupDeliverer; return backupDeliverer;
} }
public void close() public void close() {
close( false );
}
public void close( boolean peerIsKnownToBeDisconnected )
{ {
boolean notifyClose = false; boolean notifyClose = false;
synchronized ( this ) { synchronized ( this ) {
...@@ -234,6 +238,8 @@ public class NIOConnection implements Connection { ...@@ -234,6 +238,8 @@ public class NIOConnection implements Connection {
if ( state != State.CLOSING ) if ( state != State.CLOSING )
{ {
state = State.CLOSING; state = State.CLOSING;
if ( !peerIsKnownToBeDisconnected )
{
try try
{ {
deliverRawText( flashClient ? "</flash:stream>" : "</stream:stream>" ); deliverRawText( flashClient ? "</flash:stream>" : "</stream:stream>" );
...@@ -243,6 +249,7 @@ public class NIOConnection implements Connection { ...@@ -243,6 +249,7 @@ public class NIOConnection implements Connection {
// Ignore // Ignore
} }
} }
}
// deliverRawText might already have forced the state from Closing to Closed. In that case, there's no need // deliverRawText might already have forced the state from Closing to Closed. In that case, there's no need
// to invoke the CloseListeners again. // to invoke the CloseListeners again.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment