/
LeshanBootstrapServerBuilder.java
557 lines (512 loc) · 25.5 KB
/
LeshanBootstrapServerBuilder.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
/*******************************************************************************
* Copyright (c) 2017 Sierra Wireless and others.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.html.
*
* Contributors:
* Sierra Wireless - initial API and implementation
* Achim Kraus (Bosch Software Innovations GmbH) - use CoapEndpointBuilder
*******************************************************************************/
package org.eclipse.leshan.server.californium;
import java.net.InetSocketAddress;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import org.eclipse.californium.core.network.CoapEndpoint;
import org.eclipse.californium.core.network.config.NetworkConfig;
import org.eclipse.californium.core.network.config.NetworkConfig.Keys;
import org.eclipse.californium.scandium.DTLSConnector;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig;
import org.eclipse.californium.scandium.config.DtlsConnectorConfig.Builder;
import org.eclipse.californium.scandium.dtls.CertificateType;
import org.eclipse.leshan.LwM2m;
import org.eclipse.leshan.core.californium.EndpointFactory;
import org.eclipse.leshan.core.californium.Lwm2mEndpointContextMatcher;
import org.eclipse.leshan.core.model.LwM2mModel;
import org.eclipse.leshan.core.model.ObjectLoader;
import org.eclipse.leshan.server.bootstrap.BootstrapConfig;
import org.eclipse.leshan.server.bootstrap.BootstrapHandler;
import org.eclipse.leshan.server.bootstrap.BootstrapHandlerFactory;
import org.eclipse.leshan.server.bootstrap.BootstrapSessionManager;
import org.eclipse.leshan.server.bootstrap.BootstrapStore;
import org.eclipse.leshan.server.bootstrap.DefaultBootstrapHandler;
import org.eclipse.leshan.server.bootstrap.LwM2mBootstrapRequestSender;
import org.eclipse.leshan.server.californium.impl.LeshanBootstrapServer;
import org.eclipse.leshan.server.californium.impl.LwM2mBootstrapPskStore;
import org.eclipse.leshan.server.impl.DefaultBootstrapSessionManager;
import org.eclipse.leshan.server.security.BootstrapSecurityStore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Class helping you to build and configure a Californium based Leshan Bootstrap Lightweight M2M server.
* <p>
* Usage: create it, call the different setters for changing the configuration and then call the {@link #build()} method
* for creating the {@link LeshanBootstrapServer} ready to operate.
*/
public class LeshanBootstrapServerBuilder {
private static final Logger LOG = LoggerFactory.getLogger(LeshanBootstrapServerBuilder.class);
private InetSocketAddress localAddress;
private InetSocketAddress localAddressSecure;
private BootstrapStore configStore;
private BootstrapSecurityStore securityStore;
private BootstrapSessionManager sessionManager;
private BootstrapHandlerFactory bootstrapHandlerFactory;
private LwM2mModel model;
private NetworkConfig coapConfig;
private Builder dtlsConfigBuilder;
private PublicKey publicKey;
private PrivateKey privateKey;
private X509Certificate[] certificateChain;
private Certificate[] trustedCertificates;
private EndpointFactory endpointFactory;
private boolean noSecuredEndpoint;
private boolean noUnsecuredEndpoint;
/**
* Set the address/port for unsecured CoAP communication (<code>coap://</code>).
* <p>
* By default a wildcard address and the default CoAP port(5683) is used.
*
* @param hostname The address to bind. If null wildcard address is used.
* @param port A valid port value is between 0 and 65535. A port number of zero will let the system pick up an
* ephemeral port in a bind operation.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setLocalAddress(String hostname, int port) {
if (hostname == null) {
this.localAddress = new InetSocketAddress(port);
} else {
this.localAddress = new InetSocketAddress(hostname, port);
}
return this;
}
/**
* Set the address for unsecured CoAP communication (<code>coap://</code>).
* <p>
* By default a wildcard address and the default CoAP port(5683) is used.
*
* @param localAddress the socket address for <code>coap://</code>.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setLocalAddress(InetSocketAddress localAddress) {
this.localAddress = localAddress;
return this;
}
/**
* Set the address/port for secured CoAP over DTLS communication (<code>coaps://</code>).
* <p>
* By default a wildcard address and the default CoAPs port(5684) is used.
*
* @param hostname The address to bind. If null wildcard address is used.
* @param port A valid port value is between 0 and 65535. A port number of zero will let the system pick up an
* ephemeral port in a bind operation.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setLocalSecureAddress(String hostname, int port) {
if (hostname == null) {
this.localAddressSecure = new InetSocketAddress(port);
} else {
this.localAddressSecure = new InetSocketAddress(hostname, port);
}
return this;
}
/**
* Set the address for secured CoAP over DTLS communication Server (<code>coaps://</code>).
* <p>
* By default a wildcard address and the default CoAP port(5684) is used.
*
* @param localSecureAddress the socket address for <code>coaps://</code>.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setLocalSecureAddress(InetSocketAddress localSecureAddress) {
this.localAddressSecure = localSecureAddress;
return this;
}
/**
* Set the {@link PublicKey} of the server which will be used for Raw Public Key DTLS authentication.
* <p>
* This should be used for RPK support only.
* <p>
* Setting <code>publicKey</code> and <code>privateKey</code> will enable RawPublicKey DTLS authentication, see also
* {@link LeshanBootstrapServerBuilder#setPrivateKey(PrivateKey)}.
*
* @param publicKey the Raw Public Key of the bootstrap server.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
return this;
}
/**
* Set the CertificateChain of the server which will be used for X.509 DTLS authentication.
* <p>
* Setting <code>publicKey</code> and <code>privateKey</code> will enable RPK and X.509 DTLS authentication, see
* also {@link LeshanBootstrapServerBuilder#setPrivateKey(PrivateKey)}.
* <p>
* For RPK the public key will be extracted from the first X.509 certificate of the certificate chain. If you only
* need RPK support, use {@link LeshanServerBuilder#setPublicKey(PublicKey)} instead.
* <p>
* If you want to deactivate RPK mode, look at {@link LeshanBootstrapServerBuilder#setDtlsConfig(Builder)} and
* {@link DtlsConnectorConfig.Builder#setTrustCertificateTypes(CertificateType...)}
*
* @param certificateChain the certificate chain of the bootstrap server.
* @return the builder for fluent Bootstrap Server creation.
*/
public <T extends X509Certificate> LeshanBootstrapServerBuilder setCertificateChain(T[] certificateChain) {
this.certificateChain = certificateChain;
return this;
}
/**
* Set the {@link PrivateKey} of the server which will be used for RawPublicKey(RPK) and/or X.509 DTLS
* authentication.
*
* @param privateKey the Private Key of the bootstrap server.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setPrivateKey(PrivateKey privateKey) {
this.privateKey = privateKey;
return this;
}
/**
* The list of trusted certificates used to authenticate devices using X.509 DTLS authentication.
* <p>
* If you need more complex/dynamic trust behavior, look at
* {@link LeshanBootstrapServerBuilder#setDtlsConfig(Builder)} and
* {@link DtlsConnectorConfig.Builder#setCertificateVerifier(org.eclipse.californium.scandium.dtls.x509.CertificateVerifier)}
* instead.
*
* @param trustedCertificates certificates trusted by the bootstrap server.
* @return the builder for fluent Bootstrap Server creation.
*/
public <T extends Certificate> LeshanBootstrapServerBuilder setTrustedCertificates(T[] trustedCertificates) {
this.trustedCertificates = trustedCertificates;
return this;
}
/**
* Set the {@link BootstrapStore} containing bootstrap configuration to apply to each devices.
* <p>
* WARNING: There is not default implementation and this store is mandatory to create a bootstrap server.
* <p>
* See {@link BootstrapConfig} to see what is could be done during a bootstrap session.
*
* @param configStore the bootstrap configuration store.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setConfigStore(BootstrapStore configStore) {
this.configStore = configStore;
return this;
}
/**
* Set the {@link BootstrapSecurityStore} which contains data needed to authenticate devices.
* <p>
* WARNING: without security store all devices will be accepted which is not really recommended in production
* environnement.
* <p>
* There is not default implementation.
*
* @param securityStore the security store used to authenticate devices.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setSecurityStore(BootstrapSecurityStore securityStore) {
this.securityStore = securityStore;
return this;
}
/**
* Advanced setter used to define {@link BootstrapSessionManager}.
* <p>
* See {@link BootstrapSessionManager} and {@link DefaultBootstrapSessionManager} for more details.
*
* @param sessionManager the manager responsible to handle bootstrap session.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setSessionManager(BootstrapSessionManager sessionManager) {
this.sessionManager = sessionManager;
return this;
}
/**
* Advanced setter used to customize default bootstrap server behavior.
* <p>
* By default Bootstrap Server is only able to write Security, Server and ACL objects, see
* {@link #setConfigStore(BootstrapStore)}. If you need more advanced behavior you can create your own
* {@link BootstrapHandler} by inspiring yourself from {@link DefaultBootstrapHandler}. You will probably need to
* create a custom {@link BootstrapConfig} and {@link BootstrapStore} and/or change LWM2M model to use, see
* {@link #setModel(LwM2mModel)}.
*
* @param bootstrapHandlerFactory the factory used to create {@link BootstrapHandler}.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setBootstrapHandlerFactory(BootstrapHandlerFactory bootstrapHandlerFactory) {
this.bootstrapHandlerFactory = bootstrapHandlerFactory;
return this;
}
/**
* Advanced setter used to customize default the {@link LwM2mModel}. This model is mainly used for data encoding of
* Bootstrap write request.
* <p>
* By default, LWM2M object models defined in LWM2M v1.0.x are used. Out of the box, Bootstrap Server is only able
* to write Security, Server and ACL objects, see {@link #setConfigStore(BootstrapStore)}.
* <p>
* Set a different LWM2M model if you want to use a different model version of Security, Server and ACL objects, or
* if you need to write objects which are not available by default. For the second case, you need to change
* {@link BootstrapHandler} behavior as well, using {@link #setBootstrapHandlerFactory(BootstrapHandlerFactory)} and
* probably create a custom {@link BootstrapConfig} and {@link BootstrapStore}.
* <p>
* WARNING: Only 1 version by object is supported for now.
*
* @param model the LWM2M Model.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setModel(LwM2mModel model) {
this.model = model;
return this;
}
/**
* Set the CoAP/Californium {@link NetworkConfig}.
* <p>
* For advanced CoAP setting, see {@link NetworkConfig.Keys} for more details.
*
* @param coapConfig the CoAP configuration.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setCoapConfig(NetworkConfig coapConfig) {
this.coapConfig = coapConfig;
return this;
}
/**
* Set the DTLS/Scandium {@link DtlsConnectorConfig}.
* <p>
* For advanced DTLS setting.
*
* @param dtlsConfig the DTLS configuration builder.
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setDtlsConfig(DtlsConnectorConfig.Builder dtlsConfig) {
this.dtlsConfigBuilder = dtlsConfig;
return this;
}
/**
* Advanced setter used to create custom CoAP endpoint.
* <p>
* DTLSConnector is expected for secured endpoint.
*
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder setEndpointFactory(EndpointFactory endpointFactory) {
this.endpointFactory = endpointFactory;
return this;
}
/**
* Deactivate unsecured CoAP endpoint, meaning that <code>coap://</code> communication will be impossible.
*
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder disableUnsecuredEndpoint() {
this.noUnsecuredEndpoint = true;
return this;
}
/**
* Deactivate secured CoAP endpoint (DTLS), meaning that <code>coaps://</code> communication will be impossible.
*
* @return the builder for fluent Bootstrap Server creation.
*/
public LeshanBootstrapServerBuilder disableSecuredEndpoint() {
this.noSecuredEndpoint = true;
return this;
}
/**
* Create the default CoAP/Californium {@link NetworkConfig} used by the builder.
* <p>
* It could be used as a base to create a custom CoAP configuration, then use it with
* {@link #setCoapConfig(NetworkConfig)}
*
* @return the default CoAP config.
*/
public NetworkConfig createDefaultNetworkConfig() {
NetworkConfig networkConfig = new NetworkConfig();
networkConfig.set(Keys.MID_TRACKER, "NULL");
return networkConfig;
}
/**
* Create the {@link LeshanBootstrapServer}.
* <p>
* Next step will be to start it : {@link LeshanBootstrapServer#start()}.
*
* @return the LWM2M Bootstrap server.
* @throws IllegalStateException if builder configuration is not consistent.
*/
public LeshanBootstrapServer build() {
if (localAddress == null)
localAddress = new InetSocketAddress(LwM2m.DEFAULT_COAP_PORT);
// TODO we should have default implementation for BootstrapStore in leshan.server project.
if (configStore == null)
throw new IllegalStateException("BootstrapStore is mandatory");
if (sessionManager == null)
sessionManager = new DefaultBootstrapSessionManager(securityStore);
if (bootstrapHandlerFactory == null)
bootstrapHandlerFactory = new BootstrapHandlerFactory() {
@Override
public BootstrapHandler create(BootstrapStore store, LwM2mBootstrapRequestSender sender,
BootstrapSessionManager sessionManager) {
return new DefaultBootstrapHandler(store, sender, sessionManager);
}
};
if (model == null)
model = new LwM2mModel(ObjectLoader.loadDefault());
if (coapConfig == null) {
coapConfig = createDefaultNetworkConfig();
}
// handle dtlsConfig
DtlsConnectorConfig dtlsConfig = null;
if (!noSecuredEndpoint) {
if (dtlsConfigBuilder == null) {
dtlsConfigBuilder = new DtlsConnectorConfig.Builder();
}
DtlsConnectorConfig incompleteConfig = dtlsConfigBuilder.getIncompleteConfig();
// Handle PSK Store
if (incompleteConfig.getPskStore() == null && securityStore != null) {
dtlsConfigBuilder.setPskStore(new LwM2mBootstrapPskStore(securityStore));
} else {
LOG.warn(
"PskStore should be automatically set by Leshan. Using a custom implementation is not advised.");
}
// Handle secure address
if (incompleteConfig.getAddress() == null) {
if (localAddressSecure == null) {
localAddressSecure = new InetSocketAddress(LwM2m.DEFAULT_COAP_SECURE_PORT);
}
dtlsConfigBuilder.setAddress(localAddressSecure);
} else if (localAddressSecure != null && !localAddressSecure.equals(incompleteConfig.getAddress())) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for secure address: %s != %s",
localAddressSecure, incompleteConfig.getAddress()));
}
// Handle active peers
if (incompleteConfig.getMaxConnections() == null)
dtlsConfigBuilder.setMaxConnections(coapConfig.getInt(Keys.MAX_ACTIVE_PEERS));
if (incompleteConfig.getStaleConnectionThreshold() == null)
dtlsConfigBuilder.setStaleConnectionThreshold(coapConfig.getLong(Keys.MAX_PEER_INACTIVITY_PERIOD));
// handle trusted certificates
if (trustedCertificates != null) {
if (incompleteConfig.getCertificateVerifier() == null) {
if (incompleteConfig.getTrustStore() == null) {
dtlsConfigBuilder.setTrustStore(trustedCertificates);
} else if (!Arrays.equals(trustedCertificates, incompleteConfig.getTrustStore())) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for trusted Certificates (trustStore) : \n%s != \n%s",
Arrays.toString(trustedCertificates),
Arrays.toString(incompleteConfig.getTrustStore())));
}
} else if (trustedCertificates != null) {
throw new IllegalStateException(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder: if a CertificateVerifier is set, trustedCertificates must not be set.");
}
}
if (privateKey != null) {
// check conflict for private key
if (incompleteConfig.getPrivateKey() != null && !incompleteConfig.getPrivateKey().equals(privateKey)) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for private key: %s != %s",
privateKey, incompleteConfig.getPrivateKey()));
}
// if in raw key mode and not in X.509 set the raw keys
if (certificateChain == null && publicKey != null) {
if (incompleteConfig.getPublicKey() != null && !incompleteConfig.getPublicKey().equals(publicKey)) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for public key: %s != %s",
publicKey, incompleteConfig.getPublicKey()));
}
// by default trust all RPK
if (incompleteConfig.getRpkTrustStore() == null) {
dtlsConfigBuilder.setRpkTrustAll();
}
dtlsConfigBuilder.setIdentity(privateKey, publicKey);
}
// if in X.509 mode set the private key, certificate chain, public key is extracted from the certificate
if (certificateChain != null && certificateChain.length > 0) {
if (incompleteConfig.getCertificateChain() != null
&& !Arrays.asList(certificateChain).equals(incompleteConfig.getCertificateChain())) {
throw new IllegalStateException(String.format(
"Configuration conflict between LeshanBuilder and DtlsConnectorConfig.Builder for certificate chain: %s != %s",
Arrays.toString(certificateChain), incompleteConfig.getCertificateChain()));
}
// by default trust all RPK
if (incompleteConfig.getRpkTrustStore() == null) {
dtlsConfigBuilder.setRpkTrustAll();
}
dtlsConfigBuilder.setIdentity(privateKey, certificateChain, CertificateType.X_509,
CertificateType.RAW_PUBLIC_KEY);
}
}
// Deactivate SNI by default
// TODO should we support SNI ?
if (incompleteConfig.isSniEnabled() == null) {
dtlsConfigBuilder.setSniEnabled(false);
}
// we try to build the dtlsConfig, if it fail we will just not create the secured endpoint
try {
dtlsConfig = dtlsConfigBuilder.build();
} catch (IllegalStateException e) {
LOG.warn("Unable to create DTLS config and so secured endpoint.", e);
}
}
CoapEndpoint unsecuredEndpoint = null;
if (!noUnsecuredEndpoint) {
if (endpointFactory != null) {
unsecuredEndpoint = endpointFactory.createUnsecuredEndpoint(localAddress, coapConfig, null);
} else {
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setInetSocketAddress(localAddress);
builder.setNetworkConfig(coapConfig);
unsecuredEndpoint = builder.build();
}
}
CoapEndpoint securedEndpoint = null;
if (!noSecuredEndpoint && dtlsConfig != null) {
if (endpointFactory != null) {
securedEndpoint = endpointFactory.createSecuredEndpoint(dtlsConfig, coapConfig, null);
} else {
CoapEndpoint.Builder builder = new CoapEndpoint.Builder();
builder.setConnector(new DTLSConnector(dtlsConfig));
builder.setNetworkConfig(coapConfig);
builder.setEndpointContextMatcher(new Lwm2mEndpointContextMatcher());
securedEndpoint = builder.build();
}
}
if (securedEndpoint == null && unsecuredEndpoint == null) {
throw new IllegalStateException(
"All CoAP enpoints are deactivated, at least one endpoint should be activated");
}
return createBootstrapServer(unsecuredEndpoint, securedEndpoint, configStore, securityStore, sessionManager,
bootstrapHandlerFactory, model, coapConfig);
}
/**
* Create the <code>LeshanBootstrapServer</code>.
* <p>
* You can extend <code>LeshanBootstrapServerBuilder</code> and override this method to create a new builder which
* will be able to build an extended <code>LeshanBootstrapServer</code>.
*
* @param unsecuredEndpoint CoAP endpoint used for <code>coap://<code> communication.
* @param securedEndpoint CoAP endpoint used for <code>coaps://<code> communication.
* @param bsStore the bootstrap configuration store.
* @param bsSecurityStore the security store used to authenticate devices.
* @param bsSessionManager the manager responsible to handle bootstrap session.
* @param bsHandlerFactory the factory used to create {@link BootstrapHandler}.
* @param model the LWM2M model used mainly used for data encoding.
* @param coapConfig the CoAP configuration.
* @return the LWM2M Bootstrap server.
*/
protected LeshanBootstrapServer createBootstrapServer(CoapEndpoint unsecuredEndpoint, CoapEndpoint securedEndpoint,
BootstrapStore bsStore, BootstrapSecurityStore bsSecurityStore, BootstrapSessionManager bsSessionManager,
BootstrapHandlerFactory bsHandlerFactory, LwM2mModel model, NetworkConfig coapConfig) {
return new LeshanBootstrapServer(unsecuredEndpoint, securedEndpoint, bsStore, bsSecurityStore, bsSessionManager,
bsHandlerFactory, model, coapConfig);
}
}