View Javadoc
1   /*
2    * Copyright 2015 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.epoll;
17  
18  import io.netty.channel.Channel;
19  import io.netty.channel.ChannelConfig;
20  import io.netty.channel.ChannelMetadata;
21  import io.netty.channel.ChannelOutboundBuffer;
22  import io.netty.channel.ChannelPipeline;
23  import io.netty.channel.ChannelPromise;
24  import io.netty.channel.ServerChannel;
25  
26  import java.net.InetSocketAddress;
27  import java.net.SocketAddress;
28  
29  public abstract class AbstractEpollServerChannel extends AbstractEpollChannel implements ServerChannel {
30      private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
31  
32      protected AbstractEpollServerChannel(int fd) {
33          this(new LinuxSocket(fd), false);
34      }
35  
36      protected AbstractEpollServerChannel(LinuxSocket fd) {
37          this(fd, isSoErrorZero(fd));
38      }
39  
40      protected AbstractEpollServerChannel(LinuxSocket fd, boolean active) {
41          super(null, fd, active, EpollIoOps.valueOf(0));
42      }
43  
44      @Override
45      public ChannelMetadata metadata() {
46          return METADATA;
47      }
48  
49      @Override
50      protected InetSocketAddress remoteAddress0() {
51          return null;
52      }
53  
54      @Override
55      protected AbstractEpollUnsafe newUnsafe() {
56          return new EpollServerSocketUnsafe();
57      }
58  
59      @Override
60      protected void doWrite(ChannelOutboundBuffer in) throws Exception {
61          throw new UnsupportedOperationException();
62      }
63  
64      @Override
65      protected Object filterOutboundMessage(Object msg) throws Exception {
66          throw new UnsupportedOperationException();
67      }
68  
69      protected abstract Channel newChildChannel(int fd, byte[] remote, int offset, int len) throws Exception;
70  
71      final class EpollServerSocketUnsafe extends AbstractEpollUnsafe {
72          // Will hold the remote address after accept(...) was successful.
73          // We need 24 bytes for the address as maximum + 1 byte for storing the length.
74          // So use 26 bytes as it's a power of two.
75          private final byte[] acceptedAddress = new byte[26];
76  
77          @Override
78          public void connect(SocketAddress socketAddress, SocketAddress socketAddress2, ChannelPromise channelPromise) {
79              // Connect not supported by ServerChannel implementations
80              channelPromise.setFailure(new UnsupportedOperationException());
81          }
82  
83          @Override
84          void epollInReady() {
85              assert eventLoop().inEventLoop();
86              final ChannelConfig config = config();
87              if (shouldBreakEpollInReady(config)) {
88                  clearEpollIn0();
89                  return;
90              }
91              final EpollRecvByteAllocatorHandle allocHandle = recvBufAllocHandle();
92              final ChannelPipeline pipeline = pipeline();
93              allocHandle.reset(config);
94              allocHandle.attemptedBytesRead(1);
95  
96              Throwable exception = null;
97              try {
98                  try {
99                      do {
100                         // lastBytesRead represents the fd. We use lastBytesRead because it must be set so that the
101                         // EpollRecvByteAllocatorHandle knows if it should try to read again or not when autoRead is
102                         // enabled.
103                         allocHandle.lastBytesRead(socket.accept(acceptedAddress));
104                         if (allocHandle.lastBytesRead() == -1) {
105                             // this means everything was handled for now
106                             break;
107                         }
108                         allocHandle.incMessagesRead(1);
109 
110                         readPending = false;
111                         pipeline.fireChannelRead(newChildChannel(allocHandle.lastBytesRead(), acceptedAddress, 1,
112                                                                  acceptedAddress[0]));
113                     } while (allocHandle.continueReading());
114                 } catch (Throwable t) {
115                     exception = t;
116                 }
117                 allocHandle.readComplete();
118                 pipeline.fireChannelReadComplete();
119 
120                 if (exception != null) {
121                     pipeline.fireExceptionCaught(exception);
122                 }
123             } finally {
124                 if (shouldStopReading(config)) {
125                     clearEpollIn();
126                 }
127             }
128         }
129     }
130 
131     @Override
132     protected boolean doConnect(SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
133         throw new UnsupportedOperationException();
134     }
135 }