/qpid-0.16/java/common/src/main/java/org/apache/qpid/transport/network/io/IoNetworkTransport.java

# · Java · 277 lines · 214 code · 38 blank · 25 comment · 13 complexity · dc096a86848ace93d03f4fe8badb4393 MD5 · raw file

  1. /*
  2. *
  3. * Licensed to the Apache Software Foundation (ASF) under one
  4. * or more contributor license agreements. See the NOTICE file
  5. * distributed with this work for additional information
  6. * regarding copyright ownership. The ASF licenses this file
  7. * to you under the Apache License, Version 2.0 (the
  8. * "License"); you may not use this file except in compliance
  9. * with the License. You may obtain a copy of the License at
  10. *
  11. * http://www.apache.org/licenses/LICENSE-2.0
  12. *
  13. * Unless required by applicable law or agreed to in writing,
  14. * software distributed under the License is distributed on an
  15. * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  16. * KIND, either express or implied. See the License for the
  17. * specific language governing permissions and limitations
  18. * under the License.
  19. *
  20. */
  21. package org.apache.qpid.transport.network.io;
  22. import java.io.IOException;
  23. import java.net.InetAddress;
  24. import java.net.InetSocketAddress;
  25. import java.net.ServerSocket;
  26. import java.net.Socket;
  27. import java.net.SocketException;
  28. import java.nio.ByteBuffer;
  29. import javax.net.ssl.SSLContext;
  30. import javax.net.ssl.SSLServerSocketFactory;
  31. import org.apache.qpid.protocol.ProtocolEngine;
  32. import org.apache.qpid.protocol.ProtocolEngineFactory;
  33. import org.apache.qpid.transport.ConnectionSettings;
  34. import org.apache.qpid.transport.NetworkTransportConfiguration;
  35. import org.apache.qpid.transport.Receiver;
  36. import org.apache.qpid.transport.TransportException;
  37. import org.apache.qpid.transport.network.IncomingNetworkTransport;
  38. import org.apache.qpid.transport.network.NetworkConnection;
  39. import org.apache.qpid.transport.network.OutgoingNetworkTransport;
  40. import org.slf4j.LoggerFactory;
  41. public class IoNetworkTransport implements OutgoingNetworkTransport, IncomingNetworkTransport
  42. {
  43. private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(IoNetworkTransport.class);
  44. private Socket _socket;
  45. private IoNetworkConnection _connection;
  46. private long _timeout = 60000;
  47. private AcceptingThread _acceptor;
  48. public NetworkConnection connect(ConnectionSettings settings, Receiver<ByteBuffer> delegate, SSLContext sslContext)
  49. {
  50. int sendBufferSize = settings.getWriteBufferSize();
  51. int receiveBufferSize = settings.getReadBufferSize();
  52. try
  53. {
  54. _socket = new Socket();
  55. _socket.setReuseAddress(true);
  56. _socket.setTcpNoDelay(settings.isTcpNodelay());
  57. _socket.setSendBufferSize(sendBufferSize);
  58. _socket.setReceiveBufferSize(receiveBufferSize);
  59. if(LOGGER.isDebugEnabled())
  60. {
  61. LOGGER.debug("SO_RCVBUF : " + _socket.getReceiveBufferSize());
  62. LOGGER.debug("SO_SNDBUF : " + _socket.getSendBufferSize());
  63. LOGGER.debug("TCP_NODELAY : " + _socket.getTcpNoDelay());
  64. }
  65. InetAddress address = InetAddress.getByName(settings.getHost());
  66. _socket.connect(new InetSocketAddress(address, settings.getPort()));
  67. }
  68. catch (SocketException e)
  69. {
  70. throw new TransportException("Error connecting to broker", e);
  71. }
  72. catch (IOException e)
  73. {
  74. throw new TransportException("Error connecting to broker", e);
  75. }
  76. try
  77. {
  78. _connection = new IoNetworkConnection(_socket, delegate, sendBufferSize, receiveBufferSize, _timeout);
  79. _connection.start();
  80. }
  81. catch(Exception e)
  82. {
  83. try
  84. {
  85. _socket.close();
  86. }
  87. catch(IOException ioe)
  88. {
  89. //ignored, throw based on original exception
  90. }
  91. throw new TransportException("Error creating network connection", e);
  92. }
  93. return _connection;
  94. }
  95. public void close()
  96. {
  97. if(_connection != null)
  98. {
  99. _connection.close();
  100. }
  101. if(_acceptor != null)
  102. {
  103. _acceptor.close();
  104. }
  105. }
  106. public NetworkConnection getConnection()
  107. {
  108. return _connection;
  109. }
  110. public void accept(NetworkTransportConfiguration config, ProtocolEngineFactory factory, SSLContext sslContext)
  111. {
  112. try
  113. {
  114. _acceptor = new AcceptingThread(config, factory, sslContext);
  115. _acceptor.setDaemon(false);
  116. _acceptor.start();
  117. }
  118. catch (IOException e)
  119. {
  120. throw new TransportException("Unable to start server socket", e);
  121. }
  122. }
  123. private class AcceptingThread extends Thread
  124. {
  125. private volatile boolean _closed = false;
  126. private NetworkTransportConfiguration _config;
  127. private ProtocolEngineFactory _factory;
  128. private SSLContext _sslContext;
  129. private ServerSocket _serverSocket;
  130. private AcceptingThread(NetworkTransportConfiguration config,
  131. ProtocolEngineFactory factory,
  132. SSLContext sslContext)
  133. throws IOException
  134. {
  135. _config = config;
  136. _factory = factory;
  137. _sslContext = sslContext;
  138. InetSocketAddress address = config.getAddress();
  139. if(sslContext == null)
  140. {
  141. _serverSocket = new ServerSocket();
  142. }
  143. else
  144. {
  145. SSLServerSocketFactory socketFactory = _sslContext.getServerSocketFactory();
  146. _serverSocket = socketFactory.createServerSocket();
  147. }
  148. _serverSocket.setReuseAddress(true);
  149. _serverSocket.bind(address);
  150. }
  151. /**
  152. Close the underlying ServerSocket if it has not already been closed.
  153. */
  154. public void close()
  155. {
  156. LOGGER.debug("Shutting down the Acceptor");
  157. _closed = true;
  158. if (!_serverSocket.isClosed())
  159. {
  160. try
  161. {
  162. _serverSocket.close();
  163. }
  164. catch (IOException e)
  165. {
  166. throw new TransportException(e);
  167. }
  168. }
  169. }
  170. @Override
  171. public void run()
  172. {
  173. try
  174. {
  175. while (!_closed)
  176. {
  177. Socket socket = null;
  178. try
  179. {
  180. socket = _serverSocket.accept();
  181. socket.setTcpNoDelay(_config.getTcpNoDelay());
  182. final Integer sendBufferSize = _config.getSendBufferSize();
  183. final Integer receiveBufferSize = _config.getReceiveBufferSize();
  184. socket.setSendBufferSize(sendBufferSize);
  185. socket.setReceiveBufferSize(receiveBufferSize);
  186. ProtocolEngine engine = _factory.newProtocolEngine();
  187. NetworkConnection connection = new IoNetworkConnection(socket, engine, sendBufferSize, receiveBufferSize, _timeout);
  188. engine.setNetworkConnection(connection, connection.getSender());
  189. connection.start();
  190. }
  191. catch(RuntimeException e)
  192. {
  193. LOGGER.error("Error in Acceptor thread on port " + _config.getPort(), e);
  194. closeSocketIfNecessary(socket);
  195. }
  196. catch(IOException e)
  197. {
  198. if(!_closed)
  199. {
  200. LOGGER.error("Error in Acceptor thread on port " + _config.getPort(), e);
  201. closeSocketIfNecessary(socket);
  202. try
  203. {
  204. //Delay to avoid tight spinning the loop during issues such as too many open files
  205. Thread.sleep(1000);
  206. }
  207. catch (InterruptedException ie)
  208. {
  209. LOGGER.debug("Stopping acceptor due to interrupt request");
  210. _closed = true;
  211. }
  212. }
  213. }
  214. }
  215. }
  216. finally
  217. {
  218. if(LOGGER.isDebugEnabled())
  219. {
  220. LOGGER.debug("Acceptor exiting, no new connections will be accepted on port " + _config.getPort());
  221. }
  222. }
  223. }
  224. private void closeSocketIfNecessary(final Socket socket)
  225. {
  226. if(socket != null)
  227. {
  228. try
  229. {
  230. socket.close();
  231. }
  232. catch (IOException e)
  233. {
  234. LOGGER.debug("Exception while closing socket", e);
  235. }
  236. }
  237. }
  238. }
  239. }