/*
** This file is part of Filius, a network construction and simulation software.
**
** Originally created at the University of Siegen, Institute "Didactics of
** Informatics and E-Learning" by a students' project group:
** members (2006-2007):
** André Asschoff, Johannes Bade, Carsten Dittich, Thomas Gerding,
** Nadja Haßler, Ernst Johannes Klebert, Michell Weyer
** supervisors:
** Stefan Freischlad (maintainer until 2009), Peer Stechert
** Project is maintained since 2010 by Christian Eibl <filius@c.fameibl.de>
** and Stefan Freischlad
** Filius 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 2 of the License, or
** (at your option) version 3.
**
** Filius 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 Filius. If not, see <http://www.gnu.org/licenses/>.
*/
package filius.software.netzzugangsschicht;
import java.util.LinkedList;
import java.util.ListIterator;
import filius.Main;
import filius.hardware.NetzwerkInterface;
import filius.hardware.knoten.InternetKnoten;
import filius.rahmenprogramm.nachrichten.Lauscher;
import filius.software.Protokoll;
import filius.software.system.InternetKnotenBetriebssystem;
import filius.software.system.SystemSoftware;
import filius.software.vermittlungsschicht.ArpPaket;
import filius.software.vermittlungsschicht.IpPaket;
import filius.software.vermittlungsschicht.IcmpPaket;
/** Diese Klasse implementiert die Netzzugangsschicht */
public class Ethernet extends Protokoll {
/**
* Liste der Threads fuer die Ueberwachung der Netzwerkkarten
*/
private LinkedList<EthernetThread> threads = new LinkedList<EthernetThread>();
/** Puffer fuer eingehende ARP-Pakete */
private LinkedList<ArpPaket> arpPakete = new LinkedList<ArpPaket>();
/** Puffer fuer eingehende IP-Pakete */
private LinkedList<IpPaket> ipPakete = new LinkedList<IpPaket>();
/** Puffer fuer eingehende ICMP-Pakete */
private LinkedList<IcmpPaket> icmpPakete = new LinkedList<IcmpPaket>();
/** Konstruktor zur Initialisierung der Systemsoftware */
public Ethernet(SystemSoftware systemSoftware) {
super(systemSoftware);
Main.debug.println("INVOKED-2 ("+this.hashCode()+") "+getClass()+" (Ethernet), constr: Ethernet("+systemSoftware+")");
}
/** Methode fuer den Zugriff auf den Puffer mit ARP-Paketen */
public LinkedList<ArpPaket> holeARPPuffer() {
return arpPakete;
}
/** Methode fuer den Zugriff auf den Puffer mit IP-Paketen */
public LinkedList<IpPaket> holeIPPuffer() {
return ipPakete;
}
/** Methode fuer den Zugriff auf den Puffer mit ICMP-Paketen */
public LinkedList<IcmpPaket> holeICMPPuffer() {
return icmpPakete;
}
/** Methode fuer den Zugriff auf den Puffer mit IP-Paketen */
public void setzeIPPuffer(LinkedList<IpPaket> puffer) {
ipPakete = puffer;
}
/**
* sendet Pakete ueber als Ethernet-Frame weiter. Zuerst wird dazu
* ueberprueft, ob die Ziel-MAC-Adresse eine eigene Netzwerkkarte
* adressiert. Wenn dies nicht der Fall ist, wird der Frame ueber die
* Netzwerkkarte verschickt, die durch die Quell-MAC-Adresse spezifiziert
* wird.
*/
public void senden(Object daten, String startMAC, String zielMAC, String typ) {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (Ethernet), senden("+daten+","+startMAC+","+zielMAC+","+typ+")");
EthernetFrame ethernetFrame;
ListIterator it;
NetzwerkInterface nic;
boolean gesendet = false;
if(daten instanceof IcmpPaket) {
ethernetFrame = new EthernetFrame(daten, startMAC, zielMAC, typ, true);
}
else {
ethernetFrame = new EthernetFrame(daten, startMAC, zielMAC, typ);
}
it = ((InternetKnoten) holeSystemSoftware().getKnoten())
.getNetzwerkInterfaces().listIterator();
while (it.hasNext()) {
nic = (NetzwerkInterface) it.next();
if (nic.getMac().equalsIgnoreCase(zielMAC)) {
synchronized (nic.getPort().holeEingangsPuffer()) {
nic.getPort().holeEingangsPuffer().add(ethernetFrame);
nic.getPort().holeEingangsPuffer().notify();
}
gesendet = true;
}
}
if (!gesendet) {
it = ((InternetKnoten) holeSystemSoftware().getKnoten())
.getNetzwerkInterfaces().listIterator();
while (it.hasNext()) {
nic = (NetzwerkInterface) it.next();
if (nic.getMac().equalsIgnoreCase(startMAC)) {
synchronized (nic.getPort().holeAusgangsPuffer()) {
//Main.debug
//.println("EthernetThread: Paket wird in Ausgangspuffer geschrieben "
//+ nic.getPort());
nic.getPort().holeAusgangsPuffer().add(ethernetFrame);
nic.getPort().holeAusgangsPuffer().notify();
}
Lauscher.getLauscher().addDatenEinheit(nic.getMac(),
ethernetFrame);
}
}
}
}
public LinkedList<EthernetThread> getEthernetThreads() {
return threads;
}
/**
* Hier wird zu jeder Netzwerkkarte ein Thread zur Ueberwachung des
* Eingangspuffers gestartet.
*/
public void starten() {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (Ethernet), starten()");
InternetKnoten knoten;
EthernetThread interfaceBeobachter;
if (holeSystemSoftware().getKnoten() instanceof InternetKnoten) {
knoten = (InternetKnoten) holeSystemSoftware().getKnoten();
ListIterator iter = knoten.getNetzwerkInterfaces().listIterator();
while (iter.hasNext()) {
NetzwerkInterface netzwerkInterface = (NetzwerkInterface) iter
.next();
interfaceBeobachter = new EthernetThread(this,
netzwerkInterface);
interfaceBeobachter.starten();
try {
threads.add(interfaceBeobachter);
}
catch (Exception e) {
e.printStackTrace(Main.debug);
}
}
}
}
/**
* beendet alle laufenden EthernetThreads zur Ueberwachung der
* Eingangspuffer der Netzwerkkarten
*/
public void beenden() {
Main.debug.println("INVOKED ("+this.hashCode()+") "+getClass()+" (Ethernet), beenden()");
EthernetThread interfaceBeobachter;
for (int x = 0; x < threads.size(); x++) {
interfaceBeobachter = (EthernetThread) threads.get(x);
interfaceBeobachter.beenden();
}
}
}