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;
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.LinkedHashMap;
30  import java.util.Map;
31  import java.util.Map.Entry;
32  
33  import org.apache.mina.common.ExceptionMonitor;
34  
35  /**
36   * A default implementation of {@link SocketSessionConfig}.
37   *
38   * @author The Apache MINA Project (dev@mina.apache.org)
39   * @version $Rev: 576455 $, $Date: 2007-09-17 08:39:24 -0600 (Mon, 17 Sep 2007) $
40   */
41  public class DefaultSocketSessionConfig extends AbstractSocketSessionConfig {
42  
43      private static Map<InetSocketAddress, InetAddress> TEST_ADDRESSES = new LinkedHashMap<InetSocketAddress, InetAddress>();
44  
45      private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
46  
47      private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false;
48  
49      private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false;
50  
51      private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false;
52  
53      private static boolean DEFAULT_REUSE_ADDRESS = false;
54  
55      private static int DEFAULT_RECEIVE_BUFFER_SIZE = 1024;
56  
57      private static int DEFAULT_SEND_BUFFER_SIZE = 1024;
58  
59      private static int DEFAULT_TRAFFIC_CLASS = 0;
60  
61      private static boolean DEFAULT_KEEP_ALIVE = false;
62  
63      private static boolean DEFAULT_OOB_INLINE = false;
64  
65      private static int DEFAULT_SO_LINGER = -1;
66  
67      private static boolean DEFAULT_TCP_NO_DELAY = false;
68  
69      static {
70          initializeTestAddresses();
71  
72          boolean success = false;
73          for (Entry<InetSocketAddress, InetAddress> e : TEST_ADDRESSES
74                  .entrySet()) {
75              success = initializeDefaultSocketParameters(e.getKey(), e
76                      .getValue());
77              if (success) {
78                  break;
79              }
80          }
81  
82          if (!success) {
83              initializeFallbackDefaultSocketParameters();
84          }
85      }
86  
87      private static void initializeFallbackDefaultSocketParameters() {
88          Socket unconnectedSocket = new Socket(); // Use a unconnected socket.
89          try {
90              initializeDefaultSocketParameters(unconnectedSocket);
91          } catch (SocketException se) {
92              ExceptionMonitor.getInstance().exceptionCaught(se);
93  
94              try {
95                  unconnectedSocket.close();
96              } catch (IOException ioe) {
97                  ExceptionMonitor.getInstance().exceptionCaught(ioe);
98              }
99          }
100     }
101 
102     private static void initializeTestAddresses() {
103         try {
104             // IPv6 localhost
105             TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
106                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
107                             0, 0, 0, 0, 1 }), 0), InetAddress
108                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109                             0, 0, 0, 0, 1 }));
110 
111             // IPv4 localhost
112             TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
113                     .getByAddress(new byte[] { 127, 0, 0, 1 }), 0), InetAddress
114                     .getByAddress(new byte[] { 127, 0, 0, 1 }));
115 
116             // Bind to wildcard interface and connect to IPv6 localhost
117             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
118                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
119                             0, 0, 0, 0, 1 }));
120 
121             // Bind to wildcard interface and connect to IPv4 localhost
122             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
123                     .getByAddress(new byte[] { 127, 0, 0, 1 }));
124 
125         } catch (UnknownHostException e) {
126             ExceptionMonitor.getInstance().exceptionCaught(e);
127         }
128     }
129 
130     private static boolean initializeDefaultSocketParameters(
131             InetSocketAddress bindAddress, InetAddress connectAddress) {
132         ServerSocket ss = null;
133         Socket socket = null;
134 
135         try {
136             ss = new ServerSocket();
137             ss.bind(bindAddress);
138             socket = new Socket();
139 
140             // Timeout is set to 10 seconds in case of infinite blocking
141             // on some platform.
142             socket.connect(new InetSocketAddress(connectAddress, ss
143                     .getLocalPort()), 10000);
144 
145             initializeDefaultSocketParameters(socket);
146             return true;
147         } catch (Exception e) {
148             return false;
149         } finally {
150             if (socket != null) {
151                 try {
152                     socket.close();
153                 } catch (IOException e) {
154                     ExceptionMonitor.getInstance().exceptionCaught(e);
155                 }
156             }
157 
158             if (ss != null) {
159                 try {
160                     ss.close();
161                 } catch (IOException e) {
162                     ExceptionMonitor.getInstance().exceptionCaught(e);
163                 }
164             }
165         }
166     }
167 
168     private static void initializeDefaultSocketParameters(Socket socket)
169             throws SocketException {
170         DEFAULT_REUSE_ADDRESS = socket.getReuseAddress();
171         DEFAULT_RECEIVE_BUFFER_SIZE = socket.getReceiveBufferSize();
172         DEFAULT_SEND_BUFFER_SIZE = socket.getSendBufferSize();
173         DEFAULT_KEEP_ALIVE = socket.getKeepAlive();
174         DEFAULT_OOB_INLINE = socket.getOOBInline();
175         DEFAULT_SO_LINGER = socket.getSoLinger();
176         DEFAULT_TCP_NO_DELAY = socket.getTcpNoDelay();
177 
178         // Check if setReceiveBufferSize is supported.
179         try {
180             socket.setReceiveBufferSize(DEFAULT_RECEIVE_BUFFER_SIZE);
181             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = true;
182         } catch (SocketException e) {
183             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
184         }
185 
186         // Check if setSendBufferSize is supported.
187         try {
188             socket.setSendBufferSize(DEFAULT_SEND_BUFFER_SIZE);
189             SET_SEND_BUFFER_SIZE_AVAILABLE = true;
190         } catch (SocketException e) {
191             SET_SEND_BUFFER_SIZE_AVAILABLE = false;
192         }
193 
194         // Check if getTrafficClass is supported.
195         try {
196             DEFAULT_TRAFFIC_CLASS = socket.getTrafficClass();
197             GET_TRAFFIC_CLASS_AVAILABLE = true;
198         } catch (SocketException e) {
199             GET_TRAFFIC_CLASS_AVAILABLE = false;
200             DEFAULT_TRAFFIC_CLASS = 0;
201         }
202     }
203 
204     public static boolean isSetReceiveBufferSizeAvailable() {
205         return SET_RECEIVE_BUFFER_SIZE_AVAILABLE;
206     }
207 
208     public static boolean isSetSendBufferSizeAvailable() {
209         return SET_SEND_BUFFER_SIZE_AVAILABLE;
210     }
211 
212     public static boolean isGetTrafficClassAvailable() {
213         return GET_TRAFFIC_CLASS_AVAILABLE;
214     }
215 
216     public static boolean isSetTrafficClassAvailable() {
217         return SET_TRAFFIC_CLASS_AVAILABLE;
218     }
219 
220     private boolean reuseAddress = DEFAULT_REUSE_ADDRESS;
221 
222     private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
223 
224     private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE;
225 
226     private int trafficClass = DEFAULT_TRAFFIC_CLASS;
227 
228     private boolean keepAlive = DEFAULT_KEEP_ALIVE;
229 
230     private boolean oobInline = DEFAULT_OOB_INLINE;
231 
232     private int soLinger = DEFAULT_SO_LINGER;
233 
234     private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY;
235 
236     /**
237      * Creates a new instance.
238      */
239     public DefaultSocketSessionConfig() {
240     }
241 
242     public boolean isReuseAddress() {
243         return reuseAddress;
244     }
245 
246     public void setReuseAddress(boolean reuseAddress) {
247         this.reuseAddress = reuseAddress;
248     }
249 
250     public int getReceiveBufferSize() {
251         return receiveBufferSize;
252     }
253 
254     public void setReceiveBufferSize(int receiveBufferSize) {
255         this.receiveBufferSize = receiveBufferSize;
256     }
257 
258     public int getSendBufferSize() {
259         return sendBufferSize;
260     }
261 
262     public void setSendBufferSize(int sendBufferSize) {
263         this.sendBufferSize = sendBufferSize;
264     }
265 
266     public int getTrafficClass() {
267         return trafficClass;
268     }
269 
270     public void setTrafficClass(int trafficClass) {
271         this.trafficClass = trafficClass;
272     }
273 
274     public boolean isKeepAlive() {
275         return keepAlive;
276     }
277 
278     public void setKeepAlive(boolean keepAlive) {
279         this.keepAlive = keepAlive;
280     }
281 
282     public boolean isOobInline() {
283         return oobInline;
284     }
285 
286     public void setOobInline(boolean oobInline) {
287         this.oobInline = oobInline;
288     }
289 
290     public int getSoLinger() {
291         return soLinger;
292     }
293 
294     public void setSoLinger(int soLinger) {
295         this.soLinger = soLinger;
296     }
297 
298     public boolean isTcpNoDelay() {
299         return tcpNoDelay;
300     }
301 
302     public void setTcpNoDelay(boolean tcpNoDelay) {
303         this.tcpNoDelay = tcpNoDelay;
304     }
305 }