package com.opensoc.parsing;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;
import com.opensoc.helpers.topology.ErrorGenerator;
import com.opensoc.parsing.parsers.PcapParser;
import com.opensoc.pcap.PacketInfo;
import backtype.storm.generated.Grouping;
import backtype.storm.task.OutputCollector;
import backtype.storm.task.TopologyContext;
import backtype.storm.topology.IRichBolt;
import backtype.storm.topology.OutputFieldsDeclarer;
import backtype.storm.tuple.Fields;
import backtype.storm.tuple.Tuple;
import backtype.storm.tuple.Values;
/**
* The Class PcapParserBolt parses each input tuple and emits a new tuple which
* contains the information (header_json,group_key,pcap_id, timestamp, pcap) as
* defined in the output schema.
*
* @author sheetal
* @version $Revision: 1.0 $
*/
public class PcapParserBolt implements IRichBolt {
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -1449830233777209255L;
/** The Constant LOG. */
private static final Logger LOG = Logger.getLogger(PcapParserBolt.class);
/** The collector. */
private OutputCollector collector = null;
/** The conf. */
@SuppressWarnings("rawtypes")
private Map conf;
/** The number of chars to use for shuffle grouping. */
@SuppressWarnings("unused")
private int numberOfCharsToUseForShuffleGrouping = 4;
/** The divisor to convert nanos to expected time precision. */
private long timePrecisionDivisor = 1L;
// HBaseStreamPartitioner hBaseStreamPartitioner = null ;
/**
* The Constructor.
*/
public PcapParserBolt() {
}
public PcapParserBolt withTsPrecision(String tsPrecision) {
if (tsPrecision.equalsIgnoreCase("MILLI")) {
//Convert nanos to millis
LOG.info("Configured for MILLI, setting timePrecisionDivisor to 1000000L" );
timePrecisionDivisor = 1000000L;
} else if (tsPrecision.equalsIgnoreCase("MICRO")) {
//Convert nanos to micro
LOG.info("Configured for MICRO, setting timePrecisionDivisor to 1000L" );
timePrecisionDivisor = 1000L;
} else if (tsPrecision.equalsIgnoreCase("NANO")) {
//Keep nano as is.
LOG.info("Configured for NANO, setting timePrecisionDivisor to 1L" );
timePrecisionDivisor = 1L;
} else {
LOG.info("bolt.parser.ts.precision not set. Default to NANO");
timePrecisionDivisor = 1L;
}
return this;
}
/*
* (non-Javadoc)
*
* @see backtype.storm.topology.IComponent#declareOutputFields(backtype.storm
* .topology.OutputFieldsDeclarer)
*/
public void declareOutputFields(OutputFieldsDeclarer declarer) {
declarer.declareStream("message", new Fields("key", "message"));
//declarer.declareStream("pcap_index_stream", new Fields("index_json", "pcap_id"));
declarer.declareStream("pcap_header_stream", new Fields("header_json", "pcap_id"));
declarer.declareStream("pcap_data_stream", new Fields("pcap_id", "timestamp", "pcap"));
declarer.declareStream("error", new Fields("error"));
}
/*
* (non-Javadoc)
*
* @see backtype.storm.topology.IComponent#getComponentConfiguration()
*/
/**
* Method getComponentConfiguration.
*
*
*
* @return Map<String,Object> * @see
* backtype.storm.topology.IComponent#getComponentConfiguration() * @see
* backtype.storm.topology.IComponent#getComponentConfiguration() * @see
* backtype.storm.topology.IComponent#getComponentConfiguration()
*/
public Map<String, Object> getComponentConfiguration() {
return null;
}
/*
* (non-Javadoc)
*
* @see backtype.storm.task.IBolt#prepare(java.util.Map,
* backtype.storm.task.TopologyContext, backtype.storm.task.OutputCollector)
*/
public void prepare(Map stormConf, TopologyContext context, OutputCollector collector) {
this.collector = collector;
this.conf = stormConf;
if (conf.containsKey("bolt.parser.num.of.key.chars.to.use.for.shuffle.grouping")) {
this.numberOfCharsToUseForShuffleGrouping = Integer.valueOf(conf.get(
"bolt.parser.num.of.key.chars.to.use.for.shuffle.grouping").toString());
}
Grouping._Fields a;
// hBaseStreamPartitioner = new HBaseStreamPartitioner(
// conf.get("bolt.hbase.table.name").toString(),
// 0,
// Integer.parseInt(conf.get("bolt.hbase.partitioner.region.info.refresh.interval.mins").toString()))
// ;
// hBaseStreamPartitioner.prepare();
}
/**
* Processes each input tuple and emits tuple which holds the following
* information about a network packet : group_key : first 3 digits of the
* pcap_id pcap_id : generated from network packet srcIp, dstIp, protocol,
* srcPort, dstPort header_json : contains global header, ipv4 header, tcp
* header(if the n/w protocol is tcp), udp header (if the n/w protocol is udp)
* timestamp : the n/w packet capture timestamp pcap : tuple in binary array.
*
* @param input
* Tuple
* @see backtype.storm.task.IBolt#execute(Tuple)
*/
@SuppressWarnings("unchecked")
public void execute(Tuple input) {
// LOG.debug("In PcapParserBolt bolt: Got tuple " + input);
// LOG.debug("Got this pcap : " + new String(input.getBinary(0)));
List<PacketInfo> packetInfoList = null;
try {
packetInfoList = PcapParser.parse(input.getBinary(0));
if (packetInfoList != null) {
for (PacketInfo packetInfo : packetInfoList) {
String string_pcap = packetInfo.getJsonIndexDoc();
Object obj=JSONValue.parse(string_pcap);
JSONObject header=(JSONObject)obj;
JSONObject message = new JSONObject();
//message.put("key", packetInfo.getKey());
message.put("message", header);
collector.emit("message", new Values(packetInfo.getKey(), message));
//collector.emit("pcap_index_stream", new Values(packetInfo.getJsonIndexDoc(), packetInfo.getKey()));
collector.emit("pcap_header_stream", new Values(packetInfo.getJsonDoc(), packetInfo.getKey()));
collector.emit("pcap_data_stream", new Values(packetInfo.getKey(),
packetInfo.getPacketTimeInNanos() / timePrecisionDivisor,
input.getBinary(0)));
// collector.emit(new Values(packetInfo.getJsonDoc(), packetInfo
// .getKey().substring(0, numberOfCharsToUseForShuffleGrouping),
// packetInfo.getKey(), (packetInfo.getPacketHeader().getTsSec()
// * secMultiplier + packetInfo.getPacketHeader().getTsUsec()
// * microSecMultiplier), input.getBinary(0)));
}
}
} catch (Exception e) {
collector.fail(input);
e.printStackTrace();
LOG.error("Exception while processing tuple", e);
JSONObject error = ErrorGenerator.generateErrorMessage(
"Alerts problem: " + input.getBinary(0), e);
collector.emit("error", new Values(error));
return;
}
collector.ack(input);
}
/*
* (non-Javadoc)
*
* @see backtype.storm.task.IBolt#cleanup()
*/
public void cleanup() {
// TODO Auto-generated method stub
}
}