use of org.eclipse.hono.client.ClientErrorException 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.eclipse.hono.client.ClientErrorException 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.eclipse.hono.client.ClientErrorException in project hono by eclipse.
the class AbstractRequestResponseClient method sendRequest.
/**
* Sends a request message via this client's sender link to the peer.
* <p>
* This method first checks if the sender has any credit left. If not, the result handler is failed immediately.
* Otherwise, the request message is sent and a timer is started which fails the result handler,
* if no response is received within <em>requestTimeoutMillis</em> milliseconds.
*
* @param request The message to send.
* @param resultHandler The handler to notify about the outcome of the request.
* @param cacheKey The key to use for caching the response (if the service allows caching).
*/
private final void sendRequest(final Message request, final Handler<AsyncResult<R>> resultHandler, final Object cacheKey) {
context.runOnContext(req -> {
if (sender.sendQueueFull()) {
LOG.debug("cannot send request to peer, no credit left for link [target: {}]", targetAddress);
resultHandler.handle(Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "no credit available for sending request")));
} else {
final Object correlationId = Optional.ofNullable(request.getCorrelationId()).orElse(request.getMessageId());
final TriTuple<Handler<AsyncResult<R>>, Object, Object> handler = TriTuple.of(resultHandler, cacheKey, null);
replyMap.put(correlationId, handler);
sender.send(request, deliveryUpdated -> {
if (Rejected.class.isInstance(deliveryUpdated.getRemoteState())) {
final Rejected rejected = (Rejected) deliveryUpdated.getRemoteState();
if (rejected.getError() != null) {
LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]: {}", targetAddress, request.getSubject(), correlationId, rejected.getError());
cancelRequest(correlationId, Future.failedFuture(StatusCodeMapper.from(rejected.getError())));
} else {
LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]", targetAddress, request.getSubject(), correlationId);
cancelRequest(correlationId, Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_BAD_REQUEST)));
}
} else if (Accepted.class.isInstance(deliveryUpdated.getRemoteState())) {
LOG.trace("service has accepted request [target address: {}, subject: {}, correlation ID: {}]", targetAddress, request.getSubject(), correlationId);
} else {
LOG.debug("service did not accept request [target address: {}, subject: {}, correlation ID: {}]: {}", targetAddress, request.getSubject(), correlationId, deliveryUpdated.getRemoteState());
cancelRequest(correlationId, Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE)));
}
});
if (requestTimeoutMillis > 0) {
context.owner().setTimer(requestTimeoutMillis, tid -> {
cancelRequest(correlationId, Future.failedFuture(new ServerErrorException(HttpURLConnection.HTTP_UNAVAILABLE, "request timed out after " + requestTimeoutMillis + "ms")));
});
}
if (LOG.isDebugEnabled()) {
final String deviceId = MessageHelper.getDeviceId(request);
if (deviceId == null) {
LOG.debug("sent request [target address: {}, subject: {}, correlation ID: {}] to service", targetAddress, request.getSubject(), correlationId);
} else {
LOG.debug("sent request [target address: {}, subject: {}, correlation ID: {}, device ID: {}] to service", targetAddress, request.getSubject(), correlationId, deviceId);
}
}
}
});
}
use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.
the class HonoClientImpl method connect.
private void connect(final ProtonClientOptions options, final Handler<AsyncResult<HonoClient>> connectionHandler, final Handler<ProtonConnection> disconnectHandler) {
context.runOnContext(connect -> {
if (isConnectedInternal()) {
LOG.debug("already connected to server [{}:{}]", connectionFactory.getHost(), connectionFactory.getPort());
connectionHandler.handle(Future.succeededFuture(this));
} else if (connecting.compareAndSet(false, true)) {
if (options == null) {
// by default, try to re-connect forever
clientOptions = new ProtonClientOptions().setConnectTimeout(200).setReconnectAttempts(-1).setReconnectInterval(Constants.DEFAULT_RECONNECT_INTERVAL_MILLIS);
} else {
clientOptions = options;
}
connectionFactory.connect(clientOptions, remoteClose -> onRemoteClose(remoteClose, disconnectHandler), failedConnection -> onRemoteDisconnect(failedConnection, disconnectHandler), conAttempt -> {
connecting.compareAndSet(true, false);
if (conAttempt.failed()) {
if (conAttempt.cause() instanceof SecurityException) {
// SASL handshake has failed
connectionHandler.handle(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_UNAUTHORIZED, "failed to authenticate with server")));
} else {
reconnect(conAttempt.cause(), connectionHandler, disconnectHandler);
}
} else {
// make sure we try to re-connect as often as we tried to connect initially
reconnectAttempts = new AtomicInteger(0);
final ProtonConnection newConnection = conAttempt.result();
if (shuttingDown.get()) {
// if client was shut down in the meantime, we need to immediately
// close again the newly created connection
newConnection.closeHandler(null);
newConnection.disconnectHandler(null);
newConnection.close();
connectionHandler.handle(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_CONFLICT, "client is already shut down")));
} else {
setConnection(newConnection);
connectionHandler.handle(Future.succeededFuture(this));
}
}
});
} else {
LOG.debug("already trying to connect to server ...");
connectionHandler.handle(Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_CONFLICT, "already connecting to server")));
}
});
}
use of org.eclipse.hono.client.ClientErrorException in project hono by eclipse.
the class ClaimsBasedAuthorizationService method isAuthorized.
@Override
public Future<Boolean> isAuthorized(final HonoUser user, final ResourceIdentifier resource, final Activity intent) {
Objects.requireNonNull(user);
Objects.requireNonNull(resource);
Objects.requireNonNull(intent);
if (user.isExpired()) {
return Future.failedFuture(new ClientErrorException(HttpURLConnection.HTTP_FORBIDDEN, "user information expired"));
} else {
return Future.succeededFuture(user.getAuthorities().isAuthorized(resource, intent));
}
}
Aggregations