use of org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage in project milo by eclipse.
the class UascServerSymmetricHandler method onSecureMessage.
private void onSecureMessage(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
// Skip messageType
buffer.skipBytes(3);
char chunkType = (char) buffer.readByte();
if (chunkType == 'A') {
chunkBuffers.forEach(ByteBuf::release);
chunkBuffers.clear();
} else {
// Skip messageSize
buffer.skipBytes(4);
long secureChannelId = buffer.readUnsignedIntLE();
if (secureChannelId != secureChannel.getChannelId()) {
throw new UaException(StatusCodes.Bad_SecureChannelIdInvalid, "invalid secure channel id: " + secureChannelId);
}
int chunkSize = buffer.readerIndex(0).readableBytes();
if (chunkSize > maxChunkSize) {
throw new UaException(StatusCodes.Bad_TcpMessageTooLarge, String.format("max chunk size exceeded (%s)", maxChunkSize));
}
chunkBuffers.add(buffer.retain());
if (maxChunkCount > 0 && chunkBuffers.size() > maxChunkCount) {
throw new UaException(StatusCodes.Bad_TcpMessageTooLarge, String.format("max chunk count exceeded (%s)", maxChunkCount));
}
if (chunkType == 'F') {
final List<ByteBuf> buffersToDecode = chunkBuffers;
chunkBuffers = new ArrayList<>();
serializationQueue.decode((binaryDecoder, chunkDecoder) -> {
ByteBuf message;
long requestId;
try {
ChunkDecoder.DecodedMessage decodedMessage = chunkDecoder.decodeSymmetric(secureChannel, buffersToDecode);
message = decodedMessage.getMessage();
requestId = decodedMessage.getRequestId();
} catch (MessageAbortException e) {
logger.warn("Received message abort chunk; error={}, reason={}", e.getStatusCode(), e.getMessage());
return;
} catch (MessageDecodeException e) {
logger.error("Error decoding symmetric message", e);
ctx.close();
return;
}
try {
UaRequestMessage request = (UaRequestMessage) binaryDecoder.setBuffer(message).readMessage(null);
String endpointUrl = ctx.channel().attr(UascServerHelloHandler.ENDPOINT_URL_KEY).get();
EndpointDescription endpoint = ctx.channel().attr(UascServerAsymmetricHandler.ENDPOINT_KEY).get();
String path = EndpointUtil.getPath(endpointUrl);
InetSocketAddress remoteSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
ServiceRequest serviceRequest = new ServiceRequest(stackServer, request, endpoint, secureChannel.getChannelId(), remoteSocketAddress.getAddress(), secureChannel.getRemoteCertificateBytes());
serviceRequest.getFuture().whenComplete((response, fault) -> {
if (response != null) {
sendServiceResponse(ctx, requestId, request, response);
} else {
UInteger requestHandle = request.getRequestHeader().getRequestHandle();
sendServiceFault(ctx, requestId, requestHandle, fault);
}
});
stackServer.onServiceRequest(path, serviceRequest);
} catch (UaSerializationException e) {
logger.error("Error decoding UaRequestMessage", e);
sendServiceFault(ctx, requestId, uint(0), e);
} catch (Throwable t) {
logger.error("Unexpected error servicing UaRequestMessage", t);
long statusCode = UaException.extractStatusCode(t).map(StatusCode::getValue).orElse(StatusCodes.Bad_UnexpectedError);
sendServiceFault(ctx, requestId, uint(0), new UaException(statusCode, t));
} finally {
message.release();
buffersToDecode.clear();
}
});
}
}
}
use of org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage in project milo by eclipse.
the class OpcServerHttpRequestHandler method channelRead0.
@Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest httpRequest) throws Exception {
String host = httpRequest.headers().get(HttpHeaderNames.HOST);
String uri = httpRequest.uri();
String contentType = httpRequest.headers().get(HttpHeaderNames.CONTENT_TYPE);
String securityPolicyUri = httpRequest.headers().get("OPCUA-SecurityPolicy");
logger.debug("host={} uri={} contentType={} securityPolicy={}", host, uri, contentType, securityPolicyUri);
SecurityPolicy securityPolicy = securityPolicyUri != null ? SecurityPolicy.fromUri(securityPolicyUri) : SecurityPolicy.None;
MessageSecurityMode securityMode = securityPolicy == SecurityPolicy.None ? MessageSecurityMode.None : MessageSecurityMode.Sign;
EndpointDescription endpoint = stackServer.getEndpointDescriptions().stream().filter(e -> {
// TODO use contentType to determine which TransportProfile to match
boolean transportMatch = Objects.equals(e.getTransportProfileUri(), TransportProfile.HTTPS_UABINARY.getUri());
boolean pathMatch = Objects.equals(EndpointUtil.getPath(e.getEndpointUrl()), uri);
boolean securityPolicyMatch = Objects.equals(e.getSecurityPolicyUri(), securityPolicy.getUri());
boolean securityModeMatch = Objects.equals(e.getSecurityMode(), securityMode);
return transportMatch && pathMatch && securityPolicyMatch && securityModeMatch;
}).findFirst().orElseThrow(() -> new UaException(StatusCodes.Bad_TcpEndpointUrlInvalid, "unrecognized endpoint uri: " + uri));
ServerSecureChannel secureChannel = new ServerSecureChannel();
// TODO shared id per endpoint URL / path?
secureChannel.setChannelId(0L);
secureChannel.setSecurityPolicy(securityPolicy);
secureChannel.setMessageSecurityMode(securityMode);
ByteString thumbprint = ByteString.of(DigestUtil.sha1(endpoint.getServerCertificate().bytesOrEmpty()));
Optional<X509Certificate[]> certificateChain = stackServer.getConfig().getCertificateManager().getCertificateChain(thumbprint);
Optional<KeyPair> keyPair = stackServer.getConfig().getCertificateManager().getKeyPair(thumbprint);
certificateChain.ifPresent(chain -> {
secureChannel.setLocalCertificateChain(chain);
secureChannel.setLocalCertificate(chain[0]);
});
keyPair.ifPresent(secureChannel::setKeyPair);
OpcUaBinaryStreamDecoder decoder = new OpcUaBinaryStreamDecoder(stackServer.getSerializationContext());
decoder.setBuffer(httpRequest.content());
try {
UaRequestMessage request = (UaRequestMessage) decoder.readMessage(null);
UInteger requestHandle = request.getRequestHeader().getRequestHandle();
InetSocketAddress remoteSocketAddress = (InetSocketAddress) ctx.channel().remoteAddress();
ServiceRequest serviceRequest = new ServiceRequest(stackServer, request, endpoint, secureChannel.getChannelId(), remoteSocketAddress.getAddress(), null);
serviceRequest.getFuture().whenComplete((response, fault) -> {
if (response != null) {
sendServiceResponse(ctx, request, response);
} else {
sendServiceFault(ctx, requestHandle, fault);
}
});
stackServer.onServiceRequest(uri, serviceRequest);
} catch (Throwable t) {
logger.error("Error decoding UaRequestMessage", t);
sendServiceFault(ctx, null, t);
}
}
use of org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage in project milo by eclipse.
the class UaStackServer method handleServiceRequest.
private void handleServiceRequest(String path, ServiceRequest serviceRequest) {
UaRequestMessage request = serviceRequest.getRequest();
if (logger.isTraceEnabled()) {
logger.trace("ServiceRequest received path={}, requestHandle={} request={}", path, request.getRequestHeader().getRequestHandle(), request.getClass().getSimpleName());
serviceRequest.getFuture().whenComplete((response, ex) -> {
if (response != null) {
logger.trace("ServiceRequest completed path={}, requestHandle={} response={}", path, response.getResponseHeader().getRequestHandle(), response.getClass().getSimpleName());
} else {
logger.trace("ServiceRequest completed exceptionally path={}, requestHandle={}", path, request.getRequestHeader().getRequestHandle(), ex);
}
});
}
ServiceRequestHandler serviceHandler = getServiceHandler(path, request.getTypeId());
try {
if (serviceHandler != null) {
serviceHandler.handle(serviceRequest);
} else {
serviceRequest.setServiceFault(StatusCodes.Bad_ServiceUnsupported);
}
} catch (UaException e) {
serviceRequest.setServiceFault(e);
} catch (Throwable t) {
logger.error("Uncaught Throwable executing handler: {}", serviceHandler, t);
serviceRequest.setServiceFault(StatusCodes.Bad_InternalError);
}
}
Aggregations