#!/usr/bin/env python3 import argparse import collections import dpkt import json import operator import os import re import socket import subprocess import struct import sys import tabulate SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) PROJECT_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..")) TYPE_INFO_PATTERN = re.compile(r""" const\s+utils::TypeInfo\s+ (\S+)\s* # ::kType {\s* (\S+)ULL\s*,\s* # "(\S+)"\s* # "" } """, re.VERBOSE) # helpers def format_endpoint(addr, port): return "{}:{}".format(socket.inet_ntoa(addr), port) def parse_source_file(fname): ret = {} with open(fname) as f: for match in TYPE_INFO_PATTERN.finditer(f.read()): id_hex = int(match.groups()[1], 16) class_name = match.groups()[2] ret[id_hex] = class_name return ret def parse_all_source_files(dirname): ids = {} ret = subprocess.run(["find", dirname, "-name", "*.lcp.cpp"], stdout=subprocess.PIPE) ret.check_returncode() headers = list(filter(None, ret.stdout.decode("utf-8").split("\n"))) for header in headers: ids.update(parse_source_file(header)) return ids MESSAGES = parse_all_source_files(os.path.join(PROJECT_DIR, "src")) class Connection: # uint32_t message_size SIZE_FORMAT = "I" SIZE_LEN = struct.calcsize(SIZE_FORMAT) def __init__(self): self._previous = bytes() self._data = bytes() self._message = bytes() self._ts = [] self._last = None self._stats = collections.defaultdict(lambda: {"duration": [], "size": []}) self._requests = [] def _extract_message(self): if len(self._data) < self.SIZE_LEN: return False msg_len = struct.unpack_from(self.SIZE_FORMAT, self._data)[0] if len(self._data) < self.SIZE_LEN + msg_len: return False self._message = self._data[self.SIZE_LEN:] self._previous = self._data self._data = bytes() return True def add_data(self, data, direction, ts): if self._previous[-len(data):] == data \ or self._data[-len(data):] == data: print("Retransmission detected!", file=sys.stderr) return self._data += data self._ts.append(ts) if not self._extract_message(): return found = False for i in range(2, 6): if len(self._message) < (i + 1) * 8: continue message_id = struct.unpack("