View Javadoc

1   /*
2    *  Licensed to the Apache Software Foundation (ASF) under one
3    *  or more contributor license agreements.  See the NOTICE file
4    *  distributed with this work for additional information
5    *  regarding copyright ownership.  The ASF licenses this file
6    *  to you under the Apache License, Version 2.0 (the
7    *  "License"); you may not use this file except in compliance
8    *  with the License.  You may obtain a copy of the License at
9    *
10   *    http://www.apache.org/licenses/LICENSE-2.0
11   *
12   *  Unless required by applicable law or agreed to in writing,
13   *  software distributed under the License is distributed on an
14   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   *  KIND, either express or implied.  See the License for the
16   *  specific language governing permissions and limitations
17   *  under the License.
18   *
19   */
20  package org.apache.mina.transport.socket.nio;
21  
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.net.UnknownHostException;
29  import java.util.Iterator;
30  import java.util.LinkedHashMap;
31  import java.util.Map;
32  import java.util.Map.Entry;
33  
34  import org.apache.mina.common.ExceptionMonitor;
35  import org.apache.mina.common.IoConnectorConfig;
36  import org.apache.mina.common.support.BaseIoSessionConfig;
37  
38  /**
39   * An {@link IoConnectorConfig} for {@link SocketConnector}.
40   *
41   * @author The Apache Directory Project (mina-dev@directory.apache.org)
42   * @version $Rev: 647053 $, $Date: 2008-04-11 14:40:04 +0900 (Fri, 11 Apr 2008) $
43   */
44  public class SocketSessionConfigImpl extends BaseIoSessionConfig implements
45          SocketSessionConfig {
46      private static Map TEST_ADDRESSES = new LinkedHashMap();
47  
48      private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
49  
50      private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false;
51  
52      private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false;
53  
54      private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false;
55  
56      private static boolean DEFAULT_REUSE_ADDRESS = false;
57  
58      private static int DEFAULT_RECEIVE_BUFFER_SIZE = 1024;
59  
60      private static int DEFAULT_SEND_BUFFER_SIZE = 1024;
61  
62      private static int DEFAULT_TRAFFIC_CLASS = 0;
63  
64      private static boolean DEFAULT_KEEP_ALIVE = false;
65  
66      private static boolean DEFAULT_OOB_INLINE = false;
67  
68      private static int DEFAULT_SO_LINGER = -1;
69  
70      private static boolean DEFAULT_TCP_NO_DELAY = false;
71  
72      static {
73          initializeTestAddresses();
74  
75          boolean success = false;
76          for (Iterator i = TEST_ADDRESSES.entrySet().iterator(); i.hasNext();) {
77              Entry e = (Entry) i.next();
78              success = initializeDefaultSocketParameters((InetSocketAddress) e
79                      .getKey(), (InetAddress) e.getValue());
80              if (success) {
81                  break;
82              }
83          }
84  
85          if (!success) {
86              initializeFallbackDefaultSocketParameters();
87          }
88      }
89  
90      private static void initializeFallbackDefaultSocketParameters() {
91          Socket unconnectedSocket = new Socket(); // Use a unconnected socket.
92          try {
93              initializeDefaultSocketParameters(unconnectedSocket);
94          } catch (SocketException se) {
95              ExceptionMonitor.getInstance().exceptionCaught(se);
96              try {
97                  unconnectedSocket.close();
98              } catch (IOException ioe) {
99                  ExceptionMonitor.getInstance().exceptionCaught(ioe);
100             }
101         }
102     }
103 
104     private static void initializeTestAddresses() {
105         try {
106             // These two tests were disabled due to DIRMINA-560
107             // (IPv4 localhost TEST_ADDRESS causes server to hang)
108 
109             // IPv6 localhost
110             //TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
111             //        .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112             //                0, 0, 0, 0, 1 }), 0), InetAddress
113             //        .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
114             //                0, 0, 0, 0, 1 }));
115 
116             // IPv4 localhost
117             //TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
118             //        .getByAddress(new byte[] { 127, 0, 0, 1 }), 0), InetAddress
119             //        .getByAddress(new byte[] { 127, 0, 0, 1 }));
120 
121             // Bind to wildcard interface and connect to IPv6 localhost
122             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
123                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
124                             0, 0, 0, 0, 1 }));
125 
126             // Bind to wildcard interface and connect to IPv4 localhost
127             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
128                     .getByAddress(new byte[] { 127, 0, 0, 1 }));
129 
130         } catch (UnknownHostException e) {
131             ExceptionMonitor.getInstance().exceptionCaught(e);
132         }
133     }
134 
135     private static boolean initializeDefaultSocketParameters(
136             InetSocketAddress bindAddress, InetAddress connectAddress) {
137         ServerSocket ss = null;
138         Socket socket = null;
139 
140         try {
141             ss = new ServerSocket();
142             ss.bind(bindAddress);
143             socket = new Socket();
144 
145             // Timeout is set to 10 seconds in case of infinite blocking
146             // on some platform.
147             socket.connect(new InetSocketAddress(connectAddress, ss
148                     .getLocalPort()), 10000);
149 
150             initializeDefaultSocketParameters(socket);
151             return true;
152         } catch (Exception e) {
153             return false;
154         } finally {
155             if (socket != null) {
156                 try {
157                     socket.close();
158                 } catch (IOException e) {
159                     ExceptionMonitor.getInstance().exceptionCaught(e);
160                 }
161             }
162 
163             if (ss != null) {
164                 try {
165                     ss.close();
166                 } catch (IOException e) {
167                     ExceptionMonitor.getInstance().exceptionCaught(e);
168                 }
169             }
170         }
171     }
172 
173     private static void initializeDefaultSocketParameters(Socket socket)
174             throws SocketException {
175         DEFAULT_REUSE_ADDRESS = socket.getReuseAddress();
176         DEFAULT_RECEIVE_BUFFER_SIZE = socket.getReceiveBufferSize();
177         DEFAULT_SEND_BUFFER_SIZE = socket.getSendBufferSize();
178         DEFAULT_KEEP_ALIVE = socket.getKeepAlive();
179         DEFAULT_OOB_INLINE = socket.getOOBInline();
180         DEFAULT_SO_LINGER = socket.getSoLinger();
181         DEFAULT_TCP_NO_DELAY = socket.getTcpNoDelay();
182 
183         // Check if setReceiveBufferSize is supported.
184         try {
185             socket.setReceiveBufferSize(DEFAULT_RECEIVE_BUFFER_SIZE);
186             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = true;
187         } catch (SocketException e) {
188             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
189         }
190 
191         // Check if setSendBufferSize is supported.
192         try {
193             socket.setSendBufferSize(DEFAULT_SEND_BUFFER_SIZE);
194             SET_SEND_BUFFER_SIZE_AVAILABLE = true;
195         } catch (SocketException e) {
196             SET_SEND_BUFFER_SIZE_AVAILABLE = false;
197         }
198 
199         // Check if getTrafficClass is supported.
200         try {
201             DEFAULT_TRAFFIC_CLASS = socket.getTrafficClass();
202             GET_TRAFFIC_CLASS_AVAILABLE = true;
203         } catch (SocketException e) {
204             GET_TRAFFIC_CLASS_AVAILABLE = false;
205             DEFAULT_TRAFFIC_CLASS = 0;
206         }
207     }
208 
209     public static boolean isSetReceiveBufferSizeAvailable() {
210         return SET_RECEIVE_BUFFER_SIZE_AVAILABLE;
211     }
212 
213     public static boolean isSetSendBufferSizeAvailable() {
214         return SET_SEND_BUFFER_SIZE_AVAILABLE;
215     }
216 
217     public static boolean isGetTrafficClassAvailable() {
218         return GET_TRAFFIC_CLASS_AVAILABLE;
219     }
220 
221     public static boolean isSetTrafficClassAvailable() {
222         return SET_TRAFFIC_CLASS_AVAILABLE;
223     }
224 
225     private boolean reuseAddress = DEFAULT_REUSE_ADDRESS;
226 
227     private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
228 
229     private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE;
230 
231     private int trafficClass = DEFAULT_TRAFFIC_CLASS;
232 
233     private boolean keepAlive = DEFAULT_KEEP_ALIVE;
234 
235     private boolean oobInline = DEFAULT_OOB_INLINE;
236 
237     private int soLinger = DEFAULT_SO_LINGER;
238 
239     private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY;
240 
241     /**
242      * Creates a new instance.
243      */
244     public SocketSessionConfigImpl() {
245     }
246 
247     public boolean isReuseAddress() {
248         return reuseAddress;
249     }
250 
251     public void setReuseAddress(boolean reuseAddress) {
252         this.reuseAddress = reuseAddress;
253     }
254 
255     public int getReceiveBufferSize() {
256         return receiveBufferSize;
257     }
258 
259     public void setReceiveBufferSize(int receiveBufferSize) {
260         this.receiveBufferSize = receiveBufferSize;
261     }
262 
263     public int getSendBufferSize() {
264         return sendBufferSize;
265     }
266 
267     public void setSendBufferSize(int sendBufferSize) {
268         this.sendBufferSize = sendBufferSize;
269     }
270 
271     public int getTrafficClass() {
272         return trafficClass;
273     }
274 
275     public void setTrafficClass(int trafficClass) {
276         this.trafficClass = trafficClass;
277     }
278 
279     public boolean isKeepAlive() {
280         return keepAlive;
281     }
282 
283     public void setKeepAlive(boolean keepAlive) {
284         this.keepAlive = keepAlive;
285     }
286 
287     public boolean isOobInline() {
288         return oobInline;
289     }
290 
291     public void setOobInline(boolean oobInline) {
292         this.oobInline = oobInline;
293     }
294 
295     public int getSoLinger() {
296         return soLinger;
297     }
298 
299     public void setSoLinger(int soLinger) {
300         this.soLinger = soLinger;
301     }
302 
303     public boolean isTcpNoDelay() {
304         return tcpNoDelay;
305     }
306 
307     public void setTcpNoDelay(boolean tcpNoDelay) {
308         this.tcpNoDelay = tcpNoDelay;
309     }
310 }