org.opcfoundation.ua.transport.https.HttpsServerConnection.java Source code

Java tutorial

Introduction

Here is the source code for org.opcfoundation.ua.transport.https.HttpsServerConnection.java

Source

/* Copyright (c) 1996-2015, OPC Foundation. All rights reserved.
   The source code in this file is covered under a dual-license scenario:
 - RCL: for OPC Foundation members in good-standing
 - GPL V2: everybody else
   RCL license terms accompanied with this source code. See http://opcfoundation.org/License/RCL/1.00/
   GNU General Public License as published by the Free Software Foundation;
   version 2 of the License are accompanied with this source code. See http://opcfoundation.org/License/GPLv2
   This source code 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.
*/
package org.opcfoundation.ua.transport.https;

import java.net.Socket;
import java.net.SocketAddress;
import java.util.Collection;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

import org.apache.http.impl.nio.NHttpConnectionBase;
import org.apache.http.nio.NHttpServerConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opcfoundation.ua.common.ServiceResultException;
import org.opcfoundation.ua.core.StatusCodes;
import org.opcfoundation.ua.transport.CloseableObjectState;
import org.opcfoundation.ua.transport.IConnectionListener;
import org.opcfoundation.ua.transport.ServerConnection;
import org.opcfoundation.ua.transport.ServerSecureChannel;
import org.opcfoundation.ua.utils.AbstractState;

/**
 * This class implements HTTP TSL/SSL conversation.
 * 
 * The messages are serialized using binary scheme, the same as with tcp 
 * conversation.
 * 
 * Because HTTPS channel is already secure, a OPC secure channel is not opened.
 * All HTTPS communications via a URL shall be treated as a single 
 * SecureChannel that is shared by multiple Clients. Stack shall provide a 
 * unique identifier for the SecureChannel which allows Applications correlate 
 * a request with a SecureChannel.This means that Sessions can only be 
 * considered secure if the AuthenticationToken (see Part 4) is long (>20 bytes)
 * and HTTPS encryption is enabled.
 */
public class HttpsServerConnection extends AbstractState<CloseableObjectState, ServiceResultException>
        implements ServerConnection {
    private static Logger logger = LoggerFactory.getLogger(HttpsServerConnection.class);

    HttpsServer server;
    NHttpServerConnection conn;
    Socket socket;

    /** List of secure channels open in this connection */
    Map<Integer, ServerSecureChannel> secureChannels = new ConcurrentHashMap<Integer, ServerSecureChannel>();
    /** List of secure channel listener */
    CopyOnWriteArrayList<SecureChannelListener> secureChannelListeners = new CopyOnWriteArrayList<SecureChannelListener>();
    /** Listeners that follow this connection */
    CopyOnWriteArrayList<IConnectionListener> connectionListeners = new CopyOnWriteArrayList<IConnectionListener>();

    public HttpsServerConnection(HttpsServer server, NHttpServerConnection conn) {
        super(CloseableObjectState.Closed);
        this.server = server;
        this.conn = conn;
        this.socket = ((NHttpConnectionBase) conn).getSocket();
        this.conn.setSocketTimeout(60000);
    }

    @Override
    public SocketAddress getLocalAddress() {
        return socket.getLocalSocketAddress();
    }

    @Override
    public SocketAddress getRemoteAddress() {
        return socket.getRemoteSocketAddress();
    }

    public NHttpServerConnection getNHttpServerConnection() {
        return conn;
    }

    @Override
    public void getSecureChannels(Collection<ServerSecureChannel> list) {
        list.addAll(secureChannels.values());
    }

    @Override
    public void addSecureChannelListener(SecureChannelListener l) {
        secureChannelListeners.add(l);
    }

    @Override
    public void removeSecureChannelListener(SecureChannelListener l) {
        secureChannelListeners.remove(l);
    }

    @Override
    public void addConnectionListener(IConnectionListener listener) {
        connectionListeners.add(listener);
    }

    @Override
    public void removeConnectionListener(IConnectionListener listener) {
        connectionListeners.remove(listener);
    }

    @Override
    protected void onStateTransition(CloseableObjectState oldState, CloseableObjectState newState) {
        logger.debug("onStateTransition: {}->{}", oldState, newState);
        super.onStateTransition(oldState, newState);

        if (newState == CloseableObjectState.Open) {
            for (IConnectionListener l : connectionListeners)
                l.onOpen();
        }

        if (newState == CloseableObjectState.Closed) {
            ServiceResultException sre = new ServiceResultException(StatusCodes.Bad_CommunicationError);
            for (IConnectionListener l : connectionListeners) {
                l.onClosed(sre);
            }

        }
    }
}