me.xingrz.prox.transport.AbstractTransportProxy.java Source code

Java tutorial

Introduction

Here is the source code for me.xingrz.prox.transport.AbstractTransportProxy.java

Source

/*
 * Copyright (C) 2015 XiNGRZ <chenxingyu92@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

package me.xingrz.prox.transport;

import org.apache.commons.io.IOUtils;

import java.io.Closeable;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.channels.SelectableChannel;
import java.nio.channels.Selector;

import me.xingrz.prox.logging.FormattingLogger;

/**
 * ??
 *
 * @param <C> ?? {@link java.nio.channels.ServerSocketChannel}  {@link java.nio.channels.DatagramChannel}
 * @param <S> ?
 */
public abstract class AbstractTransportProxy<C extends SelectableChannel, S extends AbstractTransportProxy.Session>
        implements Closeable {

    /**
     * ?
     */
    public static abstract class Session implements Closeable {

        protected final FormattingLogger logger;

        protected final Selector selector;

        private final int sourcePort;

        private final InetAddress remoteAddress;
        private final int remotePort;

        private boolean finished = false;

        long lastActive = System.currentTimeMillis();

        public Session(Selector selector, int sourcePort, InetAddress remoteAddress, int remotePort) {
            this.selector = selector;
            this.sourcePort = sourcePort;
            this.remoteAddress = remoteAddress;
            this.remotePort = remotePort;
            this.logger = getLogger();
        }

        protected abstract FormattingLogger getLogger();

        /**
         * @return ???
         */
        public int getSourcePort() {
            return sourcePort;
        }

        /**
         * @return ?
         */
        public InetAddress getRemoteAddress() {
            return remoteAddress;
        }

        /**
         * @return ?
         */
        public int getRemotePort() {
            return remotePort;
        }

        /**
         * @return ???
         */
        public boolean isFinished() {
            return finished;
        }

        /**
         * ??
         */
        public void finish() {
            finished = true;
        }

        /**
         * ??
         */
        public void active() {
            lastActive = System.currentTimeMillis();
        }

    }

    protected final FormattingLogger logger = getLogger();

    private final long sessionTimeout;

    private final NatSessionManager<S> sessions;

    protected Selector selector;
    protected C serverChannel;

    public AbstractTransportProxy(int maxSessionCount, long sessionTimeout) {

        this.sessionTimeout = sessionTimeout;
        this.sessions = new NatSessionManager<S>(maxSessionCount) {
            @Override
            protected void onRemoved(S session) {
                IOUtils.closeQuietly(session);
                if (session.isFinished()) {
                    logger.v("Removed finished session %08x", session.hashCode());
                } else {
                    logger.v("Terminated session %08x, session count: %s", session.hashCode(), size());
                }
            }

            @Override
            protected boolean shouldRecycle(S session) {
                return shouldRecycleSession(session);
            }
        };
    }

    protected abstract FormattingLogger getLogger();

    protected abstract C createChannel(Selector selector) throws IOException;

    public abstract int port();

    public void start(Selector selector) throws IOException {
        this.selector = selector;

        serverChannel = createChannel(selector);
        logger.d("Proxy running on %d", port());
    }

    public boolean isRunning() {
        return serverChannel.isOpen();
    }

    @Override
    public void close() throws IOException {
        sessions.clear();
        serverChannel.close();
    }

    /**
     * ???
     *
     * @param sourcePort    ???
     * @param remoteAddress ?
     * @param remotePort    ?
     * @return ?
     * @throws IOException ??
     */
    protected abstract S createSession(int sourcePort, InetAddress remoteAddress, int remotePort)
            throws IOException;

    /**
     * ??
     * ?????????
     *
     * @param sourcePort    ???
     * @param remoteAddress ?
     * @param remotePort    ?
     * @return ?
     * @throws IOException ??
     */
    public S pickSession(int sourcePort, InetAddress remoteAddress, int remotePort) throws IOException {
        S session = createSession(sourcePort, remoteAddress, remotePort);
        sessions.put(sourcePort, session);
        return session;
    }

    /**
     * ??
     *
     * @param sourcePort ???
     * @return ? {@code null} ?
     */
    public S getSession(int sourcePort) {
        return sessions.get(sourcePort);
    }

    /**
     * ??
     *
     * @param sourcePort ???
     * @return ? {@code null} ?
     */
    public S finishSession(int sourcePort) {
        S session = sessions.get(sourcePort);
        sessions.remove(sourcePort);
        return session;
    }

    protected boolean shouldRecycleSession(S session) {
        return System.currentTimeMillis() - session.lastActive >= sessionTimeout;
    }

}