Search in sources :

Example 11 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class VertxBasedHttpProtocolAdapterTest method testBasicAuthFailsWrongCredentials.

@SuppressWarnings("unchecked")
@Test
public final void testBasicAuthFailsWrongCredentials(final TestContext context) {
    final Async async = context.async();
    final String encodedUserPass = Base64.getEncoder().encodeToString("testuser@DEFAULT_TENANT:password123".getBytes(StandardCharsets.UTF_8));
    doAnswer(invocation -> {
        Handler<AsyncResult<User>> resultHandler = invocation.getArgument(1);
        resultHandler.handle(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_UNAUTHORIZED, "bad credentials")));
        return null;
    }).when(credentialsAuthProvider).authenticate(any(JsonObject.class), any(Handler.class));
    vertx.createHttpClient().put(httpAdapter.getInsecurePort(), HOST, "/somenonexistingroute").putHeader(HttpHeaders.CONTENT_TYPE, HttpUtils.CONTENT_TYPE_JSON).putHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedUserPass).handler(response -> {
        context.assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED, response.statusCode());
        response.bodyHandler(totalBuffer -> {
            async.complete();
        });
    }).exceptionHandler(context::fail).end();
}
Also used : Async(io.vertx.ext.unit.Async) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject) Handler(io.vertx.core.Handler) AsyncResult(io.vertx.core.AsyncResult) Test(org.junit.Test)

Example 12 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class KuraProtocolAdapter method mapTopic.

Future<ResourceIdentifier> mapTopic(final MqttContext ctx) {
    final Future<ResourceIdentifier> result = Future.future();
    try {
        final ResourceIdentifier topic = ResourceIdentifier.fromString(ctx.message().topicName());
        ResourceIdentifier mappedTopic = null;
        if (getConfig().getControlPrefix().equals(topic.getEndpoint())) {
            // this is a "control" message
            ctx.setContentType(getConfig().getCtrlMsgContentType());
            final String[] mappedPath = Arrays.copyOf(topic.getResourcePath(), topic.getResourcePath().length);
            mappedPath[0] = getEndpoint(ctx.message().qosLevel());
            mappedTopic = ResourceIdentifier.fromPath(mappedPath);
        } else {
            // map "data" messages based on QoS
            ctx.setContentType(getConfig().getDataMsgContentType());
            final String[] mappedPath = new String[topic.getResourcePath().length + 1];
            System.arraycopy(topic.getResourcePath(), 0, mappedPath, 1, topic.getResourcePath().length);
            mappedPath[0] = getEndpoint(ctx.message().qosLevel());
            mappedTopic = ResourceIdentifier.fromPath(mappedPath);
        }
        if (mappedTopic.getResourcePath().length < 3) {
            // topic does not contain account_name and client_id
            result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "topic does not comply with Kura format"));
        } else {
            LOG.debug("mapped Kura message [topic: {}, QoS: {}] to Hono message [to: {}, device_id: {}, content-type: {}]", topic, ctx.message().qosLevel(), mappedTopic.getBasePath(), mappedTopic.getResourceId(), ctx.contentType());
            result.complete(mappedTopic);
        }
    } catch (final IllegalArgumentException e) {
        result.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "malformed topic name"));
    }
    return result;
}
Also used : ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) ClientErrorException(org.eclipse.hono.client.ClientErrorException)

Example 13 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapter method uploadMessage.

/**
 * Uploads a message to Hono Messaging.
 *
 * @param ctx The context in which the MQTT message has been published.
 * @param resource The resource that the message should be uploaded to.
 * @param payload The message payload to send.
 * @return A future indicating the outcome of the operation.
 *         <p>
 *         The future will succeed if the message has been uploaded 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 Buffer payload) {
    Objects.requireNonNull(ctx);
    Objects.requireNonNull(resource);
    Objects.requireNonNull(payload);
    switch(EndpointType.fromString(resource.getEndpoint())) {
        case TELEMETRY:
            return uploadTelemetryMessage(ctx, resource.getTenantId(), resource.getResourceId(), payload);
        case EVENT:
            return uploadEventMessage(ctx, resource.getTenantId(), resource.getResourceId(), payload);
        default:
            return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "unsupported endpoint"));
    }
}
Also used : ClientErrorException(org.eclipse.hono.client.ClientErrorException)

Example 14 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapter method uploadMessage.

private Future<Void> uploadMessage(final MqttContext ctx, final String tenant, final String deviceId, final Buffer payload, final Future<MessageSender> senderTracker, final String endpointName) {
    if (payload.length() == 0) {
        return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST, "payload must not be empty"));
    } else {
        final Future<JsonObject> tokenTracker = getRegistrationAssertion(tenant, deviceId, ctx.authenticatedDevice());
        final Future<TenantObject> tenantConfigTracker = getTenantConfiguration(tenant);
        return CompositeFuture.all(tokenTracker, tenantConfigTracker, senderTracker).compose(ok -> {
            if (tenantConfigTracker.result().isAdapterEnabled(getTypeName())) {
                final Message downstreamMessage = newMessage(String.format("%s/%s", endpointName, tenant), deviceId, ctx.message().topicName(), ctx.contentType(), payload, tokenTracker.result());
                customizeDownstreamMessage(downstreamMessage, ctx);
                return senderTracker.result().send(downstreamMessage);
            } else {
                // this adapter is not enabled for the tenant
                return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN));
            }
        }).compose(delivery -> {
            LOG.trace("successfully processed message [topic: {}, QoS: {}] for device [tenantId: {}, deviceId: {}]", ctx.message().topicName(), ctx.message().qosLevel(), tenant, deviceId);
            metrics.incrementProcessedMqttMessages(endpointName, tenant);
            onMessageSent(ctx);
            // check that the remote MQTT client is still connected before sending PUBACK
            if (ctx.deviceEndpoint().isConnected() && ctx.message().qosLevel() == MqttQoS.AT_LEAST_ONCE) {
                ctx.deviceEndpoint().publishAcknowledge(ctx.message().messageId());
            }
            return Future.<Void>succeededFuture();
        }).recover(t -> {
            if (ClientErrorException.class.isInstance(t)) {
                ClientErrorException e = (ClientErrorException) t;
                LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]: {} - {}", tenant, deviceId, endpointName, e.getErrorCode(), e.getMessage());
            } else {
                LOG.debug("cannot process message for device [tenantId: {}, deviceId: {}, endpoint: {}]", tenant, deviceId, endpointName, t);
                metrics.incrementUndeliverableMqttMessages(endpointName, tenant);
                onMessageUndeliverable(ctx);
            }
            return Future.failedFuture(t);
        });
    }
}
Also used : HttpURLConnection(java.net.HttpURLConnection) MqttQoS(io.netty.handler.codec.mqtt.MqttQoS) MqttConnectReturnCode(io.netty.handler.codec.mqtt.MqttConnectReturnCode) LoggerFactory(org.slf4j.LoggerFactory) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) Autowired(org.springframework.beans.factory.annotation.Autowired) ClientErrorException(org.eclipse.hono.client.ClientErrorException) ServiceInvocationException(org.eclipse.hono.client.ServiceInvocationException) Constants(org.eclipse.hono.util.Constants) MqttServer(io.vertx.mqtt.MqttServer) CompositeFuture(io.vertx.core.CompositeFuture) TelemetryConstants(org.eclipse.hono.util.TelemetryConstants) MessageSender(org.eclipse.hono.client.MessageSender) AbstractProtocolAdapterBase(org.eclipse.hono.service.AbstractProtocolAdapterBase) Message(org.apache.qpid.proton.message.Message) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) JsonObject(io.vertx.core.json.JsonObject) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) UsernamePasswordCredentials(org.eclipse.hono.service.auth.device.UsernamePasswordCredentials) Logger(org.slf4j.Logger) MqttServerOptions(io.vertx.mqtt.MqttServerOptions) DeviceCredentials(org.eclipse.hono.service.auth.device.DeviceCredentials) ServerErrorException(org.eclipse.hono.client.ServerErrorException) EndpointType(org.eclipse.hono.util.EndpointType) EventConstants(org.eclipse.hono.util.EventConstants) Future(io.vertx.core.Future) TenantObject(org.eclipse.hono.util.TenantObject) Objects(java.util.Objects) Buffer(io.vertx.core.buffer.Buffer) MqttAuth(io.vertx.mqtt.MqttAuth) Device(org.eclipse.hono.service.auth.device.Device) TenantObject(org.eclipse.hono.util.TenantObject) Message(org.apache.qpid.proton.message.Message) ClientErrorException(org.eclipse.hono.client.ClientErrorException) JsonObject(io.vertx.core.json.JsonObject)

Example 15 with ClientErrorException

use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.

the class AbstractVertxBasedMqttProtocolAdapterTest method testOnUnauthenticatedMessageDoesNotSendPubAckOnFailure.

/**
 * Verifies that the adapter does not send a PUBACK package to the device if
 * an event message has not been accepted by the peer.
 *
 * @param ctx The vert.x test context.
 */
@Test
public void testOnUnauthenticatedMessageDoesNotSendPubAckOnFailure(final TestContext ctx) {
    // GIVEN an adapter with a downstream event consumer
    final Future<ProtonDelivery> outcome = Future.future();
    givenAnEventSenderForOutcome(outcome);
    final MqttServer server = getMqttServer(false);
    final AbstractVertxBasedMqttProtocolAdapter<ProtocolAdapterProperties> adapter = getAdapter(server);
    // WHEN a device publishes an event
    final Buffer payload = Buffer.buffer("some payload");
    final MqttEndpoint endpoint = mock(MqttEndpoint.class);
    when(endpoint.isConnected()).thenReturn(Boolean.TRUE);
    final MqttPublishMessage messageFromDevice = mock(MqttPublishMessage.class);
    when(messageFromDevice.qosLevel()).thenReturn(MqttQoS.AT_LEAST_ONCE);
    when(messageFromDevice.messageId()).thenReturn(5555555);
    final MqttContext context = new MqttContext(messageFromDevice, endpoint);
    adapter.uploadEventMessage(context, "my-tenant", "4712", payload).setHandler(ctx.asyncAssertFailure());
    // and the peer rejects the message
    outcome.fail(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST));
    // THEN the device has not received a PUBACK
    verify(endpoint, never()).publishAcknowledge(anyInt());
}
Also used : Buffer(io.vertx.core.buffer.Buffer) ProtocolAdapterProperties(org.eclipse.hono.config.ProtocolAdapterProperties) ProtonDelivery(io.vertx.proton.ProtonDelivery) MqttEndpoint(io.vertx.mqtt.MqttEndpoint) MqttPublishMessage(io.vertx.mqtt.messages.MqttPublishMessage) MqttServer(io.vertx.mqtt.MqttServer) ClientErrorException(org.eclipse.hono.client.ClientErrorException) Test(org.junit.Test)

Aggregations

ClientErrorException (org.eclipse.hono.client.ClientErrorException)32 JsonObject (io.vertx.core.json.JsonObject)19 Future (io.vertx.core.Future)16 HttpURLConnection (java.net.HttpURLConnection)16 Handler (io.vertx.core.Handler)14 AsyncResult (io.vertx.core.AsyncResult)13 Objects (java.util.Objects)12 ServerErrorException (org.eclipse.hono.client.ServerErrorException)10 TenantConstants (org.eclipse.hono.util.TenantConstants)9 EventBusService (org.eclipse.hono.service.EventBusService)8 EventBusMessage (org.eclipse.hono.util.EventBusMessage)8 Vertx (io.vertx.core.Vertx)6 Buffer (io.vertx.core.buffer.Buffer)6 ProtonDelivery (io.vertx.proton.ProtonDelivery)6 HonoClient (org.eclipse.hono.client.HonoClient)6 MqttEndpoint (io.vertx.mqtt.MqttEndpoint)5 MqttServer (io.vertx.mqtt.MqttServer)5 Optional (java.util.Optional)5 TimeUnit (java.util.concurrent.TimeUnit)5 Message (org.apache.qpid.proton.message.Message)5