1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.channel.socket.oio;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.channel.Channel;
20 import io.netty.channel.ChannelException;
21 import io.netty.channel.ChannelFuture;
22 import io.netty.channel.ChannelFutureListener;
23 import io.netty.channel.ChannelPromise;
24 import io.netty.channel.ConnectTimeoutException;
25 import io.netty.channel.EventLoop;
26 import io.netty.channel.oio.OioByteStreamChannel;
27 import io.netty.channel.socket.ServerSocketChannel;
28 import io.netty.channel.socket.SocketChannel;
29 import io.netty.util.internal.SocketUtils;
30 import io.netty.util.internal.UnstableApi;
31 import io.netty.util.internal.logging.InternalLogger;
32 import io.netty.util.internal.logging.InternalLoggerFactory;
33
34 import java.io.IOException;
35 import java.net.InetSocketAddress;
36 import java.net.Socket;
37 import java.net.SocketAddress;
38 import java.net.SocketTimeoutException;
39
40
41
42
43
44
45 @Deprecated
46 public class OioSocketChannel extends OioByteStreamChannel implements SocketChannel {
47
48 private static final InternalLogger logger = InternalLoggerFactory.getInstance(OioSocketChannel.class);
49
50 private final Socket socket;
51 private final OioSocketChannelConfig config;
52
53
54
55
56 public OioSocketChannel() {
57 this(new Socket());
58 }
59
60
61
62
63
64
65 public OioSocketChannel(Socket socket) {
66 this(null, socket);
67 }
68
69
70
71
72
73
74
75
76 public OioSocketChannel(Channel parent, Socket socket) {
77 super(parent);
78 this.socket = socket;
79 config = new DefaultOioSocketChannelConfig(this, socket);
80
81 boolean success = false;
82 try {
83 if (socket.isConnected()) {
84 activate(socket.getInputStream(), socket.getOutputStream());
85 }
86 socket.setSoTimeout(SO_TIMEOUT);
87 success = true;
88 } catch (Exception e) {
89 throw new ChannelException("failed to initialize a socket", e);
90 } finally {
91 if (!success) {
92 try {
93 socket.close();
94 } catch (IOException e) {
95 logger.warn("Failed to close a socket.", e);
96 }
97 }
98 }
99 }
100
101 @Override
102 public ServerSocketChannel parent() {
103 return (ServerSocketChannel) super.parent();
104 }
105
106 @Override
107 public OioSocketChannelConfig config() {
108 return config;
109 }
110
111 @Override
112 public boolean isOpen() {
113 return !socket.isClosed();
114 }
115
116 @Override
117 public boolean isActive() {
118 return !socket.isClosed() && socket.isConnected();
119 }
120
121 @Override
122 public boolean isOutputShutdown() {
123 return socket.isOutputShutdown() || !isActive();
124 }
125
126 @Override
127 public boolean isInputShutdown() {
128 return socket.isInputShutdown() || !isActive();
129 }
130
131 @Override
132 public boolean isShutdown() {
133 return socket.isInputShutdown() && socket.isOutputShutdown() || !isActive();
134 }
135
136 @UnstableApi
137 @Override
138 protected final void doShutdownOutput() throws Exception {
139 shutdownOutput0();
140 }
141
142 @Override
143 public ChannelFuture shutdownOutput() {
144 return shutdownOutput(newPromise());
145 }
146
147 @Override
148 public ChannelFuture shutdownInput() {
149 return shutdownInput(newPromise());
150 }
151
152 @Override
153 public ChannelFuture shutdown() {
154 return shutdown(newPromise());
155 }
156
157 @Override
158 protected int doReadBytes(ByteBuf buf) throws Exception {
159 if (socket.isClosed()) {
160 return -1;
161 }
162 try {
163 return super.doReadBytes(buf);
164 } catch (SocketTimeoutException ignored) {
165 return 0;
166 }
167 }
168
169 @Override
170 public ChannelFuture shutdownOutput(final ChannelPromise promise) {
171 EventLoop loop = eventLoop();
172 if (loop.inEventLoop()) {
173 shutdownOutput0(promise);
174 } else {
175 loop.execute(new Runnable() {
176 @Override
177 public void run() {
178 shutdownOutput0(promise);
179 }
180 });
181 }
182 return promise;
183 }
184
185 private void shutdownOutput0(ChannelPromise promise) {
186 try {
187 shutdownOutput0();
188 promise.setSuccess();
189 } catch (Throwable t) {
190 promise.setFailure(t);
191 }
192 }
193
194 private void shutdownOutput0() throws IOException {
195 socket.shutdownOutput();
196 }
197
198 @Override
199 public ChannelFuture shutdownInput(final ChannelPromise promise) {
200 EventLoop loop = eventLoop();
201 if (loop.inEventLoop()) {
202 shutdownInput0(promise);
203 } else {
204 loop.execute(new Runnable() {
205 @Override
206 public void run() {
207 shutdownInput0(promise);
208 }
209 });
210 }
211 return promise;
212 }
213
214 private void shutdownInput0(ChannelPromise promise) {
215 try {
216 socket.shutdownInput();
217 promise.setSuccess();
218 } catch (Throwable t) {
219 promise.setFailure(t);
220 }
221 }
222
223 @Override
224 public ChannelFuture shutdown(final ChannelPromise promise) {
225 ChannelFuture shutdownOutputFuture = shutdownOutput();
226 if (shutdownOutputFuture.isDone()) {
227 shutdownOutputDone(shutdownOutputFuture, promise);
228 } else {
229 shutdownOutputFuture.addListener(new ChannelFutureListener() {
230 @Override
231 public void operationComplete(final ChannelFuture shutdownOutputFuture) throws Exception {
232 shutdownOutputDone(shutdownOutputFuture, promise);
233 }
234 });
235 }
236 return promise;
237 }
238
239 private void shutdownOutputDone(final ChannelFuture shutdownOutputFuture, final ChannelPromise promise) {
240 ChannelFuture shutdownInputFuture = shutdownInput();
241 if (shutdownInputFuture.isDone()) {
242 shutdownDone(shutdownOutputFuture, shutdownInputFuture, promise);
243 } else {
244 shutdownInputFuture.addListener(new ChannelFutureListener() {
245 @Override
246 public void operationComplete(ChannelFuture shutdownInputFuture) throws Exception {
247 shutdownDone(shutdownOutputFuture, shutdownInputFuture, promise);
248 }
249 });
250 }
251 }
252
253 private static void shutdownDone(ChannelFuture shutdownOutputFuture,
254 ChannelFuture shutdownInputFuture,
255 ChannelPromise promise) {
256 Throwable shutdownOutputCause = shutdownOutputFuture.cause();
257 Throwable shutdownInputCause = shutdownInputFuture.cause();
258 if (shutdownOutputCause != null) {
259 if (shutdownInputCause != null) {
260 logger.debug("Exception suppressed because a previous exception occurred.",
261 shutdownInputCause);
262 }
263 promise.setFailure(shutdownOutputCause);
264 } else if (shutdownInputCause != null) {
265 promise.setFailure(shutdownInputCause);
266 } else {
267 promise.setSuccess();
268 }
269 }
270
271 @Override
272 public InetSocketAddress localAddress() {
273 return (InetSocketAddress) super.localAddress();
274 }
275
276 @Override
277 public InetSocketAddress remoteAddress() {
278 return (InetSocketAddress) super.remoteAddress();
279 }
280
281 @Override
282 protected SocketAddress localAddress0() {
283 return socket.getLocalSocketAddress();
284 }
285
286 @Override
287 protected SocketAddress remoteAddress0() {
288 return socket.getRemoteSocketAddress();
289 }
290
291 @Override
292 protected void doBind(SocketAddress localAddress) throws Exception {
293 SocketUtils.bind(socket, localAddress);
294 }
295
296 @Override
297 protected void doConnect(SocketAddress remoteAddress,
298 SocketAddress localAddress) throws Exception {
299 if (localAddress != null) {
300 SocketUtils.bind(socket, localAddress);
301 }
302
303 final int connectTimeoutMillis = config().getConnectTimeoutMillis();
304 boolean success = false;
305 try {
306 SocketUtils.connect(socket, remoteAddress, connectTimeoutMillis);
307 activate(socket.getInputStream(), socket.getOutputStream());
308 success = true;
309 } catch (SocketTimeoutException e) {
310 ConnectTimeoutException cause = new ConnectTimeoutException("connection timed out after " +
311 connectTimeoutMillis + " ms: " + remoteAddress);
312 cause.setStackTrace(e.getStackTrace());
313 throw cause;
314 } finally {
315 if (!success) {
316 doClose();
317 }
318 }
319 }
320
321 @Override
322 protected void doDisconnect() throws Exception {
323 doClose();
324 }
325
326 @Override
327 protected void doClose() throws Exception {
328 socket.close();
329 }
330
331 protected boolean checkInputShutdown() {
332 if (isInputShutdown()) {
333 try {
334 Thread.sleep(config().getSoTimeout());
335 } catch (Throwable e) {
336
337 }
338 return true;
339 }
340 return false;
341 }
342
343 @Deprecated
344 @Override
345 protected void setReadPending(boolean readPending) {
346 super.setReadPending(readPending);
347 }
348
349 final void clearReadPending0() {
350 clearReadPending();
351 }
352 }