/* * Copyright 2011-17 Fraunhofer ISE, energy & meteo Systems GmbH and other contributors * * Licensed 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.openmuc.josistack; import java.io.IOException; import java.net.InetAddress; import java.nio.ByteBuffer; import java.util.concurrent.TimeoutException; import javax.net.ServerSocketFactory; import org.openmuc.jositransport.ServerTSap; import org.openmuc.jositransport.TConnection; import org.openmuc.jositransport.TConnectionListener; /** * This class implements the server Service Access Point (SAP) for the Application Control Service Element (ACSE) * protocol as defined by ISO 8650 or ITU X.217/X.227. The ACSE provides services for establishing and releasing * application-associations. The class also realizes the lower ISO Presentation Layer as defined by ISO 8823/ITU X226 * and the ISO Session Layer as defined by 8327/ITU X.225. * */ public final class ServerAcseSap implements TConnectionListener { private AcseAssociationListener associationListener = null; public ServerTSap serverTSap = null; public byte[] pSelLocal = ClientAcseSap.P_SEL_DEFAULT; /** * Use this constructor to create a server ACSE SAP that listens on a fixed port. * * @param port * the local port listen on * @param backlog * the backlog * @param bindAddr * the InetAddress to bind to * @param associationListener * the AssociationListener that will be notified when remote clients have associated. Once constructed * the AcseSAP contains a public TSAP that can be accessed to set its configuration. */ public ServerAcseSap(int port, int backlog, InetAddress bindAddr, AcseAssociationListener associationListener) { this(port, backlog, bindAddr, associationListener, ServerSocketFactory.getDefault()); } /** * Use this constructor to create a server ACSE SAP that listens on a fixed port. The server socket is created with * the given socket factory. * * @param port * the local port listen on * @param backlog * the backlog * @param bindAddr * the InetAddress to bind to * @param associationListener * the AssociationListener that will be notified when remote clients have associated. Once constructed * the AcseSAP contains a public TSAP that can be accessed to set its configuration. * @param serverSocketFactory * the server socket factory to create the socket */ public ServerAcseSap(int port, int backlog, InetAddress bindAddr, AcseAssociationListener associationListener, ServerSocketFactory serverSocketFactory) { this.associationListener = associationListener; serverTSap = new ServerTSap(port, backlog, bindAddr, this, serverSocketFactory); } /** * Start listening for incoming connections. Only for server SAPs. * * @throws IOException * if an error occures starting to listen */ public void startListening() throws IOException { if (associationListener == null || serverTSap == null) { throw new IllegalStateException("AcseSAP is unable to listen because it was not initialized."); } serverTSap.startListening(); } public void stopListening() { serverTSap.stopListening(); } /** * This function is internal and should not be called by users of this class. */ @Override public void serverStoppedListeningIndication(IOException e) { associationListener.serverStoppedListeningIndication(e); } /** * This function is internal and should not be called by users of this class. * */ @Override public void connectionIndication(TConnection tConnection) { try { AcseAssociation acseAssociation = new AcseAssociation(tConnection, pSelLocal); ByteBuffer asdu = ByteBuffer.allocate(1000); try { asdu = acseAssociation.listenForCn(asdu); } catch (IOException e) { // Server: Connection unsuccessful. tConnection.close(); return; } catch (TimeoutException e) { // Illegal state: Timeout should not occur here tConnection.close(); return; } associationListener.connectionIndication(acseAssociation, asdu); } catch (Exception e) { // Association closed because of an unexpected exception. tConnection.close(); } } }