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;
}
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()));
}
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));
}
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));
}
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));
}
Aggregations