/*_########################################################################## _## _## Copyright (C) 2011-2013 Kaito Yamada _## _########################################################################## */ package com.github.kaitoy.sneo.network; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.concurrent.BlockingQueue; import org.pcap4j.core.PacketListener; import org.pcap4j.packet.Packet; import org.pcap4j.util.MacAddress; import org.snmp4j.log.LogAdapter; import org.snmp4j.log.LogFactory; import com.github.kaitoy.sneo.network.protocol.EthernetHelper; public final class PhysicalNetworkInterface extends PacketReceiver implements NetworkInterface { private static final LogAdapter logger = LogFactory.getLogger(PhysicalNetworkInterface.class); private final MacAddress macAddress; private final boolean trunk; private final List<NifIpAddress> ipAddresses = Collections.synchronizedList(new ArrayList<NifIpAddress>()); private final PacketListener host; private final List<PacketListener> users = Collections.synchronizedList(new ArrayList<PacketListener>()); private volatile BlockingQueue<PacketContainer> sendPacketQueue = null; public PhysicalNetworkInterface( String name, MacAddress macAddress, boolean trunk, PacketListener host ) { super(name); this.macAddress = macAddress; this.trunk = trunk; this.host = host; } public MacAddress getMacAddress() { return macAddress; } public boolean isTrunk() { return trunk; } public List<NifIpAddress> getIpAddresses() { return new ArrayList<NifIpAddress>(ipAddresses); } public void addIpAddress(NifIpAddress addr) { ipAddresses.add(addr); } public void addUser(PacketListener user) { users.add(user); } void setSendPacketQueue(BlockingQueue<PacketContainer> sendPacketQueue) { this.sendPacketQueue = sendPacketQueue; } public void sendPacket(Packet packet) throws SendPacketException { if (!isRunning()) { if (logger.isDebugEnabled()) { logger.warn("Not running. Can't send a packet: " + packet); throw new SendPacketException(); } } BlockingQueue<PacketContainer> q = sendPacketQueue; if (q == null) { logger.warn("Not yet be connected. Dropped a packet: " + packet); throw new SendPacketException(); } boolean offered = q.offer(new PacketContainer(packet, this)); if (offered) { if (logger.isDebugEnabled()) { logger.debug("Sent a packet: " + packet); } } else { logger.error("Couldn't send a packet: " + packet); throw new SendPacketException(); } } @Override protected void process(PacketContainer pc) { Packet packet = pc.getPacket(); if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Received a packet from "); if (pc.getSrc() != null) { sb.append(pc.getSrc().getName()); } else { sb.append("a L2 connection"); } sb.append(": ") .append(packet); logger.debug(sb.toString()); } for (PacketListener user: users) { user.gotPacket(packet); } if (EthernetHelper.matchesDestination(packet, macAddress)) { host.gotPacket(packet); } else { if (logger.isDebugEnabled()) { StringBuilder sb = new StringBuilder(); sb.append("Dropped a packet not to me(") .append(macAddress) .append("): ") .append(packet); logger.debug(sb.toString()); } } } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(this.getClass().getSimpleName()).append("{") .append("name[").append(getName()).append("] ") .append("macAddress[").append(macAddress).append("]"); for (NifIpAddress ipAddr: ipAddresses) { sb.append("ipAddress[").append(ipAddr).append("]"); } sb.append("}"); return sb.toString(); } }