d5847cd916
Signed-off-by: Tuan-Dat Tran <tuan-dat.tran@tudattr.dev>
89 lines
2.9 KiB
Python
89 lines
2.9 KiB
Python
import sys
|
|
import time
|
|
import threading
|
|
from scapy.all import Ether, IP, UDP, send, sendp, Raw, sniff
|
|
|
|
global initial_timestamp
|
|
initial_timestamp = int(time.time() * 1000)
|
|
|
|
|
|
# Simulated ACK sending function
|
|
def send_ack(destination_IP, my_port, sender_port):
|
|
ack_data = ""
|
|
###################
|
|
# With localhost:
|
|
ack_packet = (
|
|
IP(dst=destination_IP)
|
|
/ UDP(dport=sender_port, sport=my_port)
|
|
/ Raw(load=str(ack_data))
|
|
)
|
|
send(ack_packet, verbose=False)
|
|
###################
|
|
# With netns:
|
|
# ack_packet = Ether(dst="00:00:00:00:00:04", src="00:00:00:00:00:01") / IP(dst="127.0.0.1") / UDP(dport=5551) / Raw(load=str(ack_data))
|
|
# sendp(ack_packet, verbose=False)
|
|
###################
|
|
print(f"Sent ACK: {ack_data}")
|
|
|
|
|
|
# Process incoming packets
|
|
def process_packet(pkt):
|
|
################### Save timestamps ###################
|
|
if Raw in pkt:
|
|
with open(save_file, "a") as f: # open as "a" for append
|
|
global initial_timestamp
|
|
receival_time = str(
|
|
int(time.time() * 1000) - initial_timestamp
|
|
) # time of arrival at receiver
|
|
send_time = pkt[Raw].load # time it was sent from the sender
|
|
################### Conversion & error handling ###################
|
|
try:
|
|
send_time = int(
|
|
send_time.decode("utf-8").split("X")[0]
|
|
) # decode the payload and stop at "X"
|
|
except (
|
|
ValueError
|
|
): # For the last packet without a timestamp but "END" as payload
|
|
print(f"END for {my_port}")
|
|
send_ack(destination_IP, my_port, sender_port)
|
|
return
|
|
except Exception as e:
|
|
print(f"Decoding error at {my_port}")
|
|
send_ack(destination_IP, my_port, sender_port)
|
|
return
|
|
################### Write data ###################
|
|
aoi = int(receival_time) - send_time
|
|
f.write(f"{send_time},{receival_time},{aoi}\n")
|
|
|
|
send_ack(destination_IP, my_port, sender_port)
|
|
|
|
|
|
# Main loop
|
|
def main(destination_IP, my_port, sender_port):
|
|
###################
|
|
# With localhost:
|
|
sniff(
|
|
iface="lo",
|
|
filter=f"udp and dst port {my_port}",
|
|
prn=process_packet,
|
|
store=False,
|
|
)
|
|
###################
|
|
# With netns:
|
|
# sniff(iface="ns-g", filter=f"udp and dst port {my_port}", prn=process_packet, store=False)
|
|
###################
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) != 4:
|
|
print(
|
|
"Usage: python receive_and_ack.py <destination_IP> <my_port> <sender_port>"
|
|
)
|
|
sys.exit(1)
|
|
|
|
destination_IP = sys.argv[1] # Clear
|
|
my_port = int(sys.argv[2]) # Port to listen on
|
|
sender_port = int(sys.argv[3]) # Port to send acks to
|
|
save_file = f"timestamps_{my_port}"
|
|
main(destination_IP, my_port, sender_port)
|