|
3 | 3 | import threading
|
4 | 4 | import subprocess
|
5 | 5 | import concurrent.futures
|
| 6 | +from distutils.version import LooseVersion |
6 | 7 |
|
7 | 8 | import logbook
|
8 | 9 | import sys
|
9 | 10 |
|
10 | 11 | from logbook import StreamHandler
|
11 | 12 |
|
12 | 13 | from pyshark.tshark.tshark import get_process_path, get_tshark_display_filter_flag, \
|
13 |
| - tshark_supports_json, TSharkVersionException |
| 14 | + tshark_supports_json, TSharkVersionException, get_tshark_version |
14 | 15 | from pyshark.tshark.tshark_json import packet_from_json_packet
|
15 | 16 | from pyshark.tshark.tshark_xml import packet_from_xml_packet, psml_structure_from_xml
|
16 | 17 |
|
@@ -67,6 +68,7 @@ def __init__(self, display_filter=None, only_summaries=False, eventloop=None,
|
67 | 68 | self._log = logbook.Logger(self.__class__.__name__, level=self.DEFAULT_LOG_LEVEL)
|
68 | 69 | self._closed = False
|
69 | 70 | self._custom_parameters = custom_parameters
|
| 71 | + self._tshark_version = None |
70 | 72 |
|
71 | 73 | if include_raw and not use_json:
|
72 | 74 | raise RawMustUseJsonException("use_json must be True if include_raw")
|
@@ -158,25 +160,40 @@ def _setup_eventloop(self):
|
158 | 160 | if os.name == 'posix' and isinstance(threading.current_thread(), threading._MainThread):
|
159 | 161 | asyncio.get_child_watcher().attach_loop(self.eventloop)
|
160 | 162 |
|
161 |
| - @classmethod |
162 |
| - def _get_json_separator(cls): |
163 |
| - return ("}%s%s ," % (os.linesep, os.linesep)).encode() |
| 163 | + def _get_json_separators(self): |
| 164 | + """"Returns the separators between packets in a JSON output |
164 | 165 |
|
165 |
| - @classmethod |
166 |
| - def _extract_packet_json_from_data(cls, data, got_first_packet=True): |
| 166 | + Returns a tuple of (packet_separator, end_of_file_separator, characters_to_disregard). |
| 167 | + The latter variable being the number of characters to ignore in order to pass the packet (i.e. extra newlines, |
| 168 | + commas, parenthesis). |
| 169 | + """ |
| 170 | + if LooseVersion(self._tshark_version) >= LooseVersion("3.0.0"): |
| 171 | + return ("%s },%s" % (os.linesep, os.linesep)).encode(), ("}%s]" % os.linesep).encode(), ( |
| 172 | + 1 + len(os.linesep)) |
| 173 | + else: |
| 174 | + return ("}%s%s ," % (os.linesep, os.linesep)).encode(), ("}%s%s]" % (os.linesep, os.linesep)).encode(), 1 |
| 175 | + |
| 176 | + def _extract_packet_json_from_data(self, data, got_first_packet=True): |
167 | 177 | tag_start = 0
|
168 | 178 | if not got_first_packet:
|
169 | 179 | tag_start = data.find(b"{")
|
170 | 180 | if tag_start == -1:
|
171 | 181 | return None, data
|
172 |
| - closing_tag = cls._get_json_separator() |
173 |
| - tag_end = data.find(closing_tag) |
| 182 | + packet_separator, end_separator, end_tag_strip_length = self._get_json_separators() |
| 183 | + found_separator = None |
| 184 | + |
| 185 | + tag_end = data.find(packet_separator) |
174 | 186 | if tag_end == -1:
|
175 |
| - closing_tag = ("}%s%s]" % (os.linesep, os.linesep)).encode() |
176 |
| - tag_end = data.find(closing_tag) |
177 |
| - if tag_end != -1: |
178 |
| - # Include closing parenthesis but not comma |
179 |
| - tag_end += len(closing_tag) - 1 |
| 187 | + # Not end of packet, maybe it has end of entire file? |
| 188 | + tag_end = data.find(end_separator) |
| 189 | + if tag_end != -1: |
| 190 | + found_separator = end_separator |
| 191 | + else: |
| 192 | + # Found a single packet, just add the separator without extras |
| 193 | + found_separator = packet_separator |
| 194 | + |
| 195 | + if found_separator: |
| 196 | + tag_end += len(found_separator) - end_tag_strip_length |
180 | 197 | return data[tag_start:tag_end], data[tag_end + 1:]
|
181 | 198 | return None, data
|
182 | 199 |
|
@@ -229,7 +246,8 @@ def _packets_from_tshark_sync(self, packet_count=None, existing_process=None):
|
229 | 246 | if packet_count and packets_captured >= packet_count:
|
230 | 247 | break
|
231 | 248 | finally:
|
232 |
| - self.eventloop.run_until_complete(self._cleanup_subprocess(tshark_process)) |
| 249 | + if tshark_process in self._running_processes: |
| 250 | + self.eventloop.run_until_complete(self._cleanup_subprocess(tshark_process)) |
233 | 251 |
|
234 | 252 | def apply_on_packets(self, callback, timeout=None, packet_count=None):
|
235 | 253 | """
|
@@ -357,7 +375,9 @@ async def _get_tshark_process(self, packet_count=None, stdin=None):
|
357 | 375 | """
|
358 | 376 | if self.use_json:
|
359 | 377 | output_type = 'json'
|
360 |
| - if not tshark_supports_json(self.tshark_path): |
| 378 | + if not self._tshark_version: |
| 379 | + self._tshark_version = get_tshark_version(self.tshark_path) |
| 380 | + if not tshark_supports_json(self._tshark_version): |
361 | 381 | raise TSharkVersionException("JSON only supported on Wireshark >= 2.2.0")
|
362 | 382 | else:
|
363 | 383 | output_type = 'psml' if self._only_summaries else 'pdml'
|
|
0 commit comments