001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one
003: * or more contributor license agreements. See the NOTICE file
004: * distributed with this work for additional information
005: * regarding copyright ownership. The ASF licenses this file
006: * to you under the Apache License, Version 2.0 (the
007: * "License"); you may not use this file except in compliance
008: * with the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing,
013: * software distributed under the License is distributed on an
014: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
015: * KIND, either express or implied. See the License for the
016: * specific language governing permissions and limitations
017: * under the License.
018: *
019: */
020: package org.apache.mina.transport.socket;
021:
022: import java.io.IOException;
023: import java.net.InetAddress;
024: import java.net.InetSocketAddress;
025: import java.net.ServerSocket;
026: import java.net.Socket;
027: import java.net.SocketException;
028: import java.net.UnknownHostException;
029: import java.util.LinkedHashMap;
030: import java.util.Map;
031: import java.util.Map.Entry;
032:
033: import org.apache.mina.common.ExceptionMonitor;
034:
035: /**
036: * A default implementation of {@link SocketSessionConfig}.
037: *
038: * @author The Apache MINA Project (dev@mina.apache.org)
039: * @version $Rev: 576455 $, $Date: 2007-09-17 08:39:24 -0600 (Mon, 17 Sep 2007) $
040: */
041: public class DefaultSocketSessionConfig extends
042: AbstractSocketSessionConfig {
043:
044: private static Map<InetSocketAddress, InetAddress> TEST_ADDRESSES = new LinkedHashMap<InetSocketAddress, InetAddress>();
045:
046: private static boolean SET_RECEIVE_BUFFER_SIZE_AVAILABLE = false;
047:
048: private static boolean SET_SEND_BUFFER_SIZE_AVAILABLE = false;
049:
050: private static boolean GET_TRAFFIC_CLASS_AVAILABLE = false;
051:
052: private static boolean SET_TRAFFIC_CLASS_AVAILABLE = false;
053:
054: private static boolean DEFAULT_REUSE_ADDRESS = false;
055:
056: private static int DEFAULT_RECEIVE_BUFFER_SIZE = 1024;
057:
058: private static int DEFAULT_SEND_BUFFER_SIZE = 1024;
059:
060: private static int DEFAULT_TRAFFIC_CLASS = 0;
061:
062: private static boolean DEFAULT_KEEP_ALIVE = false;
063:
064: private static boolean DEFAULT_OOB_INLINE = false;
065:
066: private static int DEFAULT_SO_LINGER = -1;
067:
068: private static boolean DEFAULT_TCP_NO_DELAY = false;
069:
070: static {
071: initializeTestAddresses();
072:
073: boolean success = false;
074: for (Entry<InetSocketAddress, InetAddress> e : TEST_ADDRESSES
075: .entrySet()) {
076: success = initializeDefaultSocketParameters(e.getKey(), e
077: .getValue());
078: if (success) {
079: break;
080: }
081: }
082:
083: if (!success) {
084: initializeFallbackDefaultSocketParameters();
085: }
086: }
087:
088: private static void initializeFallbackDefaultSocketParameters() {
089: Socket unconnectedSocket = new Socket(); // Use a unconnected socket.
090: try {
091: initializeDefaultSocketParameters(unconnectedSocket);
092: } catch (SocketException se) {
093: ExceptionMonitor.getInstance().exceptionCaught(se);
094:
095: try {
096: unconnectedSocket.close();
097: } catch (IOException ioe) {
098: ExceptionMonitor.getInstance().exceptionCaught(ioe);
099: }
100: }
101: }
102:
103: private static void initializeTestAddresses() {
104: try {
105: // IPv6 localhost
106: TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
107: .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
108: 0, 0, 0, 0, 0, 0, 0, 1 }), 0), InetAddress
109: .getByAddress(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0,
110: 0, 0, 0, 0, 0, 0, 0, 1 }));
111:
112: // IPv4 localhost
113: TEST_ADDRESSES.put(new InetSocketAddress(InetAddress
114: .getByAddress(new byte[] { 127, 0, 0, 1 }), 0),
115: 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,
121: 0, 0, 0, 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 DefaultSocketSessionConfig() {
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: }
|