View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  
28  package org.apache.hc.core5.http.io;
29  
30  import java.net.SocketAddress;
31  import java.util.concurrent.TimeUnit;
32  
33  import org.apache.hc.core5.annotation.Contract;
34  import org.apache.hc.core5.annotation.ThreadingBehavior;
35  import org.apache.hc.core5.util.Args;
36  import org.apache.hc.core5.util.TimeValue;
37  import org.apache.hc.core5.util.Timeout;
38  
39  /**
40   * Classic I/O network socket configuration.
41   *
42   * @since 4.3
43   */
44  @Contract(threading = ThreadingBehavior.IMMUTABLE)
45  public class SocketConfig {
46  
47      private static final Timeout DEFAULT_SOCKET_TIMEOUT = Timeout.ofMinutes(3);
48  
49      public static final SocketConfig DEFAULT = new Builder().build();
50  
51      private final Timeout soTimeout;
52      private final boolean soReuseAddress;
53      private final TimeValue soLinger;
54      private final boolean soKeepAlive;
55      private final boolean tcpNoDelay;
56      private final int sndBufSize;
57      private final int rcvBufSize;
58      private final int backlogSize;
59      private final SocketAddress socksProxyAddress;
60  
61      SocketConfig(
62              final Timeout soTimeout,
63              final boolean soReuseAddress,
64              final TimeValue soLinger,
65              final boolean soKeepAlive,
66              final boolean tcpNoDelay,
67              final int sndBufSize,
68              final int rcvBufSize,
69              final int backlogSize,
70              final SocketAddress socksProxyAddress) {
71          super();
72          this.soTimeout = soTimeout;
73          this.soReuseAddress = soReuseAddress;
74          this.soLinger = soLinger;
75          this.soKeepAlive = soKeepAlive;
76          this.tcpNoDelay = tcpNoDelay;
77          this.sndBufSize = sndBufSize;
78          this.rcvBufSize = rcvBufSize;
79          this.backlogSize = backlogSize;
80          this.socksProxyAddress = socksProxyAddress;
81      }
82  
83      /**
84       * @see Builder#setSoTimeout(Timeout)
85       */
86      public Timeout getSoTimeout() {
87          return soTimeout;
88      }
89  
90      /**
91       * @see Builder#setSoReuseAddress(boolean)
92       */
93      public boolean isSoReuseAddress() {
94          return soReuseAddress;
95      }
96  
97      /**
98       * @see Builder#setSoLinger(TimeValue)
99       */
100     public TimeValue getSoLinger() {
101         return soLinger;
102     }
103 
104     /**
105      * @see Builder#setSoKeepAlive(boolean)
106      */
107     public boolean isSoKeepAlive() {
108         return soKeepAlive;
109     }
110 
111     /**
112      * @see Builder#setTcpNoDelay(boolean)
113      */
114     public boolean isTcpNoDelay() {
115         return tcpNoDelay;
116     }
117 
118     /**
119      * @see Builder#setSndBufSize(int)
120      * @since 4.4
121      */
122     public int getSndBufSize() {
123         return sndBufSize;
124     }
125 
126     /**
127      * @see Builder#setRcvBufSize(int)
128      * @since 4.4
129      */
130     public int getRcvBufSize() {
131         return rcvBufSize;
132     }
133 
134     /**
135      * @see Builder#setBacklogSize(int)
136      * @since 4.4
137      */
138     public int getBacklogSize() {
139         return backlogSize;
140     }
141 
142     /**
143      * @see Builder#setSocksProxyAddress(SocketAddress)
144      */
145     public SocketAddress getSocksProxyAddress() {
146         return this.socksProxyAddress;
147     }
148 
149     @Override
150     public String toString() {
151         final StringBuilder builder = new StringBuilder();
152         builder.append("[soTimeout=").append(this.soTimeout)
153                 .append(", soReuseAddress=").append(this.soReuseAddress)
154                 .append(", soLinger=").append(this.soLinger)
155                 .append(", soKeepAlive=").append(this.soKeepAlive)
156                 .append(", tcpNoDelay=").append(this.tcpNoDelay)
157                 .append(", sndBufSize=").append(this.sndBufSize)
158                 .append(", rcvBufSize=").append(this.rcvBufSize)
159                 .append(", backlogSize=").append(this.backlogSize)
160                 .append(", socksProxyAddress=").append(this.socksProxyAddress)
161                 .append("]");
162         return builder.toString();
163     }
164 
165     public static SocketConfig.Builder custom() {
166         return new Builder();
167     }
168 
169     public static SocketConfig.Builder copy(final SocketConfig config) {
170         Args.notNull(config, "Socket config");
171         return new Builder()
172             .setSoTimeout(config.getSoTimeout())
173             .setSoReuseAddress(config.isSoReuseAddress())
174             .setSoLinger(config.getSoLinger())
175             .setSoKeepAlive(config.isSoKeepAlive())
176             .setTcpNoDelay(config.isTcpNoDelay())
177             .setSndBufSize(config.getSndBufSize())
178             .setRcvBufSize(config.getRcvBufSize())
179             .setBacklogSize(config.getBacklogSize())
180             .setSocksProxyAddress(config.getSocksProxyAddress());
181     }
182 
183     public static class Builder {
184 
185         private Timeout soTimeout;
186         private boolean soReuseAddress;
187         private TimeValue soLinger;
188         private boolean soKeepAlive;
189         private boolean tcpNoDelay;
190         private int sndBufSize;
191         private int rcvBufSize;
192         private int backlogSize;
193         private SocketAddress socksProxyAddress;
194 
195         Builder() {
196             this.soTimeout = DEFAULT_SOCKET_TIMEOUT;
197             this.soReuseAddress = false;
198             this.soLinger = TimeValue.NEG_ONE_SECOND;
199             this.soKeepAlive = false;
200             this.tcpNoDelay = true;
201             this.sndBufSize = 0;
202             this.rcvBufSize = 0;
203             this.backlogSize = 0;
204             this.socksProxyAddress = null;
205         }
206 
207         /**
208          * @see #setSoTimeout(Timeout)
209          */
210         public Builder setSoTimeout(final int soTimeout, final TimeUnit timeUnit) {
211             this.soTimeout = Timeout.of(soTimeout, timeUnit);
212             return this;
213         }
214 
215         /**
216          * Determines the default socket timeout value for blocking I/O operations.
217          * <p>
218          * Default: 3 minutes
219          * </p>
220          *
221          * @return the default socket timeout value for blocking I/O operations.
222          * @see java.net.SocketOptions#SO_TIMEOUT
223          */
224         public Builder setSoTimeout(final Timeout soTimeout) {
225             this.soTimeout = soTimeout;
226             return this;
227         }
228 
229         /**
230          * Determines the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter
231          * for newly created sockets.
232          * <p>
233          * Default: {@code false}
234          * </p>
235          *
236          * @return the default value of the {@link java.net.SocketOptions#SO_REUSEADDR} parameter.
237          * @see java.net.SocketOptions#SO_REUSEADDR
238          */
239         public Builder setSoReuseAddress(final boolean soReuseAddress) {
240             this.soReuseAddress = soReuseAddress;
241             return this;
242         }
243 
244         /**
245          * @see #setSoLinger(TimeValue)
246          */
247         public Builder setSoLinger(final int soLinger, final TimeUnit timeUnit) {
248             this.soLinger = Timeout.of(soLinger, timeUnit);
249             return this;
250         }
251 
252         /**
253          * Determines the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter
254          * for newly created sockets.
255          * <p>
256          * Default: {@code -1}
257          * </p>
258          *
259          * @return the default value of the {@link java.net.SocketOptions#SO_LINGER} parameter.
260          * @see java.net.SocketOptions#SO_LINGER
261          */
262         public Builder setSoLinger(final TimeValue soLinger) {
263             this.soLinger = soLinger;
264             return this;
265         }
266 
267         /**
268          * Determines the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter
269          * for newly created sockets.
270          * <p>
271          * Default: {@code false}
272          * </p>
273          *
274          * @return the default value of the {@link java.net.SocketOptions#SO_KEEPALIVE} parameter.
275          * @see java.net.SocketOptions#SO_KEEPALIVE
276          */
277         public Builder setSoKeepAlive(final boolean soKeepAlive) {
278             this.soKeepAlive = soKeepAlive;
279             return this;
280         }
281 
282         /**
283          * Determines the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter
284          * for newly created sockets.
285          * <p>
286          * Default: {@code false}
287          * </p>
288          *
289          * @return the default value of the {@link java.net.SocketOptions#TCP_NODELAY} parameter.
290          * @see java.net.SocketOptions#TCP_NODELAY
291          */
292         public Builder setTcpNoDelay(final boolean tcpNoDelay) {
293             this.tcpNoDelay = tcpNoDelay;
294             return this;
295         }
296 
297         /**
298          * Determines the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter
299          * for newly created sockets.
300          * <p>
301          * Default: {@code 0} (system default)
302          * </p>
303          *
304          * @return the default value of the {@link java.net.SocketOptions#SO_SNDBUF} parameter.
305          * @see java.net.SocketOptions#SO_SNDBUF
306          * @since 4.4
307          */
308         public Builder setSndBufSize(final int sndBufSize) {
309             this.sndBufSize = sndBufSize;
310             return this;
311         }
312 
313         /**
314          * Determines the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter
315          * for newly created sockets.
316          * <p>
317          * Default: {@code 0} (system default)
318          * </p>
319          *
320          * @return the default value of the {@link java.net.SocketOptions#SO_RCVBUF} parameter.
321          * @see java.net.SocketOptions#SO_RCVBUF
322          * @since 4.4
323          */
324         public Builder setRcvBufSize(final int rcvBufSize) {
325             this.rcvBufSize = rcvBufSize;
326             return this;
327         }
328 
329         /**
330          * Determines the maximum queue length for incoming connection indications
331          * (a request to connect) also known as server socket backlog.
332          * <p>
333          * Default: {@code 0} (system default)
334          * </p>
335          * @return the maximum queue length for incoming connection indications
336          * @since 4.4
337          */
338         public Builder setBacklogSize(final int backlogSize) {
339             this.backlogSize = backlogSize;
340             return this;
341         }
342 
343         /**
344          * The address of the SOCKS proxy to use.
345          */
346         public Builder setSocksProxyAddress(final SocketAddress socksProxyAddress) {
347             this.socksProxyAddress = socksProxyAddress;
348             return this;
349         }
350 
351         public SocketConfig build() {
352             return new SocketConfig(
353                     Timeout.defaultsToDisabled(soTimeout),
354                     soReuseAddress,
355                     soLinger != null ? soLinger : TimeValue.NEG_ONE_SECOND,
356                     soKeepAlive, tcpNoDelay, sndBufSize, rcvBufSize, backlogSize,
357                     socksProxyAddress);
358         }
359 
360     }
361 
362 }