/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.ignite.internal.util.nio; import java.nio.ByteBuffer; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.IgniteException; import org.apache.ignite.IgniteLogger; import org.apache.ignite.internal.util.typedef.internal.LT; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteInClosure; /** * Verifies that first bytes received in accepted (incoming) * NIO session are equal to {@link U#IGNITE_HEADER}. * <p> * First {@code U.IGNITE_HEADER.length} bytes are consumed by this filter * and all other bytes are forwarded through chain without any modification. */ public class GridConnectionBytesVerifyFilter extends GridNioFilterAdapter { /** */ private static final int MAGIC_META_KEY = GridNioSessionMetaKey.nextUniqueKey(); /** */ private static final int MAGIC_BUF_KEY = GridNioSessionMetaKey.nextUniqueKey(); /** */ private IgniteLogger log; /** * Creates a filter instance. * * @param log Logger. */ public GridConnectionBytesVerifyFilter(IgniteLogger log) { super("GridConnectionBytesVerifyFilter"); this.log = log; } /** {@inheritDoc} */ @Override public void onSessionOpened(GridNioSession ses) throws IgniteCheckedException { proceedSessionOpened(ses); } /** {@inheritDoc} */ @Override public void onSessionClosed(GridNioSession ses) throws IgniteCheckedException { proceedSessionClosed(ses); } /** {@inheritDoc} */ @Override public void onExceptionCaught( GridNioSession ses, IgniteCheckedException ex ) throws IgniteCheckedException { proceedExceptionCaught(ses, ex); } /** {@inheritDoc} */ @Override public GridNioFuture<?> onSessionWrite( GridNioSession ses, Object msg, boolean fut, IgniteInClosure<IgniteException> ackC ) throws IgniteCheckedException { return proceedSessionWrite(ses, msg, fut, ackC); } /** {@inheritDoc} */ @Override public void onMessageReceived(GridNioSession ses, Object msg) throws IgniteCheckedException { // Verify only incoming connections. if (!ses.accepted()) { proceedMessageReceived(ses, msg); return; } if (!(msg instanceof ByteBuffer)) throw new GridNioException("Failed to decode incoming message (message should be a byte buffer, is " + "filter properly placed?): " + msg.getClass()); ByteBuffer buf = (ByteBuffer)msg; Integer magic = ses.meta(MAGIC_META_KEY); if (magic == null || magic < U.IGNITE_HEADER.length) { byte[] magicBuf = ses.meta(MAGIC_BUF_KEY); if (magicBuf == null) magicBuf = new byte[U.IGNITE_HEADER.length]; int magicRead = magic == null ? 0 : magic; int cnt = buf.remaining(); buf.get(magicBuf, magicRead, Math.min(U.IGNITE_HEADER.length - magicRead, cnt)); if (cnt + magicRead < U.IGNITE_HEADER.length) { // Magic bytes are not fully read. ses.addMeta(MAGIC_META_KEY, cnt + magicRead); ses.addMeta(MAGIC_BUF_KEY, magicBuf); } else if (U.bytesEqual(magicBuf, 0, U.IGNITE_HEADER, 0, U.IGNITE_HEADER.length)) { // Magic bytes read and equal to IGNITE_HEADER. ses.removeMeta(MAGIC_BUF_KEY); ses.addMeta(MAGIC_META_KEY, U.IGNITE_HEADER.length); proceedMessageReceived(ses, buf); } else { ses.close(); LT.warn(log, "Unknown connection detected (is some other software connecting to this " + "Ignite port?) [rmtAddr=" + ses.remoteAddress() + ", locAddr=" + ses.localAddress() + ']'); } } else proceedMessageReceived(ses, buf); } /** {@inheritDoc} */ @Override public GridNioFuture<Boolean> onSessionClose(GridNioSession ses) throws IgniteCheckedException { return proceedSessionClose(ses); } /** {@inheritDoc} */ @Override public void onSessionIdleTimeout(GridNioSession ses) throws IgniteCheckedException { proceedSessionIdleTimeout(ses); } /** {@inheritDoc} */ @Override public void onSessionWriteTimeout(GridNioSession ses) throws IgniteCheckedException { proceedSessionWriteTimeout(ses); } }