1 /*
2  * hunt-amqp: AMQP library for D programming language, based on hunt-net.
3  *
4  * Copyright (C) 2018-2019 HuntLabs
5  *
6  * Website: https://www.huntlabs.net
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.amqp.ProtonClientOptions;
13 
14 import hunt.collection.LinkedHashSet;
15 import hunt.collection.Set;
16 import hunt.net.ProxyOptions;
17 import hunt.net.OpenSSLEngineOptions;
18 //import io.vertx.core.buffer.Buffer;
19 //import io.vertx.core.json.JsonObject;
20 //import io.vertx.core.net.JdkSSLEngineOptions;
21 //import io.vertx.core.net.JksOptions;
22 //import io.vertx.core.net.KeyCertOptions;
23 //import io.vertx.core.net.NetClientOptions;
24 //import io.vertx.core.net.OpenSSLEngineOptions;
25 //import io.vertx.core.net.PemKeyCertOptions;
26 //import io.vertx.core.net.PemTrustOptions;
27 //import io.vertx.core.net.PfxOptions;
28 //import io.vertx.core.net.ProxyOptions;
29 //import io.vertx.core.net.SSLEngineOptions;
30 //import io.vertx.core.net.TrustOptions;
31 import hunt.String;
32 import hunt.net.NetClientOptions;
33 import std.json;
34 import hunt.Exceptions;
35 import hunt.logging;
36 import core.time;
37 import hunt.collection.Map;
38 import hunt.collection.LinkedHashMap;
39 import std.variant;
40 
41 import hunt.amqp.generated.ProtonClientOptionsConverter;
42 /**
43  * Options for configuring {@link hunt.amqp.ProtonClient} connect operations.
44  */
45 //@DataObject(generateConverter = true, publicConverter = false)
46 class ProtonClientOptions : NetClientOptions {
47 
48   private Set!string enabledSaslMechanisms;// = new LinkedHashSet<>();
49   private int heartbeat;
50   private int maxFrameSize;
51   private string virtualHost;
52   private string sniServerName;
53 
54   this() {
55     super();
56     setHostnameVerificationAlgorithm("HTTPS");
57     enabledSaslMechanisms = new LinkedHashSet!string;
58   }
59 
60   /**
61    * Copy constructor
62    *
63    * @param other  the options to copy
64    */
65   this(ProtonClientOptions other) {
66     super(other);
67     this.enabledSaslMechanisms = new LinkedHashSet!string(other.enabledSaslMechanisms);
68     this.heartbeat = other.heartbeat;
69     this.maxFrameSize = other.maxFrameSize;
70     this.virtualHost = other.virtualHost;
71     this.sniServerName = other.sniServerName;
72   }
73 
74   /**
75    * Create options from JSON
76    *
77    * @param json  the JSON
78    */
79   this(JSONValue json) {
80     Map!(string, Variant) mp = new LinkedHashMap!(string,Variant)();
81     foreach (string key, value; json)
82     {
83       Variant tmp = value;
84       mp.put(key,tmp);
85     }
86     ProtonClientOptionsConverter.fromJson(mp, this);
87     super(this);
88   }
89 
90   /**
91    * Convert to JSON
92    *
93    * @return the JSON
94    */
95   public JSONValue toJson() {
96     implementationMissing(false);
97     JSONValue tmp;
98     return tmp;
99      //JSONValue json = super.toJson();
100      //ProtonClientOptionsConverter.toJson(this, json);
101      //return json;
102   }
103 
104   /**
105    * Get the mechanisms the client should be restricted to use.
106    *
107    * @return the mechanisms, or null/empty set if there is no restriction in place
108    */
109   public Set!string getEnabledSaslMechanisms() {
110     return enabledSaslMechanisms;
111   }
112 
113   /**
114    * Adds a mechanism name that the client may use during SASL negotiation.
115    *
116    * @param saslMechanism
117    *          the sasl mechanism name .
118    * @return a reference to this, so the API can be used fluently
119    */
120   public ProtonClientOptions addEnabledSaslMechanism(string saslMechanism) {
121    // Objects.requireNonNull(saslMechanism, "Mechanism must not be null");
122     if (saslMechanism.length == 0)
123     {
124         logError("Mechanism must not be null");
125     }
126     enabledSaslMechanisms.add(saslMechanism);
127     return this;
128   }
129 
130   override
131   public ProtonClientOptions setSendBufferSize(int sendBufferSize) {
132     super.setSendBufferSize(sendBufferSize);
133     return this;
134   }
135 
136   override
137   public ProtonClientOptions setReceiveBufferSize(int receiveBufferSize) {
138     super.setReceiveBufferSize(receiveBufferSize);
139     return this;
140   }
141 
142   override
143   public ProtonClientOptions setReuseAddress(bool reuseAddress) {
144     super.setReuseAddress(reuseAddress);
145     return this;
146   }
147 
148   override
149   public ProtonClientOptions setTrafficClass(int trafficClass) {
150     super.setTrafficClass(trafficClass);
151     return this;
152   }
153 
154   override
155   public ProtonClientOptions setTcpNoDelay(bool tcpNoDelay) {
156     super.setTcpNoDelay(tcpNoDelay);
157     return this;
158   }
159 
160   override
161   public ProtonClientOptions setTcpKeepAlive(bool tcpKeepAlive) {
162     super.setTcpKeepAlive(tcpKeepAlive);
163     return this;
164   }
165 
166   override
167   public ProtonClientOptions setSoLinger(int soLinger) {
168     super.setSoLinger(soLinger);
169     return this;
170   }
171 
172   override
173   public ProtonClientOptions setIdleTimeout(Duration idleTimeout) {
174     super.setIdleTimeout(idleTimeout);
175     return this;
176   }
177 
178   //override
179   //public ProtonClientOptions setIdleTimeoutUnit(TimeUnit idleTimeoutUnit) {
180   //  super.setIdleTimeoutUnit(idleTimeoutUnit);
181   //  return this;
182   //}
183 
184   override
185   public ProtonClientOptions setSsl(bool ssl) {
186     super.setSsl(ssl);
187     return this;
188   }
189 
190   //override
191   //public ProtonClientOptions setKeyStoreOptions(JksOptions options) {
192   //  super.setKeyStoreOptions(options);
193   //  return this;
194   //}
195   //
196   //override
197   //public ProtonClientOptions setPfxKeyCertOptions(PfxOptions options) {
198   //  super.setPfxKeyCertOptions(options);
199   //  return this;
200   //}
201   //
202   //override
203   //public ProtonClientOptions setPemKeyCertOptions(PemKeyCertOptions options) {
204   //  super.setPemKeyCertOptions(options);
205   //  return this;
206   //}
207   //
208   //override
209   //public ProtonClientOptions setTrustStoreOptions(JksOptions options) {
210   //  super.setTrustStoreOptions(options);
211   //  return this;
212   //}
213   //
214   //override
215   //public ProtonClientOptions setPemTrustOptions(PemTrustOptions options) {
216   //  super.setPemTrustOptions(options);
217   //  return this;
218   //}
219   //
220   //override
221   //public ProtonClientOptions setPfxTrustOptions(PfxOptions options) {
222   //  super.setPfxTrustOptions(options);
223   //  return this;
224   //}
225 
226   //override
227   //public ProtonClientOptions addEnabledCipherSuite(string suite) {
228   //  super.addEnabledCipherSuite(suite);
229   //  return this;
230   //}
231 
232   //override
233   //public ProtonClientOptions addCrlPath(String crlPath)  {
234   //  super.addCrlPath(crlPath);
235   //  return this;
236   //}
237   //
238   //override
239   //public ProtonClientOptions addCrlValue(Buffer crlValue)  {
240   //  super.addCrlValue(crlValue);
241   //  return this;
242   //}
243 
244   override
245   public ProtonClientOptions setTrustAll(bool trustAll) {
246     super.setTrustAll(trustAll);
247     return this;
248   }
249 
250   override
251   public ProtonClientOptions setConnectTimeout(Duration connectTimeout) {
252     super.setConnectTimeout(connectTimeout);
253     return this;
254   }
255 
256   override
257   public ProtonClientOptions setReconnectAttempts(int attempts) {
258     super.setReconnectAttempts(attempts);
259     return this;
260   }
261 
262   override
263   public ProtonClientOptions setReconnectInterval(Duration interval) {
264     super.setReconnectInterval(interval);
265     return this;
266   }
267 
268   override size_t toHash() @safe nothrow
269   {
270     int prime = 31;
271 
272     int result = cast(int)super.toHash();
273     result = prime * result + cast(int)enabledSaslMechanisms.toHash();
274     result = prime * result + this.heartbeat;
275     result = prime * result + this.maxFrameSize;
276     result = prime * result + (this.virtualHost !is null ? cast(int)this.virtualHost.hashOf : 0);
277     result = prime * result + (this.sniServerName !is null ? cast(int)this.sniServerName.hashOf : 0);
278 
279     return cast(size_t)result;
280   }
281 
282   override
283   public bool opEquals (Object obj) {
284     if (this == obj) {
285       return true;
286     }
287 
288     if (obj is null){
289       return false;
290     }
291 
292     //if (!super.equals(obj)) {
293     //  return false;
294     //}
295 
296     ProtonClientOptions other = cast(ProtonClientOptions) obj;
297     if ((enabledSaslMechanisms != other.enabledSaslMechanisms)){
298       return false;
299     }
300     if (this.heartbeat != other.heartbeat) {
301       return false;
302     }
303     if (this.maxFrameSize != other.maxFrameSize) {
304       return false;
305     }
306     if ((this.virtualHost != other.virtualHost)) {
307       return false;
308     }
309     if ((this.sniServerName != other.sniServerName)) {
310       return false;
311     }
312 
313     return true;
314   }
315 
316   override
317   public ProtonClientOptions setUseAlpn(bool useAlpn) {
318     throw new UnsupportedOperationException();
319   }
320 
321   //override
322   //public ProtonClientOptions addEnabledSecureTransportProtocol(String protocol) {
323   //  super.addEnabledSecureTransportProtocol(protocol);
324   //  return this;
325   //}
326 
327   override
328   public ProtonClientOptions setHostnameVerificationAlgorithm(string hostnameVerificationAlgorithm) {
329     super.setHostnameVerificationAlgorithm(hostnameVerificationAlgorithm);
330     return this;
331   }
332 
333   //override
334   //public ProtonClientOptions setKeyCertOptions(KeyCertOptions options) {
335   //  super.setKeyCertOptions(options);
336   //  return this;
337   //}
338 
339   override
340   public ProtonClientOptions setLogActivity(bool logEnabled) {
341     super.setLogActivity(logEnabled);
342     return this;
343   }
344 
345   override
346   public ProtonClientOptions setMetricsName(string metricsName) {
347     super.setMetricsName(metricsName);
348     return this;
349   }
350 
351   override
352   public ProtonClientOptions setProxyOptions(ProxyOptions proxyOptions) {
353     super.setProxyOptions(proxyOptions);
354     return this;
355   }
356 
357   //override
358   //public ProtonClientOptions setTrustOptions(TrustOptions options) {
359   //  super.setTrustOptions(options);
360   //  return this;
361   //}
362 
363   //override
364   //public ProtonClientOptions setJdkSslEngineOptions(JdkSSLEngineOptions sslEngineOptions) {
365   //  super.setJdkSslEngineOptions(sslEngineOptions);
366   //  return this;
367   //}
368 
369   override
370   public ProtonClientOptions setOpenSslEngineOptions(OpenSSLEngineOptions sslEngineOptions) {
371     super.setOpenSslEngineOptions(sslEngineOptions);
372     return this;
373   }
374 
375   //override
376   //public ProtonClientOptions setSslEngineOptions(SSLEngineOptions sslEngineOptions) {
377   //  super.setSslEngineOptions(sslEngineOptions);
378   //  return this;
379   //}
380 
381   override
382   public ProtonClientOptions setSslHandshakeTimeout(Duration sslHandshakeTimeout) {
383     super.setSslHandshakeTimeout(sslHandshakeTimeout);
384     return this;
385   }
386 
387   //override
388   //public ProtonClientOptions setSslHandshakeTimeoutUnit(TimeUnit sslHandshakeTimeoutUnit) {
389   //  super.setSslHandshakeTimeoutUnit(sslHandshakeTimeoutUnit);
390   //  return this;
391   //}
392 
393   override
394   public ProtonClientOptions setLocalAddress(string localAddress) {
395     super.setLocalAddress(localAddress);
396     return this;
397   }
398 
399   override
400   public ProtonClientOptions setReusePort(bool reusePort) {
401     super.setReusePort(reusePort);
402     return this;
403   }
404 
405   override
406   public ProtonClientOptions setTcpCork(bool tcpCork) {
407     super.setTcpCork(tcpCork);
408     return this;
409   }
410 
411   override
412   public ProtonClientOptions setTcpFastOpen(bool tcpFastOpen) {
413     super.setTcpFastOpen(tcpFastOpen);
414     return this;
415   }
416 
417   override
418   public ProtonClientOptions setTcpQuickAck(bool tcpQuickAck) {
419     super.setTcpQuickAck(tcpQuickAck);
420     return this;
421   }
422 
423   //override
424   //public ProtonClientOptions removeEnabledSecureTransportProtocol(String protocol) {
425   //  super.removeEnabledSecureTransportProtocol(protocol);
426   //  return this;
427   //}
428 
429   //override
430   //public ProtonClientOptions setEnabledSecureTransportProtocols(Set<String> enabledSecureTransportProtocols) {
431   //  super.setEnabledSecureTransportProtocols(enabledSecureTransportProtocols);
432   //  return this;
433   //}
434 
435   /**
436    * Override the hostname value used in the connection AMQP Open frame and TLS SNI server name (if TLS is in use).
437    * By default, the hostname specified in {@link ProtonClient#connect} will be used for both, with SNI performed
438    * implicit where a FQDN was specified.
439    *
440    * The SNI server name can also be overridden explicitly using {@link #setSniServerName(String)}.
441    *
442    * @param virtualHost hostname to set
443    * @return  current ProtonClientOptions instance
444    */
445   public ProtonClientOptions setVirtualHost(string virtualHost) {
446     this.virtualHost = virtualHost;
447     return this;
448   }
449 
450   /**
451    * Get the virtual host name override for the connection AMQP Open frame and TLS SNI server name (if TLS is in use)
452    * set by {@link #setVirtualHost(String)}.
453    *
454    * @return  the hostname
455    */
456   public string getVirtualHost() {
457     return this.virtualHost;
458   }
459 
460   /**
461    * Explicitly override the hostname to use for the TLS SNI server name.
462    *
463    * If neither the {@link ProtonClientOptions#setVirtualHost(String) virtualhost} or SNI server name is explicitly
464    * overridden, the hostname specified in {@link ProtonClient#connect} will be used, with SNI performed implicitly
465    * where a FQDN was specified.
466    *
467    * This method should typically only be needed to set different values for the [virtual] hostname and SNI server name.
468    *
469    * @param sniServerName hostname to set as SNI server name
470    * @return  current ProtonClientOptions instance
471    */
472   public ProtonClientOptions setSniServerName(string sniServerName) {
473     this.sniServerName = sniServerName;
474     return this;
475   }
476 
477   /**
478    * Get the hostname override for TLS SNI Server Name set by {@link #setSniServerName(String)}.
479    *
480    * @return  the hostname
481    */
482   public string getSniServerName() {
483     return this.sniServerName;
484   }
485 
486   /**
487    * Set the heartbeat (in milliseconds) as maximum delay between sending frames for the remote peers.
488    * If no frames are received within 2*heartbeat, the connection is closed
489    *
490    * @param heartbeat hearthbeat maximum delay
491    * @return  current ProtonClientOptions instance
492    */
493   public ProtonClientOptions setHeartbeat(int heartbeat) {
494     this.heartbeat = heartbeat;
495     return this;
496   }
497 
498   /**
499    * Return the heartbeat (in milliseconds) as maximum delay between sending frames for the remote peers.
500    *
501    * @return  hearthbeat maximum delay
502    */
503   public int getHeartbeat() {
504     return this.heartbeat;
505   }
506 
507   /**
508    * Sets the maximum frame size for the connection.
509    * <p>
510    * If this property is not set explicitly, a reasonable default value is used.
511    * <p>
512    * Setting this property to a negative value will result in no maximum frame size being announced at all.
513    *
514    * @param maxFrameSize The frame size in bytes.
515    * @return This instance for setter chaining.
516    */
517   public ProtonClientOptions setMaxFrameSize(int maxFrameSize) {
518     if (maxFrameSize < 0) {
519       this.maxFrameSize = -1;
520     } else {
521       this.maxFrameSize = maxFrameSize;
522     }
523     return this;
524   }
525 
526   /**
527    * Gets the maximum frame size for the connection.
528    * <p>
529    * If this property is not set explicitly, a reasonable default value is used.
530    *
531    * @return The frame size in bytes or -1 if no limit is set.
532    */
533   public int getMaxFrameSize() {
534     return maxFrameSize;
535   }
536 }