private static void initSender(Vertx vertx, ProtonConnection connection, ProtonSender sender) { org.apache.qpid.proton.amqp.messaging.Source remoteSource = (org.apache.qpid.proton.amqp.messaging.Source) sender.getRemoteSource(); if(remoteSource == null) { sender.setTarget(null); sender.setCondition(new ErrorCondition(AmqpError.INVALID_FIELD, "No source terminus specified")); sender.open(); sender.close(); return; sender.setSource(remoteSource); sender.setTarget(sender.getRemoteTarget()); vertx.cancelTimer(t); } else { if(!sender.sendQueueFull()) { int msgNum = sent.incrementAndGet(); System.out.println("Sending message " + msgNum + " to client, for address: " + remoteSource.getAddress()); Message m = message("Hello " + msgNum + " from Server!"); sender.send(m, delivery -> { System.out.println("Message " + msgNum + " was received by the client."); }); sender.detachHandler(x -> { vertx.cancelTimer(timer); sender.detach(); sender.free(); }); sender.closeHandler(x -> {
sender.open(); if(!sender.sendQueueFull()) { final int msgNum = sent.incrementAndGet(); Message message = message("Hello " + msgNum); sender.send(message, delivery -> { System.out.println(String.format("Message " + msgNum + " was received by the server: remote state=%s", delivery.getRemoteState())); });
private void senderOpenHandler(ProtonConnection connection, ProtonSender sender) { Source source = (Source) sender.getRemoteSource(); sender.setSource(source); log.info("[{}]: Got subscription request from {} on {}", containerId, connection.getRemoteContainer(), source.getAddress()); sender.closeHandler(handle -> { vertx.executeBlocking(promise -> { synchronized (this) { sender.close(); }); }); synchronized (this) { if (queues.get(source.getAddress()) == null || subscribers.get(source.getAddress()) != null) { senderContext.runOnContext(id -> sender.close()); sender.open(); log.info("[{}]: Opened sender for subscriber {} for address {}", containerId, connection.getRemoteContainer(), sender.getRemoteSource().getAddress()); } else { sender.close(); log.info("[{}]: Failed creating subscriber {} for address {}", containerId, connection.getRemoteContainer(), sender.getRemoteSource().getAddress(), result.cause());
Source remoteSource = (Source) serverSender.getRemoteSource(); context.assertNotNull(remoteSource, "source should not be null"); context.assertEquals(testName, remoteSource.getAddress(), "expected given address"); serverSender.setSource(remoteSource.copy()); serverSender.open(); protonMsg.setBody(new AmqpValue(sentContent)); serverSender.send(protonMsg); serverSender.setCondition(ProtonHelper.condition(AmqpError.INTERNAL_ERROR, "testing-error")); serverSender.close(); }); });
logger.debug("client [{}] provided invalid reply-to address", sender.getName()); sender.setCondition(ProtonHelper.condition(AmqpError.INVALID_FIELD, String.format("reply-to address must have the following format %s/<tenant>/<reply-address>", getName()))); sender.close(); return; sender.getName(), replyTo); sender.setCondition(ProtonHelper.condition(AmqpError.ILLEGAL_STATE, String.format("reply-to address [%s] is already subscribed", replyTo))); sender.close(); return; logger.debug("establishing response sender link with client [{}]", sender.getName()); logger.trace("forwarding reply to client [{}]: {}", sender.getName(), message.body().encodePrettily()); try { final Message amqpReply = getAmqpReply(filteredResponse); sender.send(amqpReply); } finally { flowCreditToRequestor(replyTo); sender.setQoS(ProtonQoS.AT_LEAST_ONCE); sender.getName(), replyConsumer.address()); sender.close();
@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")); } }
ProtonSender sender = conn.createSender(testName).open(); for (int i = 1; i <= totalMsgCount; i++) { final int msgNum = i; sender.send(protonMsg, delivery -> { LOG.trace("Running onUpdated for sent message " + msgNum); context.assertNotNull(delivery.getRemoteState(), "message " + msgNum + " had no remote state");
@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(); } }
final Source remoteSource = sender.getRemoteSource(); LOG.debug("client [container: {}] wants to open a link [address: {}] for receiving messages", con.getRemoteContainer(), remoteSource); if (authAttempt.succeeded() && authAttempt.result()) { Constants.copyProperties(con, sender); sender.setSource(sender.getRemoteSource()); sender.setTarget(sender.getRemoteTarget()); endpoint.onLinkAttach(con, sender, targetResource); } else { LOG.debug("subject [{}] is not authorized to READ from [{}]", user.getName(), targetResource); sender.setCondition(ProtonHelper.condition(AmqpError.UNAUTHORIZED_ACCESS.toString(), "unauthorized")); sender.close(); sender.setCondition(ProtonHelper.condition(AmqpError.NOT_FOUND, "no such address")); sender.close();
/** * 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()))); } }); }
Source remoteSource = (Source) serverSender.getRemoteSource(); context.assertNotNull(remoteSource, "source should not be null"); context.assertEquals(testName, remoteSource.getAddress(), "expected given address"); serverSender.setSource(remoteSource.copy()); serverSender.sendQueueDrainHandler(s -> { context.assertFalse(s.sendQueueFull(), "expected send queue not to be full"); protonMsg.setBody(new AmqpValue(sentContent)); serverSender.send(protonMsg); serverSender.open(); }); });
sender.sendQueueDrainHandler(sender -> { if(!completed.get() && !cancelledSub.get()) { long credit = sender.getCredit(); long newRequests = credit - outstandingRequests; sender.detachHandler(res-> { cancelSub(); sender.detach(); }); sender.closeHandler(res-> { cancelSub(); sender.close(); }); sender.openHandler(res -> { LOG.trace("Attach received"); }); sender.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"); }); }
@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(); }
protected void forwardMessage(final ProtonSender sender, final Message msg, final ProtonDelivery delivery) { ProtonHelper.accepted(delivery, true); sender.send(msg); }
sender.setQoS(qos); sender.sendQueueDrainHandler(sendQueueDrainHandler); sender.openHandler(openAttempt -> { if (openAttempt.succeeded()) { LOG.debug( sender.closeHandler(closed -> { if (closed.succeeded()) { LOG.debug("sender [{}] for container [{}] closed", address, connection.getRemoteContainer()); sender.open();
sender.setQoS(qos); sender.setAutoSettle(true); sender.openHandler(senderOpen -> { final ErrorCondition error = sender.getRemoteCondition(); if (error == null) { LOG.debug("opening sender [{}] failed", targetAddress, senderOpen.cause()); LOG.debug("sender open [target: {}, sendQueueFull: {}]", targetAddress, sender.sendQueueFull()); if (sender.getCredit() <= 0) { ctx.owner().setTimer(clientConfig.getFlowLatency(), timerID -> { LOG.debug("sender [target: {}] has {} credits after grace period of {}ms", targetAddress, sender.getCredit(), clientConfig.getFlowLatency()); result.tryComplete(sender); }); HonoProtonHelper.setDetachHandler(sender, remoteDetached -> onRemoteDetach(sender, con.getRemoteContainer(), false, closeHook)); HonoProtonHelper.setCloseHandler(sender, remoteClosed -> onRemoteDetach(sender, con.getRemoteContainer(), true, closeHook)); sender.open(); ctx.owner().setTimer(clientConfig.getLinkEstablishmentTimeout(), tid -> onTimeOut(sender, clientConfig, result)); });
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(); } } }
@Override public void onComplete() { if(!completed.getAndSet(true)) { connCtx.runOnContext(x-> { // clear the handlers, we are done sender.sendQueueDrainHandler(null); sender.detachHandler(null); sender.closeHandler(null); sender.close(); }); } }