Example usage for io.netty.buffer ByteBuf skipBytes

List of usage examples for io.netty.buffer ByteBuf skipBytes

Introduction

In this page you can find the example usage for io.netty.buffer ByteBuf skipBytes.

Prototype

public abstract ByteBuf skipBytes(int length);

Source Link

Document

Increases the current readerIndex by the specified length in this buffer.

Usage

From source file:org.asterisque.netty.MessageDecoder.java

License:Apache License

public void decode(ChannelHandlerContext ctx, ByteBuf b, List<Object> out) throws CodecException {
    ByteBuffer buffer = b.nioBuffer();
    Optional<Message> msg = codec.decode(buffer);
    if (msg.isPresent()) {
        b.skipBytes(buffer.position());
        out.add(msg.get());/* ww  w. j a v  a  2s.com*/
    }
}

From source file:org.code_house.ebus.netty.codec.MasterTelegramDecoder.java

License:Apache License

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    if (in.readableBytes() == 0) {
        return;//  w w w  .  jav a2s.c o m
    }

    // buffer we receive might be a correct frame or just data we have between frames
    int index = in.readerIndex();
    if (in.readableBytes() >= 6) {
        // seven bytes is shortest valid ebus telegram, which no data
        byte source = in.readByte();
        byte destination = in.readByte();

        boolean fromMaster = Predicates.IS_MASTER.apply(source);
        boolean broadcast = Constants.BROADCAST_ADDRESS == destination;
        boolean toSlave = Predicates.IS_SLAVE.apply(destination);
        boolean toMaster = Predicates.IS_MASTER.apply(destination);

        // if below condition is correct then we have regular frame, at least it looks like, as long as we are not sure
        // if everything is fine we do not read but just scan buffer
        if (fromMaster && (toMaster || (toSlave || broadcast))) {
            // short is encoded on two bytes
            byte commandGroup = in.readByte();
            byte command = in.readByte();
            byte length = in.readByte();

            if (in.readableBytes() >= length + 1 /* crc */) {
                ByteBuffer exchange = ByteBuffer.allocate(length);
                in.getBytes(in.readerIndex(), exchange);
                in.skipBytes(length);
                byte crc = in.readByte();

                MasterData data = new MasterData(exchange,
                        calculateCrc((byte) source, (byte) destination, commandGroup, command, length), crc);
                // below condition checks crc and verify if we fully consumed frame data and we will leave no remaining
                // bytes master buffer. If there is any data left or crc doesn't match we might just parse middle of long
                // telegram which accidentally got spliced or we missed for some reason SYN and just got corrupted
                // data.
                if (data.isValid()) {
                    out.add(new MasterHeader(source, destination, commandGroup, command, length));
                    out.add(data);
                    if (in.readableBytes() > 0) {
                        out.add(in.readBytes(super.actualReadableBytes()));
                    }
                    return;
                }
            }
        }
        // invalid data found
        in.readerIndex(index);
        out.add(in.readBytes(super.actualReadableBytes()));
    }
}

From source file:org.code_house.ebus.netty.codec.SlaveTelegramDecoder.java

License:Apache License

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
    if (in.readableBytes() == 0) {
        return;/*from w ww  . j  a v  a  2s . com*/
    }

    int index = in.readerIndex();
    // no master, no slave, no broadcast -> slave reply or ACK
    if (in.readableBytes() >= 3) {
        // we have at least three bytes which should be slave ACK, slave reply len, slave crc.
        byte ack = in.readByte();
        if (ack == Constants.ACK) { // slave confirmed received data
            byte length = in.readByte();
            if (in.readableBytes() >= length + 1 /* crc */) {
                ByteBuffer exchange = ByteBuffer.allocate(length);
                in.getBytes(in.readerIndex(), exchange);
                in.skipBytes(length);
                byte crc = in.readByte();
                SlaveData data = new SlaveData(exchange, calculateCrc(length), crc);
                if (data.isValid()) {
                    // proper slave reply
                    out.add(new Confirmation());
                    out.add(new SlaveHeader(length));
                    out.add(data);
                } else {
                    System.out.println("Slave CRC fail!!!");
                    in.discardReadBytes();
                }
            }
        } else if (ack == Constants.NACK) {
            out.add(new Rejection());
        }
    }

    if (out.isEmpty()) {
        System.out.println("slave fail -> \n" + ByteBufUtil.prettyHexDump(in));
        in.readerIndex(index);
    }

    if (in.readableBytes() > 0) {
        out.add(in.readBytes(super.actualReadableBytes()));
    }
}

From source file:org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientAcknowledgeHandler.java

License:Open Source License

private void onAcknowledge(ChannelHandlerContext ctx, ByteBuf buffer) {
    if (helloTimeout != null && !helloTimeout.cancel()) {
        helloTimeout = null;/*w w  w .j a v a2s  .c om*/
        handshakeFuture.completeExceptionally(
                new UaException(StatusCodes.Bad_Timeout, "timed out waiting for acknowledge"));
        ctx.close();
        return;
    }

    logger.debug("Received Acknowledge message on channel={}.", ctx.channel());

    buffer.skipBytes(3 + 1 + 4); // Skip messageType, chunkType, and messageSize

    AcknowledgeMessage acknowledge = AcknowledgeMessage.decode(buffer);

    long remoteProtocolVersion = acknowledge.getProtocolVersion();
    long remoteReceiveBufferSize = acknowledge.getReceiveBufferSize();
    long remoteSendBufferSize = acknowledge.getSendBufferSize();
    long remoteMaxMessageSize = acknowledge.getMaxMessageSize();
    long remoteMaxChunkCount = acknowledge.getMaxChunkCount();

    if (PROTOCOL_VERSION > remoteProtocolVersion) {
        logger.warn("Client protocol version ({}) does not match server protocol version ({}).",
                PROTOCOL_VERSION, remoteProtocolVersion);
    }

    ChannelConfig config = client.getChannelConfig();

    /* Our receive buffer size is determined by the remote send buffer size. */
    long localReceiveBufferSize = Math.min(remoteSendBufferSize, config.getMaxChunkSize());

    /* Our send buffer size is determined by the remote receive buffer size. */
    long localSendBufferSize = Math.min(remoteReceiveBufferSize, config.getMaxChunkSize());

    /* Max message size the remote can send us; not influenced by remote configuration. */
    long localMaxMessageSize = config.getMaxMessageSize();

    /* Max chunk count the remote can send us; not influenced by remote configuration. */
    long localMaxChunkCount = config.getMaxChunkCount();

    ChannelParameters parameters = new ChannelParameters(Ints.saturatedCast(localMaxMessageSize),
            Ints.saturatedCast(localReceiveBufferSize), Ints.saturatedCast(localSendBufferSize),
            Ints.saturatedCast(localMaxChunkCount), Ints.saturatedCast(remoteMaxMessageSize),
            Ints.saturatedCast(remoteReceiveBufferSize), Ints.saturatedCast(remoteSendBufferSize),
            Ints.saturatedCast(remoteMaxChunkCount));

    ctx.channel().attr(KEY_AWAITING_HANDSHAKE).set(awaitingHandshake);

    ctx.executor().execute(() -> {
        int maxArrayLength = client.getChannelConfig().getMaxArrayLength();
        int maxStringLength = client.getChannelConfig().getMaxStringLength();

        SerializationQueue serializationQueue = new SerializationQueue(client.getConfig().getExecutor(),
                parameters, maxArrayLength, maxStringLength);

        UaTcpClientMessageHandler handler = new UaTcpClientMessageHandler(client, secureChannel,
                serializationQueue, handshakeFuture);

        ctx.pipeline().addLast(handler);
    });
}

From source file:org.eclipse.milo.opcua.stack.client.transport.uasc.UascClientAcknowledgeHandler.java

License:Open Source License

private void onAcknowledge(ChannelHandlerContext ctx, ByteBuf buffer) {
    if (helloTimeout != null && !helloTimeout.cancel()) {
        helloTimeout = null;//from   w  ww  .j  a  v a  2  s  .c o m
        handshakeFuture.completeExceptionally(
                new UaException(StatusCodes.Bad_Timeout, "timed out waiting for acknowledge"));
        ctx.close();
        return;
    }

    logger.debug("Received Acknowledge message on channel={}.", ctx.channel());

    buffer.skipBytes(3 + 1 + 4); // Skip messageType, chunkType, and messageSize

    AcknowledgeMessage acknowledge = AcknowledgeMessage.decode(buffer);

    long remoteProtocolVersion = acknowledge.getProtocolVersion();
    long remoteReceiveBufferSize = acknowledge.getReceiveBufferSize();
    long remoteSendBufferSize = acknowledge.getSendBufferSize();
    long remoteMaxMessageSize = acknowledge.getMaxMessageSize();
    long remoteMaxChunkCount = acknowledge.getMaxChunkCount();

    if (PROTOCOL_VERSION > remoteProtocolVersion) {
        logger.warn("Client protocol version ({}) does not match server protocol version ({}).",
                PROTOCOL_VERSION, remoteProtocolVersion);
    }

    MessageLimits messageLimits = config.getMessageLimits();

    /* Our receive buffer size is determined by the remote send buffer size. */
    long localReceiveBufferSize = Math.min(remoteSendBufferSize, messageLimits.getMaxChunkSize());

    /* Our send buffer size is determined by the remote receive buffer size. */
    long localSendBufferSize = Math.min(remoteReceiveBufferSize, messageLimits.getMaxChunkSize());

    /* Max message size the remote can send us; not influenced by remote configuration. */
    long localMaxMessageSize = messageLimits.getMaxMessageSize();

    /* Max chunk count the remote can send us; not influenced by remote configuration. */
    long localMaxChunkCount = messageLimits.getMaxChunkCount();

    ChannelParameters parameters = new ChannelParameters(Ints.saturatedCast(localMaxMessageSize),
            Ints.saturatedCast(localReceiveBufferSize), Ints.saturatedCast(localSendBufferSize),
            Ints.saturatedCast(localMaxChunkCount), Ints.saturatedCast(remoteMaxMessageSize),
            Ints.saturatedCast(remoteReceiveBufferSize), Ints.saturatedCast(remoteSendBufferSize),
            Ints.saturatedCast(remoteMaxChunkCount));

    ctx.channel().attr(KEY_AWAITING_HANDSHAKE).set(awaitingHandshake);

    ctx.executor().execute(() -> {
        SerializationQueue serializationQueue = new SerializationQueue(config.getExecutor(), parameters,
                config.getEncodingLimits());

        UascClientMessageHandler handler = new UascClientMessageHandler(config, secureChannel,
                serializationQueue, handshakeFuture);

        ctx.pipeline().addLast(handler);
    });
}

From source file:org.eclipse.milo.opcua.stack.client.transport.uasc.UascClientMessageHandler.java

License:Open Source License

private void onOpenSecureChannel(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
    if (secureChannelTimeout != null) {
        if (secureChannelTimeout.cancel()) {
            logger.debug("OpenSecureChannel timeout canceled");

            secureChannelTimeout = null;
        } else {//w  w w  .  j a va 2  s .c o  m
            logger.warn("timed out waiting for secure channel");

            handshakeFuture.completeExceptionally(
                    new UaException(StatusCodes.Bad_Timeout, "timed out waiting for secure channel"));
            ctx.close();
            return;
        }
    }

    buffer.skipBytes(3 + 1 + 4 + 4); // skip messageType, chunkType, messageSize, secureChannelId

    AsymmetricSecurityHeader securityHeader = AsymmetricSecurityHeader.decode(buffer,
            config.getEncodingLimits().getMaxArrayLength(), config.getEncodingLimits().getMaxStringLength());

    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.validate(serverCertificateChain.get(0));
            certificateValidator.verifyTrustChain(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) -> chunkDecoder.decodeAsymmetric(secureChannel,
                buffersToDecode, new ChunkDecoder.Callback() {
                    @Override
                    public void onDecodingError(UaException ex) {
                        logger.error("Error decoding asymmetric message: {}", ex.getMessage(), ex);

                        handshakeFuture.completeExceptionally(ex);

                        ctx.close();
                    }

                    @Override
                    public void onMessageAborted(MessageAbortedException ex) {
                        logger.warn("Asymmetric message aborted. error={} reason={}", ex.getStatusCode(),
                                ex.getMessage());
                    }

                    @Override
                    public void onMessageDecoded(ByteBuf message, long requestId) {
                        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.");

                                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();
                        }
                    }
                }));
    }
}

From source file:org.eclipse.milo.opcua.stack.client.transport.uasc.UascClientMessageHandler.java

License:Open Source License

private void onSecureMessage(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
    buffer.skipBytes(3 + 1 + 4); // skip messageType, chunkType, messageSize

    long secureChannelId = buffer.readUnsignedIntLE();
    if (secureChannelId != secureChannel.getChannelId()) {
        throw new UaException(StatusCodes.Bad_SecureChannelIdInvalid,
                "invalid secure channel id: " + secureChannelId);
    }//from w  w  w.  j a v  a2 s  .co  m

    if (accumulateChunk(buffer)) {
        final List<ByteBuf> buffersToDecode = chunkBuffers;
        chunkBuffers = new ArrayList<>(maxChunkCount);

        serializationQueue.decode((binaryDecoder, chunkDecoder) -> {
            try {
                validateChunkHeaders(buffersToDecode);
            } catch (UaException e) {
                logger.error("Error validating chunk headers: {}", e.getMessage(), e);
                buffersToDecode.forEach(ReferenceCountUtil::safeRelease);
                ctx.close();
                return;
            }

            chunkDecoder.decodeSymmetric(secureChannel, buffersToDecode, new ChunkDecoder.Callback() {
                @Override
                public void onDecodingError(UaException ex) {
                    logger.error("Error decoding symmetric message: {}", ex.getMessage(), ex);

                    ctx.close();
                }

                @Override
                public void onMessageAborted(MessageAbortedException ex) {
                    logger.warn("Received message abort chunk; error={}, reason={}", ex.getStatusCode(),
                            ex.getMessage());

                    long requestId = ex.getRequestId();
                    UaTransportRequest request = pending.remove(requestId);

                    if (request != null) {
                        request.getFuture().completeExceptionally(ex);
                    } else {
                        logger.warn("No pending request for requestId={}", requestId);
                    }
                }

                @Override
                public void onMessageDecoded(ByteBuf message, long requestId) {
                    UaTransportRequest request = pending.remove(requestId);

                    try {
                        if (request != null) {
                            UaResponseMessage response = (UaResponseMessage) binaryDecoder.setBuffer(message)
                                    .readMessage(null);

                            request.getFuture().complete(response);
                        } else {
                            logger.warn("No pending request for requestId={}", requestId);
                        }
                    } catch (Throwable t) {
                        logger.error("Error decoding UaResponseMessage", t);

                        if (request != null) {
                            request.getFuture().completeExceptionally(t);
                        }
                    } finally {
                        message.release();
                    }
                }
            });
        });
    }
}

From source file:org.eclipse.milo.opcua.stack.server.handlers.UaTcpServerAsymmetricHandler.java

License:Open Source License

private void onOpenSecureChannel(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
    buffer.skipBytes(3); // Skip messageType

    char chunkType = (char) buffer.readByte();

    if (chunkType == 'A') {
        chunkBuffers.forEach(ByteBuf::release);
        chunkBuffers.clear();/* www  .j ava 2s  .  c  om*/
        headerRef.set(null);
    } else {
        buffer.skipBytes(4); // Skip messageSize

        long secureChannelId = buffer.readUnsignedInt();
        AsymmetricSecurityHeader securityHeader = AsymmetricSecurityHeader.decode(buffer);

        if (secureChannelId == 0) {
            // Okay, this is the first OpenSecureChannelRequest... carry on.
            String endpointUrl = ctx.channel().attr(UaTcpServerHelloHandler.ENDPOINT_URL_KEY).get();
            String securityPolicyUri = securityHeader.getSecurityPolicyUri();

            EndpointDescription endpointDescription = Arrays.stream(server.getEndpointDescriptions())
                    .filter(e -> {
                        String s1 = pathOrUrl(endpointUrl);
                        String s2 = pathOrUrl(e.getEndpointUrl());
                        boolean uriMatch = s1.equals(s2);
                        boolean policyMatch = e.getSecurityPolicyUri().equals(securityPolicyUri);
                        return uriMatch && policyMatch;
                    }).findFirst().orElse(null);

            if (endpointDescription == null && !server.getConfig().isStrictEndpointUrlsEnabled()) {
                endpointDescription = Arrays.stream(server.getEndpointDescriptions())
                        .filter(e -> e.getSecurityPolicyUri().equals(securityPolicyUri)).findFirst()
                        .orElse(null);
            }

            if (endpointDescription == null) {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed, "SecurityPolicy URI did not match");
            }

            secureChannel = server.openSecureChannel();
            secureChannel.setEndpointDescription(endpointDescription);
        } else {
            secureChannel = server.getSecureChannel(secureChannelId);

            if (secureChannel == null) {
                throw new UaException(StatusCodes.Bad_TcpSecureChannelUnknown,
                        "unknown secure channel id: " + secureChannelId);
            }

            if (!secureChannel.getRemoteCertificateBytes().equals(securityHeader.getSenderCertificate())) {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                        "certificate requesting renewal did not match existing certificate.");
            }

            Channel boundChannel = secureChannel.attr(UaTcpStackServer.BoundChannelKey).get();
            if (boundChannel != null && boundChannel != ctx.channel()) {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                        "received a renewal request from channel other than the bound channel.");
            }
        }

        if (!headerRef.compareAndSet(null, securityHeader)) {
            if (!securityHeader.equals(headerRef.get())) {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                        "subsequent AsymmetricSecurityHeader did not match");
            }
        }

        SecurityPolicy securityPolicy = SecurityPolicy.fromUri(securityHeader.getSecurityPolicyUri());
        secureChannel.setSecurityPolicy(securityPolicy);

        if (!securityHeader.getSenderCertificate().isNull() && securityPolicy != SecurityPolicy.None) {
            secureChannel.setRemoteCertificate(securityHeader.getSenderCertificate().bytes());

            try {
                CertificateValidator certificateValidator = server.getCertificateValidator();

                certificateValidator.validate(secureChannel.getRemoteCertificate());

                certificateValidator.verifyTrustChain(secureChannel.getRemoteCertificate(),
                        secureChannel.getRemoteCertificateChain());
            } catch (UaException e) {
                try {
                    UaException cause = new UaException(e.getStatusCode(), "security checks failed");
                    ErrorMessage errorMessage = ExceptionHandler.sendErrorMessage(ctx, cause);

                    logger.debug("[remote={}] {}.", ctx.channel().remoteAddress(), errorMessage.getReason(),
                            cause);
                } catch (Exception inner) {
                    logger.error("Error sending ErrorMessage: {}", inner.getMessage(), inner);
                }
            }
        }

        if (!securityHeader.getReceiverThumbprint().isNull()) {
            CertificateManager certificateManager = server.getCertificateManager();

            Optional<X509Certificate> localCertificate = certificateManager
                    .getCertificate(securityHeader.getReceiverThumbprint());

            Optional<KeyPair> keyPair = certificateManager.getKeyPair(securityHeader.getReceiverThumbprint());

            if (localCertificate.isPresent() && keyPair.isPresent()) {
                secureChannel.setLocalCertificate(localCertificate.get());
                secureChannel.setKeyPair(keyPair.get());
            } else {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                        "no certificate for provided thumbprint");
            }
        }

        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 (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<>(maxChunkCount);
            headerRef.set(null);

            serializationQueue.decode((binaryDecoder, chunkDecoder) -> {
                ByteBuf messageBuffer = null;

                try {
                    messageBuffer = chunkDecoder.decodeAsymmetric(secureChannel, buffersToDecode);

                    OpenSecureChannelRequest request = binaryDecoder.setBuffer(messageBuffer)
                            .decodeMessage(null);

                    logger.debug("Received OpenSecureChannelRequest ({}, id={}).", request.getRequestType(),
                            secureChannelId);

                    long requestId = chunkDecoder.getLastRequestId();
                    installSecurityToken(ctx, request, requestId);
                } catch (UaException e) {
                    logger.error("Error decoding asymmetric message: {}", e.getMessage(), e);
                    ctx.close();
                } finally {
                    if (messageBuffer != null) {
                        messageBuffer.release();
                    }
                    buffersToDecode.clear();
                }
            });
        }
    }
}

From source file:org.eclipse.milo.opcua.stack.server.transport.uasc.UascServerAsymmetricHandler.java

License:Open Source License

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List<Object> out) throws Exception {
    while (buffer.readableBytes() >= HEADER_LENGTH) {
        int messageLength = getMessageLength(buffer, maxChunkSize);

        if (buffer.readableBytes() < messageLength) {
            break;
        }//from w  w w. j  av a 2  s  . com

        MessageType messageType = MessageType.fromMediumInt(buffer.getMediumLE(buffer.readerIndex()));

        switch (messageType) {
        case OpenSecureChannel:
            onOpenSecureChannel(ctx, buffer.readSlice(messageLength));
            break;

        case CloseSecureChannel:
            logger.debug("Received CloseSecureChannelRequest");

            buffer.skipBytes(messageLength);

            if (secureChannelTimeout != null) {
                secureChannelTimeout.cancel();
                secureChannelTimeout = null;
            }

            ctx.close();
            break;

        default:
            throw new UaException(StatusCodes.Bad_TcpMessageTypeInvalid,
                    "unexpected MessageType: " + messageType);
        }
    }
}

From source file:org.eclipse.milo.opcua.stack.server.transport.uasc.UascServerAsymmetricHandler.java

License:Open Source License

private void onOpenSecureChannel(ChannelHandlerContext ctx, ByteBuf buffer) throws UaException {
    buffer.skipBytes(3); // Skip messageType

    char chunkType = (char) buffer.readByte();

    if (chunkType == 'A') {
        chunkBuffers.forEach(ByteBuf::release);
        chunkBuffers.clear();/*w  w w . j a  v a  2  s  .  c  o  m*/
        headerRef.set(null);
    } else {
        buffer.skipBytes(4); // Skip messageSize

        final long secureChannelId = buffer.readUnsignedIntLE();

        final AsymmetricSecurityHeader header = AsymmetricSecurityHeader.decode(buffer, maxArrayLength,
                maxStringLength);

        if (!headerRef.compareAndSet(null, header)) {
            if (!header.equals(headerRef.get())) {
                throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                        "subsequent AsymmetricSecurityHeader did not match");
            }
        }

        if (secureChannelId != 0) {
            if (secureChannel == null) {
                throw new UaException(StatusCodes.Bad_TcpSecureChannelUnknown,
                        "unknown secure channel id: " + secureChannelId);
            }

            if (secureChannelId != secureChannel.getChannelId()) {
                throw new UaException(StatusCodes.Bad_TcpSecureChannelUnknown,
                        "unknown secure channel id: " + secureChannelId);
            }
        }

        if (secureChannel == null) {
            secureChannel = new ServerSecureChannel();
            secureChannel.setChannelId(stackServer.getNextChannelId());

            String securityPolicyUri = header.getSecurityPolicyUri();
            SecurityPolicy securityPolicy = SecurityPolicy.fromUri(securityPolicyUri);

            secureChannel.setSecurityPolicy(securityPolicy);

            if (securityPolicy != SecurityPolicy.None) {
                secureChannel.setRemoteCertificate(header.getSenderCertificate().bytesOrEmpty());

                CertificateValidator certificateValidator = stackServer.getConfig().getCertificateValidator();

                certificateValidator.validate(secureChannel.getRemoteCertificate());
                certificateValidator.verifyTrustChain(secureChannel.getRemoteCertificateChain());

                CertificateManager certificateManager = stackServer.getConfig().getCertificateManager();

                Optional<X509Certificate[]> localCertificateChain = certificateManager
                        .getCertificateChain(header.getReceiverThumbprint());

                Optional<KeyPair> keyPair = certificateManager.getKeyPair(header.getReceiverThumbprint());

                if (localCertificateChain.isPresent() && keyPair.isPresent()) {
                    X509Certificate[] chain = localCertificateChain.get();

                    secureChannel.setLocalCertificate(chain[0]);
                    secureChannel.setLocalCertificateChain(chain);
                    secureChannel.setKeyPair(keyPair.get());
                } else {
                    throw new UaException(StatusCodes.Bad_SecurityChecksFailed,
                            "no certificate for provided thumbprint");
                }
            }
        }

        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<>();
            headerRef.set(null);

            serializationQueue.decode((binaryDecoder, chunkDecoder) -> chunkDecoder
                    .decodeAsymmetric(secureChannel, buffersToDecode, new ChunkDecoder.Callback() {
                        @Override
                        public void onDecodingError(UaException ex) {
                            logger.error("Error decoding asymmetric message: {}", ex.getMessage(), ex);

                            ctx.close();
                        }

                        @Override
                        public void onMessageAborted(MessageAbortedException ex) {
                            logger.warn("Asymmetric message aborted. error={} reason={}", ex.getStatusCode(),
                                    ex.getMessage());
                        }

                        @Override
                        public void onMessageDecoded(ByteBuf message, long requestId) {
                            try {
                                OpenSecureChannelRequest request = (OpenSecureChannelRequest) binaryDecoder
                                        .setBuffer(message).readMessage(null);

                                logger.debug("Received OpenSecureChannelRequest ({}, id={}).",
                                        request.getRequestType(), secureChannelId);

                                sendOpenSecureChannelResponse(ctx, requestId, request);
                            } catch (Throwable t) {
                                logger.error("Error decoding OpenSecureChannelRequest", t);
                                ctx.close();
                            } finally {
                                message.release();
                                buffersToDecode.clear();
                            }
                        }
                    }));
        }
    }
}