MqttClientOptionsBuilder.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. using MQTTnet.Client.ExtendedAuthenticationExchange;
  2. using MQTTnet.Formatter;
  3. using MQTTnet.Packets;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Text;
  8. namespace MQTTnet.Client.Options
  9. {
  10. public class MqttClientOptionsBuilder
  11. {
  12. readonly MqttClientOptions _options = new MqttClientOptions();
  13. MqttClientTcpOptions _tcpOptions;
  14. MqttClientWebSocketOptions _webSocketOptions;
  15. MqttClientOptionsBuilderTlsParameters _tlsParameters;
  16. MqttClientWebSocketProxyOptions _proxyOptions;
  17. public MqttClientOptionsBuilder WithProtocolVersion(MqttProtocolVersion value)
  18. {
  19. if (value == MqttProtocolVersion.Unknown)
  20. {
  21. throw new ArgumentException("Protocol version is invalid.");
  22. }
  23. _options.ProtocolVersion = value;
  24. return this;
  25. }
  26. public MqttClientOptionsBuilder WithCommunicationTimeout(TimeSpan value)
  27. {
  28. _options.CommunicationTimeout = value;
  29. return this;
  30. }
  31. public MqttClientOptionsBuilder WithCleanSession(bool value = true)
  32. {
  33. _options.CleanSession = value;
  34. return this;
  35. }
  36. public MqttClientOptionsBuilder WithNoKeepAlive()
  37. {
  38. return WithKeepAlivePeriod(TimeSpan.Zero);
  39. }
  40. public MqttClientOptionsBuilder WithKeepAlivePeriod(TimeSpan value)
  41. {
  42. _options.KeepAlivePeriod = value;
  43. return this;
  44. }
  45. public MqttClientOptionsBuilder WithKeepAliveSendInterval(TimeSpan value)
  46. {
  47. _options.KeepAliveSendInterval = value;
  48. return this;
  49. }
  50. public MqttClientOptionsBuilder WithClientId(string value)
  51. {
  52. _options.ClientId = value;
  53. return this;
  54. }
  55. public MqttClientOptionsBuilder WithWillMessage(MqttApplicationMessage value)
  56. {
  57. _options.WillMessage = value;
  58. return this;
  59. }
  60. public MqttClientOptionsBuilder WithAuthentication(string method, byte[] data)
  61. {
  62. _options.AuthenticationMethod = method;
  63. _options.AuthenticationData = data;
  64. return this;
  65. }
  66. public MqttClientOptionsBuilder WithWillDelayInterval(uint? willDelayInterval)
  67. {
  68. _options.WillDelayInterval = willDelayInterval;
  69. return this;
  70. }
  71. public MqttClientOptionsBuilder WithTopicAliasMaximum(ushort? topicAliasMaximum)
  72. {
  73. _options.TopicAliasMaximum = topicAliasMaximum;
  74. return this;
  75. }
  76. public MqttClientOptionsBuilder WithMaximumPacketSize(uint? maximumPacketSize)
  77. {
  78. _options.MaximumPacketSize = maximumPacketSize;
  79. return this;
  80. }
  81. public MqttClientOptionsBuilder WithReceiveMaximum(ushort? receiveMaximum)
  82. {
  83. _options.ReceiveMaximum = receiveMaximum;
  84. return this;
  85. }
  86. public MqttClientOptionsBuilder WithRequestProblemInformation(bool? requestProblemInformation = true)
  87. {
  88. _options.RequestProblemInformation = requestProblemInformation;
  89. return this;
  90. }
  91. public MqttClientOptionsBuilder WithRequestResponseInformation(bool? requestResponseInformation = true)
  92. {
  93. _options.RequestResponseInformation = requestResponseInformation;
  94. return this;
  95. }
  96. public MqttClientOptionsBuilder WithSessionExpiryInterval(uint? sessionExpiryInterval)
  97. {
  98. _options.SessionExpiryInterval = sessionExpiryInterval;
  99. return this;
  100. }
  101. public MqttClientOptionsBuilder WithUserProperty(string name, string value)
  102. {
  103. if (name is null) throw new ArgumentNullException(nameof(name));
  104. if (value is null) throw new ArgumentNullException(nameof(value));
  105. if (_options.UserProperties == null)
  106. {
  107. _options.UserProperties = new List<MqttUserProperty>();
  108. }
  109. _options.UserProperties.Add(new MqttUserProperty(name, value));
  110. return this;
  111. }
  112. public MqttClientOptionsBuilder WithCredentials(string username, string password = null)
  113. {
  114. byte[] passwordBuffer = null;
  115. if (password != null)
  116. {
  117. passwordBuffer = Encoding.UTF8.GetBytes(password);
  118. }
  119. return WithCredentials(username, passwordBuffer);
  120. }
  121. public MqttClientOptionsBuilder WithCredentials(string username, byte[] password = null)
  122. {
  123. _options.Credentials = new MqttClientCredentials
  124. {
  125. Username = username,
  126. Password = password
  127. };
  128. return this;
  129. }
  130. public MqttClientOptionsBuilder WithCredentials(IMqttClientCredentials credentials)
  131. {
  132. _options.Credentials = credentials;
  133. return this;
  134. }
  135. public MqttClientOptionsBuilder WithExtendedAuthenticationExchangeHandler(IMqttExtendedAuthenticationExchangeHandler handler)
  136. {
  137. _options.ExtendedAuthenticationExchangeHandler = handler;
  138. return this;
  139. }
  140. public MqttClientOptionsBuilder WithTcpServer(string server, int? port = null)
  141. {
  142. _tcpOptions = new MqttClientTcpOptions
  143. {
  144. Server = server,
  145. Port = port
  146. };
  147. return this;
  148. }
  149. // TODO: Consider creating _MqttClientTcpOptionsBuilder_ as overload.
  150. public MqttClientOptionsBuilder WithTcpServer(Action<MqttClientTcpOptions> optionsBuilder)
  151. {
  152. if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder));
  153. _tcpOptions = new MqttClientTcpOptions();
  154. optionsBuilder.Invoke(_tcpOptions);
  155. return this;
  156. }
  157. public MqttClientOptionsBuilder WithProxy(string address, string username = null, string password = null, string domain = null, bool bypassOnLocal = false, string[] bypassList = null)
  158. {
  159. _proxyOptions = new MqttClientWebSocketProxyOptions
  160. {
  161. Address = address,
  162. Username = username,
  163. Password = password,
  164. Domain = domain,
  165. BypassOnLocal = bypassOnLocal,
  166. BypassList = bypassList
  167. };
  168. return this;
  169. }
  170. public MqttClientOptionsBuilder WithProxy(Action<MqttClientWebSocketProxyOptions> optionsBuilder)
  171. {
  172. if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder));
  173. _proxyOptions = new MqttClientWebSocketProxyOptions();
  174. optionsBuilder(_proxyOptions);
  175. return this;
  176. }
  177. public MqttClientOptionsBuilder WithWebSocketServer(string uri, MqttClientOptionsBuilderWebSocketParameters parameters = null)
  178. {
  179. _webSocketOptions = new MqttClientWebSocketOptions
  180. {
  181. Uri = uri,
  182. RequestHeaders = parameters?.RequestHeaders,
  183. CookieContainer = parameters?.CookieContainer
  184. };
  185. return this;
  186. }
  187. public MqttClientOptionsBuilder WithWebSocketServer(Action<MqttClientWebSocketOptions> optionsBuilder)
  188. {
  189. if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder));
  190. _webSocketOptions = new MqttClientWebSocketOptions();
  191. optionsBuilder.Invoke(_webSocketOptions);
  192. return this;
  193. }
  194. public MqttClientOptionsBuilder WithTls(MqttClientOptionsBuilderTlsParameters parameters)
  195. {
  196. _tlsParameters = parameters;
  197. return this;
  198. }
  199. public MqttClientOptionsBuilder WithTls()
  200. {
  201. return WithTls(new MqttClientOptionsBuilderTlsParameters { UseTls = true });
  202. }
  203. public MqttClientOptionsBuilder WithTls(Action<MqttClientOptionsBuilderTlsParameters> optionsBuilder)
  204. {
  205. if (optionsBuilder == null) throw new ArgumentNullException(nameof(optionsBuilder));
  206. _tlsParameters = new MqttClientOptionsBuilderTlsParameters();
  207. optionsBuilder(_tlsParameters);
  208. return this;
  209. }
  210. public IMqttClientOptions Build()
  211. {
  212. if (_tcpOptions == null && _webSocketOptions == null)
  213. {
  214. throw new InvalidOperationException("A channel must be set.");
  215. }
  216. if (_tlsParameters != null)
  217. {
  218. if (_tlsParameters?.UseTls == true)
  219. {
  220. var tlsOptions = new MqttClientTlsOptions
  221. {
  222. UseTls = true,
  223. SslProtocol = _tlsParameters.SslProtocol,
  224. AllowUntrustedCertificates = _tlsParameters.AllowUntrustedCertificates,
  225. #if WINDOWS_UWP
  226. Certificates = _tlsParameters.Certificates?.Select(c => c.ToArray()).ToList(),
  227. #else
  228. Certificates = _tlsParameters.Certificates?.ToList(),
  229. #endif
  230. CertificateValidationCallback = _tlsParameters.CertificateValidationCallback,
  231. CertificateValidationHandler = _tlsParameters.CertificateValidationHandler,
  232. IgnoreCertificateChainErrors = _tlsParameters.IgnoreCertificateChainErrors,
  233. IgnoreCertificateRevocationErrors = _tlsParameters.IgnoreCertificateRevocationErrors
  234. };
  235. if (_tcpOptions != null)
  236. {
  237. _tcpOptions.TlsOptions = tlsOptions;
  238. }
  239. else if (_webSocketOptions != null)
  240. {
  241. _webSocketOptions.TlsOptions = tlsOptions;
  242. }
  243. }
  244. }
  245. if (_proxyOptions != null)
  246. {
  247. if (_webSocketOptions == null)
  248. {
  249. throw new InvalidOperationException("Proxies are only supported for WebSocket connections.");
  250. }
  251. _webSocketOptions.ProxyOptions = _proxyOptions;
  252. }
  253. _options.ChannelOptions = (IMqttClientChannelOptions)_tcpOptions ?? _webSocketOptions;
  254. return _options;
  255. }
  256. }
  257. }