use of org.apache.qpid.proton.amqp.transport.ErrorCondition in project vertx-proton by vert-x3.
the class MessageSubscriberWhiteboxVerificationTckTest method createServer.
private TestServer createServer() throws Exception {
return new TestServer(vertx, (connection) -> {
connection.openHandler(res -> {
LOG.trace("Client connected: " + connection.getRemoteContainer());
connection.open();
}).closeHandler(c -> {
LOG.trace("Client closing amqp connection: " + connection.getRemoteContainer());
connection.close();
connection.disconnect();
}).disconnectHandler(c -> {
LOG.trace("Client socket disconnected: " + connection.getRemoteContainer());
connection.disconnect();
}).sessionOpenHandler(session -> session.open());
connection.receiverOpenHandler(receiver -> {
if (!server.getDetachLink()) {
LOG.trace("Receiving from client to: " + receiver.getRemoteTarget().getAddress());
// This is rather naive, for example use only, proper
receiver.setTarget(receiver.getRemoteTarget());
// servers should ensure that they advertise their own
// Target settings that actually reflect what is in place.
// The request may have also been for a dynamic address.
receiver.handler((delivery, msg) -> {
String address = msg.getAddress();
if (address == null) {
address = receiver.getRemoteTarget().getAddress();
}
Section body = msg.getBody();
String content = "unknown";
if (body instanceof AmqpValue) {
content = (String) ((AmqpValue) body).getValue();
}
LOG.trace("message to:" + address + ", body: " + content);
});
receiver.closeHandler(s -> {
s.result().close();
});
}
receiver.open();
if (server.getDetachLink()) {
receiver.setCondition(new ErrorCondition(Symbol.getSymbol("Failed Subscriber Requested"), ""));
receiver.close();
}
});
});
}
use of org.apache.qpid.proton.amqp.transport.ErrorCondition in project hono by eclipse.
the class AbstractHonoClient method createReceiver.
/**
* Creates a receiver link.
* <p>
* The receiver will be created with its <em>autoAccept</em> property set to {@code true}.
*
* @param ctx The vert.x context to use for establishing the link.
* @param clientConfig The configuration properties to use.
* @param con The connection to create the link for.
* @param sourceAddress The address to receive messages from.
* @param qos The quality of service to use for the link.
* @param messageHandler The handler to invoke with every message received.
* @param closeHook The handler to invoke when the link is closed by the peer (may be {@code null}).
* @return A future for the created link. The future will be completed once the link is open.
* The future will fail with a {@link ServiceInvocationException} if the link cannot be opened.
* @throws NullPointerException if any of the arguments other than close hook is {@code null}.
*/
protected static final Future<ProtonReceiver> createReceiver(final Context ctx, final ClientConfigProperties clientConfig, final ProtonConnection con, final String sourceAddress, final ProtonQoS qos, final ProtonMessageHandler messageHandler, final Handler<String> closeHook) {
Objects.requireNonNull(ctx);
Objects.requireNonNull(clientConfig);
Objects.requireNonNull(con);
Objects.requireNonNull(sourceAddress);
Objects.requireNonNull(qos);
Objects.requireNonNull(messageHandler);
final Future<ProtonReceiver> result = Future.future();
ctx.runOnContext(go -> {
final ProtonReceiver receiver = con.createReceiver(sourceAddress);
receiver.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.FALSE);
receiver.setAutoAccept(true);
receiver.setQoS(qos);
receiver.setPrefetch(clientConfig.getInitialCredits());
receiver.handler((delivery, message) -> {
messageHandler.handle(delivery, message);
if (LOG.isTraceEnabled()) {
int remainingCredits = receiver.getCredit() - receiver.getQueued();
LOG.trace("handling message [remotely settled: {}, queued messages: {}, remaining credit: {}]", delivery.remotelySettled(), receiver.getQueued(), remainingCredits);
}
});
receiver.openHandler(recvOpen -> {
if (recvOpen.succeeded()) {
LOG.debug("receiver open [source: {}]", sourceAddress);
receiver.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.TRUE);
result.complete(recvOpen.result());
} else {
final ErrorCondition error = receiver.getRemoteCondition();
if (error == null) {
LOG.debug("opening receiver [{}] failed", sourceAddress, recvOpen.cause());
result.fail(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "cannot open receiver", recvOpen.cause()));
} else {
LOG.debug("opening receiver [{}] failed: {} - {}", sourceAddress, error.getCondition(), error.getDescription());
result.fail(StatusCodeMapper.from(error));
}
}
});
receiver.detachHandler(remoteDetached -> onRemoteDetach(receiver, con.getRemoteContainer(), false, closeHook));
receiver.closeHandler(remoteClosed -> onRemoteDetach(receiver, con.getRemoteContainer(), true, closeHook));
receiver.open();
});
return result;
}
use of org.apache.qpid.proton.amqp.transport.ErrorCondition in project hono by eclipse.
the class AbstractHonoClient method onRemoteDetach.
private static void onRemoteDetach(final ProtonReceiver receiver, final String remoteContainer, final boolean closed, final Handler<String> closeHook) {
final ErrorCondition error = receiver.getRemoteCondition();
if (error == null) {
LOG.debug("receiver [{}] detached (with closed={}) by peer [{}]", receiver.getSource().getAddress(), closed, remoteContainer);
} else {
LOG.debug("receiver [{}] detached (with closed={}) by peer [{}]: {} - {}", receiver.getSource().getAddress(), closed, remoteContainer, error.getCondition(), error.getDescription());
}
receiver.close();
final boolean linkEstablished = receiver.attachments().get(KEY_LINK_ESTABLISHED, Boolean.class);
if (linkEstablished && closeHook != null) {
closeHook.handle(receiver.getSource().getAddress());
}
}
use of org.apache.qpid.proton.amqp.transport.ErrorCondition in project hono by eclipse.
the class AbstractHonoClient method createSender.
/**
* Creates a sender link.
*
* @param ctx The vert.x context to use for establishing the link.
* @param clientConfig The configuration properties to use.
* @param con The connection to create the link for.
* @param targetAddress The target address of the link.
* @param qos The quality of service to use for the link.
* @param closeHook The handler to invoke when the link is closed by the peer (may be {@code null}).
* @return A future for the created link. The future will be completed once the link is open.
* The future will fail with a {@link ServiceInvocationException} if the link cannot be opened.
* @throws NullPointerException if any of the arguments other than close hook is {@code null}.
*/
protected static final Future<ProtonSender> createSender(final Context ctx, final ClientConfigProperties clientConfig, final ProtonConnection con, final String targetAddress, final ProtonQoS qos, final Handler<String> closeHook) {
Objects.requireNonNull(ctx);
Objects.requireNonNull(clientConfig);
Objects.requireNonNull(con);
Objects.requireNonNull(targetAddress);
Objects.requireNonNull(qos);
final Future<ProtonSender> result = Future.future();
ctx.runOnContext(create -> {
final ProtonSender sender = con.createSender(targetAddress);
sender.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.FALSE);
sender.setQoS(qos);
sender.setAutoSettle(true);
sender.openHandler(senderOpen -> {
if (senderOpen.succeeded()) {
LOG.debug("sender open [target: {}, sendQueueFull: {}]", targetAddress, sender.sendQueueFull());
sender.attachments().set(KEY_LINK_ESTABLISHED, Boolean.class, Boolean.TRUE);
// wait on credits a little time, if not already given
if (sender.sendQueueFull()) {
ctx.owner().setTimer(clientConfig.getFlowLatency(), timerID -> {
LOG.debug("sender [target: {}] has {} credits after grace period of {}ms", targetAddress, sender.getCredit(), clientConfig.getFlowLatency());
result.complete(sender);
});
} else {
result.complete(sender);
}
} else {
final ErrorCondition error = sender.getRemoteCondition();
if (error == null) {
LOG.debug("opening sender [{}] failed", targetAddress, senderOpen.cause());
result.fail(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "cannot open sender", senderOpen.cause()));
} else {
LOG.debug("opening sender [{}] failed: {} - {}", targetAddress, error.getCondition(), error.getDescription());
result.fail(StatusCodeMapper.from(error));
}
}
});
sender.detachHandler(remoteDetached -> onRemoteDetach(sender, con.getRemoteContainer(), false, closeHook));
sender.closeHandler(remoteClosed -> onRemoteDetach(sender, con.getRemoteContainer(), true, closeHook));
sender.open();
});
return result;
}
use of org.apache.qpid.proton.amqp.transport.ErrorCondition in project hono by eclipse.
the class EventEndpointTest method testOnLinkAttachDisconnectsClientsUsingWrongQos.
/**
* Verifies that the endpoint rejects a client's attempt to create a link using <em>AT_MOST_ONCE</em>
* delivery mode.
*/
@Test
public void testOnLinkAttachDisconnectsClientsUsingWrongQos() {
ProtonConnection con = mock(ProtonConnection.class);
ProtonReceiver receiver = mock(ProtonReceiver.class);
when(receiver.getRemoteQoS()).thenReturn(ProtonQoS.AT_MOST_ONCE);
ResourceIdentifier targetAddress = ResourceIdentifier.from("event", "tenant", null);
endpoint.onLinkAttach(con, receiver, targetAddress);
ArgumentCaptor<ErrorCondition> errorCondition = ArgumentCaptor.forClass(ErrorCondition.class);
verify(receiver).setCondition(errorCondition.capture());
assertThat(errorCondition.getValue(), is(ErrorConditions.ERROR_UNSUPPORTED_DELIVERY_MODE));
verify(receiver).close();
}
Aggregations