private BiConsumer<Void, Throwable> handleEnforcementCompletion(final T signal, final ActorRef sender) { return (_void, throwable) -> { if (throwable != null) { final Throwable error = throwable instanceof CompletionException ? throwable.getCause() : throwable; reportError("Error thrown during enforcement", sender, error, signal.getDittoHeaders()); } }; }
private static ShardedMessageEnvelope createEnvelope(final EntityId entityId, final Signal<?> signal) { return ShardedMessageEnvelope.of( entityId.toString(), signal.getType(), signal.toJson(signal.getImplementedSchemaVersion(), FieldType.regularOrSpecial()), signal.getDittoHeaders()); } }
@Override public void accept(final ExternalMessage externalMessage, final Signal<?> signal) { externalMessage.getEnforcementFilter().ifPresent(enforcementFilter -> { log.debug("Connection Signal ID Enforcement enabled - matching Signal ID <{}> with filter: {}", signal.getId(), enforcementFilter); enforcementFilter.match(signal.getId(), signal.getDittoHeaders()); }); } }
/** * Wrap a signal in a sharded message envelope addressed to the correct {@code EnforcerActor}. * * @param signal the signal to wrap. * @return the sharded message envelope. */ public static ShardedMessageEnvelope wrapForEnforcer(final Signal<?> signal) { final EntityId entityId; if (MessageCommand.RESOURCE_TYPE.equals(signal.getResourceType())) { entityId = EntityId.of(ThingCommand.RESOURCE_TYPE, signal.getId()); } else { entityId = EntityId.of(signal.getResourceType(), signal.getId()); } return createEnvelope(entityId, signal); }
return; if (connectionId.equals(signal.getDittoHeaders().getOrigin().orElse(null))) { log.debug("Signal dropped: was sent by myself."); return; PlaceholderFilter.filterTargets(subscribedAndAuthorizedTargets, signal.getId(), unresolvedPlaceholder -> log.info(UNRESOLVED_PLACEHOLDERS_MESSAGE, unresolvedPlaceholder)); log.debug("Forwarding signal <{}> to client actor with targets: {}.", signal.getType(), filteredTargets);
/** * Extend a signal by read-subjects header given explicitly. * * @param <T> type of the signal. * @param signal the signal to extend. * @param readSubjects explicitly-given read subjects. * @return the extended signal. */ protected static <T extends Signal> T addReadSubjectsToSignal(final Signal<T> signal, final Set<String> readSubjects) { final DittoHeaders newHeaders = signal.getDittoHeaders() .toBuilder() .readSubjects(readSubjects) .build(); return signal.setDittoHeaders(newHeaders); }
private void handleSignal(final Signal<?> signal) { LogUtil.enhanceLogWithCorrelationId(logger, signal); final DittoHeaders dittoHeaders = signal.getDittoHeaders(); if (connectionCorrelationId.equals(dittoHeaders.getOrigin().orElse(null))) { logger.debug("Got Signal <{}> in <{}> session, " + "but this was issued by this connection itself, not telling " + "eventAndResponsePublisher about it", signal.getType(), type); } else { // check if this session is "allowed" to receive the LiveSignal if (authorizationSubjects != null && !Collections.disjoint(dittoHeaders.getReadSubjects(), authorizationSubjects)) { if (matchesNamespaces(signal)) { if (matchesFilter(signal)) { logger.debug("Got Signal <{}> in <{}> session, " + "telling eventAndResponsePublisher about it: {}", signal.getType(), type, signal); eventAndResponsePublisher.tell(signal, getSelf()); } else { logger.debug("Signal does not match filter"); } } else { logger.debug("Signal does not match namespaces"); } } } }
@Override public Adaptable toAdaptable(final Signal<?> signal) { final boolean isLive = isLiveSignal(signal); final TopicPath.Channel channel = isLive ? TopicPath.Channel.LIVE : TopicPath.Channel.TWIN; if (signal instanceof MessageCommand) { return toAdaptable((MessageCommand<?, ?>) signal); } else if (signal instanceof MessageCommandResponse) { return toAdaptable((MessageCommandResponse<?, ?>) signal); } else if (signal instanceof Command) { return toAdaptable((Command<?>) signal, channel); } else if (signal instanceof CommandResponse) { return toAdaptable((CommandResponse<?>) signal, channel); } else if (signal instanceof Event) { return toAdaptable((Event<?>) signal, channel); } throw UnknownSignalException.newBuilder(signal.getName()).dittoHeaders(signal.getDittoHeaders()).build(); }
PlaceholderFilter.apply(e.getValue(), sourceSignal.getId(), THING_PLACEHOLDER, true))
return; if (connectionId.equals(signal.getDittoHeaders().getOrigin().orElse(null))) { log.debug("Signal dropped: was sent by myself."); return; PlaceholderFilter.filterTargets(subscribedAndAuthorizedTargets, signal.getId(), unresolvedPlaceholder -> log.info(UNRESOLVED_PLACEHOLDERS_MESSAGE, unresolvedPlaceholder)); log.debug("Forwarding signal <{}> to client actor with targets: {}.", signal.getType(), filteredTargets);
private Signal<?> fromLiveAdaptable(final Adaptable adaptable) { final TopicPath topicPath = adaptable.getTopicPath(); final Signal<?> liveSignal; if (TopicPath.Criterion.MESSAGES.equals(topicPath.getCriterion())) { // /things/live/messages final boolean isResponse = adaptable.getPayload().getStatus().isPresent(); if (isResponse) { liveSignal = messageCommandResponseAdapter.fromAdaptable(adaptable); } else { liveSignal = messageCommandAdapter.fromAdaptable(adaptable); } } else { liveSignal = signalFromAdaptable(adaptable, topicPath); // /things/live/(commands|events) } if (liveSignal != null) { final DittoHeadersBuilder enhancedHeadersBuilder = liveSignal.getDittoHeaders() .toBuilder() .channel(TopicPath.Channel.LIVE.getName()); return liveSignal.setDittoHeaders(enhancedHeadersBuilder.build()); } else { throw UnknownTopicPathException.newBuilder(topicPath).build(); } }
.match(ActorSubscriberMessage.OnNext.class, on -> on.element() instanceof Signal, onNext -> { final Signal<?> signal = (Signal) onNext.element(); final Optional<String> correlationIdOpt = signal.getDittoHeaders().getCorrelationId(); if (correlationIdOpt.isPresent()) { final String correlationId = correlationIdOpt.get(); logger.debug("Got new Signal <{}>, currently outstanding are <{}>", signal.getType(), outstandingCommandCorrelationIds.size()); delegateActor.tell(signal, getSelf()); } else { logger.warning("Got a Signal <{}> without correlationId, NOT accepting/forwarding it: {}", signal.getType(), signal);
@Override public Adaptable toAdaptable(final Signal<?> signal) { final boolean isLive = isLiveSignal(signal); final TopicPath.Channel channel = isLive ? TopicPath.Channel.LIVE : TopicPath.Channel.TWIN; if (signal instanceof MessageCommand) { return toAdaptable((MessageCommand<?, ?>) signal); } else if (signal instanceof MessageCommandResponse) { return toAdaptable((MessageCommandResponse<?, ?>) signal); } else if (signal instanceof Command) { return toAdaptable((Command<?>) signal, channel); } else if (signal instanceof CommandResponse) { return toAdaptable((CommandResponse<?>) signal, channel); } else if (signal instanceof Event) { return toAdaptable((Event<?>) signal, channel); } throw UnknownSignalException.newBuilder(signal.getName()).dittoHeaders(signal.getDittoHeaders()).build(); }
PlaceholderFilter.apply(e.getValue(), sourceSignal.getId(), THING_PLACEHOLDER, true))
private boolean isResponseExpected(final Signal<?> signal) { return signal instanceof Command && signal.getDittoHeaders().isResponseRequired(); }
final String correlationId = signal.getDittoHeaders().getCorrelationId().get(); if (signal instanceof SendClaimMessage) { if (signal.getDittoHeaders().isResponseRequired()) { responseReceivers.put(correlationId, sender); } else { log(signal).warning("No outstanding responses receiver for CommandResponse <{}>", signal.getType()); if (wasPublished && signal.getDittoHeaders().isResponseRequired()) { responseReceivers.put(correlationId, sender); publishToMediator(withReadSubjects, StreamingType.LIVE_COMMANDS.getDistributedPubSubTopic(), sender); if (signal.getDittoHeaders().isResponseRequired()) { responseReceivers.put(correlationId, sender); signal.getDittoHeaders().getAuthorizationContext(), WRITE); if (authorized) { final EventSendNotAllowedException eventSendNotAllowedException = EventSendNotAllowedException.newBuilder(((ThingEvent) signal).getThingId()) .dittoHeaders(signal.getDittoHeaders()) .build(); log(signal).info("Live Event was NOT authorized: <{}>", signal); " looked up! Answering with ThingNotAccessibleException.", signal.getType(),
/** * Prepares an {@link ExpiringTimerBuilder} with default {@link #AMQP_ROUNDTRIP_METRIC_NAME} and tags. * @param command The command to extract tags. * @return The prepared {@link ExpiringTimerBuilder} */ public static ExpiringTimerBuilder newAmqpRoundTripTimer(final Signal<?> command) { if (command instanceof Command) { return newAmqpRoundTripTimer((Command) command); } final String metricsUri = AMQP_ROUNDTRIP_METRIC_NAME + command.getType(); return newExpiringTimer(metricsUri) .tag(TracingTags.COMMAND_TYPE, command.getType()); }