1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17 package org.apache.tomcat.util.net;
18
19 import java.io.IOException;
20 import java.nio.ByteBuffer;
21 import java.nio.channels.ByteChannel;
22 import java.nio.channels.GatheringByteChannel;
23 import java.nio.channels.ScatteringByteChannel;
24 import java.nio.channels.Selector;
25 import java.nio.channels.SocketChannel;
26
27 import org.apache.tomcat.util.net.NioEndpoint.NioSocketWrapper;
28 import org.apache.tomcat.util.res.StringManager;
29
30 /**
31 * Base class for a SocketChannel wrapper used by the endpoint.
32 * This way, logic for an SSL socket channel remains the same as for
33 * a non SSL, making sure we don't need to code for any exception cases.
34 *
35 * @version 1.0
36 */
37 public class NioChannel implements ByteChannel, ScatteringByteChannel, GatheringByteChannel {
38
39 protected static final StringManager sm = StringManager.getManager(NioChannel.class);
40
41 protected static final ByteBuffer emptyBuf = ByteBuffer.allocate(0);
42
43 protected final SocketBufferHandler bufHandler;
44 protected SocketChannel sc = null;
45 protected NioSocketWrapper socketWrapper = null;
46
47 public NioChannel(SocketBufferHandler bufHandler) {
48 this.bufHandler = bufHandler;
49 }
50
51 /**
52 * Reset the channel
53 *
54 * @param channel the socket channel
55 * @param socketWrapper the socket wrapper
56 * @throws IOException If a problem was encountered resetting the channel
57 */
58 public void reset(SocketChannel channel, NioSocketWrapper socketWrapper) throws IOException {
59 this.sc = channel;
60 this.socketWrapper = socketWrapper;
61 bufHandler.reset();
62 }
63
64 /**
65 * @return the socketWrapper
66 */
67 NioSocketWrapper getSocketWrapper() {
68 return socketWrapper;
69 }
70
71 /**
72 * Free the channel memory
73 */
74 public void free() {
75 bufHandler.free();
76 }
77
78 /**
79 * Returns true if the network buffer has been flushed out and is empty.
80 *
81 * @param block Unused. May be used when overridden
82 * @param s Unused. May be used when overridden
83 * @param timeout Unused. May be used when overridden
84 * @return Always returns <code>true</code> since there is no network buffer
85 * in the regular channel
86 *
87 * @throws IOException Never for non-secure channel
88 */
89 public boolean flush(boolean block, Selector s, long timeout)
90 throws IOException {
91 return true;
92 }
93
94
95 /**
96 * Closes this channel.
97 *
98 * @throws IOException If an I/O error occurs
99 */
100 @Override
101 public void close() throws IOException {
102 sc.close();
103 }
104
105 /**
106 * Close the connection.
107 *
108 * @param force Should the underlying socket be forcibly closed?
109 *
110 * @throws IOException If closing the secure channel fails.
111 */
112 public void close(boolean force) throws IOException {
113 if (isOpen() || force) {
114 close();
115 }
116 }
117
118 /**
119 * Tells whether or not this channel is open.
120 *
121 * @return <code>true</code> if, and only if, this channel is open
122 */
123 @Override
124 public boolean isOpen() {
125 return sc.isOpen();
126 }
127
128 /**
129 * Writes a sequence of bytes to this channel from the given buffer.
130 *
131 * @param src The buffer from which bytes are to be retrieved
132 * @return The number of bytes written, possibly zero
133 * @throws IOException If some other I/O error occurs
134 */
135 @Override
136 public int write(ByteBuffer src) throws IOException {
137 checkInterruptStatus();
138 return sc.write(src);
139 }
140
141 @Override
142 public long write(ByteBuffer[] srcs) throws IOException {
143 return write(srcs, 0, srcs.length);
144 }
145
146 @Override
147 public long write(ByteBuffer[] srcs, int offset, int length)
148 throws IOException {
149 checkInterruptStatus();
150 return sc.write(srcs, offset, length);
151 }
152
153 /**
154 * Reads a sequence of bytes from this channel into the given buffer.
155 *
156 * @param dst The buffer into which bytes are to be transferred
157 * @return The number of bytes read, possibly zero, or <code>-1</code> if
158 * the channel has reached end-of-stream
159 * @throws IOException If some other I/O error occurs
160 */
161 @Override
162 public int read(ByteBuffer dst) throws IOException {
163 return sc.read(dst);
164 }
165
166 @Override
167 public long read(ByteBuffer[] dsts) throws IOException {
168 return read(dsts, 0, dsts.length);
169 }
170
171 @Override
172 public long read(ByteBuffer[] dsts, int offset, int length)
173 throws IOException {
174 return sc.read(dsts, offset, length);
175 }
176
177 public SocketBufferHandler getBufHandler() {
178 return bufHandler;
179 }
180
181 public SocketChannel getIOChannel() {
182 return sc;
183 }
184
185 public boolean isClosing() {
186 return false;
187 }
188
189 public boolean isHandshakeComplete() {
190 return true;
191 }
192
193 /**
194 * Performs SSL handshake hence is a no-op for the non-secure
195 * implementation.
196 *
197 * @param read Unused in non-secure implementation
198 * @param write Unused in non-secure implementation
199 * @return Always returns zero
200 * @throws IOException Never for non-secure channel
201 */
202 public int handshake(boolean read, boolean write) throws IOException {
203 return 0;
204 }
205
206 @Override
207 public String toString() {
208 return super.toString() + ":" + sc.toString();
209 }
210
211 public int getOutboundRemaining() {
212 return 0;
213 }
214
215 /**
216 * Return true if the buffer wrote data. NO-OP for non-secure channel.
217 *
218 * @return Always returns {@code false} for non-secure channel
219 *
220 * @throws IOException Never for non-secure channel
221 */
222 public boolean flushOutbound() throws IOException {
223 return false;
224 }
225
226 /**
227 * This method should be used to check the interrupt status before
228 * attempting a write.
229 *
230 * If a thread has been interrupted and the interrupt has not been cleared
231 * then an attempt to write to the socket will fail. When this happens the
232 * socket is removed from the poller without the socket being selected. This
233 * results in a connection limit leak for NIO as the endpoint expects the
234 * socket to be selected even in error conditions.
235 * @throws IOException If the current thread was interrupted
236 */
237 protected void checkInterruptStatus() throws IOException {
238 if (Thread.interrupted()) {
239 throw new IOException(sm.getString("channel.nio.interrupted"));
240 }
241 }
242
243 private ApplicationBufferHandler appReadBufHandler;
244 public void setAppReadBufHandler(ApplicationBufferHandler handler) {
245 this.appReadBufHandler = handler;
246 }
247 protected ApplicationBufferHandler getAppReadBufHandler() {
248 return appReadBufHandler;
249 }
250
251 static final NioChannel CLOSED_NIO_CHANNEL = new ClosedNioChannel();
252 public static class ClosedNioChannel extends NioChannel {
253 public ClosedNioChannel() {
254 super(SocketBufferHandler.EMPTY);
255 }
256 @Override
257 public void close() throws IOException {
258 }
259 @Override
260 public boolean isOpen() {
261 return false;
262 }
263 @Override
264 public void reset(SocketChannel channel, NioSocketWrapper socketWrapper) throws IOException {
265 }
266 @Override
267 public void free() {
268 }
269 @Override
270 public void setAppReadBufHandler(ApplicationBufferHandler handler) {
271 }
272 @Override
273 public int read(ByteBuffer dst) throws IOException {
274 return -1;
275 }
276 @Override
277 public long read(ByteBuffer[] dsts, int offset, int length)
278 throws IOException {
279 return -1L;
280 }
281 @Override
282 public int write(ByteBuffer src) throws IOException {
283 checkInterruptStatus();
284 return -1;
285 }
286 @Override
287 public long write(ByteBuffer[] srcs, int offset, int length)
288 throws IOException {
289 return -1L;
290 }
291 @Override
292 public String toString() {
293 return "Closed NioChannel";
294 }
295 }
296
297 }
298