diff --git a/src/pyshark/capture/capture.py b/src/pyshark/capture/capture.py index b7aef6e..3b4b3a1 100644 --- a/src/pyshark/capture/capture.py +++ b/src/pyshark/capture/capture.py @@ -51,7 +51,8 @@ def __init__(self, display_filter=None, only_summaries=False, eventloop=None, decryption_key=None, encryption_type="wpa-pwd", output_file=None, decode_as=None, disable_protocol=None, tshark_path=None, override_prefs=None, capture_filter=None, use_json=False, include_raw=False, - use_ek=False, custom_parameters=None, debug=False): + use_ek=False, custom_parameters=None, debug=False, store_packets=True, + disable_dissection=False, reset_session=None): self.loaded = False self.tshark_path = tshark_path @@ -61,6 +62,8 @@ def __init__(self, display_filter=None, only_summaries=False, eventloop=None, self._use_ek = use_ek self.include_raw = include_raw self._packets = [] + self._store_packets = store_packets + self._disable_dissection = disable_dissection self._current_packet = 0 self._display_filter = display_filter self._capture_filter = capture_filter @@ -77,6 +80,7 @@ def __init__(self, display_filter=None, only_summaries=False, eventloop=None, self._last_error_line = None self._stderr_handling_tasks = [] self.__tshark_version = None + self._reset_session = reset_session if include_raw and not (use_json or use_ek): raise RawMustUseJsonException( @@ -137,7 +141,10 @@ def load_packets(self, packet_count=0, timeout=None): initial_packet_amount = len(self._packets) def keep_packet(pkt): - self._packets.append(pkt) + # In a live capture where you instruct tshark to write the packets to a file on disk, this can go out of memory + # within a couple of minutes. If you don't want to store the packets internally, this is where to set the condition. + if self._store_packets: + self._packets.append(pkt) if packet_count != 0 and len(self._packets) - initial_packet_amount >= packet_count: raise StopCapture() @@ -334,6 +341,17 @@ async def _get_tshark_process(self, packet_count=None, stdin=None): raise TSharkVersionException( "JSON only supported on Wireshark >= 2.2.0") + # T-Shark uses a lot of memory when sniffing continuously in the background. + # We add an option to disable all protocol dissections. This avoid using so + # much memory if we only write to file and don't use the output. + if self._disable_dissection: + output_parameters.append("--disable-all-protocols") + + # Resetting the internal session state periodically can help save memory + # when monitoring for a long time. + if self._reset_session != None and isinstance(self._reset_session, int): + output_parameters.append("-M %i" % self._reset_session) + if self.use_json: output_type = "json" if tshark_supports_duplicate_keys(self._get_tshark_version()): diff --git a/src/pyshark/capture/live_capture.py b/src/pyshark/capture/live_capture.py index 3731bd6..41c0e00 100644 --- a/src/pyshark/capture/live_capture.py +++ b/src/pyshark/capture/live_capture.py @@ -21,7 +21,7 @@ def __init__(self, interface=None, bpf_filter=None, display_filter=None, only_su disable_protocol=None, tshark_path=None, override_prefs=None, capture_filter=None, monitor_mode=False, use_json=False, use_ek=False, include_raw=False, eventloop=None, custom_parameters=None, - debug=False): + debug=False, store_packets=True, disable_dissection=False, reset_session=None): """Creates a new live capturer on a given interface. Does not start the actual capture itself. :param interface: Name of the interface to sniff on or a list of names (str). If not given, runs on all interfaces. @@ -43,6 +43,9 @@ def __init__(self, interface=None, bpf_filter=None, display_filter=None, only_su :param use_json: DEPRECATED. Use use_ek instead. :param custom_parameters: A dict of custom parameters to pass to tshark, i.e. {"--param": "value"} or else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]. + :param store_packets: Tells the parent class whether we want the packets to be stored in memory or not. + :param disable_dissection: Tells T-Shark to disable all protocol dissectors to save memory. + :param reset_session: Tells T-Shark to reset the internal session after this number of packets to save memory. """ super(LiveCapture, self).__init__(display_filter=display_filter, only_summaries=only_summaries, decryption_key=decryption_key, encryption_type=encryption_type, @@ -51,7 +54,8 @@ def __init__(self, interface=None, bpf_filter=None, display_filter=None, only_su capture_filter=capture_filter, use_json=use_json, use_ek=use_ek, include_raw=include_raw, eventloop=eventloop, custom_parameters=custom_parameters, - debug=debug) + debug=debug, store_packets=store_packets, disable_dissection=disable_dissection, + reset_session=reset_session) self.bpf_filter = bpf_filter self.monitor_mode = monitor_mode diff --git a/src/pyshark/capture/live_ring_capture.py b/src/pyshark/capture/live_ring_capture.py index 351b208..6529f0f 100644 --- a/src/pyshark/capture/live_ring_capture.py +++ b/src/pyshark/capture/live_ring_capture.py @@ -9,7 +9,8 @@ def __init__(self, ring_file_size=1024, num_ring_files=1, ring_file_name='/tmp/p encryption_type='wpa-pwk', decode_as=None, disable_protocol=None, tshark_path=None, override_prefs=None, capture_filter=None, use_json=False, use_ek=False, include_raw=False, eventloop=None, - custom_parameters=None, debug=False): + custom_parameters=None, debug=False, store_packets=True, disable_dissection=False, + reset_session=None): """ Creates a new live capturer on a given interface. Does not start the actual capture itself. :param ring_file_size: Size of the ring file in kB, default is 1024 @@ -28,18 +29,22 @@ def __init__(self, ring_file_size=1024, num_ring_files=1, ring_file_name='/tmp/p :param tshark_path: Path of the tshark binary :param override_prefs: A dictionary of tshark preferences to override, {PREFERENCE_NAME: PREFERENCE_VALUE, ...}. :param capture_filter: Capture (wireshark) filter to use. - :param disable_protocol: Tells tshark to remove a dissector for a specifc protocol. + :param disable_protocol: Tells tshark to remove a dissector for a specific protocol. :param use_ek: Uses tshark in EK JSON mode. It is faster than XML but has slightly less data. :param use_json: DEPRECATED. Use use_ek instead. :param custom_parameters: A dict of custom parameters to pass to tshark, i.e. {"--param": "value"} or else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]. or else a list of parameters in the format ["--foo", "bar", "--baz", "foo"]. + :param store_packets: Tells the parent class whether we want the packets to be stored in memory or not. + :param disable_dissection: Tells T-Shark to disable all protocol dissectors to save memory. + :param reset_session: Tells T-Shark to reset the internal session after this number of packets to save memory. """ super(LiveRingCapture, self).__init__(interface, bpf_filter=bpf_filter, display_filter=display_filter, only_summaries=only_summaries, decryption_key=decryption_key, encryption_type=encryption_type, tshark_path=tshark_path, decode_as=decode_as, disable_protocol=disable_protocol, - override_prefs=override_prefs, capture_filter=capture_filter, + override_prefs=override_prefs, capture_filter=capture_filter, use_json=use_json, use_ek=use_ek, include_raw=include_raw, eventloop=eventloop, - custom_parameters=custom_parameters, debug=debug) + custom_parameters=custom_parameters, debug=debug, store_packets=store_packets, + disable_dissection=disable_dissection, reset_session=reset_session) self.ring_file_size = ring_file_size self.num_ring_files = num_ring_files