sender.open();
private void createSender(Vertx vertx, String address, CompletableFuture<Void> promise, int retries) { sender = connection.createSender(address); sender.openHandler(result -> { if (result.succeeded()) { createReceiver(vertx, address, promise, 0); } else { if (retries > maxRetries) { promise.completeExceptionally(result.cause()); } else { log.info("Error creating sender, retries = {}", retries); vertx.setTimer(1000, id -> createSender(vertx, address, promise, retries + 1)); } } }); sender.open(); }
public void send(String address, List<Message> messages, long timeout, TimeUnit timeUnit) throws InterruptedException { ProtonClient client = ProtonClient.create(vertx); CountDownLatch latch = new CountDownLatch(1); Queue<Message> messageQueue = new ArrayDeque<>(messages); client.connect(host, port, connectEvent -> { if (connectEvent.succeeded()) { ProtonConnection connection = connectEvent.result(); connection.open(); ProtonSender sender = connection.createSender(address); sender.openHandler(senderOpenEvent -> { if (senderOpenEvent.succeeded()) { sendNext(connection, sender, messageQueue, latch); } }); sender.open(); } }); boolean ok = latch.await(timeout, timeUnit); if (!ok) { throw new RuntimeException("Sending messages timed out, " + messageQueue.size() + " messages unsent"); } }
/** * Open the endpoint, attaching the link */ public void open() { // attach sender link to $subctrl this.sender .setQoS(ProtonQoS.AT_LEAST_ONCE) .open(); }
sender.open();
/** * Open the endpoint, attaching the link */ public void open() { // attach sender link to $lwt this.sender .setQoS(ProtonQoS.AT_LEAST_ONCE) .open(); }
@Override public void connectionOpened(ProtonConnection connection) { ProtonSender sender = connection.createSender(linkOptions.getTarget().getAddress()); sender.setTarget(linkOptions.getTarget()); sender.setQoS(clientOptions.getQos()); sender.openHandler(result -> { if (result.succeeded()) { log.info("Sender link '" + sender.getTarget().getAddress() + "' opened, sending messages"); connectPromise.complete(null); sendNext(connection, sender); } else { handleError(connection, sender.getRemoteCondition()); } }); sender.closeHandler(result -> handleError(connection, sender.getRemoteCondition())); sender.open(); }
private void partitionsAssignedHandler(Set<TopicPartition> partitions) { if (partitions.isEmpty()) { sendAmqpError(AmqpBridge.newError(AmqpBridge.AMQP_ERROR_NO_PARTITIONS, "All partitions already have a receiver")); } else { if (!this.sender.isOpen()) { this.sender .setSource(this.sender.getRemoteSource()) .open(); } } }
sender.setTarget(target); sender.open(); } else { closeReceiver();
/** * Send the AMQP_PUBREL to the related client pubrel address * * @param amqpPubrelMessage AMQP_PUBREL message */ public void publish(AmqpPubrelMessage amqpPubrelMessage, Handler<AsyncResult<ProtonDelivery>> handler) { // send AMQP_PUBREL message if (!this.senderPubrel.isOpen()) { this.senderPubrel .setQoS(ProtonQoS.AT_LEAST_ONCE) .open(); // TODO: think about starting a timer for inactivity on this link for detaching ? } this.senderPubrel.send(amqpPubrelMessage.toAmqp(), delivery -> { if (delivery.getRemoteState() == Accepted.getInstance()) { LOG.info("AMQP pubrel delivery {}", delivery.getRemoteState()); handler.handle(Future.succeededFuture(delivery)); } else { handler.handle(Future.failedFuture(String.format("AMQP pubrel delivery %s", delivery.getRemoteState()))); } }); }
}); sender.open(); });
/** * Verify that a second response link to the same address is being accepted if the first is released before. */ @Test public void testFreeSubscription() { final ProtonConnection con1 = mock(ProtonConnection.class); final ProtonConnection con2 = mock(ProtonConnection.class); final ProtonSender sender1 = mock(ProtonSender.class); final ProtonSender sender2 = mock(ProtonSender.class); final Future<Void> processingTracker = Future.future(); final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true, processingTracker); // WHEN a first sender attaches endpoint.onLinkAttach(con1, sender1, REPLY_RESOURCE); // THEN open has to be called verify(sender1).open(); // WHEN the connection closed endpoint.onConnectionClosed(con1); // THEN the unregister method has to be called verify(messageConsumer).unregister(); // WHEN a new link is attached endpoint.onLinkAttach(con2, sender2, REPLY_RESOURCE); // THEN open has to be called verify(sender2).open(); }
@Override public final void onLinkAttach(final ProtonConnection con, final ProtonSender sender, final ResourceIdentifier targetResource) { if (ProtonQoS.AT_LEAST_ONCE.equals(sender.getRemoteQoS())) { final HonoUser user = Constants.getClientPrincipal(con); sender.setQoS(ProtonQoS.AT_LEAST_ONCE).open(); logger.debug("transferring token to client..."); final Message tokenMsg = ProtonHelper.message(user.getToken()); MessageHelper.addProperty(tokenMsg, AuthenticationConstants.APPLICATION_PROPERTY_TYPE, AuthenticationConstants.TYPE_AMQP_JWT); sender.send(tokenMsg, disposition -> { if (disposition.remotelySettled()) { logger.debug("successfully transferred auth token to client"); } else { logger.debug("failed to transfer auth token to client"); } sender.close(); }); } else { onLinkDetach(sender, ProtonHelper.condition(AmqpError.INVALID_FIELD, "supports AT_LEAST_ONCE delivery mode only")); } }
/** * Verify that a second response link to the same address is being rejected. */ @Test public void testDuplicateSubscription() { final ProtonConnection con1 = mock(ProtonConnection.class); final ProtonConnection con2 = mock(ProtonConnection.class); final ProtonSender sender1 = mock(ProtonSender.class); final ProtonSender sender2 = mock(ProtonSender.class); final Future<Void> processingTracker = Future.future(); final RequestResponseEndpoint<ServiceConfigProperties> endpoint = getEndpoint(true, processingTracker); // WHEN a first sender attaches endpoint.onLinkAttach(con1, sender1, REPLY_RESOURCE); // THEN open has to be called verify(sender1).open(); // WHEN a second sender attaches endpoint.onLinkAttach(con2, sender2, REPLY_RESOURCE); // THEN close has to be called verify(sender2).close(); }
@Override public void onLinkAttach(final ProtonSender sender, final ResourceIdentifier targetResource) { /* note: we "misuse" deviceId part of the resource as reply address here */ if (targetResource.getResourceId() == null) { logger.debug("link target provided in client's link ATTACH does not match pattern \"registration/<tenant>/<reply-address>\""); sender.setCondition(condition(AmqpError.INVALID_FIELD.toString(), "link target must have the following format registration/<tenant>/<reply-address>")); sender.close(); } else { logger.debug("establishing sender link with client [{}]", MessageHelper.getLinkName(sender)); final MessageConsumer<JsonObject> replyConsumer = vertx.eventBus().consumer(targetResource.toString(), message -> { // TODO check for correct session here...? logger.trace("forwarding reply to client: {}", message.body()); final Message amqpReply = RegistrationConstants.getAmqpReply(message); sender.send(amqpReply); }); sender.closeHandler(senderClosed -> { replyConsumer.unregister(); senderClosed.result().close(); final String linkName = MessageHelper.getLinkName(sender); logger.debug("receiver closed link [{}], removing associated event bus consumer [{}]", linkName, replyConsumer.address()); }); sender.setQoS(ProtonQoS.AT_LEAST_ONCE).open(); } }
private Future<MessageConsumer> openCommandSenderLink( final ProtonSender sender, final ResourceIdentifier address, final Device authenticatedDevice, final Span span) { return createCommandConsumer(sender, address).map(consumer -> { final String tenantId = address.getTenantId(); final String deviceId = address.getResourceId(); sender.setSource(sender.getRemoteSource()); sender.setTarget(sender.getRemoteTarget()); sender.setQoS(ProtonQoS.AT_LEAST_ONCE); final Handler<AsyncResult<ProtonSender>> detachHandler = link -> { final Span detachHandlerSpan = newSpan("detach Command receiver", authenticatedDevice); sendDisconnectedTtdEvent(tenantId, deviceId, authenticatedDevice, detachHandlerSpan.context()); consumer.close(null); onLinkDetach(sender); detachHandlerSpan.finish(); }; HonoProtonHelper.setCloseHandler(sender, detachHandler); HonoProtonHelper.setDetachHandler(sender, detachHandler); sender.open(); // At this point, the remote peer's receiver link is successfully opened and is ready to receive // commands. Send "device ready for command" notification downstream. LOG.debug("established link [address: {}] for sending commands to device", address); sendConnectedTtdEvent(tenantId, deviceId, authenticatedDevice, span.context()); return consumer; }).otherwise(t -> { throw new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "cannot create command consumer"); }); }
}); serverSender.open(); });
serverSender.setSource(source); serverSender.open(); });