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: 575240 $, $Date: 2007-09-13 11:32:54 +0200 (Thu, 13 Sep 2007) $
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             // IPv6 localhost
107             TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
108                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109                             0, 0, 0, 0, 1 }), 0), InetAddress
110                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
111                             0, 0, 0, 0, 1 }));
112 
113             // IPv4 localhost
114             TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
115                     .getByAddress(new byte[] { 127, 0, 0, 1 }), 0), InetAddress
116                     .getByAddress(new byte[] { 127, 0, 0, 1 }));
117 
118             // Bind to wildcard interface and connect to IPv6 localhost
119             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
120                     .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
121                             0, 0, 0, 0, 1 }));
122 
123             // Bind to wildcard interface and connect to IPv4 localhost
124             TEST_ADDRESSES.put(new InetSocketAddress(0), InetAddress
125                     .getByAddress(new byte[] { 127, 0, 0, 1 }));
126 
127         } catch (UnknownHostException e) {
128             ExceptionMonitor.getInstance().exceptionCaught(e);
129         }
130     }
131 
132     private static boolean initializeDefaultSocketParameters(
133             InetSocketAddress bindAddress, InetAddress connectAddress) {
134         ServerSocket ss = null;
135         Socket socket = null;
136 
137         try {
138             ss = new ServerSocket();
139             ss.bind(bindAddress);
140             socket = new Socket();
141 
142             // Timeout is set to 10 seconds in case of infinite blocking
143             // on some platform.
144             socket.connect(new InetSocketAddress(connectAddress, ss
145                     .getLocalPort()), 10000);
146 
147             initializeDefaultSocketParameters(socket);
148             return true;
149         } catch (Exception e) {
150             return false;
151         } finally {
152             if (socket != null) {
153                 try {
154                     socket.close();
155                 } catch (IOException e) {
156                     ExceptionMonitor.getInstance().exceptionCaught(e);
157                 }
158             }
159 
160             if (ss != null) {
161                 try {
162                     ss.close();
163                 } catch (IOException e) {
164                     ExceptionMonitor.getInstance().exceptionCaught(e);
165                 }
166             }
167         }
168     }
169 
170     private static void initializeDefaultSocketParameters(Socket socket)
171             throws SocketException {
172         DEFAULT_REUSE_ADDRESS = socket.getReuseAddress();
173         DEFAULT_RECEIVE_BUFFER_SIZE = socket.getReceiveBufferSize();
174         DEFAULT_SEND_BUFFER_SIZE = socket.getSendBufferSize();
175         DEFAULT_KEEP_ALIVE = socket.getKeepAlive();
176         DEFAULT_OOB_INLINE = socket.getOOBInline();
177         DEFAULT_SO_LINGER = socket.getSoLinger();
178         DEFAULT_TCP_NO_DELAY = socket.getTcpNoDelay();
179 
180         // Check if setReceiveBufferSize is supported.
181         try {
182             socket.setReceiveBufferSize(DEFAULT_RECEIVE_BUFFER_SIZE);
183             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = true;
184         } catch (SocketException e) {
185             SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
186         }
187 
188         // Check if setSendBufferSize is supported.
189         try {
190             socket.setSendBufferSize(DEFAULT_SEND_BUFFER_SIZE);
191             SET_SEND_BUFFER_SIZE_AVAILABLE = true;
192         } catch (SocketException e) {
193             SET_SEND_BUFFER_SIZE_AVAILABLE = false;
194         }
195 
196         // Check if getTrafficClass is supported.
197         try {
198             DEFAULT_TRAFFIC_CLASS = socket.getTrafficClass();
199             GET_TRAFFIC_CLASS_AVAILABLE = true;
200         } catch (SocketException e) {
201             GET_TRAFFIC_CLASS_AVAILABLE = false;
202             DEFAULT_TRAFFIC_CLASS = 0;
203         }
204     }
205 
206     public static boolean isSetReceiveBufferSizeAvailable() {
207         return SET_RECEIVE_BUFFER_SIZE_AVAILABLE;
208     }
209 
210     public static boolean isSetSendBufferSizeAvailable() {
211         return SET_SEND_BUFFER_SIZE_AVAILABLE;
212     }
213 
214     public static boolean isGetTrafficClassAvailable() {
215         return GET_TRAFFIC_CLASS_AVAILABLE;
216     }
217 
218     public static boolean isSetTrafficClassAvailable() {
219         return SET_TRAFFIC_CLASS_AVAILABLE;
220     }
221 
222     private boolean reuseAddress = DEFAULT_REUSE_ADDRESS;
223 
224     private int receiveBufferSize = DEFAULT_RECEIVE_BUFFER_SIZE;
225 
226     private int sendBufferSize = DEFAULT_SEND_BUFFER_SIZE;
227 
228     private int trafficClass = DEFAULT_TRAFFIC_CLASS;
229 
230     private boolean keepAlive = DEFAULT_KEEP_ALIVE;
231 
232     private boolean oobInline = DEFAULT_OOB_INLINE;
233 
234     private int soLinger = DEFAULT_SO_LINGER;
235 
236     private boolean tcpNoDelay = DEFAULT_TCP_NO_DELAY;
237 
238     /**
239      * Creates a new instance.
240      */
241     public SocketSessionConfigImpl() {
242     }
243 
244     public boolean isReuseAddress() {
245         return reuseAddress;
246     }
247 
248     public void setReuseAddress(boolean reuseAddress) {
249         this.reuseAddress = reuseAddress;
250     }
251 
252     public int getReceiveBufferSize() {
253         return receiveBufferSize;
254     }
255 
256     public void setReceiveBufferSize(int receiveBufferSize) {
257         this.receiveBufferSize = receiveBufferSize;
258     }
259 
260     public int getSendBufferSize() {
261         return sendBufferSize;
262     }
263 
264     public void setSendBufferSize(int sendBufferSize) {
265         this.sendBufferSize = sendBufferSize;
266     }
267 
268     public int getTrafficClass() {
269         return trafficClass;
270     }
271 
272     public void setTrafficClass(int trafficClass) {
273         this.trafficClass = trafficClass;
274     }
275 
276     public boolean isKeepAlive() {
277         return keepAlive;
278     }
279 
280     public void setKeepAlive(boolean keepAlive) {
281         this.keepAlive = keepAlive;
282     }
283 
284     public boolean isOobInline() {
285         return oobInline;
286     }
287 
288     public void setOobInline(boolean oobInline) {
289         this.oobInline = oobInline;
290     }
291 
292     public int getSoLinger() {
293         return soLinger;
294     }
295 
296     public void setSoLinger(int soLinger) {
297         this.soLinger = soLinger;
298     }
299 
300     public boolean isTcpNoDelay() {
301         return tcpNoDelay;
302     }
303 
304     public void setTcpNoDelay(boolean tcpNoDelay) {
305         this.tcpNoDelay = tcpNoDelay;
306     }
307 }