io.vertx.mqtt.messages.MqttPublishMessage Java Examples

The following examples show how to use io.vertx.mqtt.messages.MqttPublishMessage. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: MqttClientImpl.java    From vertx-mqtt with Apache License 2.0 6 votes vote down vote up
/**
 * Used for calling the pubrel handler when the server acknowledge a QoS 2 message with pubrel
 *
 * @param pubrelMessageId identifier of the message acknowledged by the server
 */
private void handlePubrel(int pubrelMessageId) {
  MqttMessage message;
  synchronized (this) {
    message = qos2inbound.remove(pubrelMessageId);

    if (message == null) {
      log.warn("Received PUBREL packet without having related PUBREC packet in storage");
      return;
    }
    this.publishComplete(pubrelMessageId);
  }
  Handler<MqttPublishMessage> handler = this.publishHandler();
  if (handler != null) {
    handler.handle((MqttPublishMessage) message);
  }
}
 
Example #2
Source File: MqttClientImpl.java    From vertx-mqtt with Apache License 2.0 6 votes vote down vote up
/**
 * Sends PUBREC packet to server
 *
 * @param publishMessage a PUBLISH message to acknowledge
 */
private void publishReceived(MqttPublishMessage publishMessage) {

  MqttFixedHeader fixedHeader =
    new MqttFixedHeader(MqttMessageType.PUBREC, false, AT_MOST_ONCE, false, 0);

  MqttMessageIdVariableHeader variableHeader =
    MqttMessageIdVariableHeader.from(publishMessage.messageId());

  io.netty.handler.codec.mqtt.MqttMessage pubrec = MqttMessageFactory.newMessage(fixedHeader, variableHeader, null);

  synchronized (this) {
    qos2inbound.put(publishMessage.messageId(), publishMessage);
  }
  this.write(pubrec);
}
 
Example #3
Source File: CommandAndControlMqttIT.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
private Future<Void> subscribeToCommands(
        final String commandTargetDeviceId,
        final Handler<MqttPublishMessage> msgHandler,
        final MqttCommandEndpointConfiguration endpointConfig,
        final MqttQoS qos) {

    final Promise<Void> result = Promise.promise();
    context.runOnContext(go -> {
        mqttClient.publishHandler(msgHandler);
        mqttClient.subscribeCompletionHandler(subAckMsg -> {
            if (subAckMsg.grantedQoSLevels().contains(qos.value())) {
                result.complete();
            } else {
                result.fail("could not subscribe to command topic");
            }
        });
        mqttClient.subscribe(endpointConfig.getCommandTopicFilter(commandTargetDeviceId), qos.value());
    });
    return result.future();
}
 
Example #4
Source File: VertxBasedMqttProtocolAdapter.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * {@inheritDoc}
 */
@Override
protected Future<Void> onPublishedMessage(final MqttContext ctx) {

    return mapTopic(ctx)
            .compose(address -> validateAddress(address, ctx.authenticatedDevice()))
            .compose(targetAddress -> mapMessage(ctx, targetAddress))
            .compose(mappedMessage -> {
                final MqttPublishMessage mqttPublishMessage = MqttPublishMessage.create(
                        ctx.message().messageId(),
                        ctx.message().qosLevel(),
                        ctx.message().isDup(),
                        ctx.message().isRetain(),
                        ctx.message().topicName(),
                        mappedMessage.getPayload().getByteBuf());
                return uploadMessage(ctx, mappedMessage.getTargetAddress(), mqttPublishMessage);
            })
            .recover(t -> {
                log.debug("discarding message [topic: {}] from {}",
                        ctx.message().topicName(), ctx.authenticatedDevice(), t);
                return Future.failedFuture(t);
            });
}
 
Example #5
Source File: HttpBasedMessageMappingTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the result returned by the mapping service contains the
 * original payload and target address if no mapper has been defined for
 * the gateway.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapMessageSucceedsIfNoMapperIsSet(final VertxTestContext ctx) {

    config.setMapperEndpoints(Map.of("mapper", MapperEndpoint.from("host", 1234, "/uri", false)));
    final ResourceIdentifier targetAddress = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, "gateway");
    final MqttPublishMessage message = newMessage(MqttQoS.AT_LEAST_ONCE, TelemetryConstants.TELEMETRY_ENDPOINT);
    final MqttContext context = newContext(message, new Device(TEST_TENANT_ID, "gateway"));

    messageMapping.mapMessage(context, targetAddress, new JsonObject())
        .onComplete(ctx.succeeding(mappedMessage -> {
            ctx.verify(() -> {
                assertThat(mappedMessage.getTargetAddress()).isEqualTo(targetAddress);
                assertThat(mappedMessage.getPayload()).isEqualTo(message.payload());
                assertThat(mappedMessage.getAdditionalProperties()).isEmpty();
                verify(mapperWebClient, never()).post(anyInt(), anyString(), anyString());
            });
            ctx.completeNow();
        }));
}
 
Example #6
Source File: HttpBasedMessageMappingTest.java    From hono with Eclipse Public License 2.0 6 votes vote down vote up
/**
 * Verifies that the result returned by the mapping service contains the
 * original payload and target address if no mapper endpoint has been configured
 * for the adapter.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapMessageSucceedsIfNoMapperEndpointIsConfigured(final VertxTestContext ctx) {

    final ResourceIdentifier targetAddress = ResourceIdentifier.from(TelemetryConstants.TELEMETRY_ENDPOINT, TEST_TENANT_ID, "gateway");
    final MqttPublishMessage message = newMessage(MqttQoS.AT_LEAST_ONCE, TelemetryConstants.TELEMETRY_ENDPOINT);
    final MqttContext context = newContext(message, new Device(TEST_TENANT_ID, "gateway"));

    messageMapping.mapMessage(context, targetAddress, new JsonObject().put(RegistrationConstants.FIELD_MAPPER, "mapper"))
        .onComplete(ctx.succeeding(mappedMessage -> {
            ctx.verify(() -> {
                assertThat(mappedMessage.getTargetAddress()).isEqualTo(targetAddress);
                assertThat(mappedMessage.getPayload()).isEqualTo(message.payload());
                assertThat(mappedMessage.getAdditionalProperties()).isEmpty();
                verify(mapperWebClient, never()).post(anyInt(), anyString(), anyString());
            });
            ctx.completeNow();
        }));
}
 
Example #7
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter rejects QoS 2 messages published to the <em>telemetry</em> endpoint.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapTopicFailsForQoS2TelemetryMessage(final VertxTestContext ctx) {

    givenAnAdapter();

    // WHEN a device publishes a message with QoS 2 to a "telemetry" topic
    final MqttPublishMessage message = newMessage(MqttQoS.EXACTLY_ONCE, TelemetryConstants.TELEMETRY_ENDPOINT);
    adapter.mapTopic(newContext(message, null)).onComplete(ctx.failing(t -> {
        // THEN the message cannot be mapped to a topic
        assertServiceInvocationException(ctx, t, HttpURLConnection.HTTP_BAD_REQUEST);
        ctx.completeNow();
    }));
}
 
Example #8
Source File: MqttContextTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the tenant is determined from the published message's topic if
 * the device has not been authenticated.
 */
@Test
public void testTenantIsRetrievedFromTopic() {
    final MqttPublishMessage msg = newMessage(TelemetryConstants.TELEMETRY_ENDPOINT_SHORT, "tenant", "device");
    final MqttContext context = MqttContext.fromPublishPacket(msg, mock(MqttEndpoint.class));
    assertEquals("tenant", context.tenant());
}
 
Example #9
Source File: MqttContextTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies the values retrieved from the <em>property-bag</em> of a message's topic.
 */
@Test
public void verifyPropertyBagRetrievedFromTopic() {
    final Device device = new Device("tenant", "device");
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn("event/tenant/device/?param1=value1&param2=value2");
    final MqttContext context = MqttContext.fromPublishPacket(msg, mock(MqttEndpoint.class), device);

    assertNotNull(context.propertyBag());
    assertEquals("value1", context.propertyBag().getProperty("param1"));
    assertEquals("value2", context.propertyBag().getProperty("param2"));
    assertEquals("event/tenant/device", context.topic().toString());
}
 
Example #10
Source File: KuraProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private static MqttPublishMessage newMessage(final MqttQoS qosLevel, final String topic, final Buffer payload) {

        final MqttPublishMessage message = mock(MqttPublishMessage.class);
        when(message.qosLevel()).thenReturn(qosLevel);
        when(message.topicName()).thenReturn(topic);
        when(message.payload()).thenReturn(payload);
        return message;
    }
 
Example #11
Source File: HttpBasedMessageMappingTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private static MqttPublishMessage newMessage(final MqttQoS qosLevel, final String topic, final Buffer payload) {
    final MqttPublishMessage message = mock(MqttPublishMessage.class);
    when(message.qosLevel()).thenReturn(qosLevel);
    when(message.topicName()).thenReturn(topic);
    when(message.payload()).thenReturn(payload);
    return message;
}
 
Example #12
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
private static MqttPublishMessage newMessage(final MqttQoS qosLevel, final String topic, final Buffer payload) {

        final MqttPublishMessage message = mock(MqttPublishMessage.class);
        when(message.qosLevel()).thenReturn(qosLevel);
        when(message.topicName()).thenReturn(topic);
        when(message.payload()).thenReturn(payload);
        return message;
    }
 
Example #13
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter rejects messages published to topics containing an endpoint
 * other than <em>telemetry</em> or <em>event</em>.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapTopicFailsForUnknownEndpoint(final VertxTestContext ctx) {

    givenAnAdapter();

    // WHEN a device publishes a message to a topic with an unknown endpoint
    final MqttPublishMessage message = newMessage(MqttQoS.AT_MOST_ONCE, "unknown");
    adapter.mapTopic(newContext(message, null)).onComplete(ctx.failing(t -> {
        // THEN the message cannot be mapped to a topic
        assertServiceInvocationException(ctx, t, HttpURLConnection.HTTP_NOT_FOUND);
        ctx.completeNow();
    }));
}
 
Example #14
Source File: MqttContext.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Creates a new context for a published message.
 *
 * @param publishedMessage The published MQTT message.
 * @param deviceEndpoint The endpoint representing the device
 *                       that has published the message.
 * @param authenticatedDevice The authenticated device identity.
 * @return The context.
 * @throws NullPointerException if message or endpoint are {@code null}.
 */
public static MqttContext fromPublishPacket(
        final MqttPublishMessage publishedMessage,
        final MqttEndpoint deviceEndpoint,
        final Device authenticatedDevice) {

    Objects.requireNonNull(publishedMessage);
    Objects.requireNonNull(deviceEndpoint);

    final MqttContext result = new MqttContext();
    result.message = publishedMessage;
    result.deviceEndpoint = deviceEndpoint;
    result.authenticatedDevice = authenticatedDevice;
    if (publishedMessage.topicName() != null) {
        try {
            Optional.ofNullable(PropertyBag.fromTopic(publishedMessage.topicName()))
                    .ifPresentOrElse(propertyBag -> {
                        result.topic = ResourceIdentifier.fromString(propertyBag.topicWithoutPropertyBag());
                        result.propertyBag = propertyBag;
                    }, () -> result.topic = ResourceIdentifier.fromString(publishedMessage.topicName()));
            result.endpoint = MetricsTags.EndpointType.fromString(result.topic.getEndpoint());
        } catch (final IllegalArgumentException e) {
            // malformed topic
        }
    }
    return result;
}
 
Example #15
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter rejects QoS 0 messages published to the <em>event</em> endpoint.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapTopicFailsForQoS0EventMessage(final VertxTestContext ctx) {

    givenAnAdapter();

    // WHEN a device publishes a message with QoS 0 to an "event" topic
    final MqttPublishMessage message = newMessage(MqttQoS.AT_MOST_ONCE, EventConstants.EVENT_ENDPOINT);
    adapter.mapTopic(newContext(message, null)).onComplete(ctx.failing(t -> {
        // THEN the message cannot be mapped to a topic
        assertServiceInvocationException(ctx, t, HttpURLConnection.HTTP_BAD_REQUEST);
        ctx.completeNow();
    }));
}
 
Example #16
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter rejects QoS 2 messages published to the <em>event</em> endpoint.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapTopicFailsForQoS2EventMessage(final VertxTestContext ctx) {

    givenAnAdapter();

    // WHEN a device publishes a message with QoS 2 to an "event" topic
    final MqttPublishMessage message = newMessage(MqttQoS.EXACTLY_ONCE, EventConstants.EVENT_ENDPOINT);
    adapter.mapTopic(newContext(message, null)).onComplete(ctx.failing(t -> {
        // THEN the message cannot be mapped to a topic
        assertServiceInvocationException(ctx, t, HttpURLConnection.HTTP_BAD_REQUEST);
        ctx.completeNow();
    }));
}
 
Example #17
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter supports all required topic names.
 *
 * @param ctx The helper to use for running tests on vert.x.
 */
@Test
public void testMapTopicSupportsShortAndLongTopicNames(final VertxTestContext ctx) {

    givenAnAdapter();

    MqttPublishMessage message = newMessage(MqttQoS.AT_LEAST_ONCE, EventConstants.EVENT_ENDPOINT);
    MqttContext context = newContext(message, null);
    adapter.mapTopic(context).onComplete(ctx.succeeding(address -> {
        ctx.verify(() -> assertThat(MetricsTags.EndpointType.fromString(address.getEndpoint())).isEqualTo(MetricsTags.EndpointType.EVENT));
    }));

    message = newMessage(MqttQoS.AT_LEAST_ONCE, EventConstants.EVENT_ENDPOINT_SHORT);
    context = newContext(message, null);
    adapter.mapTopic(context).onComplete(ctx.succeeding(address -> {
        ctx.verify(() -> assertThat(MetricsTags.EndpointType.fromString(address.getEndpoint())).isEqualTo(MetricsTags.EndpointType.EVENT));
    }));

    message = newMessage(MqttQoS.AT_LEAST_ONCE, TelemetryConstants.TELEMETRY_ENDPOINT);
    context = newContext(message, null);
    adapter.mapTopic(context).onComplete(ctx.succeeding(address -> {
        ctx.verify(() -> assertThat(MetricsTags.EndpointType.fromString(address.getEndpoint())).isEqualTo(MetricsTags.EndpointType.TELEMETRY));
    }));

    message = newMessage(MqttQoS.AT_LEAST_ONCE, TelemetryConstants.TELEMETRY_ENDPOINT_SHORT);
    context = newContext(message, null);
    adapter.mapTopic(context).onComplete(ctx.succeeding(address -> {
        ctx.verify(() -> assertThat(MetricsTags.EndpointType.fromString(address.getEndpoint())).isEqualTo(MetricsTags.EndpointType.TELEMETRY));
    }));

    message = newMessage(MqttQoS.AT_LEAST_ONCE, "unknown");
    context = newContext(message, null);
    adapter.mapTopic(context).onComplete(ctx.failing());
    ctx.completeNow();

}
 
Example #18
Source File: MqttClientImpl.java    From vertx-mqtt with Apache License 2.0 5 votes vote down vote up
/**
 * Used for calling the publish handler when the server publishes a message
 *
 * @param msg published message
 */
private void handlePublish(MqttPublishMessage msg) {

  Handler<MqttPublishMessage> handler;
  switch (msg.qosLevel()) {

    case AT_MOST_ONCE:
      handler = this.publishHandler();
      if (handler != null) {
        handler.handle(msg);
      }
      break;

    case AT_LEAST_ONCE:
      this.publishAcknowledge(msg.messageId());
      handler = this.publishHandler();
      if (handler != null) {
        handler.handle(msg);
      }
      break;

    case EXACTLY_ONCE:
      this.publishReceived(msg);
      // we will handle the PUBLISH when a PUBREL comes
      break;
  }
}
 
Example #19
Source File: MqttServerConnection.java    From vertx-mqtt with Apache License 2.0 5 votes vote down vote up
/**
 * Used for calling the publish handler when the remote MQTT client publishes a message
 *
 * @param msg published message
 */
void handlePublish(MqttPublishMessage msg) {

  synchronized (this.so) {
    if (this.checkConnected()) {
      this.endpoint.handlePublish(msg);
    }
  }
}
 
Example #20
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter does not forward a message published by a device if the topic is empty and closes the
 * connection to the device.
 */
@Test
public void testUploadTelemetryMessageFailsForEmptyTopic() {

    // GIVEN an adapter
    config.setAuthenticationRequired(false);
    final MqttServer server = getMqttServer(false);
    final AbstractVertxBasedMqttProtocolAdapter<MqttProtocolAdapterProperties> adapter = getAdapter(server);
    forceClientMocksToConnected();
    final DownstreamSender sender = givenAQoS0TelemetrySender();

    final MqttEndpoint endpoint = mockEndpoint();
    when(endpoint.isConnected()).thenReturn(Boolean.TRUE);
    adapter.handleEndpointConnection(endpoint);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<MqttPublishMessage>> messageHandler = ArgumentCaptor.forClass(Handler.class);
    verify(endpoint).publishHandler(messageHandler.capture());

    // WHEN a device publishes a message that has no topic
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn(null);
    when(msg.qosLevel()).thenReturn(MqttQoS.AT_MOST_ONCE);

    messageHandler.getValue().handle(msg);

    // THEN the device gets disconnected
    verify(endpoint).close();
    // and the message is not forwarded downstream
    verify(sender, never()).send(any(Message.class), any());
    // and the message has not been reported as processed
    verify(metrics, never()).reportTelemetry(
            any(MetricsTags.EndpointType.class),
            anyString(),
            any(),
            eq(MetricsTags.ProcessingOutcome.FORWARDED),
            any(MetricsTags.QoS.class),
            anyInt(),
            any());
}
 
Example #21
Source File: MqttContextTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the tenant is determined from the authenticated device.
 */
@Test
public void testTenantIsRetrievedFromAuthenticatedDevice() {
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn("t");
    final Device device = new Device("tenant", "device");
    final MqttContext context = MqttContext.fromPublishPacket(msg, mock(MqttEndpoint.class), device);
    assertEquals("tenant", context.tenant());
}
 
Example #22
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the adapter discards messages that contain a malformed topic.
 */
@Test
public void testHandlePublishedMessageFailsForMalformedTopic() {

    // GIVEN an adapter
    final MqttServer server = getMqttServer(false);
    final AbstractVertxBasedMqttProtocolAdapter<MqttProtocolAdapterProperties> adapter = getAdapter(server);

    // WHEN a device publishes a message with a malformed topic
    final MqttEndpoint device = mockEndpoint();
    final Buffer payload = Buffer.buffer("hello");
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.qosLevel()).thenReturn(MqttQoS.AT_LEAST_ONCE);
    when(msg.topicName()).thenReturn(null);
    when(msg.payload()).thenReturn(payload);
    adapter.handlePublishedMessage(newMqttContext(msg, device));

    // THEN the message is not processed
    verify(metrics, never()).reportTelemetry(
            any(MetricsTags.EndpointType.class),
            anyString(),
            any(),
            eq(MetricsTags.ProcessingOutcome.FORWARDED),
            any(MetricsTags.QoS.class),
            anyInt(),
            any());
    // and no PUBACK is sent to the device
    verify(device, never()).publishAcknowledge(anyInt());
}
 
Example #23
Source File: AbstractVertxBasedMqttProtocolAdapter.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Forwards a message to the AMQP Messaging Network.
 *
 * @param ctx The context in which the MQTT message has been published.
 * @param resource The resource that the message should be forwarded to.
 * @param message The message to send.
 * @return A future indicating the outcome of the operation.
 *         <p>
 *         The future will succeed if the message has been forwarded successfully.
 *         Otherwise the future will fail with a {@link ServiceInvocationException}.
 * @throws NullPointerException if any of context, resource or payload is {@code null}.
 * @throws IllegalArgumentException if the payload is empty.
 */
public final Future<Void> uploadMessage(
        final MqttContext ctx,
        final ResourceIdentifier resource,
        final MqttPublishMessage message) {

    Objects.requireNonNull(ctx);
    Objects.requireNonNull(resource);
    Objects.requireNonNull(message);

    switch (MetricsTags.EndpointType.fromString(resource.getEndpoint())) {
    case TELEMETRY:
        return uploadTelemetryMessage(
                ctx,
                resource.getTenantId(),
                resource.getResourceId(),
                message.payload());
    case EVENT:
        return uploadEventMessage(
                ctx,
                resource.getTenantId(),
                resource.getResourceId(),
                message.payload());
    case COMMAND:
        return uploadCommandResponseMessage(ctx, resource);
    default:
        return Future
                .failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "unsupported endpoint"));
    }

}
 
Example #24
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the TTL for a downstream event is set to the given <em>time-to-live</em> value in the
 * <em>property-bag</em>.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void verifyEventMessageUsesTtlValueGivenInPropertyBag(final VertxTestContext ctx) {
    // Given an adapter
    final AbstractVertxBasedMqttProtocolAdapter<MqttProtocolAdapterProperties> adapter = getAdapter(
            getMqttServer(false));
    forceClientMocksToConnected();

    final DownstreamSender sender = mock(DownstreamSender.class);
    when(downstreamSenderFactory.getOrCreateEventSender(anyString()))
            .thenReturn(Future.succeededFuture(sender));

    // WHEN a "device" of "tenant" publishes an event message with a TTL value of 30 seconds.
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn("e/tenant/device/?hono-ttl=30&param2=value2");
    when(msg.qosLevel()).thenReturn(MqttQoS.AT_LEAST_ONCE);
    adapter.uploadEventMessage(
            newMqttContext(msg, mockEndpoint()),
            "tenant",
            "device",
            Buffer.buffer("test")).onComplete(ctx.failing(t -> {
                ctx.verify(() -> {
                    final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);
                    verify(sender).sendAndWaitForOutcome(messageCaptor.capture(), (SpanContext) any());

                    // THEN the TTL value of the amqp message is 10 seconds.
                    assertThat(messageCaptor.getValue().getTtl()).isEqualTo(30 * 1000);
                });
                ctx.completeNow();
            }));
}
 
Example #25
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 5 votes vote down vote up
/**
 * Verifies that the TTL for a downstream event is limited by the <em>max-ttl</em> specified for a tenant, if the
 * given <em>time-to-live</em> duration in the <em>property-bag</em> exceeds the <em>max-ttl</em> value.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void verifyEventMessageLimitsTtlToMaxValue(final VertxTestContext ctx) {
    // Given the maximum ttl as 10 seconds for the given tenant.
    final TenantObject myTenantConfig = TenantObject.from("tenant", true)
            .setResourceLimits(new ResourceLimits().setMaxTtl(10L));
    when(tenantClient.get(eq("tenant"), (SpanContext) any())).thenReturn(Future.succeededFuture(myTenantConfig));
    // Given an adapter
    final AbstractVertxBasedMqttProtocolAdapter<MqttProtocolAdapterProperties> adapter = getAdapter(
            getMqttServer(false));
    forceClientMocksToConnected();
    final DownstreamSender sender = mock(DownstreamSender.class);
    when(downstreamSenderFactory.getOrCreateEventSender(anyString()))
            .thenReturn(Future.succeededFuture(sender));

    // WHEN a device publishes an event message with a TTL value of 30 seconds.
    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn("e/tenant/device/?hono-ttl=30&param2=value2");
    when(msg.qosLevel()).thenReturn(MqttQoS.AT_LEAST_ONCE);
    adapter.uploadEventMessage(
            newMqttContext(msg, mockEndpoint()),
            "tenant",
            "device",
            Buffer.buffer("test")).onComplete(ctx.failing(t -> {
                ctx.verify(() -> {
                    final ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class);

                    verify(sender).sendAndWaitForOutcome(messageCaptor.capture(), (SpanContext) any());

                    // THEN the TTL value of the amqp message is 10 seconds.
                    assertThat(messageCaptor.getValue().getTtl()).isEqualTo(10 * 1000);
                });
                ctx.completeNow();
            }));
}
 
Example #26
Source File: MqttClientImpl.java    From vertx-mqtt with Apache License 2.0 4 votes vote down vote up
/**
 * Handle the MQTT message received from the remote MQTT server
 *
 * @param msg Incoming Packet
 */
private void handleMessage(ChannelHandlerContext chctx, Object msg) {

  // handling directly native Netty MQTT messages, some of them are translated
  // to the related Vert.x ones for polyglotization
  if (msg instanceof io.netty.handler.codec.mqtt.MqttMessage) {

    io.netty.handler.codec.mqtt.MqttMessage mqttMessage = (io.netty.handler.codec.mqtt.MqttMessage) msg;

    DecoderResult result = mqttMessage.decoderResult();
    if (result.isFailure()) {
      chctx.pipeline().fireExceptionCaught(result.cause());
      return;
    }
    if (!result.isFinished()) {
      chctx.pipeline().fireExceptionCaught(new Exception("Unfinished message"));
      return;
    }

    log.debug(String.format("Incoming packet %s", msg));
    switch (mqttMessage.fixedHeader().messageType()) {

      case CONNACK:

        io.netty.handler.codec.mqtt.MqttConnAckMessage connack = (io.netty.handler.codec.mqtt.MqttConnAckMessage) mqttMessage;

        MqttConnAckMessage mqttConnAckMessage = MqttConnAckMessage.create(
          connack.variableHeader().connectReturnCode(),
          connack.variableHeader().isSessionPresent());
        handleConnack(mqttConnAckMessage);
        break;

      case PUBLISH:

        io.netty.handler.codec.mqtt.MqttPublishMessage publish = (io.netty.handler.codec.mqtt.MqttPublishMessage) mqttMessage;
        ByteBuf newBuf = VertxHandler.safeBuffer(publish.payload(), chctx.alloc());

        MqttPublishMessage mqttPublishMessage = MqttPublishMessage.create(
          publish.variableHeader().packetId(),
          publish.fixedHeader().qosLevel(),
          publish.fixedHeader().isDup(),
          publish.fixedHeader().isRetain(),
          publish.variableHeader().topicName(),
          newBuf);
        handlePublish(mqttPublishMessage);
        break;

      case PUBACK:
        handlePuback(((MqttMessageIdVariableHeader) mqttMessage.variableHeader()).messageId());
        break;

      case PUBREC:
        handlePubrec(((MqttMessageIdVariableHeader) mqttMessage.variableHeader()).messageId());
        break;

      case PUBREL:
        handlePubrel(((MqttMessageIdVariableHeader) mqttMessage.variableHeader()).messageId());
        break;

      case PUBCOMP:
        handlePubcomp(((MqttMessageIdVariableHeader) mqttMessage.variableHeader()).messageId());
        break;

      case SUBACK:

        io.netty.handler.codec.mqtt.MqttSubAckMessage unsuback = (io.netty.handler.codec.mqtt.MqttSubAckMessage) mqttMessage;

        MqttSubAckMessage mqttSubAckMessage = MqttSubAckMessage.create(
          unsuback.variableHeader().messageId(),
          unsuback.payload().grantedQoSLevels());
        handleSuback(mqttSubAckMessage);
        break;

      case UNSUBACK:
        handleUnsuback(((MqttMessageIdVariableHeader) mqttMessage.variableHeader()).messageId());
        break;

      case PINGRESP:
        handlePingresp();
        break;

      default:

        chctx.pipeline().fireExceptionCaught(new Exception("Wrong message type " + msg.getClass().getName()));
        break;
    }

  } else {

    chctx.pipeline().fireExceptionCaught(new Exception("Wrong message type"));
  }
}
 
Example #27
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 4 votes vote down vote up
private static MqttContext newMqttContext(final MqttPublishMessage message, final MqttEndpoint endpoint) {
    final MqttContext result = MqttContext.fromPublishPacket(message, endpoint);
    result.setTracingContext(mock(SpanContext.class));
    return result;
}
 
Example #28
Source File: MqttClientImpl.java    From vertx-mqtt with Apache License 2.0 4 votes vote down vote up
private synchronized Handler<MqttPublishMessage> publishHandler() {
  return this.publishHandler;
}
 
Example #29
Source File: VertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 4 votes vote down vote up
private static MqttPublishMessage newMessage(final MqttQoS qosLevel, final String topic) {
    return newMessage(qosLevel, topic, Buffer.buffer("test"));
}
 
Example #30
Source File: AbstractVertxBasedMqttProtocolAdapterTest.java    From hono with Eclipse Public License 2.0 4 votes vote down vote up
/**
 * Verifies that the adapter does not forward a message published by a device if the device's registration status
 * cannot be asserted.
 */
@Test
public void testUploadTelemetryMessageFailsForUnknownDevice() {

    // GIVEN an adapter
    config.setAuthenticationRequired(false);
    final MqttServer server = getMqttServer(false);
    final AbstractVertxBasedMqttProtocolAdapter<MqttProtocolAdapterProperties> adapter = getAdapter(server);
    forceClientMocksToConnected();
    givenAQoS0TelemetrySender();

    // WHEN an unknown device publishes a telemetry message
    when(regClient.assertRegistration(eq("unknown"), any(), any())).thenReturn(
            Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND)));
    final DownstreamSender sender = givenAQoS0TelemetrySender();

    final MqttEndpoint endpoint = mockEndpoint();
    when(endpoint.isConnected()).thenReturn(Boolean.TRUE);
    adapter.handleEndpointConnection(endpoint);
    @SuppressWarnings("unchecked")
    final ArgumentCaptor<Handler<MqttPublishMessage>> messageHandler = ArgumentCaptor.forClass(Handler.class);
    verify(endpoint).publishHandler(messageHandler.capture());

    final MqttPublishMessage msg = mock(MqttPublishMessage.class);
    when(msg.topicName()).thenReturn("t/my-tenant/unknown");
    when(msg.qosLevel()).thenReturn(MqttQoS.AT_MOST_ONCE);

    messageHandler.getValue().handle(msg);

    // THEN the message has not been sent downstream
    verify(sender, never()).send(any(Message.class), any());
    // and the message has not been reported as processed
    verify(metrics, never()).reportTelemetry(
            any(MetricsTags.EndpointType.class),
            anyString(),
            any(),
            eq(MetricsTags.ProcessingOutcome.FORWARDED),
            any(MetricsTags.QoS.class),
            anyInt(),
            any());
    // and the connection is closed
    verify(endpoint).close();
}