/*
* TeleStax, Open Source Cloud Communications
* Copyright 2011-2014, TeleStax Inc. and individual contributors
* by the @authors tag.
*
* This program is free software: you can redistribute it and/or modify
* under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation; either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
package org.jdiameter.server.impl.io.sctp;
import java.net.InetAddress;
import java.nio.channels.Selector;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import org.jdiameter.client.api.parser.IMessageParser;
import org.jdiameter.common.api.concurrent.DummyConcurrentFactory;
import org.jdiameter.common.api.concurrent.IConcurrentFactory;
import org.jdiameter.server.api.IMetaData;
import org.jdiameter.server.api.io.INetworkConnectionListener;
import org.jdiameter.server.api.io.INetworkGuard;
import org.mobicents.protocols.api.Association;
import org.mobicents.protocols.api.Server;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* SCTP implementation of {@link org.jdiameter.server.api.io.INetworkGuard}.
*
* @author <a href="mailto:brainslog@gmail.com"> Alexandre Mendonca </a>
* @author <a href="mailto:baranowb@gmail.com"> Bartosz Baranowski </a>
*/
public class NetworkGuard implements INetworkGuard {
private static final Logger logger = LoggerFactory.getLogger(NetworkGuard.class);
protected IMessageParser parser;
protected IConcurrentFactory concurrentFactory;
protected int port;
protected CopyOnWriteArrayList<INetworkConnectionListener> listeners = new CopyOnWriteArrayList<INetworkConnectionListener>();
protected boolean isWork = false;
protected Selector selector;
protected List<SCTPServerConnection> serverConnections;
protected InetAddress[] localAddresses;
@Deprecated
public NetworkGuard(InetAddress inetAddress, int port, IMessageParser parser) throws Exception {
this(inetAddress, port, null, parser, null);
}
public NetworkGuard(InetAddress inetAddress, int port, IConcurrentFactory concurrentFactory, IMessageParser parser, IMetaData data) throws Exception {
this(new InetAddress[]{inetAddress}, port, concurrentFactory, parser, data);
}
public NetworkGuard(InetAddress[] inetAddresses, int port, IConcurrentFactory concurrentFactory, IMessageParser parser, IMetaData data) throws Exception {
this.port = port;
this.localAddresses = inetAddresses;
this.parser = parser;
this.concurrentFactory = concurrentFactory == null ? new DummyConcurrentFactory() : concurrentFactory;
this.serverConnections = new ArrayList<SCTPServerConnection>();
try {
for (InetAddress ia : inetAddresses) {
final SCTPServerConnection sctpServerConnection = new SCTPServerConnection(null, ia, port, parser, null, this);
this.serverConnections.add(sctpServerConnection);
}
}
catch (Exception exc) {
try {
destroy();
}
catch (Exception e) {
// ignore
}
throw new Exception(exc);
}
}
public void run() {
try {
while (isWork) {
Thread.sleep(10000);
}
}
catch (Exception exc) {
logger.warn("Server socket stopped", exc);
}
}
@Override
public void addListener(INetworkConnectionListener listener) {
if (!listeners.contains(listener)) {
listeners.add(listener);
}
}
@Override
public void remListener(INetworkConnectionListener listener) {
listeners.remove(listener);
}
@Override
public String toString() {
return "NetworkGuard:" + (this.serverConnections.size() != 0 ? this.serverConnections : "closed");
}
public void onNewRemoteConnection(Server globalServer, Association association, SCTPServerConnection connection) {
logger.debug("New remote connection");
try {
final String peerAddress = association.getPeerAddress();
final int peerPort = association.getPeerPort();
final String localAddress = association.getHostAddress();
final int localPort = association.getHostPort();
SCTPServerConnection remoteClientConnection = new SCTPServerConnection(null, InetAddress.getByName(peerAddress),
peerPort, InetAddress.getByName(localAddress), localPort, parser, null, this, globalServer, association, connection.getManagement());
notifyListeners(remoteClientConnection);
}
catch (Exception exc) {
logger.error("Error creating new remote connection");
}
}
@Override
public void destroy() {
logger.debug("Destroying");
Iterator<SCTPServerConnection> it = this.serverConnections.iterator();
while (it.hasNext()) {
try {
SCTPServerConnection server = it.next();
it.remove();
if (server != null && server.isConnected()) {
server.disconnect();
server.destroy();
}
}
catch (Exception e) {
logger.error("", e);
}
}
}
private void notifyListeners(SCTPServerConnection server) {
for (INetworkConnectionListener listener : this.listeners) {
try {
listener.newNetworkConnection(server);
}
catch (Exception e) {
logger.debug("Connection listener threw exception!", e);
}
}
}
}