View Javadoc
1   /*
2    * Copyright 2012 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.channel.oio;
17  
18  import io.netty.channel.AbstractChannel;
19  import io.netty.channel.Channel;
20  import io.netty.channel.ChannelPromise;
21  import io.netty.channel.EventLoop;
22  import io.netty.channel.ThreadPerChannelEventLoop;
23  
24  import java.net.SocketAddress;
25  
26  /**
27   * Abstract base class for {@link Channel} implementations that use Old-Blocking-IO
28   *
29   * @deprecated use NIO / EPOLL / KQUEUE transport.
30   */
31  @Deprecated
32  public abstract class AbstractOioChannel extends AbstractChannel {
33  
34      protected static final int SO_TIMEOUT = 1000;
35  
36      boolean readPending;
37      boolean readWhenInactive;
38      final Runnable readTask = new Runnable() {
39          @Override
40          public void run() {
41              doRead();
42          }
43      };
44      private final Runnable clearReadPendingRunnable = new Runnable() {
45          @Override
46          public void run() {
47              readPending = false;
48          }
49      };
50  
51      /**
52       * @see AbstractChannel#AbstractChannel(Channel)
53       */
54      protected AbstractOioChannel(Channel parent) {
55          super(parent);
56      }
57  
58      @Override
59      protected AbstractUnsafe newUnsafe() {
60          return new DefaultOioUnsafe();
61      }
62  
63      private final class DefaultOioUnsafe extends AbstractUnsafe {
64          @Override
65          public void connect(
66                  final SocketAddress remoteAddress,
67                  final SocketAddress localAddress, final ChannelPromise promise) {
68              if (!promise.setUncancellable() || !ensureOpen(promise)) {
69                  return;
70              }
71  
72              try {
73                  boolean wasActive = isActive();
74                  doConnect(remoteAddress, localAddress);
75  
76                  // Get the state as trySuccess() may trigger an ChannelFutureListener that will close the Channel.
77                  // We still need to ensure we call fireChannelActive() in this case.
78                  boolean active = isActive();
79  
80                  safeSetSuccess(promise);
81                  if (!wasActive && active) {
82                      pipeline().fireChannelActive();
83                  }
84              } catch (Throwable t) {
85                  safeSetFailure(promise, annotateConnectException(t, remoteAddress));
86                  closeIfClosed();
87              }
88          }
89      }
90  
91      @Override
92      protected boolean isCompatible(EventLoop loop) {
93          return loop instanceof ThreadPerChannelEventLoop;
94      }
95  
96      /**
97       * Connect to the remote peer using the given localAddress if one is specified or {@code null} otherwise.
98       */
99      protected abstract void doConnect(
100             SocketAddress remoteAddress, SocketAddress localAddress) throws Exception;
101 
102     @Override
103     protected void doBeginRead() throws Exception {
104         if (readPending) {
105             return;
106         }
107         if (!isActive()) {
108             readWhenInactive = true;
109             return;
110         }
111 
112         readPending = true;
113         eventLoop().execute(readTask);
114     }
115 
116     protected abstract void doRead();
117 
118     /**
119      * @deprecated No longer supported.
120      * No longer supported.
121      */
122     @Deprecated
123     protected boolean isReadPending() {
124         return readPending;
125     }
126 
127     /**
128      * @deprecated Use {@link #clearReadPending()} if appropriate instead.
129      * No longer supported.
130      */
131     @Deprecated
132     protected void setReadPending(final boolean readPending) {
133         if (isRegistered()) {
134             EventLoop eventLoop = eventLoop();
135             if (eventLoop.inEventLoop()) {
136                 this.readPending = readPending;
137             } else {
138                 eventLoop.execute(new Runnable() {
139                     @Override
140                     public void run() {
141                         AbstractOioChannel.this.readPending = readPending;
142                     }
143                 });
144             }
145         } else {
146             this.readPending = readPending;
147         }
148     }
149 
150     /**
151      * Set read pending to {@code false}.
152      */
153     protected final void clearReadPending() {
154         if (isRegistered()) {
155             EventLoop eventLoop = eventLoop();
156             if (eventLoop.inEventLoop()) {
157                 readPending = false;
158             } else {
159                 eventLoop.execute(clearReadPendingRunnable);
160             }
161         } else {
162             // Best effort if we are not registered yet clear readPending. This happens during channel initialization.
163             readPending = false;
164         }
165     }
166 }