This commit is contained in:
Greg Wilkins 2011-10-06 16:39:14 +11:00
parent 76cdf9badb
commit ed9d9a0a33
3 changed files with 116 additions and 3 deletions

View File

@ -47,6 +47,7 @@ public interface EndPoint
* The buffer may chose to do a compact before filling.
* @return an <code>int</code> value indicating the number of bytes
* filled or -1 if EOF is reached.
* @throws EofException If input is shutdown or the endpoint is closed.
*/
int fill(Buffer buffer) throws IOException;
@ -59,6 +60,7 @@ public interface EndPoint
*
* @param buffer The buffer to flush. This buffers getIndex is updated.
* @return the number of bytes written
* @throws EofException If the endpoint is closed or output is shutdown.
*/
int flush(Buffer buffer) throws IOException;
@ -157,7 +159,7 @@ public interface EndPoint
/* ------------------------------------------------------------ */
/** Flush any buffered output.
* May fail to write all data if endpoint is non-blocking
* @throws IOException
* @throws EofException If the endpoint is closed or output is shutdown.
*/
public void flush() throws IOException;

View File

@ -38,21 +38,42 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
private final SelectorManager.SelectSet _selectSet;
private final SelectorManager _manager;
private SelectionKey _key;
private final Runnable _handler = new Runnable()
{
public void run() { handle(); }
};
/** The desired value for {@link SelectionKey#interestOps()} */
private int _interestOps;
/**
* The connection instance is the handler for any IO activity on the endpoint.
* There is a different type of connection for HTTP, AJP, WebSocket and
* ProxyConnect. The connection may change for an SCEP as it is upgraded
* from HTTP to proxy connect or websocket.
*/
private volatile Connection _connection;
/** true if a thread has been dispatched to handle this endpoint */
private boolean _dispatched = false;
/** true if a non IO dispatch (eg async resume) is outstanding */
private boolean _redispatched = false;
/** true if the last write operation succeed and wrote all offered bytes */
private volatile boolean _writable = true;
private SelectionKey _key;
private int _interestOps;
/** True if a thread has is blocked in {@link #blockReadable(long)} */
private boolean _readBlocked;
/** True if a thread has is blocked in {@link #blockWritable(long)} */
private boolean _writeBlocked;
/** true if {@link SelectSet#destroyEndPoint(SelectChannelEndPoint)} has not been called */
private boolean _open;
private volatile long _idleTimestamp;
/* ------------------------------------------------------------ */

View File

@ -14,9 +14,15 @@
package org.eclipse.jetty.io;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.Reader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import org.eclipse.jetty.util.IO;
import org.junit.Test;
@ -42,4 +48,88 @@ public class IOTest
out.toString(),
"The quick brown fox jumped over the lazy dog");
}
@Test
public void testHalfCloses() throws Exception
{
ServerSocket connector = new ServerSocket(0);
Socket client = new Socket("localhost",connector.getLocalPort());
System.err.println(client);
Socket server = connector.accept();
System.err.println(server);
// we can write both ways
client.getOutputStream().write(1);
assertEquals(1,server.getInputStream().read());
server.getOutputStream().write(1);
assertEquals(1,client.getInputStream().read());
// shutdown output results in read -1
client.shutdownOutput();
assertEquals(-1,server.getInputStream().read());
// Even though EOF has been read, the server input is not seen as shutdown
assertFalse(server.isInputShutdown());
// and we can read -1 again
assertEquals(-1,server.getInputStream().read());
// but cannot write
try { client.getOutputStream().write(1); assertTrue(false); } catch (SocketException e) {}
// but can still write in opposite direction.
server.getOutputStream().write(1);
assertEquals(1,client.getInputStream().read());
// server can shutdown input to match the shutdown out of client
server.shutdownInput();
// now we EOF instead of reading -1
try { server.getInputStream().read(); assertTrue(false); } catch (SocketException e) {}
// but can still write in opposite direction.
server.getOutputStream().write(1);
assertEquals(1,client.getInputStream().read());
// client can shutdown input
client.shutdownInput();
// now we EOF instead of reading -1
try { client.getInputStream().read(); assertTrue(false); } catch (SocketException e) {}
// But we can still write at the server (data which will never be read)
server.getOutputStream().write(1);
// and the server output is not shutdown
assertFalse( server.isOutputShutdown() );
// until we explictly shut it down
server.shutdownOutput();
// and now we can't write
try { server.getOutputStream().write(1); assertTrue(false); } catch (SocketException e) {}
// but the sockets are still open
assertFalse(client.isClosed());
assertFalse(server.isClosed());
// but if we close one end
client.close();
// it is seen as closed.
assertTrue(client.isClosed());
// but not the other end
assertFalse(server.isClosed());
// which has to be closed explictly
server.close();
assertTrue(server.isClosed());
}
}