From c5a878028f60c4ab095e78ee7a1bfbd1bd08573a Mon Sep 17 00:00:00 2001 From: Mike Bailey <jmbailey@nps.edu> Date: Wed, 14 Aug 2019 14:17:56 -0700 Subject: [PATCH] Make validator class --- .../nps/moves/dis7/util/DisNetworking.java | 74 +++-- .../dis7/util/playerrecorder/Player.java | 2 +- .../dis7/util/playerrecorder/Recorder.java | 10 +- .../playerrecorder/ValidationPdusMakerV1.java | 281 ++++++++++++++++++ validation/README.md | 14 + validation/dis7-v1.0.dislog | 74 +++++ 6 files changed, 418 insertions(+), 37 deletions(-) create mode 100644 src/edu/nps/moves/dis7/util/playerrecorder/ValidationPdusMakerV1.java create mode 100644 validation/README.md create mode 100644 validation/dis7-v1.0.dislog diff --git a/src/edu/nps/moves/dis7/util/DisNetworking.java b/src/edu/nps/moves/dis7/util/DisNetworking.java index 611bfd4a3f..72f67bd38f 100644 --- a/src/edu/nps/moves/dis7/util/DisNetworking.java +++ b/src/edu/nps/moves/dis7/util/DisNetworking.java @@ -2,7 +2,6 @@ * Copyright (c) 2008-2019, MOVES Institute, Naval Postgraduate School. All rights reserved. * This work is licensed under the BSD open source license, available at https://www.movesinstitute.org/licenses/bsd.html */ - package edu.nps.moves.dis7.util; import edu.nps.moves.dis7.Pdu; @@ -18,12 +17,18 @@ import java.util.Enumeration; */ public class DisNetworking { - public class BuffAndLength { - public byte[] buff; public int length; - public BuffAndLength(byte[]buff,int length) - {this.buff=buff;this.length=length;} + public class BuffAndLength + { + public byte[] buff; + public int length; + + public BuffAndLength(byte[] buff, int length) + { + this.buff = buff; + this.length = length; + } } - + private int DIS_PORT = 3000; private String MCAST_GROUP = "230.0.0.0"; private static final int MAX_DIS_PDU_SIZE = 8192; @@ -38,65 +43,68 @@ public class DisNetworking DIS_PORT = port; MCAST_GROUP = mcastgroup; } - + public int getPort() { return DIS_PORT; } - + public String getIp() { return MCAST_GROUP; } - + public Pdu receivePdu() throws IOException { PduFactory pduFactory = new PduFactory(); BuffAndLength blen = receiveRawPdu(); return pduFactory.createPdu(blen.buff); } - + public BuffAndLength receiveRawPdu() throws IOException { MulticastSocket socket; DatagramPacket packet; - PduFactory pduFactory = new PduFactory(); socket = new MulticastSocket(DIS_PORT); InetAddress maddr = InetAddress.getByName(MCAST_GROUP); socket.setNetworkInterface(findIp4Interface()); socket.joinGroup(maddr); - byte buffer[] = new byte[MAX_DIS_PDU_SIZE]; packet = new DatagramPacket(buffer, buffer.length); - - System.out.println("Listening on "+MCAST_GROUP+":"+DIS_PORT+" if:"+socket.getNetworkInterface().getDisplayName()); - socket.receive(packet); //blocks here waiting for next DIS pdu to be received on broadcast IP and specified port + //System.out.println("Listening on " + MCAST_GROUP + ":" + DIS_PORT + " if:" + socket.getNetworkInterface().getDisplayName()); + socket.receive(packet); //blocks here waiting for next DIS pdu to be received on broadcast IP and specified port //System.out.println("packet received from " + packet.getSocketAddress()); + socket.close(); - return new BuffAndLength(packet.getData(),packet.getLength()); + return new BuffAndLength(packet.getData(), packet.getLength()); } - + public void sendPdu(Pdu pdu) throws IOException { - // turn object into byte stream - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - DataOutputStream dos = new DataOutputStream(baos); - pdu.marshal(dos); - byte[] data = baos.toByteArray(); - - MulticastSocket msocket = new MulticastSocket(); - InetAddress maddr = InetAddress.getByName(MCAST_GROUP); - // load byte buffer into packet and send - DatagramPacket packet = new DatagramPacket(data, data.length, maddr, DIS_PORT); - msocket.setNetworkInterface(findIp4Interface()); - msocket.send(packet); - - msocket.close(); - System.out.println("sent to "+maddr.getHostAddress()+":"+DIS_PORT); + // turn object into byte stream + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream dos = new DataOutputStream(baos); + pdu.marshal(dos); + + sendRawPdu(baos.toByteArray()); } - + + public void sendRawPdu(byte[] data) throws IOException + { + MulticastSocket msocket = new MulticastSocket(); + InetAddress maddr = InetAddress.getByName(MCAST_GROUP); + + // load byte buffer into packet and send + DatagramPacket packet = new DatagramPacket(data, data.length, maddr, DIS_PORT); + msocket.setNetworkInterface(findIp4Interface()); + msocket.send(packet); + + msocket.close(); + //System.out.println("sent to " + maddr.getHostAddress() + ":" + DIS_PORT); + } + /* find proper interface */ private static NetworkInterface findIp4Interface() throws SocketException { diff --git a/src/edu/nps/moves/dis7/util/playerrecorder/Player.java b/src/edu/nps/moves/dis7/util/playerrecorder/Player.java index d40116d2e3..ba074eed4f 100644 --- a/src/edu/nps/moves/dis7/util/playerrecorder/Player.java +++ b/src/edu/nps/moves/dis7/util/playerrecorder/Player.java @@ -97,7 +97,7 @@ public class Player } byte[] buffer = decdr.decode(sa[1]); - //Pdu pdu = pduFactory.createPdu(buffer); + DatagramPacket packet = new DatagramPacket(buffer, buffer.length, addr, port); dsock.send(packet); diff --git a/src/edu/nps/moves/dis7/util/playerrecorder/Recorder.java b/src/edu/nps/moves/dis7/util/playerrecorder/Recorder.java index 26bdd88f66..b887daa2cd 100644 --- a/src/edu/nps/moves/dis7/util/playerrecorder/Recorder.java +++ b/src/edu/nps/moves/dis7/util/playerrecorder/Recorder.java @@ -43,13 +43,12 @@ public class Recorder implements PduReceiver @Override public void receivePdu(byte[] buff, int len) { - //Pdu pdu = makePdu(type,buff,len); long packetRcvNanoTime = System.nanoTime(); if (startNanoTime == null) startNanoTime = packetRcvNanoTime; byte[] timeAr = Longs.toByteArray(packetRcvNanoTime - startNanoTime); - System.out.println("wrote time "+(packetRcvNanoTime - startNanoTime)); + //System.out.println("wrote time "+(packetRcvNanoTime - startNanoTime)); sb.setLength(0); sb.append(encdr.encodeToString(timeAr)); @@ -86,7 +85,12 @@ public class Recorder implements PduReceiver System.out.println("IOException closing file: " + ex.getMessage()); } } - + + public String getLogFile() + { + return logFile.getAbsolutePath(); + } + private void writeHeader() throws IOException { String template = "Beginning of DIS capture file, %s."; diff --git a/src/edu/nps/moves/dis7/util/playerrecorder/ValidationPdusMakerV1.java b/src/edu/nps/moves/dis7/util/playerrecorder/ValidationPdusMakerV1.java new file mode 100644 index 0000000000..0b52536d61 --- /dev/null +++ b/src/edu/nps/moves/dis7/util/playerrecorder/ValidationPdusMakerV1.java @@ -0,0 +1,281 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package edu.nps.moves.dis7.util.playerrecorder; + +import edu.nps.moves.dis7.enumerations.Country; +import edu.nps.moves.dis7.util.DisNetworking; +import edu.nps.moves.dis7.util.PduFactory; +import edu.nps.moves.dis7.*; +import java.io.File; +import java.io.IOException; +import java.nio.file.Path; + +/** + * ValidationPdusMakerV1.java created on Aug 14, 2019 + * MOVES Institute Naval Postgraduate School, Monterey, CA, USA www.nps.edu + * <p> + * This class produces and sends to the net a "standard" stream of Pdus, which may then be captured and + * saved by an instance of @see edu.nps.moves.dis7.util.playerrecorder.Recorder. After future changes + * to the DIS library, another run of this class may be done and an instance of @see edu.nps.moves.dis7.util.playerrecorder.LogCompare may + * be used to detect differences. + * <p> + * The main method here takes 1. a directory name, and 2. a file name, in that order. File type ".dislog" will be appended. + * If run with an argument count different that 2, the default values of "validatorOut" and "validationLog.txt" are used. + * + * @author Mike Bailey, jmbailey@nps.edu + * @version $Id$ + */ +public class ValidationPdusMakerV1 +{ + //@formatter:off + public static final Country COUNTRY_V1 = Country.BARBADOS_BRB; + public static final byte EXERCISEID_V1 = (byte) 0x11; + public static final short SITEID_V1 = (short) 0x2222; + public static final short APPLICATIONID_V1 = (short) 0x3333; + public static final boolean USEABSOLUTETIME_V1 = true; + //@formatter:on + + PduFactory factory; + DisNetworking disnet; + Recorder recorder; + /** + * + * @param dir directory to save pdu log file + * @param fn filename of log file, will append an integer to prevent overwriting + * @return exit indicator ala @see java.lang.System#exit . + * @throws java.lang.Exception from network write or pdu creation + */ + public int run(String dir, String fn) throws Exception + { + File dirfile = new File(dir); + dirfile.mkdirs(); + Path dirpath = dirfile.toPath(); + + /* PduFactory is initialized with country, exerciseId, siteId, applicationId and a boolean specifying absolute DIS time use. + Those values are automatically inserted by PduFactory into those created pdus which use them. The time field of the DIS pdu + is set to the time of creation of the instance. All those may be overridden in the pdu object. Also, multiple PduFactory instances + may co-exist containing alternate defaults. + + The values here are used for creating the validation pdu log, and must also be used for future comparison + */ + factory = new PduFactory(COUNTRY_V1, EXERCISEID_V1, SITEID_V1, APPLICATIONID_V1, USEABSOLUTETIME_V1); + disnet = new DisNetworking(); + recorder = new Recorder(dirpath,fn); + + // Start a thread to receive and record pdus; this is a datagram socket and is non-interruptible; thread will go away on Sys exit + Thread receiverThrd = new Thread(() -> { + int count = 1; + System.out.println("Packet reception count"); + while (true) { + try { + DisNetworking.BuffAndLength blen = disnet.receiveRawPdu(); + //System.out.println("" + count++ + " Got pdu from DisNetworking"); + recorder.receivePdu(blen.buff, blen.length); + System.out.println("\r"+count++); + } + catch (IOException ex) { + System.err.println("Exception receiving Pdu: " + ex.getLocalizedMessage()); + } + } + }); + receiverThrd.setPriority(Thread.NORM_PRIORITY); + receiverThrd.setDaemon(true); + receiverThrd.start(); + + /* The standard validation log consists of one of each defined pdu from 1, ENTITY_STATE, to 72, ATTRIBUTE. There is no pdu of type 0. + This sequence of statements unnecessarily creates 72 instance variables. Those are intended to make it easy to customize the contents of + the created pdus. It would be advisable to fill out more content in the pdus to ensure the correctness of the pdu in the net packet. + */ + EntityStatePdu pdu1 = factory.makeEntityStatePdu(); //1 + sendPdu(pdu1); + FirePdu pdu2 = factory.makeFirePdu(); //2 + sendPdu(pdu2); + DetonationPdu pdu3 = factory.makeDetonationPdu(); //3 + sendPdu(pdu3); + CollisionPdu pdu4 = factory.makeCollisionPdu(); //4 + sendPdu(pdu4); + ServiceRequestPdu pdu5 = factory.makeServiceRequestPdu(); //5 + sendPdu(pdu5); + ResupplyOfferPdu pdu6 = factory.makeResupplyOfferPdu(); //6 + sendPdu(pdu6); + ResupplyReceivedPdu pdu7 = factory.makeResupplyReceivedPdu(); //7 + sendPdu(pdu7); + ResupplyCancelPdu pdu8 = factory.makeResupplyCancelPdu(); //8 + sendPdu(pdu8); + RepairCompletePdu pdu9 = factory.makeRepairCompletePdu(); //9 + sendPdu(pdu9); + RepairResponsePdu pdu10 = factory.makeRepairResponsePdu(); //10 + sendPdu(pdu10); + + CreateEntityPdu pdu11 = factory.makeCreateEntityPdu(); //11 + sendPdu(pdu11); + RemoveEntityPdu pdu12 = factory.makeRemoveEntityPdu(); //12 + sendPdu(pdu12); + StartResumePdu pdu13 = factory.makeStartResumePdu(); //13 + sendPdu(pdu13); + StopFreezePdu pdu14 = factory.makeStopFreezePdu(); //14 + sendPdu(pdu14); + AcknowledgePdu pdu15 = factory.makeAcknowledgePdu(); //15 + sendPdu(pdu15); + ActionRequestPdu pdu16 = factory.makeActionRequestPdu(); //16 + sendPdu(pdu16); + ActionResponsePdu pdu17 = factory.makeActionResponsePdu(); //17 + sendPdu(pdu17); + DataQueryPdu pdu18 = factory.makeDataQueryPdu(); //18 + sendPdu(pdu18); + SetDataPdu pdu19 = factory.makeSetDataPdu(); //19 + sendPdu(pdu19); + DataPdu pdu20 = factory.makeDataPdu(); //20 + sendPdu(pdu20); + + EventReportPdu pdu21 = factory.makeEventReportPdu(); //21 + sendPdu(pdu21); + CommentPdu pdu22 = factory.makeCommentPdu(); //22 + sendPdu(pdu22); + ElectromagneticEmissionPdu pdu23 = factory.makeElectronicEmissionsPdu(); //23 + sendPdu(pdu23); + DesignatorPdu pdu24 = factory.makeDesignatorPdu(); //24 + sendPdu(pdu24); + TransmitterPdu pdu25 = factory.makeTransmitterPdu(); //25 + sendPdu(pdu25); + SignalPdu pdu26 = factory.makeSignalPdu(); //26 + sendPdu(pdu26); + ReceiverPdu pdu27 = factory.makeReceiverPdu(); //27 + sendPdu(pdu27); + IFFPdu pdu28 = factory.makeIffPdu(); //28 + sendPdu(pdu28); + UnderwaterAcousticPdu pdu29 = factory.makeUnderwaterAcousticPdu(); //29 + sendPdu(pdu29); + SEESPdu pdu30 = factory.makeSeesPdu(); //30 + sendPdu(pdu30); + + IntercomSignalPdu pdu31 = factory.makeIntercomSignalPdu(); //31 + sendPdu(pdu31); + IntercomControlPdu pdu32 = factory.makeIntercomControlPdu(); //32 + sendPdu(pdu32); + AggregateStatePdu pdu33 = factory.makeAggregateStatePdu(); //33 + sendPdu(pdu33); + IsGroupOfPdu pdu34 = factory.makeIsGroupOfPdu(); //34 + sendPdu(pdu34); + TransferOwnershipPdu pdu35 = factory.makeTransferOwnershipPdu(); //35 + sendPdu(pdu35); + IsPartOfPdu pdu36 = factory.makeIsPartOfPdu(); //36 + sendPdu(pdu36); + MinefieldStatePdu pdu37 = factory.makeMinefieldStatePdu(); //37 + sendPdu(pdu37); + MinefieldQueryPdu pdu38 = factory.makeMinefieldQueryPdu(); //38 + sendPdu(pdu38); + MinefieldDataPdu pdu39 = factory.makeMinefieldDataPdu(); //39 + sendPdu(pdu39); + MinefieldResponseNACKPdu pdu40 = factory.makeMinefieldResponseNackPdu(); //40 + sendPdu(pdu40); + + EnvironmentalProcessPdu pdu41 = factory.makeEnvironmentalProcessPdu(); //41 + sendPdu(pdu41); + GriddedDataPdu pdu42 = factory.makeGriddedDataPdu(); //42 + sendPdu(pdu42); + PointObjectStatePdu pdu43 = factory.makePointObjectStatePdu(); //43 + sendPdu(pdu43); + LinearObjectStatePdu pdu44 = factory.makeLinearObjectStatePdu(); //44 + sendPdu(pdu44); + ArealObjectStatePdu pdu45 = factory.makeArealObjectStatePdu(); //45 + sendPdu(pdu45); + TSPIPdu pdu46 = factory.makeTspiPdu(); //46 + sendPdu(pdu46); + AppearancePdu pdu47 = factory.makeAppearancePdu(); //47 + sendPdu(pdu47); + ArticulatedPartsPdu pdu48 = factory.makeArticulatedPartsPdu(); //48 + sendPdu(pdu48); + LEFirePdu pdu49 = factory.makeLEFirePdu(); //49 + sendPdu(pdu49); + LEDetonationPdu pdu50 = factory.makeLEDetonationPdu(); //50 + sendPdu(pdu50); + + CreateEntityReliablePdu pdu51 = factory.makeCreateEntityReliablePdu(); //51 + sendPdu(pdu51); + RemoveEntityReliablePdu pdu52 = factory.makeRemoveEntityReliablePdu(); //52 + sendPdu(pdu52); + StartResumeReliablePdu pdu53 = factory.makeStartResumeReliablePdu(); //53 + sendPdu(pdu53); + StopFreezeReliablePdu pdu54 = factory.makeStopFreezeReliablePdu(); //54 + sendPdu(pdu54); + AcknowledgeReliablePdu pdu55 = factory.makeAcknowledgeReliablePdu(); //55 + sendPdu(pdu55); + ActionRequestReliablePdu pdu56 = factory.makeActionRequestReliablePdu(); //56 + sendPdu(pdu56); + ActionResponseReliablePdu pdu57 = factory.makeActionResponseReliablePdu(); //57 + sendPdu(pdu57); + DataQueryReliablePdu pdu58 = factory.makeDataQueryReliablePdu(); //58 + sendPdu(pdu58); + SetDataReliablePdu pdu59 = factory.makeSetDataReliablePdu(); //59 + sendPdu(pdu59); + DataReliablePdu pdu60 = factory.makeDataReliablePdu(); //60 + sendPdu(pdu60); + + EventReportReliablePdu pdu61 = factory.makeEventReportReliablePdu(); //6 + sendPdu(pdu61); + CommentReliablePdu pdu62 = factory.makeCommentReliablePdu(); //6 + sendPdu(pdu62); + RecordReliablePdu pdu63 = factory.makeRecordReliablePdu(); //6 + sendPdu(pdu63); + SetRecordReliablePdu pdu64 = factory.makeSetRecordReliablePdu(); //6 + sendPdu(pdu64); + RecordQueryReliablePdu pdu65 = factory.makeRecordQueryReliablePdu(); //6 + sendPdu(pdu65); + CollisionElasticPdu pdu66 = factory.makeCollisionElasticPdu(); //6 + sendPdu(pdu66); + EntityStateUpdatePdu pdu67 = factory.makeEntityStateUpdatePdu(); //6 + sendPdu(pdu67); + DirectedEnergyFirePdu pdu68 = factory.makeDirectedEnergyFirePdu(); //6 + sendPdu(pdu68); + EntityDamageStatusPdu pdu69 = factory.makeEntityDamageStatusPdu(); //6 + sendPdu(pdu69); + InformationOperationsActionPdu pdu70 = factory.makeInformationOperationsActionPdu(); //70 + sendPdu(pdu70); + + InformationOperationsReportPdu pdu71 = factory.makeInformationOperationsReportPdu(); //71 + sendPdu(pdu71); + AttributePdu pdu72 = factory.makeAttributePdu(); //72 + sendPdu(pdu72); + + System.out.println(); + + recorder.stopAndClose(); + + System.out.println("Successful run"); + System.out.println("Pdus logged to "+recorder.getLogFile()); + return 0; // no error + } + + private void sendPdu(Pdu pdu) throws IOException + { + disnet.sendPdu(pdu); + sleep(100L); // Necessary because reading is asynchronous from the writing and DisNetworking is inefficiently + // making and closing a socket each time, potentially losing a packet or two. Better performance from DisThreadedNetIF. + } + + private void sleep(long ms) + { + try{Thread.sleep(ms);}catch(InterruptedException ex) {} + } + + public static final String DEFAULT_DIR = "validatorOut"; + public static final String DEFAULT_NAME = "validationLog.txt"; + + public static void main(String[] args) + { + try { + if (args.length == 2) + System.exit(new ValidationPdusMakerV1().run(args[0], args[1])); + else + System.exit(new ValidationPdusMakerV1().run(DEFAULT_DIR, DEFAULT_DIR)); + } + catch (Exception ex) { + System.err.println(ex.getClass().getSimpleName() + ": " + ex.getLocalizedMessage()); + System.exit(1); //error + } + } +} diff --git a/validation/README.md b/validation/README.md new file mode 100644 index 0000000000..b944d56728 --- /dev/null +++ b/validation/README.md @@ -0,0 +1,14 @@ + +<h2>DIS Library Validation</h2> +When new code is added to the Open DIS libraries, it is important to ensure correctness of produced network objects (PDUs) with those produced by previous versions. This also implies correctness per the IEEE and SISO specifications, so the initial basis for comparison must be manually (or otherwise) confirmed to match. + +Validation within this library is done through several classes in the `edu.nps.moves.dis7.util.playerrecorder` package: + +1. `Recorder` -- accepts byte arrays read from the net and appends them to a log file. +2. `Player`-- reads byte arrays from a log file and sends them out over the net. +3. `LogCompare` -- compares log files and reports differences to the console. +4. `ValidationPdusMakerV1` -- generates and records the "official" sequence of Pdus used to validate a library. + +To create a log file using the current library, run the main() method in`ValidationPdusMakerV1`. You may pass it a directory name and a file name. If run without arguments, the defaults are `./validatorOut` and `validationLog.txt`. + +Once there are 2 or more log files to compare, pass the paths to both files to `LogCompare`. diff --git a/validation/dis7-v1.0.dislog b/validation/dis7-v1.0.dislog new file mode 100644 index 0000000000..eee82b93e3 --- /dev/null +++ b/validation/dis7-v1.0.dislog @@ -0,0 +1,74 @@ +!Begin!Beginning of DIS capture file, validatorOut27.dislog. +AAAAAAAAAAA=,BxEBASUAZDMAjCgAIiIzMwAAAAAAAAATAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAZW3t4=,BxECAiUCYC0AYCgAIiIzMwAAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAxsXgE=,BxEDAiUEO4cAaCgAAAAAAAAAAAAAAAAAAAAAAAAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAABJ5RXs=,BxEEASUGFuEAPCgAIiIzMwAAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAABiP2rQ=,BxEFAyUH8j0AHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAAB7bKf8=,BxEGAyUJ25MAHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAACTkI88=,BxEHAyULtu0AHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAACrnrrw=,BxEIAyUNiPUAGCgAIiIzMwAAIiIzMwAA +AAAAADEl3kw=,BxEJAyUPcksAHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAADd4W/w=,BxEKAyURYEsAHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAAD2V5ZM=,BxELBSUTQE8AHCgAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAEPmEfY=,BxEMBSUVLk0AHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAAEo9fbI=,BxENBSUXHE0ALCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAFBmPPE=,BxEOBSUY/E8AJygAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAFZ5DiQ=,BxEPBSUa16sAICgAIiIzMwAAAAAAAAAAAAEAAAAAAAA= +AAAAAFyuejI=,BxEQBSUcwQEAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAGMIrtE=,BxERBSUerv8AKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAGlUKZo=,BxESBSUgnP8AKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAG9fb1g=,BxETBSUic7EAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAHVohVE=,BxEUBSUkSmEAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAHuJ0TI=,BxEVBSUmKmUAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAIHbAXQ=,BxEWBSUoGGUAICgAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAIgTTL0=,BxEXBiUqAbsAHCgAIiIzMwAAIiIzMwAAAAAAAA== +AAAAAI5V8Wo=,BxEYBiUr6xEAWCgAIiIzMwAAAAAiIjMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAJS2wn8=,BxEZBCUt3bkAaygAIiIzMwAAAAAAAAcAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAJs3H8s=,BxEaBCUvy7cAICgAIiIzMwAAAAAAAAAAAAAAAAAAAAA= +AAAAAKFvmWo=,BxEbBCUxvl8AJCgAIiIzMwAAAAAAAAAAAAAAACIiMzMAAAAA +AAAAAKfKXsQ=,BxEcBiUzsQcAPCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAK4OVC8=,BxEdBiU1ml0AICgAIiIzMwAAIiIzMwAAAAAAAAAAAAA= +AAAAALQglhY=,BxEeBiU3dbcAHCgAAAAAAAAAAAAAAAAAAAAAAA== +AAAAALorNC4=,BxEfBCU5TGkAICgAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAMB4Bzc=,BxEgBCU7OmkAKCgAAAAiIjMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAMbqtqc=,BxEhByU9MbkAiCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAMz3rVE=,BxEiByU/CGsAKCgAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAANMR2cs=,BxEjByVA6G8AKCgAIiIzMwAAIiIzMwAAAAAAAAAAIiIzMwAAAAAAAA== +AAAAANmCNHU=,BxEkByVC378ANCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATAAAAAA== +AAAAAN+sYOc=,BxElCCVEv8MARigAIiIzMwAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAOXcBmk=,BxEmCCVGpHEAKCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAATAAAAAA== +AAAAAOvsBhs=,BxEnCCVIf8sALCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAEwAAAAA= +AAAAAPICoqg=,BxEoCCVKWycAGigAAAAAAAAAAAAAAAAAAAA= +AAAAAPge8mE=,BxEpCSVMNoEAHygAIiIzMwAAAAAAEwAAAAAAAAAAAAA= +AAAAAP5tDtg=,BxEqCSVOJH8AQCgAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAQS+qcQ=,BxErCSVQEn8AVygAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAQrPkC4=,BxEsCSVR7dkAKCgAIiIzMwAAIiIzMwAAAAAAACIiMzMiIjMzAAAAAA== +AAAAAREBECY=,BxEtCSVT0ocALygAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAARdjSeY=,BxEuCyVVxS8AOAAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAR18wvc=,BxEvCyVXoIkARQAAAAAAAAAAAAAAAAAAEwAAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAASO4H30=,BxEwCyVZid8AEwAAAAAAAAAAAA== +AAAAASnEPgw=,BxExCyVbYJEARQAAIiIzMwAAACIiMzMAACIiMzMAACIiMzMAAAAAAAAAAAAAAAAAEwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAS/ViA4=,BxEyCyVdO+sAUQAAIiIzMwAAAAAiIjMzAAAiIjMzAAAiIjMzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAATX42+I=,BxEzCiVfG+8AICgAIiIzMwAAIiIzMwAAAAAAAAAAAAA= +AAAAATv7beA=,BxE0CiVg8qEAICgAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAUIfM3M=,BxE1CiVi0qUAMCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAUhfwqo=,BxE2CiVku/sAJygAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAU5jUhs=,BxE3CiVmkq0AICgAIiIzMwAAAAAAAAAAAAEAAAAAAAA= +AAAAAVRrrDM=,BxE4CiVoaV0ALCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAVp9ZuU=,BxE5CiVqRLkAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAWCTwMk=,BxE6CiVsIBMALCgAAAAAAAAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAWayk/Q=,BxE7CiVuABcAKCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAWzGRkk=,BxE8CiVv23EAKCgAIiIzMwAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAXLPD1o=,BxE9CiVxsiMAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAXjYxQA=,BxE+CiVziNUAICgAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +AAAAAX8iQGM=,BxE/CiV1cisAJCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAYU4LsU=,BxFACiV3TYUAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAYtEZxE=,BxFBCiV5KOEAKCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAZGOeUQ=,BxFCASV7Ft8AZCgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAZeVyKA=,BxFDASV87ZEASCgAIiIzMwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAZ2wXcw=,BxFEAiV+yOsAVigAIiIzMwAAIiIzMwAAAAAAEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +AAAAAaPDwnM=,BxFFAiWApEcAGCgAAAAAAAAAAAAAAAAA +AAAAAanyh7Y=,BxFGDSWCiPMAOCgAAAAAAAAAIiIzMwAAAAAAAAAAAAAAAAAAAAAAACIiMzMAACIiMzMAAAAAAAA= +AAAAAbAXnZg=,BxFHDSWEaPcAKCgAAAAAAAAAAAAAACIiMzMAACIiMzMAAAAAAAAAAA== +AAAAAbmPgQg=,BxFIASWHTfUAICgAIiIzMwAAAAAAAAAAAAAD6QAAAAA= +!End!End of DIS capture file, validatorOut27.dislog. -- GitLab