Search in sources :

Example 1 with ProtonDelivery

use of io.vertx.proton.ProtonDelivery in project vertx-proton by vert-x3.

the class ProtonSenderImpl method send.

@Override
public ProtonDelivery send(byte[] tag, Message message, Handler<ProtonDelivery> onUpdated) {
    if (anonymousSender && message.getAddress() == null) {
        throw new IllegalArgumentException("Message must have an address when using anonymous sender.");
    }
    // TODO: prevent odd combination of onRecieved callback + SenderSettleMode.SETTLED, or just allow it?
    // start a new delivery..
    Delivery delivery = sender().delivery(tag);
    int BUFFER_SIZE = 1024;
    byte[] encodedMessage = new byte[BUFFER_SIZE];
    // protonj has a nice encode2 method which tells us what
    // encoded message length would be even if our buffer is too small.
    MessageImpl msg = (MessageImpl) message;
    int len = msg.encode2(encodedMessage, 0, BUFFER_SIZE);
    // looks like the message is bigger than our initial buffer, lets resize and try again.
    if (len > encodedMessage.length) {
        encodedMessage = new byte[len];
        msg.encode(encodedMessage, 0, len);
    }
    sender().send(encodedMessage, 0, len);
    if (link.getSenderSettleMode() == SenderSettleMode.SETTLED) {
        delivery.settle();
    }
    // ends the delivery.
    sender().advance();
    ProtonDeliveryImpl protonDeliveryImpl = new ProtonDeliveryImpl(delivery);
    if (onUpdated != null) {
        protonDeliveryImpl.setAutoSettle(autoSettle);
        protonDeliveryImpl.handler(onUpdated);
    } else {
        protonDeliveryImpl.setAutoSettle(true);
    }
    getSession().getConnectionImpl().flush();
    return protonDeliveryImpl;
}
Also used : Delivery(org.apache.qpid.proton.engine.Delivery) ProtonDelivery(io.vertx.proton.ProtonDelivery) MessageImpl(org.apache.qpid.proton.message.impl.MessageImpl)

Example 2 with ProtonDelivery

use of io.vertx.proton.ProtonDelivery in project hono by eclipse.

the class MessageForwardingEndpointTest method testForwardMessageAcceptsCorrectRegistrationAssertion.

/**
 * Verifies that a message containing a matching registration assertion is
 * forwarded to the downstream adapter.
 */
@Test
public void testForwardMessageAcceptsCorrectRegistrationAssertion() {
    final String validToken = getToken(SECRET, "tenant", "4711");
    final UpstreamReceiver client = mock(UpstreamReceiver.class);
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final DownstreamAdapter adapter = mock(DownstreamAdapter.class);
    when(tokenValidator.isValid(validToken, "tenant", "4711")).thenReturn(Boolean.TRUE);
    final MessageForwardingEndpoint<HonoMessagingConfigProperties> endpoint = getEndpoint();
    endpoint.setRegistrationAssertionValidator(tokenValidator);
    endpoint.setDownstreamAdapter(adapter);
    // WHEN processing a message bearing a valid registration assertion
    final Message msg = ProtonHelper.message();
    MessageHelper.addRegistrationAssertion(msg, validToken);
    MessageHelper.addAnnotation(msg, MessageHelper.APP_PROPERTY_RESOURCE, "telemetry/tenant/4711");
    endpoint.forwardMessage(client, delivery, msg);
    // THEN the message is sent downstream
    verify(adapter).processMessage(client, delivery, msg);
    verify(client, never()).close(any(ErrorCondition.class));
    // and the assertion has been removed from the message
    assertThat("downstream message should not contain registration assertion", MessageHelper.getRegistrationAssertion(msg), is(nullValue()));
}
Also used : ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) ErrorCondition(org.apache.qpid.proton.amqp.transport.ErrorCondition) Test(org.junit.Test)

Example 3 with ProtonDelivery

use of io.vertx.proton.ProtonDelivery in project hono by eclipse.

the class MessageForwardingEndpointTest method testMessageHandlerRejectsMalformedMessage.

/**
 * Verifies that the endpoint rejects messages that do not pass formal verification.
 */
@SuppressWarnings({ "unchecked" })
@Test
public void testMessageHandlerRejectsMalformedMessage() {
    // GIVEN an endpoint with an attached client
    final ResourceIdentifier targetAddress = ResourceIdentifier.fromString("telemetry/tenant");
    final ProtonConnection connection = mock(ProtonConnection.class);
    when(connection.getRemoteContainer()).thenReturn("test-client");
    final ProtonReceiver receiver = mock(ProtonReceiver.class);
    when(receiver.getRemoteQoS()).thenReturn(ProtonQoS.AT_MOST_ONCE);
    final DownstreamAdapter adapter = mock(DownstreamAdapter.class);
    doAnswer(invocation -> {
        final Handler<AsyncResult<Void>> resultHandler = invocation.getArgument(1);
        resultHandler.handle(Future.succeededFuture());
        return null;
    }).when(adapter).onClientAttach(any(UpstreamReceiver.class), any(Handler.class));
    final MessageForwardingEndpoint<HonoMessagingConfigProperties> endpoint = getEndpoint(false);
    endpoint.setDownstreamAdapter(adapter);
    endpoint.onLinkAttach(connection, receiver, targetAddress);
    final ArgumentCaptor<ProtonMessageHandler> messageHandler = ArgumentCaptor.forClass(ProtonMessageHandler.class);
    verify(receiver).handler(messageHandler.capture());
    // WHEN a client sends a malformed message
    final Message message = ProtonHelper.message("malformed");
    final ProtonDelivery upstreamDelivery = mock(ProtonDelivery.class);
    messageHandler.getValue().handle(upstreamDelivery, message);
    // THEN the endpoint rejects the message
    final ArgumentCaptor<Rejected> deliveryState = ArgumentCaptor.forClass(Rejected.class);
    verify(upstreamDelivery).disposition(deliveryState.capture(), eq(Boolean.TRUE));
    assertThat(deliveryState.getValue().getError().getCondition(), is(AmqpError.DECODE_ERROR));
    // but does not close the link
    verify(receiver, never()).close();
    // and the message is not forwarded to the downstream adapter
    verify(adapter, never()).processMessage(any(UpstreamReceiver.class), eq(upstreamDelivery), eq(message));
}
Also used : ProtonReceiver(io.vertx.proton.ProtonReceiver) Message(org.apache.qpid.proton.message.Message) ProtonDelivery(io.vertx.proton.ProtonDelivery) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) Handler(io.vertx.core.Handler) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) ResourceIdentifier(org.eclipse.hono.util.ResourceIdentifier) ProtonConnection(io.vertx.proton.ProtonConnection) ProtonMessageHandler(io.vertx.proton.ProtonMessageHandler) AsyncResult(io.vertx.core.AsyncResult) Test(org.junit.Test)

Example 4 with ProtonDelivery

use of io.vertx.proton.ProtonDelivery in project hono by eclipse.

the class ForwardingTelemetryDownstreamAdapterTest method testProcessMessageForwardsDownstreamDisposition.

/**
 * Verifies that an unsettled telemetry message received from an upstream client is
 * forwarded to the downstream container and the downstream container's disposition
 * is forwarded to the upstream client.
 *
 * @param ctx The test context.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testProcessMessageForwardsDownstreamDisposition(final TestContext ctx) {
    final UpstreamReceiver client = TestSupport.newClient();
    // GIVEN an adapter with a connection to a downstream container
    final ProtonSender sender = TestSupport.newMockSender(false);
    final ForwardingTelemetryDownstreamAdapter adapter = new ForwardingTelemetryDownstreamAdapter(vertx, TestSupport.newMockSenderFactory(sender));
    adapter.setMetrics(mock(MessagingMetrics.class));
    adapter.setDownstreamConnectionFactory(connectionFactory);
    adapter.start(Future.future());
    adapter.addSender(client, sender);
    // WHEN processing an unsettled telemetry message
    final Message msg = ProtonHelper.message(TELEMETRY_MSG_CONTENT);
    MessageHelper.addDeviceId(msg, DEVICE_ID);
    final ProtonDelivery upstreamDelivery = mock(ProtonDelivery.class);
    when(upstreamDelivery.remotelySettled()).thenReturn(Boolean.FALSE);
    adapter.processMessage(client, upstreamDelivery, msg);
    // THEN the message is being delivered to the downstream container
    final ArgumentCaptor<Handler> deliveryHandler = ArgumentCaptor.forClass(Handler.class);
    verify(sender).send(eq(msg), deliveryHandler.capture());
    // and when the downstream container rejects the message
    final ProtonDelivery downstreamDelivery = mock(ProtonDelivery.class);
    when(downstreamDelivery.remotelySettled()).thenReturn(Boolean.TRUE);
    when(downstreamDelivery.getRemoteState()).thenReturn(new Rejected());
    deliveryHandler.getValue().handle(downstreamDelivery);
    // then the upstream delivery is settled with the rejected outcome
    verify(upstreamDelivery).disposition(any(Rejected.class), eq(Boolean.TRUE));
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) Message(org.apache.qpid.proton.message.Message) ProtonDelivery(io.vertx.proton.ProtonDelivery) Handler(io.vertx.core.Handler) UpstreamReceiver(org.eclipse.hono.messaging.UpstreamReceiver) Rejected(org.apache.qpid.proton.amqp.messaging.Rejected) MessagingMetrics(org.eclipse.hono.messaging.MessagingMetrics) Test(org.junit.Test)

Example 5 with ProtonDelivery

use of io.vertx.proton.ProtonDelivery in project hono by eclipse.

the class ForwardingEventDownstreamAdapterTest method testProcessMessageForwardsMessageToDownstreamSender.

/**
 * Verifies that an event uploaded by an upstream client is forwarded to the
 * downstream container.
 *
 * @param ctx The test context.
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
@Test
public void testProcessMessageForwardsMessageToDownstreamSender(final TestContext ctx) {
    final UpstreamReceiver client = newClient();
    final ProtonDelivery delivery = mock(ProtonDelivery.class);
    final ProtonDelivery downstreamDelivery = mock(ProtonDelivery.class);
    when(downstreamDelivery.getRemoteState()).thenReturn(ACCEPTED);
    when(downstreamDelivery.remotelySettled()).thenReturn(true);
    // GIVEN an adapter with a connection to a downstream container
    final Async msgSent = ctx.async();
    ProtonSender sender = newMockSender(false);
    when(sender.send(any(Message.class), any(Handler.class))).then(invocation -> {
        msgSent.complete();
        final Handler handler = invocation.getArgument(1);
        handler.handle(downstreamDelivery);
        return null;
    });
    ForwardingEventDownstreamAdapter adapter = new ForwardingEventDownstreamAdapter(vertx, newMockSenderFactory(sender));
    adapter.setMetrics(mock(MessagingMetrics.class));
    adapter.setDownstreamConnectionFactory(newMockConnectionFactory(false));
    adapter.start(Future.future());
    adapter.addSender(client, sender);
    // WHEN processing an event
    Message msg = ProtonHelper.message(EVENT_MSG_CONTENT);
    MessageHelper.addDeviceId(msg, DEVICE_ID);
    adapter.processMessage(client, delivery, msg);
    // THEN the message has been delivered to the downstream container
    msgSent.await(1000);
    // and disposition was returned
    verify(delivery).disposition(any(Accepted.class), eq(Boolean.TRUE));
}
Also used : ProtonSender(io.vertx.proton.ProtonSender) ProtonDelivery(io.vertx.proton.ProtonDelivery) Message(org.apache.qpid.proton.message.Message) Async(io.vertx.ext.unit.Async) Handler(io.vertx.core.Handler) UpstreamReceiver(org.eclipse.hono.messaging.UpstreamReceiver) MessagingMetrics(org.eclipse.hono.messaging.MessagingMetrics) Accepted(org.apache.qpid.proton.amqp.messaging.Accepted) Test(org.junit.Test)

Aggregations

ProtonDelivery (io.vertx.proton.ProtonDelivery)38 Test (org.junit.Test)31 Message (org.apache.qpid.proton.message.Message)29 Handler (io.vertx.core.Handler)21 ProtonSender (io.vertx.proton.ProtonSender)15 Rejected (org.apache.qpid.proton.amqp.messaging.Rejected)15 ProtonReceiver (io.vertx.proton.ProtonReceiver)13 Async (io.vertx.ext.unit.Async)12 Vertx (io.vertx.core.Vertx)11 ProtonHelper (io.vertx.proton.ProtonHelper)11 JsonObject (io.vertx.core.json.JsonObject)10 TestContext (io.vertx.ext.unit.TestContext)10 VertxUnitRunner (io.vertx.ext.unit.junit.VertxUnitRunner)10 Before (org.junit.Before)10 Rule (org.junit.Rule)10 RunWith (org.junit.runner.RunWith)10 ArgumentCaptor (org.mockito.ArgumentCaptor)10 Mockito (org.mockito.Mockito)10 Context (io.vertx.core.Context)9 HttpURLConnection (java.net.HttpURLConnection)9