PageRenderTime 26ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/transport-sctp/src/main/java/io/netty/channel/sctp/oio/OioSctpServerChannel.java

https://gitlab.com/taichu/netty
Java | 308 lines | 243 code | 34 blank | 31 comment | 20 complexity | d486fc451ad7e5ff8af1d2c0b0978000 MD5 | raw file
  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. * 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.oio;
  17. import com.sun.nio.sctp.SctpChannel;
  18. import com.sun.nio.sctp.SctpServerChannel;
  19. import io.netty.channel.ChannelException;
  20. import io.netty.channel.ChannelFuture;
  21. import io.netty.channel.ChannelMetadata;
  22. import io.netty.channel.ChannelOutboundBuffer;
  23. import io.netty.channel.ChannelPromise;
  24. import io.netty.channel.oio.AbstractOioMessageChannel;
  25. import io.netty.channel.sctp.DefaultSctpServerChannelConfig;
  26. import io.netty.channel.sctp.SctpServerChannelConfig;
  27. import io.netty.util.internal.logging.InternalLogger;
  28. import io.netty.util.internal.logging.InternalLoggerFactory;
  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.nio.channels.Selector;
  35. import java.util.Collections;
  36. import java.util.Iterator;
  37. import java.util.LinkedHashSet;
  38. import java.util.List;
  39. import java.util.Set;
  40. /**
  41. * {@link io.netty.channel.sctp.SctpServerChannel} implementation which use blocking mode to accept new
  42. * connections and create the {@link OioSctpChannel} 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 OioSctpServerChannel extends AbstractOioMessageChannel
  48. implements io.netty.channel.sctp.SctpServerChannel {
  49. private static final InternalLogger logger =
  50. InternalLoggerFactory.getInstance(OioSctpServerChannel.class);
  51. private static final ChannelMetadata METADATA = new ChannelMetadata(false, 1);
  52. private static SctpServerChannel newServerSocket() {
  53. try {
  54. return SctpServerChannel.open();
  55. } catch (IOException e) {
  56. throw new ChannelException("failed to create a sctp server channel", e);
  57. }
  58. }
  59. private final SctpServerChannel sch;
  60. private final SctpServerChannelConfig config;
  61. private final Selector selector;
  62. /**
  63. * Create a new instance with an new {@link SctpServerChannel}
  64. */
  65. public OioSctpServerChannel() {
  66. this(newServerSocket());
  67. }
  68. /**
  69. * Create a new instance from the given {@link SctpServerChannel}
  70. *
  71. * @param sch the {@link SctpServerChannel} which is used by this instance
  72. */
  73. public OioSctpServerChannel(SctpServerChannel sch) {
  74. super(null);
  75. if (sch == null) {
  76. throw new NullPointerException("sctp server channel");
  77. }
  78. this.sch = sch;
  79. boolean success = false;
  80. try {
  81. sch.configureBlocking(false);
  82. selector = Selector.open();
  83. sch.register(selector, SelectionKey.OP_ACCEPT);
  84. config = new OioSctpServerChannelConfig(this, sch);
  85. success = true;
  86. } catch (Exception e) {
  87. throw new ChannelException("failed to initialize a sctp server channel", e);
  88. } finally {
  89. if (!success) {
  90. try {
  91. sch.close();
  92. } catch (IOException e) {
  93. logger.warn("Failed to close a sctp server channel.", e);
  94. }
  95. }
  96. }
  97. }
  98. @Override
  99. public ChannelMetadata metadata() {
  100. return METADATA;
  101. }
  102. @Override
  103. public SctpServerChannelConfig config() {
  104. return config;
  105. }
  106. @Override
  107. public InetSocketAddress remoteAddress() {
  108. return null;
  109. }
  110. @Override
  111. public InetSocketAddress localAddress() {
  112. return (InetSocketAddress) super.localAddress();
  113. }
  114. @Override
  115. public boolean isOpen() {
  116. return sch.isOpen();
  117. }
  118. @Override
  119. protected SocketAddress localAddress0() {
  120. try {
  121. Iterator<SocketAddress> i = sch.getAllLocalAddresses().iterator();
  122. if (i.hasNext()) {
  123. return i.next();
  124. }
  125. } catch (IOException e) {
  126. // ignore
  127. }
  128. return null;
  129. }
  130. @Override
  131. public Set<InetSocketAddress> allLocalAddresses() {
  132. try {
  133. final Set<SocketAddress> allLocalAddresses = sch.getAllLocalAddresses();
  134. final Set<InetSocketAddress> addresses = new LinkedHashSet<InetSocketAddress>(allLocalAddresses.size());
  135. for (SocketAddress socketAddress : allLocalAddresses) {
  136. addresses.add((InetSocketAddress) socketAddress);
  137. }
  138. return addresses;
  139. } catch (Throwable ignored) {
  140. return Collections.emptySet();
  141. }
  142. }
  143. @Override
  144. public boolean isActive() {
  145. return isOpen() && localAddress0() != null;
  146. }
  147. @Override
  148. protected void doBind(SocketAddress localAddress) throws Exception {
  149. sch.bind(localAddress, config.getBacklog());
  150. }
  151. @Override
  152. protected void doClose() throws Exception {
  153. try {
  154. selector.close();
  155. } catch (IOException e) {
  156. logger.warn("Failed to close a selector.", e);
  157. }
  158. sch.close();
  159. }
  160. @Override
  161. protected int doReadMessages(List<Object> buf) throws Exception {
  162. if (!isActive()) {
  163. return -1;
  164. }
  165. SctpChannel s = null;
  166. int acceptedChannels = 0;
  167. try {
  168. final int selectedKeys = selector.select(SO_TIMEOUT);
  169. if (selectedKeys > 0) {
  170. final Iterator<SelectionKey> selectionKeys = selector.selectedKeys().iterator();
  171. for (;;) {
  172. SelectionKey key = selectionKeys.next();
  173. selectionKeys.remove();
  174. if (key.isAcceptable()) {
  175. s = sch.accept();
  176. if (s != null) {
  177. buf.add(new OioSctpChannel(this, s));
  178. acceptedChannels ++;
  179. }
  180. }
  181. if (!selectionKeys.hasNext()) {
  182. return acceptedChannels;
  183. }
  184. }
  185. }
  186. } catch (Throwable t) {
  187. logger.warn("Failed to create a new channel from an accepted sctp channel.", t);
  188. if (s != null) {
  189. try {
  190. s.close();
  191. } catch (Throwable t2) {
  192. logger.warn("Failed to close a sctp channel.", t2);
  193. }
  194. }
  195. }
  196. return acceptedChannels;
  197. }
  198. @Override
  199. public ChannelFuture bindAddress(InetAddress localAddress) {
  200. return bindAddress(localAddress, newPromise());
  201. }
  202. @Override
  203. public ChannelFuture bindAddress(final InetAddress localAddress, final ChannelPromise promise) {
  204. if (eventLoop().inEventLoop()) {
  205. try {
  206. sch.bindAddress(localAddress);
  207. promise.setSuccess();
  208. } catch (Throwable t) {
  209. promise.setFailure(t);
  210. }
  211. } else {
  212. eventLoop().execute(new Runnable() {
  213. @Override
  214. public void run() {
  215. bindAddress(localAddress, promise);
  216. }
  217. });
  218. }
  219. return promise;
  220. }
  221. @Override
  222. public ChannelFuture unbindAddress(InetAddress localAddress) {
  223. return unbindAddress(localAddress, newPromise());
  224. }
  225. @Override
  226. public ChannelFuture unbindAddress(final InetAddress localAddress, final ChannelPromise promise) {
  227. if (eventLoop().inEventLoop()) {
  228. try {
  229. sch.unbindAddress(localAddress);
  230. promise.setSuccess();
  231. } catch (Throwable t) {
  232. promise.setFailure(t);
  233. }
  234. } else {
  235. eventLoop().execute(new Runnable() {
  236. @Override
  237. public void run() {
  238. unbindAddress(localAddress, promise);
  239. }
  240. });
  241. }
  242. return promise;
  243. }
  244. @Override
  245. protected void doConnect(
  246. SocketAddress remoteAddress, SocketAddress localAddress) throws Exception {
  247. throw new UnsupportedOperationException();
  248. }
  249. @Override
  250. protected SocketAddress remoteAddress0() {
  251. return null;
  252. }
  253. @Override
  254. protected void doDisconnect() throws Exception {
  255. throw new UnsupportedOperationException();
  256. }
  257. @Override
  258. protected void doWrite(ChannelOutboundBuffer in) throws Exception {
  259. throw new UnsupportedOperationException();
  260. }
  261. @Override
  262. protected Object filterOutboundMessage(Object msg) throws Exception {
  263. throw new UnsupportedOperationException();
  264. }
  265. private final class OioSctpServerChannelConfig extends DefaultSctpServerChannelConfig {
  266. private OioSctpServerChannelConfig(OioSctpServerChannel channel, SctpServerChannel javaChannel) {
  267. super(channel, javaChannel);
  268. }
  269. @Override
  270. protected void autoReadCleared() {
  271. clearReadPending();
  272. }
  273. }
  274. }