< prev index next >
1 /*
2 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 */
24 package java.net.http;
25
26 import java.io.IOException;
27 import java.nio.ByteBuffer;
28 import java.nio.channels.ByteChannel;
29 import java.nio.channels.GatheringByteChannel;
30 import java.nio.channels.SelectableChannel;
31 import java.nio.channels.SelectionKey;
32
33 //
34 // Used to implement WebSocket. Each RawChannel corresponds to a TCP connection
35 // (SocketChannel) but is connected to a Selector and an ExecutorService for
36 // invoking the send and receive callbacks. Also includes SSL processing.
37 //
38 final class RawChannel implements ByteChannel, GatheringByteChannel {
39
40 private final HttpClientImpl client;
41 private final HttpConnection connection;
42 private volatile boolean closed;
43
44 private interface RawEvent {
45
46 /** must return the selector interest op flags OR'd. */
47 int interestOps();
48
49 /** called when event occurs. */
50 void handle();
51 }
52
53 interface NonBlockingEvent extends RawEvent { }
54
55 RawChannel(HttpClientImpl client, HttpConnection connection) {
56 this.client = client;
57 this.connection = connection;
58 }
59
60 private class RawAsyncEvent extends AsyncEvent {
61
62 private final RawEvent re;
63
64 RawAsyncEvent(RawEvent re) {
65 super(AsyncEvent.BLOCKING); // BLOCKING & !REPEATING
66 this.re = re;
67 }
68
69 RawAsyncEvent(RawEvent re, int flags) {
70 super(flags);
71 this.re = re;
72 }
73
74 @Override
75 public SelectableChannel channel() {
76 return connection.channel();
77 }
78
79 // must return the selector interest op flags OR'd
80 @Override
81 public int interestOps() {
82 return re.interestOps();
83 }
84
85 // called when event occurs
86 @Override
87 public void handle() {
88 re.handle();
89 }
90
91 @Override
92 public void abort() { }
93 }
94
95 private class NonBlockingRawAsyncEvent extends RawAsyncEvent {
96
97 NonBlockingRawAsyncEvent(RawEvent re) {
98 super(re, 0); // !BLOCKING & !REPEATING
99 }
100 }
101
102 /*
103 * Register given event whose callback will be called once only.
104 * (i.e. register new event for each callback)
105 */
106 public void registerEvent(RawEvent event) throws IOException {
107 if (!(event instanceof NonBlockingEvent)) {
108 throw new InternalError();
109 }
110 if ((event.interestOps() & SelectionKey.OP_READ) != 0
111 && connection.buffer.hasRemaining()) {
112 // FIXME: a hack to deal with leftovers from previous reads into an
113 // internal buffer (works in conjunction with change in
114 // java.net.http.PlainHttpConnection.readImpl(java.nio.ByteBuffer)
115 connection.channel().configureBlocking(false);
116 event.handle();
117 } else {
118 client.registerEvent(new NonBlockingRawAsyncEvent(event));
119 }
120 }
121
122 @Override
123 public int read(ByteBuffer dst) throws IOException {
124 assert !connection.channel().isBlocking();
125 return connection.read(dst);
126 }
127
128 @Override
129 public boolean isOpen() {
130 return !closed;
131 }
132
133 @Override
134 public void close() throws IOException {
135 closed = true;
136 connection.close();
137 }
138
139 @Override
140 public long write(ByteBuffer[] src) throws IOException {
141 return connection.write(src, 0, src.length);
142 }
143
144 @Override
145 public long write(ByteBuffer[] src, int offset, int len)
146 throws IOException {
147 return connection.write(src, offset, len);
148 }
149
150 @Override
151 public int write(ByteBuffer src) throws IOException {
152 return (int) connection.write(src);
153 }
154 }
< prev index next >