/*
* Copyright (c) 2005-2011 KOM - Multimedia Communications Lab
*
* This file is part of PeerfactSim.KOM.
*
* PeerfactSim.KOM 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 3 of the License, or
* any later version.
*
* PeerfactSim.KOM 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 PeerfactSim.KOM. If not, see .
*
*/
package de.tud.kom.p2psim.impl.network;
import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.api.analyzer.ConnectivityAnalyzer;
import de.tud.kom.p2psim.api.analyzer.MessageAnalyzer.Reason;
import de.tud.kom.p2psim.api.analyzer.NetlayerAnalyzer;
import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.linklayer.mac.PhyType;
import de.tud.kom.p2psim.api.network.NetMessage;
import de.tud.kom.p2psim.api.network.NetMessageListener;
import de.tud.kom.p2psim.api.network.NetMsgEvent;
import de.tud.kom.p2psim.api.network.SimNetInterface;
import de.tud.kom.p2psim.api.network.SimNetworkComponent;
import de.tud.kom.p2psim.api.transport.TransProtocol;
import de.tud.kom.p2psim.impl.network.modular.db.NetMeasurementDB;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
import de.tudarmstadt.maki.simonstrator.api.Monitor.Level;
import de.tudarmstadt.maki.simonstrator.api.component.core.MonitorComponent.AnalyzerNotAvailableException;
import de.tudarmstadt.maki.simonstrator.api.component.network.Bandwidth;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetID;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetInterface;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Location;
import de.tudarmstadt.maki.simonstrator.api.component.transport.ConnectivityListener;
/**
* This abstract class provides a skeletal implementation of the
* StandaloneNetLayer interface to lighten the effort for implementing this interface.
*
* All Netlayers implementing this abstract base class can only provide exactly one {@link NetInterface},
* i.e., they do not have multiple communication interfaces. For simulations with multiple interfaces,
* you need to use the routedNetLayer and corresponding Linklayers.
*
* @author Sebastian Kaune
* @author Konstantin Pussep
* @version 3.0, 11/29/2007
*
*/
public abstract class AbstractNetLayer implements SimNetworkComponent,
SimNetInterface {
private final List msgListeners;
private final List connListeners;
private final NetID myID;
protected NetMeasurementDB.Host hostMeta;
private boolean online;
private Location position;
Bandwidth currentBandwidth;
Bandwidth maxBandwidth;
private final SimHost host;
protected boolean hasAnalyzer = false;
protected NetlayerAnalyzer netAnalyzerProxy;
/**
* Abstract constructor called by a subclass of this instance
*
* @param maxDownBandwidth
* the maximum physical download bandwidth
* @param maxUpBandwidth
* the maximum physical upload bandwidth
* @param position
* the NetPosition of the network layer
*/
public AbstractNetLayer(SimHost host, NetID netId, Bandwidth maxBandwidth,
Location position, NetMeasurementDB.Host hostMeta) {
this.myID = netId;
this.msgListeners = new LinkedList();
this.connListeners = new LinkedList();
this.maxBandwidth = maxBandwidth;
this.currentBandwidth = maxBandwidth.clone();
this.position = position;
this.hostMeta = hostMeta;
this.host = host;
}
@Override
public void initialize() {
/*
* Bind the analyzer-Proxy
*/
try {
netAnalyzerProxy = Monitor.get(NetlayerAnalyzer.class);
hasAnalyzer = true;
} catch (AnalyzerNotAvailableException e) {
// no analyzer, no problem
}
}
@Override
public void shutdown() {
throw new AssertionError(
"You are not supposed to shutdown this component.");
}
/**
* This message is called by the subnet to deliver a new NetMessage to a
* remote NetLayer. (@see de.tud.kom.p2psim.impl.network.AbstractSubnet).
* Calling this method informs further all registered NetMsgListeners about
* the receipt of this NetMessage using a appropriate NetMsgEvent.
*
* @param message
* The NetMessage that was received by the NetLayer.
*/
public void receive(NetMessage message) {
if (this.isOnline()) {
// log.info(Simulator.getSimulatedRealtime() + " Receiving " +
// message);
if (hasAnalyzer) {
netAnalyzerProxy
.netMsgEvent(message, getHost(),
Reason.RECEIVE);
}
NetMsgEvent event = new NetMsgEvent(message, this);
if (msgListeners == null || msgListeners.isEmpty()) {
if (hasAnalyzer) {
netAnalyzerProxy.netMsgEvent(message, getHost(),
Reason.DROP);
}
Monitor.log(AbstractNetLayer.class, Level.WARN,
"Cannot deliver message "
+ message.getPayload() + " at netID=" + myID
+ " as no message msgListeners registered");
} else {
for (NetMessageListener listener : msgListeners) {
listener.messageArrived(event);
}
}
} else {
if (hasAnalyzer) {
netAnalyzerProxy.netMsgEvent(message, getHost(), Reason.DROP);
}
}
}
/**
* Return whether the required transport protocol is supported by the given
* NetLayer instance
*
* @param protocol
* the required transport protocol
* @return true if supported
*/
protected abstract boolean isSupported(TransProtocol protocol);
/**
* As the download bandwidth of a host might be shared between concurrently
* established connections, this method will be used by the subnet in order
* to adapt the current available download bandwidth.
*
* @param currentDownBandwidth
* the new available download bandwidth
*/
@Deprecated
public void setCurrentDownBandwidth(long currentDownBandwidth) {
this.currentBandwidth.setDownBW(currentDownBandwidth);
}
/**
* As the upload bandwidth of a host might be shared between concurrently
* established connections, this method will be used by the subnet in order
* to adapt the current available upload bandwidth.
*
* @param currentUpBandwidth
* the new available upload bandwidth
*/
@Deprecated
public void setCurrentUpBandwidth(long currentUpBandwidth) {
this.currentBandwidth.setUpBW(currentUpBandwidth);
}
public void setCurrentBandwidth(Bandwidth currentBandwidth) {
this.currentBandwidth = currentBandwidth;
}
/*
* (non-Javadoc)
*
* @seede.tud.kom.p2psim.api.api.network.NetLayer#addNetMsgListener(
* NetMessageListener) listener)
*/
public void addNetMsgListener(NetMessageListener listener) {
if (!this.msgListeners.contains(listener)) {
this.msgListeners.add(listener);
}
}
public List getNetMsgListeners() {
return this.msgListeners;
}
/*
* (non-Javadoc)
*
* @seede.tud.kom.p2psim.api.api.network.NetLayer#removeNetMsgListener(
* NetMessageListener) listener)
*/
public void removeNetMsgListener(NetMessageListener listener) {
this.msgListeners.remove(listener);
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#getNetID()
*/
public NetID getNetID() {
return this.myID;
}
@Override
public NetID getLocalInetAddress() {
return this.myID;
}
@Override
public NetID getBroadcastAddress() {
return IPv4NetID.LOCAL_BROADCAST;
}
@Override
public SimNetInterface getByName(NetInterfaceName name) {
if (name == NetInterfaceName.ETHERNET) {
return this;
} else {
throw new AssertionError("This NetLayer supports only ETHERNET!");
}
}
@Override
public NetID getByName(String name) {
return new IPv4NetID(name);
}
@Override
public SimNetInterface getByNetId(NetID netID) {
if (getLocalInetAddress().equals(netID)) {
return this;
} else {
return null;
}
}
@Override
public Iterable getNetworkInterfaces() {
List list = new LinkedList();
list.add(this);
return list;
}
@Override
public Iterable getSimNetworkInterfaces() {
List list = new LinkedList();
list.add(this);
return list;
}
@Override
public NetInterfaceName getName() {
return NetInterfaceName.ETHERNET;
}
@Override
public int getMTU() {
return PhyType.ETHERNET.getDefaultMTU();
}
@Override
public boolean isUp() {
return isOnline();
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#goOffline()
*/
public void goOffline() {
if (this.online) {
this.online = false;
for (ConnectivityListener connListener : connListeners) {
connListener.wentOffline(host, this);
}
try {
Monitor.get(ConnectivityAnalyzer.class).wentOffline(host);
} catch (AnalyzerNotAvailableException e) {
//
}
}
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#goOnline()
*/
public void goOnline() {
if (!this.online) {
this.online = true;
for (ConnectivityListener connListener : connListeners) {
connListener.wentOnline(host, this);
}
try {
Monitor.get(ConnectivityAnalyzer.class).wentOnline(host);
} catch (AnalyzerNotAvailableException e) {
//
}
}
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#isOffline()
*/
@Override
public boolean isOffline() {
return !online;
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#isOnline()
*/
@Override
public boolean isOnline() {
return online;
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.common.Component#getHost()
*/
@Override
public SimHost getHost() {
return this.host;
}
/*
* (non-Javadoc)
*
* @see de.tud.kom.p2psim.api.api.network.NetLayer#getNetPosition()
*/
@Override
public Location getNetPosition() {
return this.position;
}
@Override
public Bandwidth getCurrentBandwidth() {
return currentBandwidth;
}
@Override
public Bandwidth getMaxBandwidth() {
return maxBandwidth;
}
/*
* (non-Javadoc)
*
* @see
* de.tud.kom.p2psim.api.network.NetLayer#removeConnectivityListener(de.
* tud.kom.p2psim.api.common.ConnectivityListener)
*/
@Override
public void removeConnectivityListener(ConnectivityListener listener) {
this.connListeners.remove(listener);
}
@Override
public void addConnectivityListener(ConnectivityListener listener) {
this.connListeners.add(listener);
}
/**
* Gets the dB host meta from NetMessurementDB
*
* @return the dB host meta
*/
public NetMeasurementDB.Host getDBHostMeta() {
return hostMeta;
}
}