File capture extends the basic Capture interface and adds several capabilites which can only be done with files, as opposed to live captures for example. You can modify the contents of the file using FileCapture API and its supporting interface. You also have access to lower level API which works more closely with the structure of the file, such as records. At this lower level some knowledge of the file structure is neccessary and is explained in various API documentation sections. The file structure is still fairely abstracted and you may continue to work with generic records instead of specified ones.
Capture files contain network packet data captured from a network interface and stored in the file. The FileCapture interface provides an abstraction to the possible formats for capture files.
FileCapture extends the standard Capture interface and adds several methods that provide file related information.
RecordIterator<BlockRecord> i = fileCapture.getBlockRecordIterator(); if (i.hasNext() == false) { return; } BlockRecord block = i.next();All capture files utilize a similar format that there is atleast 1 block record which contains 0 or more data records. Data records are typically packet records. There can also be other record types which hold various meta information such as counters and properties.
RecordIterator<BlockRecord> blocks = fileCapture.getBlockRecordIterator(); while (blocks.hasNext() { BlockRecord block = blocks.next(); RecordIterator<DataRecord> i = block.getRecordIterator(); while (i.hasNext()) { DataRecord record = i.next(); System.out.printf("Record type=%s", record.getRecordType().toString()); } }The reason you aquire the block as an iterator is the certain formats have more than one block in the file. Most only have 1 though, so if you know that you are going to be working with a PCAP or SNOOP file, you can simply just aquire the block record immediately without putting everything in a loop. Notice that this extra level of inderection with the Block records is only neccessary when accessing records. The PacketIterator returns and manipulates packet records no matter which block they physicaly reside. You aquire the PacketIterator directly from the FileCapture.
try { PacketIterator<FilePacket> i = fileCapture.getPacketIterator(); while (i.hasNext()) { FilePacket packet = i.next(); System.out.println(packet.toString()); } } catch (IOException e) { e.printStackTrace(); }or the more compact Java 5 version:
try { for (FilePacket packet: fileCapture) { System.out.println(packet.toString()); } catch (IORuntimeException e) { e.ioException().printStackTrace(); }Notice that the second version throws IORuntimeException while the first throws the plain old IOException if any IO errors are encountered. This is because the normal java.util.Iterator and java.lang.Iterable interfaces do not provide a way to allow and applications throw any exceptions besides runtime exceptions. You still need to surround your loops around an iterator with try/catch statements in order to catch any IO errors thrown as a IORuntimeException.
Another way to access packets within a capture file is using the CaptureIndexer interface. The indexer provides a type of a List view of all the packets within the capture file. You use indexes to access a specific packet found within the file. Use the getPacketIndexer method to aquire a reference to an indexer of all the packets within the file.
The indexer only provides a view of the file, its typically not able to load all packets into memory from a file as some capture files can be very large. So the indexer pulls packets in and out of memory as neccessary when requested. For efficiency is goes a lot of caching of packets using SoftReferences. You must keep in mind, that any operation on the packet indexer may result in an IO operation, this has a performance and resource impact.
Both methods of accessing packets and records provide methods for modifying the capture file. Packets and records can be removed, switched, replaced and inserted anywhere within the file. All changes are first stored in memory and at certain points flushed to physical medium which is when the backend file gets physically modified. At anytime you can call on undoAllChanges method which discards all changes that have not been flushed and reverts to the original state of the file. If any changes had already been flushed to the file, those changes are not undone. @author Mark Bednarczyk @author Sly Technologies, Inc.
|
|
|
|
|
|