/*
** 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.ListIterator;
import filius.Main;
import filius.gui.GUIContainer;
import filius.gui.netzwerksicht.GUIKabelItem;
import filius.hardware.NetzwerkInterface;
import filius.hardware.Port;
import filius.rahmenprogramm.nachrichten.Lauscher;
import filius.software.ProtokollThread;
import filius.software.vermittlungsschicht.ArpPaket;
import filius.software.vermittlungsschicht.IpPaket;
import filius.software.vermittlungsschicht.IcmpPaket;
/**
* Diese Klasse ueberwacht die Eingangspuffer von Netzwerkkarten.
*/
public class EthernetThread extends ProtokollThread {
/** die Netzwerkkarte, deren Anschluss ueberwacht wird */
private NetzwerkInterface netzwerkInterface;
/** die Ethernet-Schicht */
private Ethernet ethernet;
/**
* Der Konstruktor zur Initialisierung des zu ueberwachenden Puffers und der
* Ethernet-Schicht und der Netzwerkkarte
*/
public EthernetThread(Ethernet ethernet, NetzwerkInterface nic) {
super(nic.getPort().holeEingangsPuffer());
Main.debug.println("INVOKED-2 ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (EthernetThread), constr: EthernetThread("+ethernet+","+nic+")");
this.ethernet = ethernet;
this.netzwerkInterface = nic;
}
/**
* Hier werden die Nutzdaten des ankommenden Frames entweder in den Puffer
* fuer IP-Pakete oder fuer ARP-Pakete geschrieben.
*/
protected void verarbeiteDatenEinheit(Object datenEinheit) {
Main.debug.println("INVOKED ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (EthernetThread), verarbeiteDateneinheit("+datenEinheit.toString()+")");
EthernetFrame etp;
etp = (EthernetFrame) datenEinheit;
// record receipt (independent of further processing)
Lauscher.getLauscher().addDatenEinheit(netzwerkInterface.getMac(),etp);
// only process in case of correct MAC address, i.e., this packet is addressed for this NIC (or broadcast)
// otherwise stop processing:
if (! etp.getZielMacAdresse().equalsIgnoreCase("FF:FF:FF:FF:FF:FF") // broadcast
&& ! etp.getZielMacAdresse().equals(this.netzwerkInterface.getMac()))
return;
////
// Main.debug.println(getClass().toString()
// +"\n\tverareiteDatenEinheit() wurde aufgerufen"
// +"\n\t"+etp.getQuellMacAdresse()+" -> "+etp.getZielMacAdresse()
// +", Protokoll: "+etp.getTyp()
// +", ICMP? "+(etp.isICMP()));
if (etp.getTyp().equals(EthernetFrame.IP)) {
if(etp.isICMP()) {
synchronized (ethernet.holeICMPPuffer()) {
ethernet.holeICMPPuffer().add((IcmpPaket) etp.getDaten());
// Main.debug.println("DEBUG ("+this.hashCode()+", T"+this.getId()+") "+getClass()+" (EthernetThread), verarbeiteDateneinheit, ICMPPuffer="+ethernet.holeICMPPuffer().getFirst().toString());
ethernet.holeICMPPuffer().notifyAll(); // 'all' means: Terminal ping command (if any in this instance) and default network packet processing
}
}
else {
synchronized (ethernet.holeIPPuffer()) {
ethernet.holeIPPuffer().add((IpPaket) etp.getDaten());
ethernet.holeIPPuffer().notify();
}
}
}
else if (etp.getTyp().equals(EthernetFrame.ARP)) {
// if ARP packet is not addressed to this specific NIC, but possibly another NIC of this node, then return
// (this is meant to prevent routers from responding to all ARP packets meant for some of their NICs
// without even having received the packet on this specific NIC, i.e., without physical connection)
if(!((ArpPaket)etp.getDaten()).getZielIp().equals(netzwerkInterface.getIp())) {
Main.debug.println("ERROR ("+this.hashCode()+"): ARP packet seems to be sent from a NIC ("+
((ArpPaket)etp.getDaten()).getQuellIp()+","+((ArpPaket)etp.getDaten()).getQuellMacAdresse()+
") not connected to the currently considered NIC ("+
netzwerkInterface.getIp()+","+netzwerkInterface.getMac()+")"
);
return;
}
// otherwise process ARP packet
synchronized (ethernet.holeARPPuffer()) {
ethernet.holeARPPuffer().add((ArpPaket) etp.getDaten());
ethernet.holeARPPuffer().notify();
}
}
else {
Main.debug.println("ERROR ("+this.hashCode()+"): Paket konnte nicht zugeordnet werden");
}
}
}