View Javadoc
1   /*
2    * Copyright 2011 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    * http://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.sctp.nio;
17  
18  import com.sun.nio.sctp.SctpChannel;
19  import com.sun.nio.sctp.SctpServerChannel;
20  import io.netty.channel.ChannelException;
21  import io.netty.channel.ChannelFuture;
22  import io.netty.channel.ChannelMetadata;
23  import io.netty.channel.ChannelOutboundBuffer;
24  import io.netty.channel.ChannelPromise;
25  import io.netty.channel.nio.AbstractNioMessageChannel;
26  import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
27  import io.netty.channel.sctp.SctpServerChannelConfig;
28  
29  import java.io.IOException;
30  import java.net.InetAddress;
31  import java.net.InetSocketAddress;
32  import java.net.SocketAddress;
33  import java.nio.channels.SelectionKey;
34  import java.util.Collections;
35  import java.util.Iterator;
36  import java.util.LinkedHashSet;
37  import java.util.List;
38  import java.util.Set;
39  
40  /**
41   * {@link io.netty.channel.sctp.SctpServerChannel} implementation which use non-blocking mode to accept new
42   * connections and create the {@link NioSctpChannel} for them.
43   *
44   * Be aware that not all operations systems support SCTP. Please refer to the documentation of your operation system,
45   * to understand what you need to do to use it. Also this feature is only supported on Java 7+.
46   */
47  public class NioSctpServerChannel extends AbstractNioMessageChannel
48          implements io.netty.channel.sctp.SctpServerChannel {
49      private static final ChannelMetadata METADATA = new ChannelMetadata(false, 16);
50  
51      private static SctpServerChannel newSocket() {
52          try {
53              return SctpServerChannel.open();
54          } catch (IOException e) {
55              throw new ChannelException(
56                      "Failed to open a server socket.", e);
57          }
58      }
59  
60      private final SctpServerChannelConfig config;
61  
62      /**
63       * Create a new instance
64       */
65      public NioSctpServerChannel() {
66          super(null, newSocket(), SelectionKey.OP_ACCEPT);
67          config = new NioSctpServerChannelConfig(this, javaChannel());
68      }
69  
70      @Override
71      public ChannelMetadata metadata() {
72          return METADATA;
73      }
74  
75      @Override
76      public Set<InetSocketAddress> allLocalAddresses() {
77          try {
78              final Set<SocketAddress> allLocalAddresses = javaChannel().getAllLocalAddresses();
79              final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
80              for (SocketAddress socketAddress : allLocalAddresses) {
81                  addresses.add((InetSocketAddress) socketAddress);
82              }
83              return addresses;
84          } catch (Throwable ignored) {
85              return Collections.emptySet();
86          }
87      }
88  
89      @Override
90      public SctpServerChannelConfig config() {
91          return config;
92      }
93  
94      @Override
95      public boolean isActive() {
96          return isOpen() && !allLocalAddresses().isEmpty();
97      }
98  
99      @Override
100     public InetSocketAddress remoteAddress() {
101         return null;
102     }
103 
104     @Override
105     public InetSocketAddress localAddress() {
106         return (InetSocketAddress) super.localAddress();
107     }
108 
109     @Override
110     protected SctpServerChannel javaChannel() {
111         return (SctpServerChannel) super.javaChannel();
112     }
113 
114     @Override
115     protected SocketAddress localAddress0() {
116         try {
117             Iterator<SocketAddress> i = javaChannel().getAllLocalAddresses().iterator();
118             if (i.hasNext()) {
119                 return i.next();
120             }
121         } catch (IOException e) {
122             // ignore
123         }
124         return null;
125     }
126 
127     @Override
128     protected void doBind(SocketAddress localAddress) throws Exception {
129         javaChannel().bind(localAddress, config.getBacklog());
130     }
131 
132     @Override
133     protected void doClose() throws Exception {
134         javaChannel().close();
135     }
136 
137     @Override
138     protected int doReadMessages(List<Object> buf) throws Exception {
139         SctpChannel ch = javaChannel().accept();
140         if (ch == null) {
141             return 0;
142         }
143         buf.add(new NioSctpChannel(this, ch));
144         return 1;
145     }
146 
147     @Override
148     public ChannelFuture bindAddress(InetAddress localAddress) {
149         return bindAddress(localAddress, newPromise());
150     }
151 
152     @Override
153     public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
154         if (eventLoop().inEventLoop()) {
155             try {
156                 javaChannel().bindAddress(localAddress);
157                 promise.setSuccess();
158             } catch (Throwable t) {
159                 promise.setFailure(t);
160             }
161         } else {
162             eventLoop().execute(new Runnable() {
163                 @Override
164                 public void run() {
165                     bindAddress(localAddress, promise);
166                 }
167             });
168         }
169         return promise;
170     }
171 
172     @Override
173     public ChannelFuture unbindAddress(InetAddress localAddress) {
174         return unbindAddress(localAddress, newPromise());
175     }
176 
177     @Override
178     public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
179         if (eventLoop().inEventLoop()) {
180             try {
181                 javaChannel().unbindAddress(localAddress);
182                 promise.setSuccess();
183             } catch (Throwable t) {
184                 promise.setFailure(t);
185             }
186         } else {
187             eventLoop().execute(new Runnable() {
188                 @Override
189                 public void run() {
190                     unbindAddress(localAddress, promise);
191                 }
192             });
193         }
194         return promise;
195     }
196 
197     // Unnecessary stuff
198     @Override
199     protected boolean doConnect(
200             SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
201         throw new UnsupportedOperationException();
202     }
203 
204     @Override
205     protected void doFinishConnect() throws Exception {
206         throw new UnsupportedOperationException();
207     }
208 
209     @Override
210     protected SocketAddress remoteAddress0() {
211         return null;
212     }
213 
214     @Override
215     protected void doDisconnect() throws Exception {
216         throw new UnsupportedOperationException();
217     }
218 
219     @Override
220     protected boolean doWriteMessage(Object msg, ChannelOutboundBuffer in) throws Exception {
221         throw new UnsupportedOperationException();
222     }
223 
224     @Override
225     protected Object filterOutboundMessage(Object msg) throws Exception {
226         throw new UnsupportedOperationException();
227     }
228 
229     private final class NioSctpServerChannelConfig extends DefaultSctpServerChannelConfig {
230         private NioSctpServerChannelConfig(NioSctpServerChannel channel, SctpServerChannel javaChannel) {
231             super(channel, javaChannel);
232         }
233 
234         @Override
235         protected void autoReadCleared() {
236             clearReadPending();
237         }
238     }
239 }