changeset 517:36d1920e57f0

PcapScanner
author Devel 1
date Mon, 21 Aug 2017 17:13:41 +0200
parents 8c11c2e8a23c
children 3ca6df6dd9cb
files stress-tester-reporter/pom.xml stress-tester/src/main/java/com/passus/st/ParseException.java stress-tester/src/main/java/com/passus/st/PcapReporter.java stress-tester/src/main/java/com/passus/st/PcapScanner.java stress-tester/src/test/java/com/passus/st/PcapScannerTest.java stress-tester/src/test/java/com/passus/st/emitter/nio/NioEmitterTest.java
diffstat 6 files changed, 246 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/stress-tester-reporter/pom.xml	Mon Aug 21 13:48:38 2017 +0200
+++ b/stress-tester-reporter/pom.xml	Mon Aug 21 17:13:41 2017 +0200
@@ -37,8 +37,8 @@
         <!--
           avro-ipc depends on Selvlet API 2.5
           wiremock depends on Servlet API 3.1
-          Selvlet API version used in test depends on order of classpath elements
-          if stress-tester-reporter is higher than wiremock, some wiremock tests will fail.
+          Selvlet API version used in test depends on order of classpath elements.
+          If stress-tester-reporter is higher than wiremock, some wiremock tests will fail.
           So we must exclude v2.5 and explicitly add v3.1
         -->
 
--- a/stress-tester/src/main/java/com/passus/st/ParseException.java	Mon Aug 21 13:48:38 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,20 +0,0 @@
-package com.passus.st;
-
-/**
- *
- * @author Mirosław Hawrot
- */
-public class ParseException extends RuntimeException {
-
-    public ParseException() {
-        super();
-    }
-
-    public ParseException(String message) {
-        super(message);
-    }
-
-    public ParseException(String message, Throwable cause) {
-        super(message, cause);
-    }
-}
--- a/stress-tester/src/main/java/com/passus/st/PcapReporter.java	Mon Aug 21 13:48:38 2017 +0200
+++ b/stress-tester/src/main/java/com/passus/st/PcapReporter.java	Mon Aug 21 17:13:41 2017 +0200
@@ -2,6 +2,7 @@
 
 import com.passus.data.ByteBuff;
 import com.passus.data.HeapByteBuff;
+import com.passus.net.PortRangeSet;
 import com.passus.net.http.HttpMessage;
 import com.passus.net.http.HttpMessageEncoder;
 import com.passus.net.http.HttpRequest;
@@ -39,6 +40,7 @@
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.DefaultParser;
 import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
@@ -62,6 +64,11 @@
                 .build()
         );
 
+        options.addOption(option("hp", "httpPorts").desc("Specify HTTP ports in input file (default: 80, 8080)")
+                .hasArg().argName("ports")
+                .build()
+        );
+
         options.addOption(option("ri", "reporterIp").desc("Reporter ip address.")
                 .required()
                 .hasArg().argName("ip")
@@ -81,7 +88,6 @@
             if (cl.hasOption("l")) {
                 logLevel = cl.getOptionValue("l");
             }
-
             Log4jConfigurationFactory.enableFactory(logLevel);
 
             InetAddress addr = InetAddress.getByName(cl.getOptionValue("ri"));
@@ -94,6 +100,17 @@
             eventSrc.setPcapFile(clArgs[0]);
             eventSrc.setAllowPartialSession(cl.hasOption("ps"));
             eventSrc.setCollectMetrics(true);
+
+            if (cl.hasOption("hp")) {
+                PortRangeSet portsRanges = eventSrc.getPortsRange();
+                portsRanges.clear();
+
+                String[] ports = cl.getOptionValues("hp");
+                for (String port : ports) {
+                    portsRanges.add(port);
+                }
+            }
+
             ScheduledMetricsCollector collector = new ScheduledMetricsCollector();
             SummrizeMetricsCollectionHandler summMetricsHandler = new SummrizeMetricsCollectionHandler();
             if (cl.hasOption("wm")) {
@@ -134,7 +151,7 @@
             collector.flush(true);
 
             printMetrics(summMetricsHandler.getMetrics(), startTime);
-        } catch (org.apache.commons.cli.ParseException e) {
+        } catch (ParseException e) {
             System.out.println(e.getMessage());
             printHelp(options);
         } catch (Exception e) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/main/java/com/passus/st/PcapScanner.java	Mon Aug 21 17:13:41 2017 +0200
@@ -0,0 +1,186 @@
+package com.passus.st;
+
+import com.passus.net.http.HttpMessage;
+import com.passus.net.http.URL;
+import static com.passus.st.Main.printHelp;
+import com.passus.st.client.Event;
+import com.passus.st.client.EventHandler;
+import com.passus.st.client.http.HttpSessionPayloadEvent;
+import com.passus.st.source.PcapSessionEventSource;
+import static com.passus.st.utils.CliUtils.option;
+import java.net.MalformedURLException;
+import java.util.HashSet;
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.DefaultParser;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+/**
+ *
+ * @author mikolaj.podbielski
+ */
+public class PcapScanner implements EventHandler {
+
+    private static final int MOD = 100;
+
+    private final HashSet<String> values = new HashSet<>();
+    private final Extractor extractor;
+    private int count;
+
+    public PcapScanner(Extractor extractor) {
+        this.extractor = extractor;
+    }
+
+    public HashSet<String> getValues() {
+        return values;
+    }
+
+    public void scan(String path, int port) throws InterruptedException {
+        scan(path, port, true);
+    }
+
+    public void scan(String path, int port, boolean allowPartialSession) throws InterruptedException {
+        System.out.println("scanning " + path);
+        PcapSessionEventSource eventSrc = new PcapSessionEventSource();
+        eventSrc.setPcapFile(path);
+        eventSrc.setAllowPartialSession(true);
+        eventSrc.getPortsRange().add(port);
+        eventSrc.setHandler(this);
+        eventSrc.start();
+
+        Thread.sleep(100);
+        while (eventSrc.isWorking()) {
+            Thread.sleep(100);
+        }
+        eventSrc.stop();
+    }
+
+    @Override
+    public void handle(Event event) {
+        if (event instanceof HttpSessionPayloadEvent) {
+            Object extracted = extractor.extract((HttpSessionPayloadEvent) event);
+            if (extracted != null) {
+                values.add(extracted.toString());
+//                System.out.println(extracted.toString());
+            }
+            ++count;
+            if (count % MOD == 0) {
+                System.out.println("payloads scanned: " + count);
+            }
+        }
+    }
+
+    public interface Extractor {
+
+        public Object extract(HttpSessionPayloadEvent event);
+    }
+
+    public interface URLExtractor {
+
+        public Object extract(URL url);
+    }
+
+    public interface MessageExtractor {
+
+        public Object extarct(HttpMessage msg);
+    }
+
+    public static void main(String... args) {
+        AppUtils.registerAll();
+        final Options options = new Options();
+
+        options.addOption(option("l", "logLevel").desc("Log level.")
+                .hasArg().argName("level")
+                .build()
+        );
+
+        options.addOption(option("ips", "ignorePartialSession").desc("Ignore partial sessions.")
+                .hasArg(false)
+                .build()
+        );
+
+        options.addOption(option("e", "extractor").desc("Extraction expression, default resph:Set-Cookie")
+                .hasArg().argName("message")
+                .build()
+        );
+
+        try {
+            CommandLine cl = new DefaultParser().parse(options, args);
+            String[] clArgs = cl.getArgs();
+            if (clArgs.length != 1) {
+                System.err.println("Pcap file required.");
+                printHelp(options);
+                return;
+            }
+
+            String logLevel = "error";
+            if (cl.hasOption("l")) {
+                logLevel = cl.getOptionValue("l");
+            }
+            Log4jConfigurationFactory.enableFactory(logLevel);
+
+            int port = 80;
+            if (cl.hasOption("hp")) {
+                port = Integer.parseInt(cl.getOptionValue("hp"));
+            }
+
+            final String defaultExtractor = "respHdr:Set-Cookie";
+            String extractorSpec = cl.getOptionValue("e", defaultExtractor);
+            Extractor extractor = createExtractor(extractorSpec);
+
+            PcapScanner scanner = new PcapScanner(extractor);
+            scanner.scan(clArgs[0], port, !cl.hasOption("ips"));
+
+            System.out.println("\n --== Scanned values:");
+            scanner.getValues().forEach(System.out::println);
+        } catch (ParseException e) {
+            System.out.println(e.getMessage());
+            printHelp(options);
+        } catch (Exception e) {
+            e.printStackTrace(System.err);
+        }
+    }
+
+    private static Object urlExtract(HttpSessionPayloadEvent event, URLExtractor ue) {
+        try {
+            return ue.extract(URL.parse(event.getRequest().getUrl()));
+        } catch (MalformedURLException ex) {
+            ex.printStackTrace(System.err);
+            return null;
+        }
+    }
+    
+//    private static Object msgExtract(HttpMessage event, MessageExtractor me) {
+//        return 
+//    }
+
+    private static Extractor createExtractor(String spec) throws ParseException {
+        int idx = spec.indexOf(':');
+        String type;
+        String arg;
+        if (idx < 0) {
+            type = spec;
+            arg = null;
+        } else {
+            type = spec.substring(0, idx);
+            arg = spec.substring(idx + 1);
+        }
+
+        switch (type) {
+            case "url":
+                return (e) -> e.getRequest().getUrl();
+            case "path":
+                return (e) -> urlExtract(e, (URL url) -> url.getPath());
+            case "query":
+                return (e) -> urlExtract(e, (URL url) -> url.getQuery());
+//            case "header":
+            //TODO
+            case "reqHdr":
+                return (e) -> e.getRequest().getHeaders().get(arg);
+            case "respHdr":
+                return (e) -> e.getResponse().getHeaders().get(arg);
+            default:
+                throw new ParseException("Invalid extractor spec: " + spec);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/stress-tester/src/test/java/com/passus/st/PcapScannerTest.java	Mon Aug 21 17:13:41 2017 +0200
@@ -0,0 +1,37 @@
+package com.passus.st;
+
+import com.passus.net.http.HttpHeaders;
+import org.apache.logging.log4j.Level;
+import org.testng.annotations.Test;
+
+/**
+ *
+ * @author mikolaj.podbielski
+ */
+public class PcapScannerTest {
+
+    public static void main(String[] args) {
+        String ST = "C:\\Users\\mikolaj.podbielski\\Desktop\\hg\\stress-tester\\stress-tester\\";
+        PcapScanner.main(ST + "ndiag.pcap");
+    }
+
+    @Test
+    public void testScanAll() throws InterruptedException {
+        Log4jConfigurationFactory.enableFactory(Level.INFO);
+        PcapScanner.Extractor extractor = (event) -> event.getResponse().getHeaders().get(HttpHeaders.SET_COOKIE);
+        PcapScanner scanner = new PcapScanner(extractor);
+        scanAll(scanner);
+        System.out.println("\n --== Scanned values:");
+        scanner.getValues().forEach(System.out::println);
+    }
+
+    private static void scanAll(PcapScanner scanner) throws InterruptedException {
+        String ST = "C:\\Users\\mikolaj.podbielski\\Desktop\\hg\\stress-tester\\stress-tester\\";
+        scanner.scan(ST + "ndiag.pcap", 8080);
+        scanner.scan(ST + "netim.pcap", 9190);
+        scanner.scan(ST + "arx.pcap", 80);
+        scanner.scan(ST + "http5b1.pcap", 80);
+        scanner.scan(ST + "basic_digest.pcap", 80);
+    }
+
+}
--- a/stress-tester/src/test/java/com/passus/st/emitter/nio/NioEmitterTest.java	Mon Aug 21 13:48:38 2017 +0200
+++ b/stress-tester/src/test/java/com/passus/st/emitter/nio/NioEmitterTest.java	Mon Aug 21 17:13:41 2017 +0200
@@ -127,7 +127,8 @@
 
         assertEquals(EventType.CHANNEL_INACTIVE, handler.get(index++).getType());
         assertEquals(EventType.CHANNEL_UNREGISTERED, handler.get(index++).getType());
-        assertTrue(resContentBuff.toString().endsWith(content));
+        String responseContent = resContentBuff.toString();
+        assertTrue(responseContent.endsWith(content));
     }
 
     @Test(enabled = true)