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