Skip to content

Commit

Permalink
#875: add LowerLayerSetter class to tweak lower layer request parameter
Browse files Browse the repository at this point in the history
  • Loading branch information
sbernard31 committed Aug 28, 2020
1 parent 8e2fcf7 commit 5dc0bd0
Show file tree
Hide file tree
Showing 12 changed files with 594 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@
import org.eclipse.leshan.server.registration.RegistrationServiceImpl;
import org.eclipse.leshan.server.registration.RegistrationStore;
import org.eclipse.leshan.server.registration.RegistrationUpdate;
import org.eclipse.leshan.server.request.LowerLayerSetter;
import org.eclipse.leshan.server.request.LwM2mRequestSender;
import org.eclipse.leshan.server.request.LwM2mRequestSender2;
import org.eclipse.leshan.server.security.Authorizer;
import org.eclipse.leshan.server.security.EditableSecurityStore;
import org.eclipse.leshan.server.security.SecurityInfo;
Expand All @@ -87,6 +89,7 @@
* <p>
* The {@link LeshanServerBuilder} should be the preferred way to build an instance of {@link LeshanServer}.
*/
@SuppressWarnings("deprecation")
public class LeshanServer {

private static final Logger LOG = LoggerFactory.getLogger(LeshanServer.class);
Expand Down Expand Up @@ -474,7 +477,7 @@ public LwM2mModelProvider getModelProvider() {
*/
public <T extends LwM2mResponse> T send(Registration destination, DownlinkRequest<T> request)
throws InterruptedException {
return requestSender.send(destination, request, DEFAULT_TIMEOUT);
return send(destination, request, DEFAULT_TIMEOUT);
}

/**
Expand All @@ -500,7 +503,42 @@ public <T extends LwM2mResponse> T send(Registration destination, DownlinkReques
*/
public <T extends LwM2mResponse> T send(Registration destination, DownlinkRequest<T> request, long timeoutInMs)
throws InterruptedException {
return requestSender.send(destination, request, timeoutInMs);
return send(destination, request, null, timeoutInMs);
}

/**
* Send a Lightweight M2M request synchronously. Will block until a response is received from the remote server.
* <p>
* The synchronous way could block a thread during a long time so it is more recommended to use the asynchronous
* way.
*
* @param destination The {@link Registration} associate to the device we want to sent the request.
* @param request The request to send to the client.
* @param lowerLayerSetter to tweak lower layer request (e.g. coap request)
* @param timeoutInMs The global timeout to wait in milliseconds (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout)
* @return the LWM2M response. The response can be <code>null</code> if the timeout expires (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout).
*
* @throws CodecException if request payload can not be encoded.
* @throws InterruptedException if the thread was interrupted.
* @throws RequestRejectedException if the request is rejected by foreign peer.
* @throws RequestCanceledException if the request is cancelled.
* @throws SendFailedException if the request can not be sent. E.g. error at CoAP or DTLS/UDP layer.
* @throws InvalidResponseException if the response received is malformed.
* @throws ClientSleepingException if client is currently sleeping.
*/
public <T extends LwM2mResponse> T send(Registration destination, DownlinkRequest<T> request,
LowerLayerSetter lowerLayerSetter, long timeoutInMs) throws InterruptedException {
if (requestSender instanceof LwM2mRequestSender2) {
return ((LwM2mRequestSender2) requestSender).send(destination, request, lowerLayerSetter, timeoutInMs);
} else {
if (lowerLayerSetter != null) {
LOG.warn("{} should implement the new interface LwM2mRequestSender2",
requestSender.getClass().getCanonicalName());
}
return requestSender.send(destination, request, timeoutInMs);
}
}

/**
Expand Down Expand Up @@ -533,7 +571,7 @@ public <T extends LwM2mResponse> T send(Registration destination, DownlinkReques
*/
public <T extends LwM2mResponse> void send(Registration destination, DownlinkRequest<T> request,
ResponseCallback<T> responseCallback, ErrorCallback errorCallback) {
requestSender.send(destination, request, DEFAULT_TIMEOUT, responseCallback, errorCallback);
send(destination, request, DEFAULT_TIMEOUT, responseCallback, errorCallback);
}

/**
Expand Down Expand Up @@ -565,7 +603,52 @@ public <T extends LwM2mResponse> void send(Registration destination, DownlinkReq
*/
public <T extends LwM2mResponse> void send(Registration destination, DownlinkRequest<T> request, long timeoutInMs,
ResponseCallback<T> responseCallback, ErrorCallback errorCallback) {
requestSender.send(destination, request, timeoutInMs, responseCallback, errorCallback);
send(destination, request, null, timeoutInMs, responseCallback, errorCallback);
}

/**
* Send a Lightweight M2M {@link DownlinkRequest} asynchronously to a LWM2M client.
* <p>
* The Californium API does not ensure that message callback are exclusive. E.g. In some race condition, you can get
* a onReponse call and a onCancel one. This method ensures that you will receive only one event. Meaning, you get
* either 1 response or 1 error.
*
* @param destination The {@link Registration} associate to the device we want to sent the request.
* @param request The request to send to the client.
* @param lowerLayerSetter to tweak lower layer request (e.g. coap request)
* @param timeoutInMs The global timeout to wait in milliseconds (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout)
* @param responseCallback a callback called when a response is received (successful or error response). This
* callback MUST NOT be null.
* @param errorCallback a callback called when an error or exception occurred when response is received. It can be :
* <ul>
* <li>{@link RequestRejectedException} if the request is rejected by foreign peer.</li>
* <li>{@link RequestCanceledException} if the request is cancelled.</li>
* <li>{@link SendFailedException} if the request can not be sent. E.g. error at CoAP or DTLS/UDP layer.</li>
* <li>{@link InvalidResponseException} if the response received is malformed.</li>
* <li>{@link ClientSleepingException} if client is currently sleeping.</li>
* <li>{@link TimeoutException} if the timeout expires (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout).</li>
* <li>or any other RuntimeException for unexpected issue.
* </ul>
* This callback MUST NOT be null.
* @throws CodecException if request payload can not be encoded.
*
* @since 1.2
*/
public <T extends LwM2mResponse> void send(Registration destination, DownlinkRequest<T> request,
LowerLayerSetter lowerLayerSetter, long timeoutInMs, ResponseCallback<T> responseCallback,
ErrorCallback errorCallback) {
if (requestSender instanceof LwM2mRequestSender2) {
((LwM2mRequestSender2) requestSender).send(destination, request, lowerLayerSetter, timeoutInMs,
responseCallback, errorCallback);
} else {
if (lowerLayerSetter != null) {
LOG.warn("{} should implement the new interface LwM2mRequestSender2",
requestSender.getClass().getCanonicalName());
}
requestSender.send(destination, request, timeoutInMs, responseCallback, errorCallback);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public CaliforniumLwM2mBootstrapRequestSender(Endpoint secureEndpoint, Endpoint
public <T extends LwM2mResponse> T send(BootstrapSession destination, DownlinkRequest<T> request, long timeoutInMs)
throws InterruptedException {
return sender.sendLwm2mRequest(destination.getEndpoint(), destination.getIdentity(), destination.getId(), model,
null, request, timeoutInMs, false);
null, request, null, timeoutInMs, false);
}

/**
Expand Down Expand Up @@ -117,7 +117,7 @@ public <T extends LwM2mResponse> T send(BootstrapSession destination, DownlinkRe
public <T extends LwM2mResponse> void send(BootstrapSession destination, DownlinkRequest<T> request,
long timeoutInMs, ResponseCallback<T> responseCallback, ErrorCallback errorCallback) {
sender.sendLwm2mRequest(destination.getEndpoint(), destination.getIdentity(), destination.getId(), model, null,
request, timeoutInMs, responseCallback, errorCallback, false);
request, null, timeoutInMs, responseCallback, errorCallback, false);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@
import org.eclipse.leshan.server.californium.observation.ObservationServiceImpl;
import org.eclipse.leshan.server.model.LwM2mModelProvider;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.request.LwM2mRequestSender;
import org.eclipse.leshan.server.request.LowerLayerSetter;
import org.eclipse.leshan.server.request.LwM2mRequestSender2;

/**
* An implementation of {@link LwM2mRequestSender} and {@link CoapRequestSender} based on Californium.
* An implementation of {@link LwM2mRequestSender2} and {@link CoapRequestSender} based on Californium.
*/
public class CaliforniumLwM2mRequestSender implements LwM2mRequestSender, CoapRequestSender, Destroyable {
public class CaliforniumLwM2mRequestSender implements LwM2mRequestSender2, CoapRequestSender, Destroyable {

private final ObservationServiceImpl observationService;
private final LwM2mModelProvider modelProvider;
Expand Down Expand Up @@ -95,13 +96,42 @@ public CaliforniumLwM2mRequestSender(Endpoint secureEndpoint, Endpoint nonSecure
@Override
public <T extends LwM2mResponse> T send(Registration destination, DownlinkRequest<T> request, long timeoutInMs)
throws InterruptedException {
return send(destination, request, null, timeoutInMs);
}

/**
* Send a Lightweight M2M request synchronously. Will block until a response is received from the remote server.
* <p>
* The synchronous way could block a thread during a long time so it is more recommended to use the asynchronous
* way.
*
* @param destination The {@link Registration} associate to the device we want to sent the request.
* @param request The request to send to the client.
* @param lowerLayerSetter to tweak lower layer request (e.g. coap request)
* @param timeoutInMs The global timeout to wait in milliseconds (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout)
* @return the LWM2M response. The response can be <code>null</code> if the timeout expires (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout).
*
* @throws CodecException if request payload can not be encoded.
* @throws InterruptedException if the thread was interrupted.
* @throws RequestRejectedException if the request is rejected by foreign peer.
* @throws RequestCanceledException if the request is cancelled.
* @throws SendFailedException if the request can not be sent. E.g. error at CoAP or DTLS/UDP layer.
* @throws InvalidResponseException if the response received is malformed.
* @throws UnconnectedPeerException if client is not connected (no dtls connection available).
*/
@Override
public <T extends LwM2mResponse> T send(Registration destination, DownlinkRequest<T> request,
LowerLayerSetter lowerLayerSetter, long timeoutInMs) throws InterruptedException {

// Retrieve the objects definition
final LwM2mModel model = modelProvider.getObjectModel(destination);

// Send requests synchronously
T response = sender.sendLwm2mRequest(destination.getEndpoint(), destination.getIdentity(), destination.getId(),
model, destination.getRootPath(), request, timeoutInMs, destination.canInitiateConnection());
model, destination.getRootPath(), request, lowerLayerSetter, timeoutInMs,
destination.canInitiateConnection());

// Handle special observe case
if (response != null && response.getClass() == ObserveResponse.class && response.isSuccess()) {
Expand Down Expand Up @@ -140,12 +170,47 @@ public <T extends LwM2mResponse> T send(Registration destination, DownlinkReques
@Override
public <T extends LwM2mResponse> void send(final Registration destination, DownlinkRequest<T> request,
long timeoutInMs, final ResponseCallback<T> responseCallback, ErrorCallback errorCallback) {
send(destination, request, null, timeoutInMs, responseCallback, errorCallback);
}

/**
* Send a Lightweight M2M {@link DownlinkRequest} asynchronously to a LWM2M client.
*
* The Californium API does not ensure that message callback are exclusive. E.g. In some race condition, you can get
* a onReponse call and a onCancel one. This method ensures that you will receive only one event. Meaning, you get
* either 1 response or 1 error.
*
* @param destination The {@link Registration} associate to the device we want to sent the request.
* @param request The request to send to the client.
* @param lowerLayerSetter to tweak lower layer request (e.g. coap request)
* @param timeoutInMs The global timeout to wait in milliseconds (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout)
* @param responseCallback a callback called when a response is received (successful or error response). This
* callback MUST NOT be null.
* @param errorCallback a callback called when an error or exception occurred when response is received. It can be :
* <ul>
* <li>{@link RequestRejectedException} if the request is rejected by foreign peer.</li>
* <li>{@link RequestCanceledException} if the request is cancelled.</li>
* <li>{@link SendFailedException} if the request can not be sent. E.g. error at CoAP or DTLS/UDP layer.</li>
* <li>{@link InvalidResponseException} if the response received is malformed.</li>
* <li>{@link UnconnectedPeerException} if client is not connected (no dtls connection available).</li>
* <li>{@link TimeoutException} if the timeout expires (see
* https://github.com/eclipse/leshan/wiki/Request-Timeout).</li>
* <li>or any other RuntimeException for unexpected issue.
* </ul>
* This callback MUST NOT be null.
* @throws CodecException if request payload can not be encoded.
*/
@Override
public <T extends LwM2mResponse> void send(final Registration destination, DownlinkRequest<T> request,
LowerLayerSetter lowerLayerSetter, long timeoutInMs, final ResponseCallback<T> responseCallback,
ErrorCallback errorCallback) {
// Retrieve the objects definition
final LwM2mModel model = modelProvider.getObjectModel(destination);

// Send requests asynchronously
sender.sendLwm2mRequest(destination.getEndpoint(), destination.getIdentity(), destination.getId(), model,
destination.getRootPath(), request, timeoutInMs, new ResponseCallback<T>() {
destination.getRootPath(), request, lowerLayerSetter, timeoutInMs, new ResponseCallback<T>() {
@Override
public void onResponse(T response) {
if (response != null && response.getClass() == ObserveResponse.class && response.isSuccess()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@
import org.eclipse.leshan.server.queue.QueueModeLwM2mRequestSender;
import org.eclipse.leshan.server.registration.Registration;
import org.eclipse.leshan.server.request.LwM2mRequestSender;
import org.eclipse.leshan.server.request.LwM2mRequestSender2;

/**
* A {@link LwM2mRequestSender} and {@link CoapRequestSender} which supports LWM2M Queue Mode.
* A {@link LwM2mRequestSender2} and {@link CoapRequestSender} which supports LWM2M Queue Mode.
*/
@SuppressWarnings("deprecation")
public class CaliforniumQueueModeRequestSender extends QueueModeLwM2mRequestSender
implements CoapRequestSender, Destroyable {

Expand Down
Loading

0 comments on commit 5dc0bd0

Please sign in to comment.