1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
42
43
44
45
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
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
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
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 }