use of org.eclipse.milo.opcua.stack.core.UaServiceFaultException in project netxms by netxms.
the class ServerConnection method handleExecutionException.
/**
* Handle execution exception during operation. Depending on exception cause
* can do reconnect and execute provided action, or re-throw original exeption.
*
* @param e original exception
* @param action action to be executed if reconnect is possible and successful
* @return result of action execution
* @throws Exception in case of failure
*/
private <T extends Object> T handleExecutionException(ExecutionException e, Callable<T> action) throws Exception {
if (e.getCause() instanceof UaServiceFaultException) {
UaServiceFaultException se = (UaServiceFaultException) e.getCause();
disconnect();
long status = se.getStatusCode().getValue();
if ((status == StatusCodes.Bad_CommunicationError) || (status == StatusCodes.Bad_ConnectionClosed) || (status == StatusCodes.Bad_Disconnect) || (status == StatusCodes.Bad_EndOfStream) || (status == StatusCodes.Bad_InvalidState) || (status == StatusCodes.Bad_NoCommunication) || (status == StatusCodes.Bad_NotConnected) || (status == StatusCodes.Bad_SecureChannelClosed) || (status == StatusCodes.Bad_SecureChannelIdInvalid) || (status == StatusCodes.Bad_ServerNotConnected) || (status == StatusCodes.Bad_SessionClosed) || (status == StatusCodes.Bad_SessionIdInvalid) || (status == StatusCodes.Bad_TcpInternalError) || (status == StatusCodes.Bad_UnexpectedError)) {
Platform.writeDebugLog(6, String.format("OPCUA: reconnect after error (%s)", se.getStatusCode().toString()));
connect();
return action.call();
}
}
throw e;
}
use of org.eclipse.milo.opcua.stack.core.UaServiceFaultException in project milo by eclipse.
the class OpcUaClient method maybeHandleServiceFault.
private void maybeHandleServiceFault(UaResponseMessage response, Throwable ex) {
if (faultListeners.isEmpty())
return;
if (ex != null) {
if (ex instanceof UaServiceFaultException) {
UaServiceFaultException faultException = (UaServiceFaultException) ex;
ServiceFault serviceFault = faultException.getServiceFault();
logger.debug("Notifying {} ServiceFaultListeners", faultListeners.size());
faultNotificationQueue.submit(() -> faultListeners.forEach(h -> h.onServiceFault(serviceFault)));
} else if (ex.getCause() instanceof UaServiceFaultException) {
UaServiceFaultException faultException = (UaServiceFaultException) ex.getCause();
ServiceFault serviceFault = faultException.getServiceFault();
logger.debug("Notifying {} ServiceFaultListeners", faultListeners.size());
faultNotificationQueue.submit(() -> faultListeners.forEach(h -> h.onServiceFault(serviceFault)));
}
}
}
use of org.eclipse.milo.opcua.stack.core.UaServiceFaultException in project milo by eclipse.
the class UascClientMessageHandler method onOpenSecureChannel.
private void onOpenSecureChannel(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
if (secureChannelTimeout != null) {
if (secureChannelTimeout.cancel()) {
logger.debug("OpenSecureChannel timeout canceled");
secureChannelTimeout = null;
} else {
logger.warn("timed out waiting for secure channel");
handshakeFuture.completeExceptionally(new UaException(StatusCodes.Bad_Timeout, "timed out waiting for secure channel"));
ctx.close();
return;
}
}
// skip messageType, chunkType, messageSize, secureChannelId
buffer.skipBytes(3 + 1 + 4 + 4);
AsymmetricSecurityHeader securityHeader = AsymmetricSecurityHeader.decode(buffer, config.getEncodingLimits());
if (headerRef.compareAndSet(null, securityHeader)) {
// first time we've received the header; validate and verify the server certificate
CertificateValidator certificateValidator = config.getCertificateValidator();
SecurityPolicy securityPolicy = SecurityPolicy.fromUri(securityHeader.getSecurityPolicyUri());
if (securityPolicy != SecurityPolicy.None) {
ByteString serverCertificateBytes = securityHeader.getSenderCertificate();
List<X509Certificate> serverCertificateChain = CertificateUtil.decodeCertificates(serverCertificateBytes.bytesOrEmpty());
certificateValidator.validateCertificateChain(serverCertificateChain);
}
} else {
if (!securityHeader.equals(headerRef.get())) {
throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "subsequent AsymmetricSecurityHeader did not match");
}
}
if (accumulateChunk(buffer)) {
final List<ByteBuf> buffersToDecode = chunkBuffers;
chunkBuffers = new ArrayList<>(maxChunkCount);
serializationQueue.decode((binaryDecoder, chunkDecoder) -> {
ByteBuf message;
try {
ChunkDecoder.DecodedMessage decodedMessage = chunkDecoder.decodeAsymmetric(secureChannel, buffersToDecode);
message = decodedMessage.getMessage();
} catch (MessageAbortException e) {
logger.warn("Received message abort chunk; error={}, reason={}", e.getStatusCode(), e.getMessage());
return;
} catch (MessageDecodeException e) {
logger.error("Error decoding asymmetric message", e);
handshakeFuture.completeExceptionally(e);
ctx.close();
return;
}
try {
UaResponseMessage response = (UaResponseMessage) binaryDecoder.setBuffer(message).readMessage(null);
StatusCode serviceResult = response.getResponseHeader().getServiceResult();
if (serviceResult.isGood()) {
OpenSecureChannelResponse oscr = (OpenSecureChannelResponse) response;
secureChannel.setChannelId(oscr.getSecurityToken().getChannelId().longValue());
logger.debug("Received OpenSecureChannelResponse.");
NonceUtil.validateNonce(oscr.getServerNonce(), secureChannel.getSecurityPolicy());
installSecurityToken(ctx, oscr);
handshakeFuture.complete(secureChannel);
} else {
ServiceFault serviceFault = (response instanceof ServiceFault) ? (ServiceFault) response : new ServiceFault(response.getResponseHeader());
handshakeFuture.completeExceptionally(new UaServiceFaultException(serviceFault));
ctx.close();
}
} catch (Throwable t) {
logger.error("Error decoding OpenSecureChannelResponse", t);
handshakeFuture.completeExceptionally(t);
ctx.close();
} finally {
message.release();
}
});
}
}
use of org.eclipse.milo.opcua.stack.core.UaServiceFaultException in project milo by eclipse.
the class UaStackClient method deliverResponse.
/**
* Complete {@code future} with {@code response} on the {@code deliveryQueue}.
* <p>
* This is done for two reasons:
* 1. the transport future is completed on its serialization queue thread, which we want to get off of ASAP.
* 2. the futures need to be completed serially, in the order received from the server.
*
* @param request the original {@link UaRequestMessage}.
* @param response the {@link UaResponseMessage}.
* @param future the {@link CompletableFuture} awaiting completion.
*/
private void deliverResponse(UaRequestMessage request, @Nullable UaResponseMessage response, @Nullable Throwable failure, CompletableFuture<UaResponseMessage> future) {
deliveryQueue.submit(() -> {
if (response != null) {
ResponseHeader header = response.getResponseHeader();
UInteger requestHandle = header.getRequestHandle();
if (header.getServiceResult().isGood()) {
future.complete(response);
} else {
ServiceFault serviceFault;
if (response instanceof ServiceFault) {
serviceFault = (ServiceFault) response;
} else {
serviceFault = new ServiceFault(header);
}
if (logger.isDebugEnabled()) {
logger.debug("Received ServiceFault request={} requestHandle={}, result={}", request.getClass().getSimpleName(), requestHandle, header.getServiceResult());
}
future.completeExceptionally(new UaServiceFaultException(serviceFault));
}
} else {
assert failure != null;
if (logger.isDebugEnabled()) {
logger.debug("sendRequest() failed, request={}, requestHandle={}", request.getClass().getSimpleName(), request.getRequestHeader().getRequestHandle(), failure);
}
future.completeExceptionally(failure);
}
});
}
Aggregations