Search in sources :

Example 61 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class AbstractMessageSenderConnectionEventProducer method sendNotificationEvent.

private Future<Void> sendNotificationEvent(final Context context, final Device authenticatedDevice, final String protocolAdapter, final String remoteId, final String cause, final JsonObject data, final SpanContext spanContext) {
    if (authenticatedDevice == null) {
        // we only handle authenticated devices
        return Future.succeededFuture();
    }
    final String tenantId = authenticatedDevice.getTenantId();
    final String deviceId = authenticatedDevice.getDeviceId();
    return context.getTenantClient().get(tenantId, spanContext).compose(tenant -> {
        final JsonObject payload = new JsonObject();
        payload.put("cause", cause);
        payload.put("remote-id", remoteId);
        payload.put("source", protocolAdapter);
        if (data != null) {
            payload.put("data", data);
        }
        return Optional.ofNullable(context.getMessageSenderClient()).map(client -> client.sendEvent(tenant, new RegistrationAssertion(deviceId), EventConstants.EVENT_CONNECTION_NOTIFICATION_CONTENT_TYPE, payload.toBuffer(), null, spanContext)).orElseGet(Future::succeededFuture);
    });
}
Also used : Optional(java.util.Optional) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) JsonObject(io.vertx.core.json.JsonObject) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) SpanContext(io.opentracing.SpanContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) JsonObject(io.vertx.core.json.JsonObject) Future(io.vertx.core.Future)

Example 62 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class AbstractProtocolAdapterBase method sendTtdEvent.

@Override
public final Future<Void> sendTtdEvent(final String tenant, final String deviceId, final Device authenticatedDevice, final Integer ttd, final SpanContext context) {
    Objects.requireNonNull(tenant);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(ttd);
    final Future<RegistrationAssertion> tokenTracker = getRegistrationAssertion(tenant, deviceId, authenticatedDevice, context);
    final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant, context);
    return CompositeFuture.all(tokenTracker, tenantConfigTracker).compose(ok -> {
        if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
            final Map<String, Object> props = new HashMap<>();
            props.put(MessageHelper.APP_PROPERTY_ORIG_ADAPTER, getTypeName());
            props.put(MessageHelper.APP_PROPERTY_QOS, QoS.AT_LEAST_ONCE.ordinal());
            props.put(MessageHelper.APP_PROPERTY_DEVICE_TTD, ttd);
            return getEventSender(tenantConfigTracker.result()).sendEvent(tenantConfigTracker.result(), tokenTracker.result(), EventConstants.CONTENT_TYPE_EMPTY_NOTIFICATION, null, props, context).onSuccess(s -> log.debug("successfully sent TTD notification [tenant: {}, device-id: {}, TTD: {}]", tenant, deviceId, ttd)).onFailure(t -> log.debug("failed to send TTD notification [tenant: {}, device-id: {}, TTD: {}]", tenant, deviceId, ttd, t));
        } else {
            // this adapter is not enabled for the tenant
            return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
        }
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) DecodeException(io.vertx.core.json.DecodeException) Context(io.vertx.core.Context) NoopResourceLimitChecks(org.eclipse.hono.adapter.resourcelimits.NoopResourceLimitChecks) TelemetrySender(org.eclipse.hono.client.telemetry.TelemetrySender) MessagingType(org.eclipse.hono.util.MessagingType) Map(java.util.Map) CredentialsClient(org.eclipse.hono.client.registry.CredentialsClient) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) EventSender(org.eclipse.hono.client.telemetry.EventSender) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) HttpResponseStatus(io.netty.handler.codec.http.HttpResponseStatus) TenantClient(org.eclipse.hono.client.registry.TenantClient) MessageHelper(org.eclipse.hono.util.MessageHelper) ServiceBaseUtils(org.eclipse.hono.service.util.ServiceBaseUtils) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) TrustOptions(io.vertx.core.net.TrustOptions) List(java.util.List) Buffer(io.vertx.core.buffer.Buffer) CommandRouterClient(org.eclipse.hono.client.command.CommandRouterClient) Optional(java.util.Optional) QoS(org.eclipse.hono.util.QoS) ConnectionLimitManager(org.eclipse.hono.adapter.limiting.ConnectionLimitManager) Lifecycle(org.eclipse.hono.util.Lifecycle) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.TenantDisabledOrNotRegisteredException) ConnectionEventProducer(org.eclipse.hono.adapter.monitoring.ConnectionEventProducer) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) CommandResponseSender(org.eclipse.hono.client.command.CommandResponseSender) ArrayList(java.util.ArrayList) DeviceDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.DeviceDisabledOrNotRegisteredException) CompositeFuture(io.vertx.core.CompositeFuture) Status(io.vertx.ext.healthchecks.Status) HealthCheckHandler(io.vertx.ext.healthchecks.HealthCheckHandler) DeviceRegistrationClient(org.eclipse.hono.client.registry.DeviceRegistrationClient) GatewayDisabledOrNotRegisteredException(org.eclipse.hono.client.registry.GatewayDisabledOrNotRegisteredException) TelemetryExecutionContext(org.eclipse.hono.util.TelemetryExecutionContext) Strings(org.eclipse.hono.util.Strings) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) Promise(io.vertx.core.Promise) Vertx(io.vertx.core.Vertx) Sample(io.micrometer.core.instrument.Timer.Sample) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) CommandConsumerFactory(org.eclipse.hono.client.command.CommandConsumerFactory) ValidityBasedTrustOptions(org.eclipse.hono.service.auth.ValidityBasedTrustOptions) ServiceClient(org.eclipse.hono.client.util.ServiceClient) ConnectionAttemptOutcome(org.eclipse.hono.service.metric.MetricsTags.ConnectionAttemptOutcome) AbstractServiceBase(org.eclipse.hono.service.AbstractServiceBase) ResourceLimitChecks(org.eclipse.hono.adapter.resourcelimits.ResourceLimitChecks) TenantObject(org.eclipse.hono.util.TenantObject) HashMap(java.util.HashMap) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject) TenantObject(org.eclipse.hono.util.TenantObject)

Example 63 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class VertxBasedAmqpProtocolAdapter method doUploadCommandResponseMessage.

private Future<Void> doUploadCommandResponseMessage(final AmqpContext context, final ResourceIdentifier resource, final Span currentSpan) {
    final Future<CommandResponse> responseTracker = Optional.ofNullable(getCommandResponse(context.getMessage())).map(Future::succeededFuture).orElseGet(() -> {
        TracingHelper.logError(currentSpan, String.format("invalid message (correlationId: %s, address: %s, status: %s)", context.getMessage().getCorrelationId(), context.getMessage().getAddress(), MessageHelper.getStatus(context.getMessage())));
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "malformed command response message"));
    });
    final Future<TenantObject> tenantTracker = getTenantConfiguration(resource.getTenantId(), currentSpan.context());
    return CompositeFuture.all(tenantTracker, responseTracker).compose(ok -> {
        final CommandResponse commandResponse = responseTracker.result();
        log.trace("sending command response [device-id: {}, status: {}, correlation-id: {}, reply-to: {}]", resource.getResourceId(), commandResponse.getStatus(), commandResponse.getCorrelationId(), commandResponse.getReplyToId());
        final Map<String, Object> items = new HashMap<>(3);
        items.put(Fields.EVENT, "sending command response");
        items.put(TracingHelper.TAG_CORRELATION_ID.getKey(), commandResponse.getCorrelationId());
        items.put(MessageHelper.APP_PROPERTY_STATUS, commandResponse.getStatus());
        currentSpan.log(items);
        final Future<RegistrationAssertion> tokenFuture = getRegistrationAssertion(resource.getTenantId(), resource.getResourceId(), context.getAuthenticatedDevice(), currentSpan.context());
        final Future<TenantObject> tenantValidationTracker = CompositeFuture.all(isAdapterEnabled(tenantTracker.result()), checkMessageLimit(tenantTracker.result(), context.getPayloadSize(), currentSpan.context())).map(success -> tenantTracker.result());
        return CompositeFuture.all(tenantValidationTracker, tokenFuture).compose(success -> sendCommandResponse(tenantTracker.result(), tokenFuture.result(), commandResponse, currentSpan.context()));
    }).map(delivery -> {
        log.trace("forwarded command response from device [tenant: {}, device-id: {}]", resource.getTenantId(), resource.getResourceId());
        metrics.reportCommand(Direction.RESPONSE, resource.getTenantId(), tenantTracker.result(), ProcessingOutcome.FORWARDED, context.getPayloadSize(), context.getTimer());
        return delivery;
    }).recover(t -> {
        log.debug("cannot process command response from device [tenant: {}, device-id: {}]", resource.getTenantId(), resource.getResourceId(), t);
        metrics.reportCommand(Direction.RESPONSE, resource.getTenantId(), tenantTracker.result(), ProcessingOutcome.from(t), context.getPayloadSize(), context.getTimer());
        return Future.failedFuture(t);
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonReceiver(io.vertx.proton.ProtonReceiver) LifecycleChange(org.eclipse.hono.notification.deviceregistry.LifecycleChange) DeviceChangeNotification(org.eclipse.hono.notification.deviceregistry.DeviceChangeNotification) Tags(io.opentracing.tag.Tags) ProtonServer(io.vertx.proton.ProtonServer) HonoProtonHelper(org.eclipse.hono.util.HonoProtonHelper) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) EndpointType(org.eclipse.hono.service.metric.MetricsTags.EndpointType) Modified(org.apache.qpid.proton.amqp.messaging.Modified) DeviceCredentials(org.eclipse.hono.adapter.auth.device.DeviceCredentials) Map(java.util.Map) DeliveryState(org.apache.qpid.proton.amqp.transport.DeliveryState) AuthorizationException(org.eclipse.hono.adapter.AuthorizationException) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) Fields(io.opentracing.log.Fields) AmqpError(org.apache.qpid.proton.amqp.transport.AmqpError) TracingHelper(org.eclipse.hono.tracing.TracingHelper) ProtonSaslAuthenticatorFactory(io.vertx.proton.sasl.ProtonSaslAuthenticatorFactory) AllDevicesOfTenantDeletedNotification(org.eclipse.hono.notification.deviceregistry.AllDevicesOfTenantDeletedNotification) TenantServiceBasedX509Authentication(org.eclipse.hono.adapter.auth.device.TenantServiceBasedX509Authentication) Predicate(java.util.function.Predicate) Collection(java.util.Collection) CommandContext(org.eclipse.hono.client.command.CommandContext) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ProtonQoS(io.vertx.proton.ProtonQoS) MessageHelper(org.eclipse.hono.util.MessageHelper) Collectors(java.util.stream.Collectors) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) Objects(java.util.Objects) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) List(java.util.List) QoS(org.eclipse.hono.service.metric.MetricsTags.QoS) TenantTraceSamplingHelper(org.eclipse.hono.tracing.TenantTraceSamplingHelper) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Optional(java.util.Optional) Span(io.opentracing.Span) ProtonSender(io.vertx.proton.ProtonSender) NotificationEventBusSupport(org.eclipse.hono.notification.NotificationEventBusSupport) ProtonLink(io.vertx.proton.ProtonLink) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) ProtonServerOptions(io.vertx.proton.ProtonServerOptions) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ConnectionLimitManager(org.eclipse.hono.adapter.limiting.ConnectionLimitManager) Command(org.eclipse.hono.client.command.Command) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) HashMap(java.util.HashMap) ClientErrorException(org.eclipse.hono.client.ClientErrorException) AdapterDisabledException(org.eclipse.hono.adapter.AdapterDisabledException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) OptionalInt(java.util.OptionalInt) AtomicReference(java.util.concurrent.atomic.AtomicReference) Function(java.util.function.Function) Commands(org.eclipse.hono.client.command.Commands) Constants(org.eclipse.hono.util.Constants) CompositeFuture(io.vertx.core.CompositeFuture) ProtonSession(io.vertx.proton.ProtonSession) Symbol(org.apache.qpid.proton.amqp.Symbol) AdapterConnectionsExceededException(org.eclipse.hono.adapter.AdapterConnectionsExceededException) Target(org.apache.qpid.proton.amqp.transport.Target) UnsignedLong(org.apache.qpid.proton.amqp.UnsignedLong) Message(org.apache.qpid.proton.message.Message) HttpUtils(org.eclipse.hono.service.http.HttpUtils) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) TenantChangeNotification(org.eclipse.hono.notification.deviceregistry.TenantChangeNotification) Strings(org.eclipse.hono.util.Strings) UsernamePasswordAuthProvider(org.eclipse.hono.adapter.auth.device.UsernamePasswordAuthProvider) CredentialsApiAuthProvider(org.eclipse.hono.adapter.auth.device.CredentialsApiAuthProvider) AbstractProtocolAdapterBase(org.eclipse.hono.adapter.AbstractProtocolAdapterBase) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) Promise(io.vertx.core.Promise) ServerErrorException(org.eclipse.hono.client.ServerErrorException) ProtonHelper(io.vertx.proton.ProtonHelper) Sample(io.micrometer.core.instrument.Timer.Sample) Released(org.apache.qpid.proton.amqp.messaging.Released) CommandResponse(org.eclipse.hono.client.command.CommandResponse) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Source(org.apache.qpid.proton.amqp.transport.Source) ConnectionAttemptOutcome(org.eclipse.hono.service.metric.MetricsTags.ConnectionAttemptOutcome) MemoryBasedConnectionLimitStrategy(org.eclipse.hono.adapter.limiting.MemoryBasedConnectionLimitStrategy) X509AuthProvider(org.eclipse.hono.adapter.auth.device.X509AuthProvider) Handler(io.vertx.core.Handler) Collections(java.util.Collections) DefaultConnectionLimitManager(org.eclipse.hono.adapter.limiting.DefaultConnectionLimitManager) TenantObject(org.eclipse.hono.util.TenantObject) HashMap(java.util.HashMap) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) ClientErrorException(org.eclipse.hono.client.ClientErrorException) TenantObject(org.eclipse.hono.util.TenantObject) CommandResponse(org.eclipse.hono.client.command.CommandResponse)

Example 64 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class AbstractHonoResource method getPutRequestDeviceAndAuth.

/**
 * Gets a device identity for a CoAP PUT request which contains a tenant and device id in its URI.
 *
 * @param exchange The CoAP exchange with URI and/or peer's principal.
 * @return A future indicating the outcome of the operation.
 *         The future will be succeeded if the device can be determined from the CoAP exchange,
 *         otherwise the future will be failed with a {@link ClientErrorException}.
 */
public Future<RequestDeviceAndAuth> getPutRequestDeviceAndAuth(final CoapExchange exchange) {
    final List<String> pathList = exchange.getRequestOptions().getUriPath();
    if (pathList.isEmpty()) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "missing request URI"));
    } else if (pathList.size() == 1) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "missing tenant and device ID in URI"));
    } else if (pathList.size() == 2) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "missing device ID in URI"));
    }
    try {
        final String[] path = pathList.toArray(new String[pathList.size()]);
        final ResourceIdentifier identifier = ResourceIdentifier.fromPath(path);
        final Device device = new Device(identifier.getTenantId(), identifier.getResourceId());
        final Principal peer = exchange.advanced().getRequest().getSourceContext().getPeerIdentity();
        if (peer == null) {
            // unauthenticated device request
            return Future.succeededFuture(new RequestDeviceAndAuth(device, null, null));
        } else {
            return TracingSupportingHonoResource.getAuthenticatedDevice(exchange).map(authenticatedDevice -> new RequestDeviceAndAuth(device, TracingSupportingHonoResource.getAuthId(exchange), authenticatedDevice));
        }
    } catch (final IllegalArgumentException cause) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "invalid request URI"));
    }
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) Device(org.eclipse.hono.auth.Device) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Principal(java.security.Principal)

Example 65 with Device

use of org.eclipse.hono.auth.Device in project hono by eclipse.

the class AbstractHonoResource method createCommandConsumer.

/**
 * Creates a consumer for command messages to be sent to a device.
 *
 * @param ttdSecs The number of seconds the device waits for a command.
 * @param tenantObject The tenant configuration object.
 * @param deviceId The identifier of the device.
 * @param gatewayId The identifier of the gateway that is acting on behalf of the device or {@code null} otherwise.
 * @param context The device's currently executing CoAP request context.
 * @param responseReady A future to complete once one of the following conditions are met:
 *            <ul>
 *            <li>the request did not include a <em>hono-ttd</em> query-parameter or</li>
 *            <li>a command has been received and the response ready future has not yet been completed or</li>
 *            <li>the ttd has expired</li>
 *            </ul>
 * @param uploadMessageSpan The OpenTracing Span used for tracking the processing of the request.
 * @return A future indicating the outcome of the operation.
 *         <p>
 *         The future will be completed with the created message consumer or {@code null}, if the response can be
 *         sent back to the device without waiting for a command.
 *         <p>
 *         The future will be failed with a {@code ServiceInvocationException} if the message consumer could not be
 *         created.
 * @throws NullPointerException if any of the parameters other than TTD or gatewayId is {@code null}.
 */
protected final Future<CommandConsumer> createCommandConsumer(final Integer ttdSecs, final TenantObject tenantObject, final String deviceId, final String gatewayId, final CoapContext context, final Handler<AsyncResult<Void>> responseReady, final Span uploadMessageSpan) {
    Objects.requireNonNull(tenantObject);
    Objects.requireNonNull(deviceId);
    Objects.requireNonNull(context);
    Objects.requireNonNull(responseReady);
    Objects.requireNonNull(uploadMessageSpan);
    if (ttdSecs == null || ttdSecs <= 0) {
        // no need to wait for a command
        responseReady.handle(Future.succeededFuture());
        return Future.succeededFuture();
    }
    final AtomicBoolean requestProcessed = new AtomicBoolean(false);
    uploadMessageSpan.setTag(MessageHelper.APP_PROPERTY_DEVICE_TTD, ttdSecs);
    final Span waitForCommandSpan = TracingHelper.buildChildSpan(getTracer(), uploadMessageSpan.context(), "create consumer and wait for command", getAdapter().getTypeName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(TracingHelper.TAG_TENANT_ID, tenantObject.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, deviceId).start();
    final Handler<CommandContext> commandHandler = commandContext -> {
        final Span processCommandSpan = TracingHelper.buildFollowsFromSpan(getTracer(), waitForCommandSpan.context(), "process received command").withTag(Tags.COMPONENT.getKey(), getAdapter().getTypeName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(TracingHelper.TAG_TENANT_ID, tenantObject.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, deviceId).addReference(References.FOLLOWS_FROM, commandContext.getTracingContext()).start();
        Tags.COMPONENT.set(commandContext.getTracingSpan(), getAdapter().getTypeName());
        commandContext.logCommandToSpan(processCommandSpan);
        final Command command = commandContext.getCommand();
        final Sample commandSample = getAdapter().getMetrics().startTimer();
        if (isCommandValid(command, processCommandSpan)) {
            if (requestProcessed.compareAndSet(false, true)) {
                waitForCommandSpan.finish();
                getAdapter().checkMessageLimit(tenantObject, command.getPayloadSize(), processCommandSpan.context()).onComplete(result -> {
                    if (result.succeeded()) {
                        addMicrometerSample(commandContext, commandSample);
                        // put command context to routing context and notify
                        context.put(CommandContext.KEY_COMMAND_CONTEXT, commandContext);
                    } else {
                        commandContext.reject(result.cause());
                        TracingHelper.logError(processCommandSpan, "rejected command for device", result.cause());
                        getAdapter().getMetrics().reportCommand(command.isOneWay() ? Direction.ONE_WAY : Direction.REQUEST, tenantObject.getTenantId(), tenantObject, ProcessingOutcome.from(result.cause()), command.getPayloadSize(), commandSample);
                    }
                    cancelCommandReceptionTimer(context);
                    setTtdStatus(context, TtdStatus.COMMAND);
                    responseReady.handle(Future.succeededFuture());
                    processCommandSpan.finish();
                });
            } else {
                final String errorMsg = "waiting time for command has elapsed or another command has already been processed";
                LOG.debug("{} [tenantId: {}, deviceId: {}]", errorMsg, tenantObject.getTenantId(), deviceId);
                getAdapter().getMetrics().reportCommand(command.isOneWay() ? Direction.ONE_WAY : Direction.REQUEST, tenantObject.getTenantId(), tenantObject, ProcessingOutcome.UNDELIVERABLE, command.getPayloadSize(), commandSample);
                commandContext.release(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, errorMsg));
                TracingHelper.logError(processCommandSpan, errorMsg);
                processCommandSpan.finish();
            }
        } else {
            getAdapter().getMetrics().reportCommand(command.isOneWay() ? Direction.ONE_WAY : Direction.REQUEST, tenantObject.getTenantId(), tenantObject, ProcessingOutcome.UNPROCESSABLE, command.getPayloadSize(), commandSample);
            LOG.debug("command message is invalid: {}", command);
            commandContext.reject("malformed command message");
            TracingHelper.logError(processCommandSpan, "malformed command message");
            processCommandSpan.finish();
        }
    };
    final Future<CommandConsumer> commandConsumerFuture;
    if (gatewayId != null) {
        // gateway scenario
        commandConsumerFuture = getAdapter().getCommandConsumerFactory().createCommandConsumer(tenantObject.getTenantId(), deviceId, gatewayId, commandHandler, Duration.ofSeconds(ttdSecs), waitForCommandSpan.context());
    } else {
        commandConsumerFuture = getAdapter().getCommandConsumerFactory().createCommandConsumer(tenantObject.getTenantId(), deviceId, commandHandler, Duration.ofSeconds(ttdSecs), waitForCommandSpan.context());
    }
    return commandConsumerFuture.onFailure(thr -> {
        TracingHelper.logError(waitForCommandSpan, thr);
        waitForCommandSpan.finish();
    }).map(consumer -> {
        if (!requestProcessed.get()) {
            // if the request was not responded already, add a timer for triggering an empty response
            addCommandReceptionTimer(context, requestProcessed, responseReady, ttdSecs, waitForCommandSpan);
            context.startAcceptTimer(vertx, tenantObject, getAdapter().getConfig().getTimeoutToAck());
        }
        // for unregistering the command consumer (which is something the parent request span doesn't wait for)
        return new CommandConsumer() {

            @Override
            public Future<Void> close(final SpanContext ignored) {
                final Span closeConsumerSpan = TracingHelper.buildFollowsFromSpan(getTracer(), waitForCommandSpan.context(), "close consumer").withTag(Tags.COMPONENT.getKey(), getAdapter().getTypeName()).withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT).withTag(TracingHelper.TAG_TENANT_ID, tenantObject.getTenantId()).withTag(TracingHelper.TAG_DEVICE_ID, deviceId).start();
                return consumer.close(closeConsumerSpan.context()).onFailure(thr -> TracingHelper.logError(closeConsumerSpan, thr)).onComplete(ar -> closeConsumerSpan.finish());
            }
        };
    });
}
Also used : HttpURLConnection(java.net.HttpURLConnection) ResponseCode(org.eclipse.californium.core.coap.CoAP.ResponseCode) CoapExchange(org.eclipse.californium.core.server.resources.CoapExchange) Response(org.eclipse.californium.core.coap.Response) Command(org.eclipse.hono.client.command.Command) LoggerFactory(org.slf4j.LoggerFactory) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Constants(org.eclipse.hono.util.Constants) Tags(io.opentracing.tag.Tags) ProcessingOutcome(org.eclipse.hono.service.metric.MetricsTags.ProcessingOutcome) CompositeFuture(io.vertx.core.CompositeFuture) EndpointType(org.eclipse.hono.service.metric.MetricsTags.EndpointType) TtdStatus(org.eclipse.hono.service.metric.MetricsTags.TtdStatus) References(io.opentracing.References) Duration(java.time.Duration) Map(java.util.Map) MediaTypeRegistry(org.eclipse.californium.core.coap.MediaTypeRegistry) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) TracingHelper(org.eclipse.hono.tracing.TracingHelper) AsyncResult(io.vertx.core.AsyncResult) CommandConstants(org.eclipse.hono.util.CommandConstants) Logger(org.slf4j.Logger) Tracer(io.opentracing.Tracer) Direction(org.eclipse.hono.service.metric.MetricsTags.Direction) Promise(io.vertx.core.Promise) CommandContext(org.eclipse.hono.client.command.CommandContext) MetricsTags(org.eclipse.hono.service.metric.MetricsTags) Vertx(io.vertx.core.Vertx) ServerErrorException(org.eclipse.hono.client.ServerErrorException) RegistrationAssertion(org.eclipse.hono.util.RegistrationAssertion) MessageHelper(org.eclipse.hono.util.MessageHelper) Sample(io.micrometer.core.instrument.Timer.Sample) Future(io.vertx.core.Future) Device(org.eclipse.hono.auth.Device) TenantObject(org.eclipse.hono.util.TenantObject) SpanContext(io.opentracing.SpanContext) Objects(java.util.Objects) List(java.util.List) Principal(java.security.Principal) Buffer(io.vertx.core.buffer.Buffer) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) Optional(java.util.Optional) Span(io.opentracing.Span) OptionSet(org.eclipse.californium.core.coap.OptionSet) Handler(io.vertx.core.Handler) SpanContext(io.opentracing.SpanContext) CommandContext(org.eclipse.hono.client.command.CommandContext) Sample(io.micrometer.core.instrument.Timer.Sample) Span(io.opentracing.Span) AtomicBoolean(java.util.concurrent.atomic.AtomicBoolean) Command(org.eclipse.hono.client.command.Command) CommandConsumer(org.eclipse.hono.client.command.CommandConsumer) ServerErrorException(org.eclipse.hono.client.ServerErrorException)

Aggregations

Device (org.eclipse.hono.auth.Device)115 HttpURLConnection (java.net.HttpURLConnection)74 Test (org.junit.jupiter.api.Test)72 Future (io.vertx.core.Future)69 ClientErrorException (org.eclipse.hono.client.ClientErrorException)67 Buffer (io.vertx.core.buffer.Buffer)66 Handler (io.vertx.core.Handler)63 TenantObject (org.eclipse.hono.util.TenantObject)63 Promise (io.vertx.core.Promise)59 Constants (org.eclipse.hono.util.Constants)58 Span (io.opentracing.Span)55 RegistrationAssertion (org.eclipse.hono.util.RegistrationAssertion)55 SpanContext (io.opentracing.SpanContext)53 VertxTestContext (io.vertx.junit5.VertxTestContext)52 VertxExtension (io.vertx.junit5.VertxExtension)51 MessageHelper (org.eclipse.hono.util.MessageHelper)51 ExtendWith (org.junit.jupiter.api.extension.ExtendWith)51 Mockito.when (org.mockito.Mockito.when)51 Truth.assertThat (com.google.common.truth.Truth.assertThat)50 ResourceIdentifier (org.eclipse.hono.util.ResourceIdentifier)47