1 /*
2  * Copyright (c) 2011-2017 Contributors to the Eclipse Foundation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License 2.0 which is available at
6  * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
7  * which is available at https://www.apache.org/licenses/LICENSE-2.0.
8  *
9  * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
10  */
11 
12 module hunt.net.NetServerOptions;
13 
14 import hunt.net.ClientAuth;
15 import hunt.net.OpenSSLEngineOptions;
16 import hunt.net.TcpSslOptions;
17 
18 import hunt.Exceptions;
19 import hunt.io.TcpStreamOptions;
20 import hunt.system.Memory;
21 
22 import core.time;
23 
24 /**
25  * Options for configuring a {@link hunt.net.NetServer}.
26  *
27  * @author <a href="http://tfox.org">Tim Fox</a>
28  */
29 class NetServerOptions : TcpSslOptions {
30 
31     // Server specific HTTP stuff
32 
33     /**
34      * The default port to listen on = 0 (meaning a random ephemeral free port will be chosen)
35      */
36     enum int DEFAULT_PORT = 0;
37 
38     /**
39      * The default host to listen on = "0.0.0.0" (meaning listen on all available interfaces).
40      */
41     enum string DEFAULT_HOST = "0.0.0.0";
42 
43     /**
44      * The default accept backlog = 1024
45      */
46     enum int DEFAULT_ACCEPT_BACKLOG = -1;
47 
48     /**
49      * Default value of whether client auth is required (SSL/TLS) = No
50      */
51     enum ClientAuth DEFAULT_CLIENT_AUTH = ClientAuth.NONE;
52 
53     /**
54      * Default value of whether the server supports SNI = false
55      */
56     enum bool DEFAULT_SNI = false;
57 
58     private ushort port;
59     private string host;
60     private int acceptBacklog;
61     private ClientAuth clientAuth;
62     private bool sni;
63     private size_t _workerThreadSize = 0;
64     private size_t _ioThreadSize = 2;
65 
66     /**
67      * Default constructor
68      */
69     this() {
70         super();
71         init();
72     }
73 
74     /**
75      * Copy constructor
76      *
77      * @param other  the options to copy
78      */
79     this(NetServerOptions other) {
80         super(other);
81         this.port = other.getPort();
82         this.host = other.getHost();
83         this.acceptBacklog = other.getAcceptBacklog();
84         this.clientAuth = other.getClientAuth();
85         this.sni = other.isSni();
86         _workerThreadSize = other._workerThreadSize;
87         _ioThreadSize = other._ioThreadSize;
88     }
89 
90     size_t ioThreadSize() {
91         return _ioThreadSize;
92     }
93 
94     NetServerOptions ioThreadSize(size_t value) {
95         _ioThreadSize = value;
96         return this;
97     }
98 
99     size_t workerThreadSize() {
100         return _workerThreadSize;
101     }
102 
103     NetServerOptions workerThreadSize(size_t value) {
104         _workerThreadSize = value;
105         return this;
106     }
107 
108     override NetServerOptions setSendBufferSize(int sendBufferSize) {
109         super.setSendBufferSize(sendBufferSize);
110         return this;
111     }
112 
113     override NetServerOptions setReceiveBufferSize(int receiveBufferSize) {
114         super.setReceiveBufferSize(receiveBufferSize);
115         return this;
116     }
117 
118     override NetServerOptions setReuseAddress(bool reuseAddress) {
119         super.setReuseAddress(reuseAddress);
120         return this;
121     }
122 
123     override NetServerOptions setReusePort(bool reusePort) {
124         super.setReusePort(reusePort);
125         return this;
126     }
127 
128     override NetServerOptions setTrafficClass(int trafficClass) {
129         super.setTrafficClass(trafficClass);
130         return this;
131     }
132 
133     override NetServerOptions setTcpNoDelay(bool tcpNoDelay) {
134         super.setTcpNoDelay(tcpNoDelay);
135         return this;
136     }
137 
138     override NetServerOptions setTcpKeepAlive(bool tcpKeepAlive) {
139         super.setTcpKeepAlive(tcpKeepAlive);
140         return this;
141     }
142 
143     override NetServerOptions setSoLinger(int soLinger) {
144         super.setSoLinger(soLinger);
145         return this;
146     }
147 
148     // override
149     // NetServerOptions setUsePooledBuffers(bool usePooledBuffers) {
150     //     super.setUsePooledBuffers(usePooledBuffers);
151     //     return this;
152     // }
153 
154     override NetServerOptions setIdleTimeout(Duration idleTimeout) {
155         super.setIdleTimeout(idleTimeout);
156         return this;
157     }
158 
159     override NetServerOptions setSsl(bool ssl) {
160         super.setSsl(ssl);
161         return this;
162     }
163 
164     override NetServerOptions setUseAlpn(bool useAlpn) {
165         super.setUseAlpn(useAlpn);
166         return this;
167     }
168 
169     // override
170     // NetServerOptions setSslEngineOptions(SSLEngineOptions sslEngineOptions) {
171     //     super.setSslEngineOptions(sslEngineOptions);
172     //     return this;
173     // }
174 
175     // override
176     // NetServerOptions setJdkSslEngineOptions(JdkSSLEngineOptions sslEngineOptions) {
177     //     return cast(NetServerOptions) super.setSslEngineOptions(sslEngineOptions);
178     // }
179 
180     override NetServerOptions setOpenSslEngineOptions(OpenSSLEngineOptions sslEngineOptions) {
181         return cast(NetServerOptions) super.setOpenSslEngineOptions(sslEngineOptions);
182     }
183 
184     // override
185     // NetServerOptions setKeyCertOptions(KeyCertOptions options) {
186     //     super.setKeyCertOptions(options);
187     //     return this;
188     // }
189 
190     // override
191     // NetServerOptions setKeyStoreOptions(JksOptions options) {
192     //     super.setKeyStoreOptions(options);
193     //     return this;
194     // }
195 
196     // override
197     // NetServerOptions setPfxKeyCertOptions(PfxOptions options) {
198     //     return cast(NetServerOptions) super.setPfxKeyCertOptions(options);
199     // }
200 
201     // override
202     // NetServerOptions setPemKeyCertOptions(PemKeyCertOptions options) {
203     //     return cast(NetServerOptions) super.setPemKeyCertOptions(options);
204     // }
205 
206     // override
207     // NetServerOptions setTrustOptions(TrustOptions options) {
208     //     super.setTrustOptions(options);
209     //     return this;
210     // }
211 
212     // override
213     // NetServerOptions setTrustStoreOptions(JksOptions options) {
214     //     super.setTrustStoreOptions(options);
215     //     return this;
216     // }
217 
218     // override
219     // NetServerOptions setPfxTrustOptions(PfxOptions options) {
220     //     return cast(NetServerOptions) super.setPfxTrustOptions(options);
221     // }
222 
223     // override
224     // NetServerOptions setPemTrustOptions(PemTrustOptions options) {
225     //     return cast(NetServerOptions) super.setPemTrustOptions(options);
226     // }
227 
228     // override
229     // NetServerOptions addEnabledCipherSuite(string suite) {
230     //     super.addEnabledCipherSuite(suite);
231     //     return this;
232     // }
233 
234     // override
235     // NetServerOptions addEnabledSecureTransportProtocol(string protocol) {
236     //     super.addEnabledSecureTransportProtocol(protocol);
237     //     return this;
238     // }
239 
240     // override
241     // NetServerOptions removeEnabledSecureTransportProtocol(string protocol) {
242     //     return cast(NetServerOptions) super.removeEnabledSecureTransportProtocol(protocol);
243     // }
244 
245     override NetServerOptions setTcpFastOpen(bool tcpFastOpen) {
246         return cast(NetServerOptions) super.setTcpFastOpen(tcpFastOpen);
247     }
248 
249     override NetServerOptions setTcpCork(bool tcpCork) {
250         return cast(NetServerOptions) super.setTcpCork(tcpCork);
251     }
252 
253     override NetServerOptions setTcpQuickAck(bool tcpQuickAck) {
254         return cast(NetServerOptions) super.setTcpQuickAck(tcpQuickAck);
255     }
256 
257     // override
258     // NetServerOptions addCrlPath(string crlPath) {
259     //     return cast(NetServerOptions) super.addCrlPath(crlPath);
260     // }
261 
262     // override
263     // NetServerOptions addCrlValue(Buffer crlValue) {
264     //     return cast(NetServerOptions) super.addCrlValue(crlValue);
265     // }
266 
267     // override
268     // NetServerOptions setEnabledSecureTransportProtocols(Set!(string) enabledSecureTransportProtocols) {
269     //     return cast(NetServerOptions) super.setEnabledSecureTransportProtocols(enabledSecureTransportProtocols);
270     // }
271 
272     override NetServerOptions setSslHandshakeTimeout(Duration sslHandshakeTimeout) {
273         return cast(NetServerOptions) super.setSslHandshakeTimeout(sslHandshakeTimeout);
274     }
275 
276     // override
277     // NetServerOptions setSslHandshakeTimeoutUnit(TimeUnit sslHandshakeTimeoutUnit) {
278     //     return cast(NetServerOptions) super.setSslHandshakeTimeoutUnit(sslHandshakeTimeoutUnit);
279     // }
280 
281     /**
282      * @return the value of accept backlog
283      */
284     int getAcceptBacklog() {
285         return acceptBacklog;
286     }
287 
288     /**
289      * Set the accept back log
290      *
291      * @param acceptBacklog accept backlog
292      * @return a reference to this, so the API can be used fluently
293      */
294     NetServerOptions setAcceptBacklog(int acceptBacklog) {
295         this.acceptBacklog = acceptBacklog;
296         return this;
297     }
298 
299     /**
300      *
301      * @return the port
302      */
303     ushort getPort() {
304         return port;
305     }
306 
307     /**
308      * Set the port
309      *
310      * @param port  the port
311      * @return a reference to this, so the API can be used fluently
312      */
313     NetServerOptions setPort(ushort port) {
314         this.port = port;
315         return this;
316     }
317 
318     /**
319      *
320      * @return the host
321      */
322     string getHost() {
323         return host;
324     }
325 
326     /**
327      * Set the host
328      * @param host  the host
329      * @return a reference to this, so the API can be used fluently
330      */
331     NetServerOptions setHost(string host) {
332         this.host = host;
333         return this;
334     }
335 
336     ClientAuth getClientAuth() {
337         return clientAuth;
338     }
339 
340     /**
341      * Set whether client auth is required
342      *
343      * @param clientAuth One of "NONE, REQUEST, REQUIRED". If it's set to "REQUIRED" then server will require the
344      *                   SSL cert to be presented otherwise it won't accept the request. If it's set to "REQUEST" then
345      *                   it won't mandate the certificate to be presented, basically make it optional.
346      * @return a reference to this, so the API can be used fluently
347      */
348     NetServerOptions setClientAuth(ClientAuth clientAuth) {
349         this.clientAuth = clientAuth;
350         return this;
351     }
352 
353     override NetServerOptions setLogActivity(bool logEnabled) {
354         return cast(NetServerOptions) super.setLogActivity(logEnabled);
355     }
356 
357     /**
358      * @return whether the server supports Server Name Indication
359      */
360     bool isSni() {
361         return sni;
362     }
363 
364     /**
365      * Set whether the server supports Server Name Indiciation
366      *
367      * @return a reference to this, so the API can be used fluently
368      */
369     NetServerOptions setSni(bool sni) {
370         this.sni = sni;
371         return this;
372     }
373 
374     override bool opEquals(Object o) {
375         if (this is o)
376             return true;
377         if (!super.opEquals(o))
378             return false;
379 
380         NetServerOptions that = cast(NetServerOptions) o;
381         if (that is null)
382             return false;
383 
384         if (acceptBacklog != that.acceptBacklog)
385             return false;
386         if (clientAuth != that.clientAuth)
387             return false;
388         if (port != that.port)
389             return false;
390         if (host != that.host)
391             return false;
392         if (sni != that.sni)
393             return false;
394 
395         return true;
396     }
397 
398     override size_t toHash() @trusted nothrow {
399         size_t result = super.toHash();
400         result = 31 * result + port;
401         result = 31 * result + (host !is null ? host.hashOf() : 0);
402         result = 31 * result + acceptBacklog;
403         result = 31 * result + clientAuth.hashOf();
404         result = 31 * result + (sni ? 1 : 0);
405         return result;
406     }
407 
408     private void init() {
409         this.port = DEFAULT_PORT;
410         this.host = DEFAULT_HOST;
411         this.acceptBacklog = DEFAULT_ACCEPT_BACKLOG;
412         this.clientAuth = DEFAULT_CLIENT_AUTH;
413         this.sni = DEFAULT_SNI;
414         _ioThreadSize = totalCPUs - 1;
415 
416         this.setTcpKeepAlive(true);
417     }
418 }