Search in sources :

Example 1 with UaRequestMessage

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();
                }
            });
        }
    }
}
Also used : UaSerializationException(org.eclipse.milo.opcua.stack.core.UaSerializationException) UaRequestMessage(org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage) UaException(org.eclipse.milo.opcua.stack.core.UaException) InetSocketAddress(java.net.InetSocketAddress) MessageAbortException(org.eclipse.milo.opcua.stack.core.channel.MessageAbortException) EndpointDescription(org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription) ByteBuf(io.netty.buffer.ByteBuf) CompositeByteBuf(io.netty.buffer.CompositeByteBuf) StatusCode(org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode) Unsigned.uint(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint) ServiceRequest(org.eclipse.milo.opcua.stack.server.services.ServiceRequest) ChunkDecoder(org.eclipse.milo.opcua.stack.core.channel.ChunkDecoder) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger) MessageDecodeException(org.eclipse.milo.opcua.stack.core.channel.MessageDecodeException)

Example 2 with UaRequestMessage

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);
    }
}
Also used : ServerSecureChannel(org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel) MessageSecurityMode(org.eclipse.milo.opcua.stack.core.types.enumerated.MessageSecurityMode) KeyPair(java.security.KeyPair) OpcUaBinaryStreamDecoder(org.eclipse.milo.opcua.stack.core.serialization.OpcUaBinaryStreamDecoder) UaRequestMessage(org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage) UaException(org.eclipse.milo.opcua.stack.core.UaException) ByteString(org.eclipse.milo.opcua.stack.core.types.builtin.ByteString) InetSocketAddress(java.net.InetSocketAddress) ByteString(org.eclipse.milo.opcua.stack.core.types.builtin.ByteString) EndpointDescription(org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription) ServiceRequest(org.eclipse.milo.opcua.stack.server.services.ServiceRequest) SecurityPolicy(org.eclipse.milo.opcua.stack.core.security.SecurityPolicy) UInteger(org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger)

Example 3 with UaRequestMessage

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);
    }
}
Also used : ServiceRequestHandler(org.eclipse.milo.opcua.stack.server.services.ServiceRequestHandler) UaRequestMessage(org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage) UaException(org.eclipse.milo.opcua.stack.core.UaException)

Aggregations

UaException (org.eclipse.milo.opcua.stack.core.UaException)3 UaRequestMessage (org.eclipse.milo.opcua.stack.core.serialization.UaRequestMessage)3 InetSocketAddress (java.net.InetSocketAddress)2 UInteger (org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger)2 EndpointDescription (org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription)2 ServiceRequest (org.eclipse.milo.opcua.stack.server.services.ServiceRequest)2 ByteBuf (io.netty.buffer.ByteBuf)1 CompositeByteBuf (io.netty.buffer.CompositeByteBuf)1 KeyPair (java.security.KeyPair)1 UaSerializationException (org.eclipse.milo.opcua.stack.core.UaSerializationException)1 ChunkDecoder (org.eclipse.milo.opcua.stack.core.channel.ChunkDecoder)1 MessageAbortException (org.eclipse.milo.opcua.stack.core.channel.MessageAbortException)1 MessageDecodeException (org.eclipse.milo.opcua.stack.core.channel.MessageDecodeException)1 ServerSecureChannel (org.eclipse.milo.opcua.stack.core.channel.ServerSecureChannel)1 SecurityPolicy (org.eclipse.milo.opcua.stack.core.security.SecurityPolicy)1 OpcUaBinaryStreamDecoder (org.eclipse.milo.opcua.stack.core.serialization.OpcUaBinaryStreamDecoder)1 ByteString (org.eclipse.milo.opcua.stack.core.types.builtin.ByteString)1 StatusCode (org.eclipse.milo.opcua.stack.core.types.builtin.StatusCode)1 Unsigned.uint (org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint)1 MessageSecurityMode (org.eclipse.milo.opcua.stack.core.types.enumerated.MessageSecurityMode)1