< prev index next >
src/java.httpclient/share/classes/java/net/http/RawChannel.java
Print this page
@@ -26,34 +26,32 @@
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.SelectableChannel;
+import java.nio.channels.SelectionKey;
-/**
- * Used to implement WebSocket. Each RawChannel corresponds to
- * a TCP connection (SocketChannel) but is connected to a Selector
- * and an ExecutorService for invoking the send and receive callbacks
- * Also includes SSL processing.
- */
-class RawChannel implements ByteChannel, GatheringByteChannel {
+//
+// Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
+// (SocketChannel) but is connected to a Selector and an ExecutorService for
+// invoking the send and receive callbacks. Also includes SSL processing.
+//
+final class RawChannel implements ByteChannel, GatheringByteChannel {
private final HttpClientImpl client;
private final HttpConnection connection;
- private boolean closed;
+ private volatile boolean closed;
private interface RawEvent {
/** must return the selector interest op flags OR'd. */
int interestOps();
/** called when event occurs. */
void handle();
}
- interface BlockingEvent extends RawEvent { }
-
interface NonBlockingEvent extends RawEvent { }
RawChannel(HttpClientImpl client, HttpConnection connection) {
this.client = client;
this.connection = connection;
@@ -62,62 +60,70 @@
private class RawAsyncEvent extends AsyncEvent {
private final RawEvent re;
RawAsyncEvent(RawEvent re) {
+ super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING
+ this.re = re;
+ }
+
+ RawAsyncEvent(RawEvent re, int flags) {
+ super(flags);
this.re = re;
}
+ @Override
public SelectableChannel channel() {
return connection.channel();
}
// must return the selector interest op flags OR'd
+ @Override
public int interestOps() {
return re.interestOps();
}
// called when event occurs
+ @Override
public void handle() {
re.handle();
}
- public void abort() {}
- }
-
- private class BlockingRawAsyncEvent extends RawAsyncEvent
- implements AsyncEvent.Blocking {
-
- BlockingRawAsyncEvent(RawEvent re) {
- super(re);
- }
+ @Override
+ public void abort() { }
}
- private class NonBlockingRawAsyncEvent extends RawAsyncEvent
- implements AsyncEvent.NonBlocking {
+ private class NonBlockingRawAsyncEvent extends RawAsyncEvent {
NonBlockingRawAsyncEvent(RawEvent re) {
- super(re);
+ super(re, 0); // !BLOCKING & !REPEATING
}
}
/*
* Register given event whose callback will be called once only.
* (i.e. register new event for each callback)
*/
public void registerEvent(RawEvent event) throws IOException {
- if (event instanceof BlockingEvent) {
- client.registerEvent(new BlockingRawAsyncEvent(event));
- } else if (event instanceof NonBlockingEvent) {
- client.registerEvent(new NonBlockingRawAsyncEvent(event));
- } else {
+ if (!(event instanceof NonBlockingEvent)) {
throw new InternalError();
}
+ if ((event.interestOps() & SelectionKey.OP_READ) != 0
+ && connection.buffer.hasRemaining()) {
+ // FIXME: a hack to deal with leftovers from previous reads into an
+ // internal buffer (works in conjunction with change in
+ // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
+ connection.channel().configureBlocking(false);
+ event.handle();
+ } else {
+ client.registerEvent(new NonBlockingRawAsyncEvent(event));
+ }
}
@Override
public int read(ByteBuffer dst) throws IOException {
+ assert !connection.channel().isBlocking();
return connection.read(dst);
}
@Override
public boolean isOpen() {
< prev index next >