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.LinkedHashMap;
30  import java.util.Map;
31  import java.util.Map.Entry;
32  
33  import org.apache.mina.common.ExceptionMonitor;
34  import org.apache.mina.common.IoConnectorConfig;
35  import org.apache.mina.common.support.BaseIoSessionConfig;
36  
37  /**
38   * An {@link IoConnectorConfig} for {@link SocketConnector}.
39   *
40   * @author The Apache Directory Project (mina-dev@directory.apache.org)
41   * @version $Rev: 575241 $, $Date: 2007-09-13 18:32:59 +0900 (Thu, 13 Sep 2007) $
42   */
43  public class SocketSessionConfigImpl extends BaseIoSessionConfig implements
44          SocketSessionConfig {
45      private static Map<InetSocketAddress, InetAddress> TEST_ADDRESSES = new LinkedHashMap<InetSocketAddress, InetAddress>();
46  
47      private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
48  
49      private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false;
50  
51      private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false;
52  
53      private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false;
54  
55      private static boolean DEFAULT_REUSE_ADDRESS = false;
56  
57      private static int DEFAULT_RECEIVE_BUFFER_SIZE = 1024;
58  
59      private static int DEFAULT_SEND_BUFFER_SIZE = 1024;
60  
61      private static int DEFAULT_TRAFFIC_CLASS = 0;
62  
63      private static boolean DEFAULT_KEEP_ALIVE = false;
64  
65      private static boolean DEFAULT_OOB_INLINE = false;
66  
67      private static int DEFAULT_SO_LINGER = -1;
68  
69      private static boolean DEFAULT_TCP_NO_DELAY = false;
70  
71      static {
72          initializeTestAddresses();
73  
74          boolean success = false;
75          for (Entry<InetSocketAddress, InetAddress> e : TEST_ADDRESSES
76                  .entrySet()) {
77              success = initializeDefaultSocketParameters(e.getKey(), e
78                      .getValue());
79              if (success) {
80                  break;
81              }
82          }
83  
84          if (!success) {
85              initializeFallbackDefaultSocketParameters();
86          }
87      }
88  
89      private static void initializeFallbackDefaultSocketParameters() {
90          Socket unconnectedSocket = new Socket(); // Use a unconnected socket.
91          try {
92              initializeDefaultSocketParameters(unconnectedSocket);
93          } catch (SocketException se) {
94              ExceptionMonitor.getInstance().exceptionCaught(se);
95  
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 }