/*
* Copyright 2010 NCHOVY
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.krakenapps.pcap.decoder.ip;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.krakenapps.pcap.decoder.ethernet.EthernetFrame;
import org.krakenapps.pcap.decoder.ethernet.EthernetProcessor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* @author mindori
*/
public class IpDecoder implements EthernetProcessor {
private IpReassembler reassembler;
private final Map<Integer, Set<IpProcessor>> callbacks;
private final Logger logger = LoggerFactory.getLogger(IpDecoder.class.getName());
public IpDecoder() {
reassembler = new IpReassembler();
callbacks = new HashMap<Integer, Set<IpProcessor>>();
}
public void register(int protocol, IpProcessor processor) {
Set<IpProcessor> processors = callbacks.get(protocol);
if (processors == null) {
processors = new HashSet<IpProcessor>();
callbacks.put(protocol, processors);
}
processors.add(processor);
}
public void unregister(int protocol, IpProcessor processor) {
Set<IpProcessor> processors = callbacks.get(protocol);
if (processors == null)
return;
processors.remove(processor);
}
public void process(EthernetFrame frame) {
Ipv4Packet packet = Ipv4Packet.parse(frame.getData());
packet.setL2Frame(frame);
if (logger.isDebugEnabled())
logger.debug(packet.toString());
// (DF = 1) OR (It's Last fragment and FragmentOffset == 0)
if ((packet.getFlags() & 0x02) == 2 || ((packet.getFlags() & 0x07) == 0 && packet.getFragmentOffset() == 0)) {
// After, packet -> TCP
dispatch(packet);
} else {
Ipv4Packet reassembled = reassembler.tryReassemble(packet);
if (reassembled != null) {
dispatch(reassembled);
}
}
reassembler.drop();
}
private void dispatch(Ipv4Packet packet) {
// dispatch packet for specific protocol
dispatchProtocol(packet.getProtocol(), packet);
// dispatch packet for all
dispatchProtocol(0, packet);
}
private void dispatchProtocol(int protocol, Ipv4Packet packet) {
// callback.onReceived(packet);
Set<IpProcessor> processors = callbacks.get(protocol);
if (processors != null)
for (IpProcessor processor : processors)
processor.process(packet);
packet = null;
}
}