use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class AuthenticationServerClient method getToken.
private Future<HonoUser> getToken(final ProtonConnection openCon) {
final Promise<HonoUser> result = Promise.promise();
final ProtonMessageHandler messageHandler = (delivery, message) -> {
final String type = MessageHelper.getApplicationProperty(message.getApplicationProperties(), AuthenticationConstants.APPLICATION_PROPERTY_TYPE, String.class);
if (AuthenticationConstants.TYPE_AMQP_JWT.equals(type)) {
final String payload = MessageHelper.getPayloadAsString(message);
if (payload != null) {
final HonoUser user = new HonoUserAdapter() {
@Override
public String getToken() {
return payload;
}
};
LOG.debug("successfully retrieved token from Authentication service");
result.complete(user);
} else {
result.fail(new ServerErrorException(HttpURLConnection.HTTP_INTERNAL_ERROR, "message from Authentication service contains no body"));
}
} else {
result.fail(new ServerErrorException(HttpURLConnection.HTTP_INTERNAL_ERROR, "Authentication service issued unsupported token [type: " + type + "]"));
}
};
openReceiver(openCon, messageHandler).onComplete(attempt -> {
if (attempt.succeeded()) {
vertx.setTimer(5000, tid -> {
result.tryFail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "time out reached while waiting for token from Authentication service"));
});
LOG.debug("opened receiver link to Authentication service, waiting for token ...");
} else {
result.fail(attempt.cause());
}
});
return result.future();
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class HonoConnectionImpl method createReceiver.
@Override
public Future<ProtonReceiver> createReceiver(final String sourceAddress, final ProtonQoS qos, final ProtonMessageHandler messageHandler, final int preFetchSize, final boolean autoAccept, final Handler<String> remoteCloseHook) {
Objects.requireNonNull(sourceAddress);
Objects.requireNonNull(qos);
Objects.requireNonNull(messageHandler);
if (preFetchSize < 0) {
throw new IllegalArgumentException("pre-fetch size must be >= 0");
}
return executeOnContext(result -> {
checkConnected().compose(v -> {
final Promise<ProtonReceiver> receiverPromise = Promise.promise();
final ProtonReceiver receiver = session.createReceiver(sourceAddress);
if (clientConfigProperties.getMaxMessageSize() > ClientConfigProperties.MAX_MESSAGE_SIZE_UNLIMITED) {
receiver.setMaxMessageSize(new UnsignedLong(clientConfigProperties.getMaxMessageSize()));
}
receiver.setAutoAccept(autoAccept);
receiver.setQoS(qos);
receiver.setPrefetch(preFetchSize);
receiver.handler((delivery, message) -> {
HonoProtonHelper.onReceivedMessageDeliveryUpdatedFromRemote(delivery, d -> log.debug("got unexpected disposition update for received message [remote state: {}]", delivery.getRemoteState()));
try {
messageHandler.handle(delivery, message);
if (log.isTraceEnabled()) {
final int remainingCredits = receiver.getCredit() - receiver.getQueued();
log.trace("handling message [remotely settled: {}, queued messages: {}, remaining credit: {}]", delivery.remotelySettled(), receiver.getQueued(), remainingCredits);
}
} catch (final Exception ex) {
log.warn("error handling message", ex);
ProtonHelper.released(delivery, true);
}
});
final DisconnectListener<HonoConnection> disconnectBeforeOpenListener = (con) -> {
log.debug("opening receiver [{}] failed: got disconnected", sourceAddress);
receiverPromise.tryFail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "not connected"));
};
oneTimeDisconnectListeners.add(disconnectBeforeOpenListener);
receiver.openHandler(recvOpen -> {
oneTimeDisconnectListeners.remove(disconnectBeforeOpenListener);
// the result future may have already been completed here in case of a link establishment timeout
if (receiverPromise.future().isComplete()) {
log.debug("ignoring server response for opening receiver [{}]: receiver creation already timed out", sourceAddress);
} else if (recvOpen.failed()) {
// this means that we have received the peer's attach
// and the subsequent detach frame in one TCP read
final ErrorCondition error = receiver.getRemoteCondition();
if (error == null) {
log.debug("opening receiver [{}] failed", sourceAddress, recvOpen.cause());
receiverPromise.tryFail(new ClientErrorException(HttpURLConnection.HTTP_NOT_FOUND, "cannot open receiver", recvOpen.cause()));
} else {
log.debug("opening receiver [{}] failed: {} - {}", sourceAddress, error.getCondition(), error.getDescription());
receiverPromise.tryFail(StatusCodeMapper.fromAttachError(error));
}
} else if (HonoProtonHelper.isLinkEstablished(receiver)) {
log.debug("receiver open [source: {}]", sourceAddress);
receiverPromise.tryComplete(recvOpen.result());
} else {
// this means that the peer did not create a local terminus for the link
// and will send a detach frame for closing the link very shortly
// see AMQP 1.0 spec section 2.6.3
log.debug("peer did not create terminus for source [{}] and will detach the link", sourceAddress);
receiverPromise.tryFail(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE));
}
});
HonoProtonHelper.setDetachHandler(receiver, remoteDetached -> onRemoteDetach(receiver, connection.getRemoteContainer(), false, remoteCloseHook));
HonoProtonHelper.setCloseHandler(receiver, remoteClosed -> onRemoteDetach(receiver, connection.getRemoteContainer(), true, remoteCloseHook));
receiver.open();
vertx.setTimer(clientConfigProperties.getLinkEstablishmentTimeout(), tid -> {
final boolean notOpenedAndNotDisconnectedYet = oneTimeDisconnectListeners.remove(disconnectBeforeOpenListener);
if (notOpenedAndNotDisconnectedYet) {
onLinkEstablishmentTimeout(receiver, clientConfigProperties, receiverPromise);
}
});
return receiverPromise.future();
}).onComplete(result);
});
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class ProtonBasedNotificationReceiverTest method assertReceiverLinkCreated.
private static Map<String, ProtonMessageHandler> assertReceiverLinkCreated(final HonoConnection connection) {
final Map<String, ProtonMessageHandler> resultMap = new HashMap<>();
final ArgumentCaptor<ProtonMessageHandler> messageHandlerCaptor = ArgumentCaptor.forClass(ProtonMessageHandler.class);
final ArgumentCaptor<String> addressCaptor = ArgumentCaptor.forClass(String.class);
verify(connection, atLeastOnce()).createReceiver(addressCaptor.capture(), any(ProtonQoS.class), messageHandlerCaptor.capture(), VertxMockSupport.anyHandler());
final List<ProtonMessageHandler> handlers = messageHandlerCaptor.getAllValues();
final List<String> addresses = addressCaptor.getAllValues();
for (int i = 0; i < handlers.size(); i++) {
resultMap.put(addresses.get(i), handlers.get(i));
}
return resultMap;
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class AuthenticationServerClient method getToken.
private void getToken(final ProtonConnection openCon, final Future<HonoUser> authResult) {
final ProtonMessageHandler messageHandler = (delivery, message) -> {
String type = MessageHelper.getApplicationProperty(message.getApplicationProperties(), AuthenticationConstants.APPLICATION_PROPERTY_TYPE, String.class);
if (AuthenticationConstants.TYPE_AMQP_JWT.equals(type)) {
Section body = message.getBody();
if (body instanceof AmqpValue) {
final String token = ((AmqpValue) body).getValue().toString();
HonoUser user = new HonoUserAdapter() {
@Override
public String getToken() {
return token;
}
};
LOG.debug("successfully retrieved token from Authentication service");
authResult.complete(user);
} else {
authResult.fail("message from Authentication service contains no body");
}
} else {
authResult.fail("Authentication service issued unsupported token [type: " + type + "]");
}
};
openReceiver(openCon, messageHandler).compose(openReceiver -> {
LOG.debug("opened receiver link to Authentication service, waiting for token ...");
}, authResult);
}
use of io.vertx.proton.ProtonMessageHandler in project hono by eclipse.
the class RequestResponseClientTest method testCreateAndSendRequestReturnsCorrespondingResponseMessage.
/**
* Verifies that the client returns the service's response message that correlates with the request.
*
* @param ctx The vert.x test context.
*/
@Test
public void testCreateAndSendRequestReturnsCorrespondingResponseMessage(final VertxTestContext ctx) {
// WHEN sending a request message to the peer
client.compose(c -> c.createAndSendRequest("request", null, Buffer.buffer("hello"), "text/plain", SimpleRequestResponseResult::from, span)).onComplete(ctx.succeeding(s -> {
ctx.verify(() -> {
// THEN the response is passed to the handler registered with the request
assertEquals(200, s.getStatus());
assertEquals("payload", s.getPayload().toString());
verify(sample).completed(isA(Accepted.class));
// and a timer has been set to time out the request
final ArgumentCaptor<Handler<Long>> timeoutHandlerCaptor = VertxMockSupport.argumentCaptorHandler();
verify(vertx).setTimer(eq(clientConfig.getRequestTimeout()), timeoutHandlerCaptor.capture());
// triggering the timer now that the request has been handled should not invoke the sampler timeout method
timeoutHandlerCaptor.getValue().handle(1L);
verify(sample, never()).timeout();
});
ctx.completeNow();
}));
// WHEN a response is received for the request
final Message request = verifySenderSendAndUpdateDelivery(new Accepted());
final ProtonMessageHandler responseHandler = verifyResponseHandlerSet();
final Message response = ProtonHelper.message("payload");
response.setCorrelationId(request.getMessageId());
MessageHelper.addProperty(response, MessageHelper.APP_PROPERTY_STATUS, 200);
final ProtonDelivery delivery = mock(ProtonDelivery.class);
responseHandler.handle(delivery, response);
}
Aggregations