Skip to content

Commit 26b2ceb

Browse files
committed
Pass timestamp to Server for saving to PCAP
1 parent 4c07f9d commit 26b2ceb

File tree

2 files changed

+35
-9
lines changed

2 files changed

+35
-9
lines changed

src/libinspector/device_detail_page.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,11 @@ def label_thread():
126126
dt_object = datetime.datetime.fromtimestamp(packet.time)
127127
timestamp_str = dt_object.strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
128128
logger.info(f"[Packets] Packet reports time-stamp of {timestamp_str}")
129-
pending_packet_list.append(base64.b64encode(packet.original).decode('utf-8'))
129+
packet_metadata = {
130+
"time": packet.time,
131+
"raw_data": base64.b64encode(packet.original).decode('utf-8')
132+
}
133+
pending_packet_list.append(packet_metadata)
130134

131135
payload = _labeling_event_deque.popleft()
132136
payload['packets'] = pending_packet_list

src/libinspector/server/packet_collector.py

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -101,21 +101,36 @@ def label_packets():
101101
400: Error if required fields are missing or packet decoding fails.
102102
500: Error if database insertion fails.
103103
"""
104+
raw_packets = []
105+
capture_times = []
106+
capture_lengths = []
107+
104108
data = request.get_json()
105109
app.logger.info("Received POST data:", json.dumps(data, indent=4))
106110
required_keys = ["packets", "prolific_id", "mac_address", "device_name", "activity_label", "start_time", "end_time"]
107111
if not data or not all(key in data for key in required_keys):
108112
app.logger.warning("Missing required fields in POST data")
109113
return jsonify({"error": "Missing required fields"}), 400
114+
115+
if not is_prolific_id_valid(data["prolific_id"]):
116+
app.logger.warning("Invalid Prolific ID received")
117+
return jsonify({"error": "Prolific ID is invalid"}), 500
118+
110119
try:
111-
raw_packets = [base64.b64decode(pkt) for pkt in data["packets"]]
120+
for pkt_metadata in data["packets"]:
121+
# Validate essential keys are present
122+
if not isinstance(pkt_metadata, dict) or 'time' not in pkt_metadata or 'raw_data' not in pkt_metadata:
123+
app.logger.error("Packet object missing 'time' or 'raw_data' key.")
124+
return jsonify({"error": "Packet metadata structure is invalid"}), 400
125+
126+
raw_data_bytes = base64.b64decode(pkt_metadata["raw_data"])
127+
raw_packets.append(raw_data_bytes)
128+
capture_times.append(float(pkt_metadata["time"]))
129+
capture_lengths.append(len(raw_data_bytes))
112130
except Exception as e:
113131
app.logger.warning(f"Packet decoding occurred for collection '{data['prolific_id']}': {e}")
114132
return jsonify({"error": "Packet decoding failed"}), 400
115133

116-
if not is_prolific_id_valid(data["prolific_id"]):
117-
app.logger.warning("Invalid Prolific ID received")
118-
return jsonify({"error": "Prolific ID is invalid"}), 500
119134
folder_path: str = os.path.join(str(data["prolific_id"]), str(data["device_name"]), str(data["activity_label"]))
120135
fullpath = os.path.normpath(os.path.join(packet_root_dir, folder_path))
121136
if not fullpath.startswith(packet_root_dir):
@@ -130,7 +145,9 @@ def label_packets():
130145
"activity_label": data["activity_label"],
131146
"start_time": int(data["start_time"]),
132147
"end_time": int(data["end_time"]),
133-
"raw_packets": raw_packets
148+
"raw_packets": raw_packets,
149+
"capture_times": capture_times,
150+
"capture_lengths": capture_lengths
134151
}
135152
try:
136153
prolific_user_packets_collected.insert_one(doc)
@@ -142,7 +159,7 @@ def label_packets():
142159
os.makedirs(fullpath, exist_ok=True)
143160
pcap_file_name: str = make_pcap_filename(int(data["start_time"]), int(data["end_time"]))
144161
pcap_name: str = os.path.join(fullpath, pcap_file_name)
145-
save_packets_to_pcap(raw_packets, pcap_name)
162+
save_packets_to_pcap(raw_packets, capture_times, pcap_name)
146163
except Exception as e:
147164
# If file saving fails, return a 500 but note that the DB save succeeded
148165
app.logger.warning(f"PCAP File Save FAILED for ID: {e}")
@@ -173,22 +190,27 @@ def make_pcap_filename(start_time: int, end_time: int) -> str:
173190
return filename
174191

175192

176-
def save_packets_to_pcap(raw_packets: list, filename="output.pcap"):
193+
def save_packets_to_pcap(raw_packets: list, capture_times: list, filename="output.pcap"):
177194
"""
178195
Saves a list of raw packet bytes to a pcap file.
179196
180197
Args:
181198
raw_packets (list): List of bytes objects representing raw packets.
199+
capture_times (list): The epoch time of each packet when it was captured by IoT Inspector.
182200
filename (str): Output pcap file name.
183201
"""
184202
scapy_packets = []
185-
for pkt_bytes in raw_packets:
203+
for i, pkt_bytes in enumerate(raw_packets):
186204
try:
187205
pkt = Ether(pkt_bytes)
188206
if pkt.__class__.__name__ == "Raw":
189207
pkt = IP(pkt_bytes)
190208
except Exception:
191209
pkt = IP(pkt_bytes)
210+
211+
# CRITICAL STEP: Assign the supplied original capture time
212+
# This is guaranteed to be correct for ALL packets.
213+
pkt.time = capture_times[i]
192214
scapy_packets.append(pkt)
193215
wrpcap(filename, scapy_packets)
194216

0 commit comments

Comments
 (0)