/*
* Copyright (C) 2010 Alexander Kolosov
*
* This file is part of FlowBrook.
*
* FlowBrook is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* FlowBrook 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with FlowBrook. If not, see <http://www.gnu.org/licenses/>
*/
package ru.petrsu.akolosov.flowbrook.flowtools;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.Date;
import ru.petrsu.akolosov.flowbrook.FlowRecord;
import ru.petrsu.akolosov.flowbrook.FlowRecordIterator;
import ru.petrsu.akolosov.flowbrook.FlowRecordPool;
import ru.petrsu.akolosov.flowbrook.FlowSource;
import ru.petrsu.akolosov.flowbrook.FlowSourceException;
/**
*
* @author Alexander Kolosov
*/
final class FlowToolsSource implements FlowSource {
/* OxCF10 is a magic sequence of flow-tools captured files */
private final static short MAGIC_NUMBER = (short) 0xCF10;
/* Generic header length is magic number (2) + byte order (1) + stream version (1) + data offset (4) */
final static int GENERIC_HEADER_LENGTH = 4;
private int streamVersion;
private FlowToolsInput ftInput;
private FlowToolsHeader ftHeader;
FlowToolsSource(FlowToolsInput ftInput) throws IOException, FlowToolsException {
this.ftInput = ftInput;
processHeader();
}
private void processHeader() throws IOException, FlowToolsException {
ByteOrder byteOrder;
int dataOffset;
ByteBuffer bb = ByteBuffer.allocate(GENERIC_HEADER_LENGTH);
ftInput.open();
if (ftInput.read(bb) < bb.limit())
throw new FlowToolsException("Short read of generic header.");
/* Check magic sequence */
if (MAGIC_NUMBER != bb.getShort())
throw new FlowToolsException("Bad magic number.");
/* Parse byte order */
byteOrder = determineByteOrder(bb.get());
bb.order(byteOrder);
/* Parse stream version */
streamVersion = bb.get();
if ( !(streamVersion == 1 || streamVersion == 3) )
throw new UnsupportedOperationException("Only stream format version 1 and 3 is supported");
if (streamVersion == 1) { /* stream version 1 */
ftHeader = new FlowToolsVer1Header(ftInput, byteOrder);
} else { /* stream version 3 */
ftHeader = new FlowToolsVer3Header(ftInput, byteOrder);
}
ftHeader.process();
ftInput.close();
}
private ByteOrder determineByteOrder(byte o) throws FlowToolsException {
if (o == 1)
return ByteOrder.LITTLE_ENDIAN;
else if (o == 2)
return ByteOrder.BIG_ENDIAN;
throw new FlowToolsException("Can't determine byte order.");
}
protected int getDataOffset() {
return GENERIC_HEADER_LENGTH + ftHeader.getHeaderSize();
}
protected FTSRecordProcessor getRecordProcessor(FlowRecordPool pool) {
return FTSRecordProcessor.getInstance(ftHeader, pool);
}
public FlowRecordIterator getRecordIterator(FlowRecordPool pool) throws FlowSourceException {
try {
return ftInput.getRecordIterator(getRecordProcessor(pool), getDataOffset());
} catch (IOException ex) {
throw new FlowSourceException(ex);
}
}
public Date getFirstFlowTime() {
return ftHeader.getFirstFlowTime();
}
public Date getLastFlowTime() {
return ftHeader.getLastFlowTime();
}
public long getFlowsCount() {
return ftHeader.getFlowCount();
}
public String getIdentity() {
return ftInput.getIdentity();
}
public FlowRecordIterator getRecordIterator() throws FlowSourceException {
return getRecordIterator(new FlowRecordPool());
}
}