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