All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.jetty.websocket.common.io.IOState Maven / Gradle / Ivy

//
//  ========================================================================
//  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
//  ------------------------------------------------------------------------
//  All rights reserved. This program and the accompanying materials
//  are made available under the terms of the Eclipse Public License v1.0
//  and Apache License v2.0 which accompanies this distribution.
//
//      The Eclipse Public License is available at
//      http://www.eclipse.org/legal/epl-v10.html
//
//      The Apache License v2.0 is available at
//      http://www.opensource.org/licenses/apache2.0.php
//
//  You may elect to redistribute this code under either of these licenses.
//  ========================================================================
//

package org.eclipse.jetty.websocket.common.io;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.websocket.common.ConnectionState;

/**
 * Simple state tracker for Input / Output and {@link ConnectionState}
 */
public class IOState
{
    private static final Logger LOG = Log.getLogger(IOState.class);
    private ConnectionState state;
    private final AtomicBoolean inputClosed;
    private final AtomicBoolean outputClosed;

    private final AtomicBoolean cleanClose;
    private final AtomicBoolean remoteCloseInitiated;
    private final AtomicBoolean localCloseInitiated;

    public IOState()
    {
        this.state = ConnectionState.CONNECTING;
        this.inputClosed = new AtomicBoolean(false);
        this.outputClosed = new AtomicBoolean(false);
        this.remoteCloseInitiated = new AtomicBoolean(false);
        this.localCloseInitiated = new AtomicBoolean(false);
        this.cleanClose = new AtomicBoolean(false);
    }

    public void assertInputOpen() throws IOException
    {
        if (isInputClosed())
        {
            throw new IOException("Connection input is closed");
        }
    }

    public void assertOutputOpen() throws IOException
    {
        if (isOutputClosed())
        {
            throw new IOException("Connection output is closed");
        }
    }

    public boolean awaitClosed(long duration)
    {
        return (isInputClosed() && isOutputClosed());
    }

    public ConnectionState getConnectionState()
    {
        return state;
    }

    public ConnectionState getState()
    {
        return state;
    }

    public boolean isClosed()
    {
        return (isInputClosed() && isOutputClosed());
    }

    public boolean isCloseInitiated()
    {
        return remoteCloseInitiated.get() || localCloseInitiated.get();
    }

    public boolean isInputClosed()
    {
        return inputClosed.get();
    }

    public boolean isOpen()
    {
        return (getState() != ConnectionState.CLOSED);
    }

    public boolean isOutputClosed()
    {
        return outputClosed.get();
    }

    /**
     * Test for if connection should disconnect or response on a close handshake.
     * 
     * @param incoming
     *            true if incoming close
     * @param close
     *            the close details.
     * @return true if connection should be disconnected now, or false if response to close should be issued.
     */
    public boolean onCloseHandshake(boolean incoming)
    {
        boolean in = inputClosed.get();
        boolean out = outputClosed.get();
        if (incoming)
        {
            in = true;
            this.inputClosed.set(true);

            if (!localCloseInitiated.get())
            {
                remoteCloseInitiated.set(true);
            }
        }
        else
        {
            out = true;
            this.outputClosed.set(true);

            if ( !remoteCloseInitiated.get() )
            {
                localCloseInitiated.set(true);
            }
        }

        LOG.debug("onCloseHandshake({}), input={}, output={}",incoming,in,out);

        if (in && out)
        {
            LOG.debug("Close Handshake satisfied, disconnecting");
            cleanClose.set(true);
            return true;
        }

        return false;
    }

    public void setConnectionState(ConnectionState connectionState)
    {
        this.state = connectionState;
    }

    public void setState(ConnectionState state)
    {
        this.state = state;
    }

    public boolean wasCleanClose()
    {
        return cleanClose.get();
    }

    public boolean wasLocalCloseInitiated()
    {
        return localCloseInitiated.get();
    }

    public boolean wasRemoteCloseInitiated()
    {
        return remoteCloseInitiated.get();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy