diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/ExchangeObserverAdapter.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/ExchangeObserverAdapter.java new file mode 100644 index 0000000000..a3410a1bba --- /dev/null +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/ExchangeObserverAdapter.java @@ -0,0 +1,35 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.leshan.server.californium.impl; + +import org.eclipse.californium.core.network.Exchange; +import org.eclipse.californium.core.network.ExchangeObserver; + +/** + * An abstract adapter class for reacting to exchange events. The methods in this class are empty. This class exists as + * convenience for creating exchange observer objects. + */ +// TODO should be part of californium ? +public class ExchangeObserverAdapter implements ExchangeObserver { + + @Override + public void completed(Exchange exchange) { + } + + @Override + public void contextEstablished(Exchange exchange) { + } +} diff --git a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java index dfc01a7769..de318cb7dc 100644 --- a/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java +++ b/leshan-server-cf/src/main/java/org/eclipse/leshan/server/californium/impl/RegisterResource.java @@ -41,6 +41,7 @@ import org.eclipse.leshan.core.response.DeregisterResponse; import org.eclipse.leshan.core.response.RegisterResponse; import org.eclipse.leshan.core.response.UpdateResponse; +import org.eclipse.leshan.server.impl.SendableResponse; import org.eclipse.leshan.server.registration.RegistrationHandler; import org.eclipse.leshan.server.registration.RegistrationService; import org.slf4j.Logger; @@ -187,7 +188,9 @@ private void handleRegister(CoapExchange exchange, Request request) { // Handle request // ------------------------------- InetSocketAddress serverEndpoint = exchange.advanced().getEndpoint().getAddress(); - RegisterResponse response = registrationHandler.register(sender, registerRequest, serverEndpoint); + final SendableResponse sendableResponse = registrationHandler.register(sender, + registerRequest, serverEndpoint); + RegisterResponse response = sendableResponse.getResponse(); // Create CoAP Response from LwM2m request // ------------------------------- @@ -197,6 +200,7 @@ private void handleRegister(CoapExchange exchange, Request request) { } else { exchange.respond(fromLwM2mCode(response.getCode()), response.getErrorMessage()); } + sendableResponse.sent(); } private void handleUpdate(CoapExchange exchange, Request request, String registrationId) { @@ -223,10 +227,12 @@ private void handleUpdate(CoapExchange exchange, Request request, String registr UpdateRequest updateRequest = new UpdateRequest(registrationId, lifetime, smsNumber, binding, objectLinks); // Handle request - UpdateResponse updateResponse = registrationHandler.update(sender, updateRequest); + final SendableResponse sendableResponse = registrationHandler.update(sender, updateRequest); + UpdateResponse updateResponse = sendableResponse.getResponse(); // Create CoAP Response from LwM2m request exchange.respond(fromLwM2mCode(updateResponse.getCode()), updateResponse.getErrorMessage()); + sendableResponse.sent(); } private void handleDeregister(CoapExchange exchange, String registrationId) { @@ -237,10 +243,13 @@ private void handleDeregister(CoapExchange exchange, String registrationId) { DeregisterRequest deregisterRequest = new DeregisterRequest(registrationId); // Handle request - DeregisterResponse deregisterResponse = registrationHandler.deregister(sender, deregisterRequest); + final SendableResponse sendableResponse = registrationHandler.deregister(sender, + deregisterRequest); + DeregisterResponse deregisterResponse = sendableResponse.getResponse(); // Create CoAP Response from LwM2m request exchange.respond(fromLwM2mCode(deregisterResponse.getCode()), deregisterResponse.getErrorMessage()); + sendableResponse.sent(); } // Since the V1_0-20150615-D version of specification, the registration update should be a CoAP POST. diff --git a/leshan-server-core/src/main/java/org/eclipse/leshan/server/impl/SendableResponse.java b/leshan-server-core/src/main/java/org/eclipse/leshan/server/impl/SendableResponse.java new file mode 100644 index 0000000000..48154e6493 --- /dev/null +++ b/leshan-server-core/src/main/java/org/eclipse/leshan/server/impl/SendableResponse.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * 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 + *******************************************************************************/ +package org.eclipse.leshan.server.impl; + +import org.eclipse.leshan.core.response.LwM2mResponse; + +/** + * A Response wrapper which can be notify when the response is sent + */ +public class SendableResponse { + + private T response; + private Runnable sentCallback; + + public SendableResponse(T response) { + this(response, null); + } + + public SendableResponse(T response, Runnable sentCallback) { + this.response = response; + this.sentCallback = sentCallback; + } + + public T getResponse() { + return response; + } + + public void sent() { + if (sentCallback != null) + sentCallback.run(); + } +} diff --git a/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java b/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java index 8fbea66dde..596ca14311 100644 --- a/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java +++ b/leshan-server-core/src/main/java/org/eclipse/leshan/server/registration/RegistrationHandler.java @@ -26,6 +26,7 @@ import org.eclipse.leshan.core.response.RegisterResponse; import org.eclipse.leshan.core.response.UpdateResponse; import org.eclipse.leshan.server.impl.RegistrationServiceImpl; +import org.eclipse.leshan.server.impl.SendableResponse; import org.eclipse.leshan.server.security.Authorizer; import org.eclipse.leshan.util.RandomStringUtils; import org.slf4j.Logger; @@ -47,7 +48,7 @@ public RegistrationHandler(RegistrationServiceImpl registrationService, Authoriz this.authorizer = authorizer; } - public RegisterResponse register(Identity sender, RegisterRequest registerRequest, + public SendableResponse register(Identity sender, RegisterRequest registerRequest, InetSocketAddress serverEndpoint) { Registration.Builder builder = new Registration.Builder(RegistrationHandler.createRegistrationId(), @@ -59,82 +60,98 @@ public RegisterResponse register(Identity sender, RegisterRequest registerReques .smsNumber(registerRequest.getSmsNumber()).registrationDate(new Date()).lastUpdate(new Date()) .additionalRegistrationAttributes(registerRequest.getAdditionalAttributes()); - Registration registration = builder.build(); + final Registration registration = builder.build(); // We must check if the client is using the right identity. if (!authorizer.isAuthorized(registerRequest, registration, sender)) { - return RegisterResponse.forbidden(null); + return new SendableResponse<>(RegisterResponse.forbidden(null)); } // Add registration to the store - Deregistration deregistration = registrationService.getStore().addRegistration(registration); + final Deregistration deregistration = registrationService.getStore().addRegistration(registration); - // notify new registration and de-registration + // Create callback to notify new registration and de-registration LOG.debug("New registration: {}", registration); - if (deregistration != null) { - registrationService.fireUnregistered(deregistration.getRegistration(), deregistration.getObservations()); - } - registrationService.fireRegistred(registration); - - return RegisterResponse.success(registration.getId()); + + Runnable whenSent = new Runnable() { + @Override + public void run() { + if (deregistration != null) { + registrationService.fireUnregistered(deregistration.getRegistration(), + deregistration.getObservations()); + } + registrationService.fireRegistred(registration); + } + }; + return new SendableResponse<>(RegisterResponse.success(registration.getId()), whenSent); } - public UpdateResponse update(Identity sender, UpdateRequest updateRequest) { + public SendableResponse update(Identity sender, UpdateRequest updateRequest) { // We must check if the client is using the right identity. Registration registration = registrationService.getById(updateRequest.getRegistrationId()); if (registration == null) { - return UpdateResponse.notFound(); + return new SendableResponse<>(UpdateResponse.notFound()); } if (!authorizer.isAuthorized(updateRequest, registration, sender)) { // TODO replace by Forbidden if https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/181 is // closed. - return UpdateResponse.badRequest("forbidden"); + return new SendableResponse<>(UpdateResponse.badRequest("forbidden")); } // Create update - RegistrationUpdate update = new RegistrationUpdate(updateRequest.getRegistrationId(), sender + final RegistrationUpdate update = new RegistrationUpdate(updateRequest.getRegistrationId(), sender .getPeerAddress().getAddress(), sender.getPeerAddress().getPort(), updateRequest.getLifeTimeInSec(), updateRequest.getSmsNumber(), updateRequest.getBindingMode(), updateRequest.getObjectLinks()); // update registration - Registration updatedRegistration = registrationService.getStore().updateRegistration(update); + final Registration updatedRegistration = registrationService.getStore().updateRegistration(update); if (updatedRegistration == null) { LOG.debug("Invalid update: registration {} not found", registration.getId()); - return UpdateResponse.notFound(); + return new SendableResponse<>(UpdateResponse.notFound()); } else { LOG.debug("Updated registration {} by {}", updatedRegistration, update); - // notify registration update - registrationService.fireUpdated(update, updatedRegistration); - return UpdateResponse.success(); + // Create callback to notify registration update + Runnable whenSent = new Runnable() { + @Override + public void run() { + registrationService.fireUpdated(update, updatedRegistration); + }; + }; + return new SendableResponse<>(UpdateResponse.success(), whenSent); } } - public DeregisterResponse deregister(Identity sender, DeregisterRequest deregisterRequest) { + public SendableResponse deregister(Identity sender, DeregisterRequest deregisterRequest) { // We must check if the client is using the right identity. Registration registration = registrationService.getById(deregisterRequest.getRegistrationId()); if (registration == null) { - return DeregisterResponse.notFound(); + return new SendableResponse<>(DeregisterResponse.notFound()); } if (!authorizer.isAuthorized(deregisterRequest, registration, sender)) { // TODO replace by Forbidden if https://github.com/OpenMobileAlliance/OMA_LwM2M_for_Developers/issues/181 is // closed. - return DeregisterResponse.badRequest("forbidden"); + return new SendableResponse<>(DeregisterResponse.badRequest("forbidden")); } - Deregistration deregistration = registrationService.getStore() + final Deregistration deregistration = registrationService.getStore() .removeRegistration(deregisterRequest.getRegistrationId()); if (deregistration != null) { LOG.debug("Deregistered client: {}", deregistration.getRegistration()); - // notify new de-registration - registrationService.fireUnregistered(deregistration.getRegistration(), deregistration.getObservations()); - return DeregisterResponse.success(); + // Create callback to notify new de-registration + Runnable whenSent = new Runnable() { + @Override + public void run() { + registrationService.fireUnregistered(deregistration.getRegistration(), deregistration.getObservations()); + }; + }; + return new SendableResponse<>(DeregisterResponse.success(), whenSent); } else { LOG.debug("Invalid deregistration : registration {} not found", registration.getId()); - return DeregisterResponse.notFound(); + return new SendableResponse<>(DeregisterResponse.notFound()); } }